修复接口内容缺失

This commit is contained in:
super
2026-04-08 16:14:26 +08:00
parent 336338cff5
commit 0327d1cc51
17 changed files with 13738 additions and 1034 deletions

View File

@@ -475,6 +475,13 @@ function rowKeyForMatch(row: ProductRiskShopQueueItem) {
return `${name}\u0001${id}`
}
function removeMatchedRowsLocally(rows: ProductRiskShopQueueItem[]) {
if (!rows.length) return
const keys = new Set(rows.map((row) => rowKeyForMatch(row)))
matchedItems.value = matchedItems.value.filter((row) => !keys.has(rowKeyForMatch(row)))
saveMatchedItemsToStorage()
}
async function removeMatchedRow(row: ProductRiskShopQueueItem) {
const key = rowKeyForMatch(row)
const backup = [...matchedItems.value]
@@ -608,14 +615,24 @@ function isTaskTerminalById(taskId?: number) {
return s === 'SUCCESS' || s === 'FAILED'
}
const currentSectionItems = computed(() =>
historyItems.value.filter(
const currentSectionItems = computed(() => {
const out = historyItems.value.filter(
(row) =>
row.taskId &&
pollingTaskIds.value.includes(row.taskId) &&
!isTaskTerminalById(row.taskId),
),
)
)
const existingTaskIds = new Set(out.map((row) => row.taskId).filter((id): id is number => typeof id === 'number'))
for (const taskId of pollingTaskIds.value) {
if (existingTaskIds.has(taskId)) continue
const snapshot = taskSnapshots.value[taskId]
const items = snapshot?.items || []
const first = items[0]
if (first) out.push(first)
}
return out
})
const historySectionItems = computed(() =>
historyItems.value.filter(
@@ -706,6 +723,37 @@ function stopPolling() {
}
}
async function waitForTaskTerminal(taskId: number) {
while (true) {
const batch = await getProductRiskTasksBatch([taskId])
const detail = (batch.items || []).find((d) => d.task?.id === taskId)
const status = detail?.task?.status || ''
if (detail) {
taskSnapshots.value = {
...taskSnapshots.value,
[taskId]: detail,
}
saveTaskSnapshotsToStorage()
}
if (status) {
taskDetails.value[taskId] = status
saveTaskDetailsToStorage()
}
if (status === 'SUCCESS' || status === 'FAILED') {
removePollingTask(taskId)
await loadHistory()
await loadDashboard()
return status
}
await new Promise<void>((resolve) => {
window.setTimeout(() => resolve(), getPollIntervalMs())
})
}
}
async function confirmAdd() {
const name = shopInput.value.trim()
if (!name) {
@@ -808,9 +856,14 @@ async function runMatch() {
}
}
function statusText(item: ProductRiskHistoryItem) {
function resolvedTaskStatus(item: ProductRiskHistoryItem) {
const tid = item.taskId
const st = tid ? taskStatusOf(tid) : item.taskStatus
if (!tid) return item.taskStatus || ''
return taskStatusOf(tid) || item.taskStatus || ''
}
function statusText(item: ProductRiskHistoryItem) {
const st = resolvedTaskStatus(item)
if (st === 'SUCCESS') return '已完成'
if (st === 'FAILED') return '失败'
if (st === 'RUNNING') return '执行中'
@@ -819,17 +872,15 @@ function statusText(item: ProductRiskHistoryItem) {
}
function statusClass(item: ProductRiskHistoryItem) {
const tid = item.taskId
const st = tid ? taskStatusOf(tid) : item.taskStatus
const st = resolvedTaskStatus(item)
if (st === 'SUCCESS' || item.success) return 'success'
if (st === 'FAILED') return 'failed'
return 'running'
}
function canDownload(item: ProductRiskHistoryItem) {
if (!item.resultId) return false
const tid = item.taskId
const st = tid ? taskStatusOf(tid) : item.taskStatus
if (!item.resultId || !item.downloadUrl) return false
const st = resolvedTaskStatus(item)
return st === 'SUCCESS' || item.success === true
}
@@ -894,26 +945,27 @@ async function pushToPythonQueue() {
}
pushing.value = true
queuePayloadText.value = ''
let createdTaskId: number | null = null
try {
const created = await createProductRiskTask(toPush)
createdTaskId = created.taskId
taskSnapshots.value = {
...taskSnapshots.value,
[created.taskId]: {
task: { id: created.taskId, status: 'RUNNING' },
items: created.items,
},
}
saveTaskSnapshotsToStorage()
addPollingTask(created.taskId)
for (let i = 0; i < toPush.length; i++) {
const item = toPush[i]
const created = await createProductRiskTask([item])
const taskId = created.taskId
taskSnapshots.value = {
...taskSnapshots.value,
[taskId]: {
task: { id: taskId, status: 'RUNNING' },
items: created.items,
},
}
saveTaskSnapshotsToStorage()
addPollingTask(taskId)
ensurePolling(true)
const payload = {
type: 'product-risk-resolve-run',
ts: Date.now(),
data: {
taskId: created.taskId,
taskId,
items: [item],
country_codes: [...orderedCountryCodes.value],
risk_listing_filter: productRiskListingFilter.value,
@@ -922,18 +974,32 @@ async function pushToPythonQueue() {
queuePayloadText.value = JSON.stringify(payload, null, 2)
const pushResult = await api.enqueue_json(payload)
if (!pushResult?.success) {
removePollingTask(created.taskId)
removePollingTask(taskId)
queuePushResult.value = `${i + 1}/${toPush.length} 条推送失败:${pushResult?.error || '未知错误'}`
ElMessage.error(queuePushResult.value)
return
}
queuePushResult.value = `任务 ${created.taskId}:已入队 ${i + 1}/${toPush.length} 条店铺,当前队列长度:${pushResult.queue_size ?? '-'}`
removeMatchedRowsLocally([item])
queuePushResult.value = toPush.length > 1
? `任务 ${taskId}:第 ${i + 1}/${toPush.length} 条店铺已入队,等待执行完成...`
: `任务 ${taskId} 已入队,等待执行完成...`
const finalStatus = await waitForTaskTerminal(taskId)
if (finalStatus !== 'SUCCESS') {
queuePushResult.value = `任务 ${taskId} 执行失败,已停止后续店铺推送`
ElMessage.error(queuePushResult.value)
return
}
queuePushResult.value = i + 1 < toPush.length
? `任务 ${taskId} 已完成,继续推送下一条(${i + 1}/${toPush.length}`
: `任务 ${taskId} 已完成`
}
ElMessage.success(`创建任务 ${created.taskId}${toPush.length} 条店铺已逐条入队`)
ElMessage.success(`按顺序完成 ${toPush.length} 条店铺推送`)
await loadHistory()
ensurePolling(true)
} catch (e) {
if (createdTaskId != null) removePollingTask(createdTaskId)
queuePushResult.value = e instanceof Error ? e.message : '推送异常'
ElMessage.error(queuePushResult.value)
} finally {

View File

@@ -9,13 +9,20 @@
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
"@/*": [
"./src/*"
]
},
"types": ["vite/client"]
"types": [
"vite/client"
]
},
"include": [
"src/**/*.ts",
@@ -25,5 +32,9 @@
"auto-imports.d.ts",
"components.d.ts"
],
"references": [{ "path": "./tsconfig.node.json" }]
}
"references": [
{
"path": "./tsconfig.node.json"
}
]
}