提交工作更新
This commit is contained in:
@@ -181,10 +181,27 @@ function loadTaskSnapshotsFromStorage() { try { const raw = window.localStorage.
|
||||
function saveTaskSnapshotsToStorage() { setStorageJson(taskSnapshotsStorageKey(), taskSnapshots.value, Object.keys(taskSnapshots.value).length === 0) }
|
||||
function loadMatchedItemsFromStorage() { try { const raw = window.localStorage.getItem(matchedItemsStorageKey()); matchedItems.value = raw ? JSON.parse(raw) : [] } catch { matchedItems.value = [] } }
|
||||
function saveMatchedItemsToStorage() { setStorageJson(matchedItemsStorageKey(), matchedItems.value, matchedItems.value.length === 0) }
|
||||
function isTaskMissingError(error: unknown) { const message = error instanceof Error ? error.message : String(error || ''); return message.includes('任务不存在') }
|
||||
function syncPollingIdsWithTaskState() { const nextIds = pollingTaskIds.value.filter((taskId) => (taskDetails.value[taskId] || taskSnapshots.value[taskId]?.task?.status) === 'RUNNING'); if (nextIds.length === pollingTaskIds.value.length) return; pollingTaskIds.value = nextIds; savePollingIds() }
|
||||
function addPollingTask(taskId: number) { if (!pollingTaskIds.value.includes(taskId)) { pollingTaskIds.value = [...pollingTaskIds.value, taskId]; savePollingIds() } }
|
||||
function clearDispatchTimer(taskId: number) { const timer = dispatchTimers.get(taskId); if (timer) { window.clearTimeout(timer); dispatchTimers.delete(taskId) } }
|
||||
function removePollingTask(taskId: number) { clearDispatchTimer(taskId); pollingTaskIds.value = pollingTaskIds.value.filter((id) => id !== taskId); delete taskDetails.value[taskId]; savePollingIds(); saveTaskDetailsToStorage() }
|
||||
function removePollingTask(taskId: number) {
|
||||
clearDispatchTimer(taskId)
|
||||
pollingTaskIds.value = pollingTaskIds.value.filter((id) => id !== taskId)
|
||||
delete taskDetails.value[taskId]
|
||||
if (taskSnapshots.value[taskId]) {
|
||||
const nextSnapshots = { ...taskSnapshots.value }
|
||||
delete nextSnapshots[taskId]
|
||||
taskSnapshots.value = nextSnapshots
|
||||
saveTaskSnapshotsToStorage()
|
||||
}
|
||||
savePollingIds()
|
||||
saveTaskDetailsToStorage()
|
||||
}
|
||||
function removeTaskLocally(taskId: number) {
|
||||
removePollingTask(taskId)
|
||||
historyItems.value = historyItems.value.filter((row) => normalizeTaskId(row.taskId) !== taskId)
|
||||
}
|
||||
function stopPollingTask(taskId: number, keepStatus = true) { pollingTaskIds.value = pollingTaskIds.value.filter((id) => id !== taskId); if (!keepStatus) delete taskDetails.value[taskId]; savePollingIds(); saveTaskDetailsToStorage() }
|
||||
function isTaskTerminalStatus(status?: string) { return status === 'SUCCESS' || status === 'FAILED' || status === 'COMPLETED' }
|
||||
function isTaskTerminalById(taskId?: number) { if (!taskId) return false; const status = taskDetails.value[taskId] || taskSnapshots.value[taskId]?.task?.status; return isTaskTerminalStatus(status) }
|
||||
@@ -230,12 +247,12 @@ function restoreScheduledDispatches() { const taskIds = new Set<number>(pollingT
|
||||
function startScheduleHeartbeat() { if (scheduleHeartbeatTimer) return; scheduleHeartbeatTimer = window.setInterval(() => { void pumpScheduledQueue() }, 1000) }
|
||||
function stopScheduleHeartbeat() { if (!scheduleHeartbeatTimer) return; window.clearInterval(scheduleHeartbeatTimer); scheduleHeartbeatTimer = null }
|
||||
function handleScheduleRecovery() { restoreScheduledDispatches(); if (pollingTaskIds.value.length) ensurePolling(true) }
|
||||
async function refreshTaskBatch() { if (!pollingTaskIds.value.length) return { settledTaskIds: [] as number[] }; try { const batch = await getShopMatchTasksBatch(pollingTaskIds.value); const nextSnapshots = { ...taskSnapshots.value }; const settledTaskIds = new Set<number>(); for (const missingId of batch.missingTaskIds || []) { removePollingTask(missingId); delete nextSnapshots[missingId] } for (const detail of batch.items || []) { const taskId = detail.task?.id; if (!taskId) continue; nextSnapshots[taskId] = detail; const status = detail.task?.status || ''; if (!status) continue; taskDetails.value[taskId] = status; if (isTaskTerminalStatus(status)) { removePollingTask(taskId); settledTaskIds.add(taskId); continue } if (status === 'SCHEDULED') { stopPollingTask(taskId); settledTaskIds.add(taskId) } } taskSnapshots.value = nextSnapshots; saveTaskSnapshotsToStorage(); saveTaskDetailsToStorage(); restoreScheduledDispatches(); return { settledTaskIds: Array.from(settledTaskIds) } } catch { return { settledTaskIds: [] as number[] } } }
|
||||
async function refreshTaskBatch() { if (!pollingTaskIds.value.length) return { settledTaskIds: [] as number[] }; try { const batch = await getShopMatchTasksBatch(pollingTaskIds.value); const nextSnapshots = { ...taskSnapshots.value }; const settledTaskIds = new Set<number>(); for (const missingId of batch.missingTaskIds || []) { removeTaskLocally(missingId); delete nextSnapshots[missingId]; settledTaskIds.add(missingId) } for (const detail of batch.items || []) { const taskId = detail.task?.id; if (!taskId) continue; nextSnapshots[taskId] = detail; const status = detail.task?.status || ''; if (!status) continue; taskDetails.value[taskId] = status; if (isTaskTerminalStatus(status)) { removePollingTask(taskId); settledTaskIds.add(taskId); continue } if (status === 'SCHEDULED') { stopPollingTask(taskId); settledTaskIds.add(taskId) } } taskSnapshots.value = nextSnapshots; saveTaskSnapshotsToStorage(); saveTaskDetailsToStorage(); restoreScheduledDispatches(); return { settledTaskIds: Array.from(settledTaskIds) } } catch { return { settledTaskIds: [] as number[] } } }
|
||||
function getPollIntervalMs() { return document.visibilityState === 'visible' ? 4000 : 10000 }
|
||||
function scheduleNextPoll(immediate = false) { if (pollTimer.value) { if (!immediate) return; window.clearTimeout(pollTimer.value); pollTimer.value = null } const run = async () => { pollTimer.value = null; if (pollingInFlight.value || !pollingTaskIds.value.length) { if (pollingTaskIds.value.length) scheduleNextPoll(); return } pollingInFlight.value = true; try { const { settledTaskIds } = await refreshTaskBatch(); if (settledTaskIds.length) await Promise.allSettled([loadHistory(), loadDashboard()]) } finally { pollingInFlight.value = false } if (pollingTaskIds.value.length) pollTimer.value = window.setTimeout(run, getPollIntervalMs()) }; if (immediate) void run(); else pollTimer.value = window.setTimeout(run, getPollIntervalMs()) }
|
||||
function ensurePolling(immediate = false) { scheduleNextPoll(immediate) }
|
||||
function stopPolling() { if (pollTimer.value) { window.clearTimeout(pollTimer.value); pollTimer.value = null } }
|
||||
async function waitForTaskTerminal(taskId: number) { while (true) { const batch = await getShopMatchTasksBatch([taskId]); const detail = (batch.items || []).find((item) => item.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 (isTaskTerminalStatus(status)) { removePollingTask(taskId); await loadHistory(); await loadDashboard(); restoreScheduledDispatches(); return status } await new Promise<void>((resolve) => { window.setTimeout(() => resolve(), getPollIntervalMs()) }) } }
|
||||
async function waitForTaskTerminal(taskId: number) { while (true) { const batch = await getShopMatchTasksBatch([taskId]); if ((batch.missingTaskIds || []).includes(taskId)) { removeTaskLocally(taskId); await loadHistory(); await loadDashboard(); restoreScheduledDispatches(); return 'FAILED' } const detail = (batch.items || []).find((item) => item.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 (isTaskTerminalStatus(status)) { removePollingTask(taskId); await loadHistory(); await loadDashboard(); restoreScheduledDispatches(); return status } await new Promise<void>((resolve) => { window.setTimeout(() => resolve(), getPollIntervalMs()) }) } }
|
||||
function resolvedTaskStatus(item: ShopMatchHistoryItem) { const taskId = normalizeTaskId(item.taskId); if (!taskId) return item.taskStatus || ''; return taskDetails.value[taskId] || taskSnapshots.value[taskId]?.task?.status || item.taskStatus || '' }
|
||||
function taskSnapshotOf(item: ShopMatchHistoryItem) { const taskId = normalizeTaskId(item.taskId); return taskId ? taskSnapshots.value[taskId] : undefined }
|
||||
function currentTaskStageText(item: ShopMatchHistoryItem) { const snapshot = taskSnapshotOf(item); const task = snapshot?.task; const stages = task?.scheduleStages || []; if (!stages.length) return ''; const total = stages.length; const activeIndex = typeof task?.activeStageIndex === 'number' ? task.activeStageIndex : undefined; const currentIndex = typeof task?.currentStageIndex === 'number' ? task.currentStageIndex : undefined; if (typeof activeIndex === 'number') return `执行进度: 第 ${activeIndex + 1}/${total} 次执行中`; if (typeof currentIndex === 'number') return `执行进度: 等待第 ${currentIndex + 1}/${total} 次`; return `执行进度: 共 ${total} 次`}
|
||||
@@ -250,10 +267,7 @@ async function deleteTaskRecord(item: ShopMatchHistoryItem) {
|
||||
try {
|
||||
if (taskId > 0) {
|
||||
await deleteShopMatchTask(taskId)
|
||||
removePollingTask(taskId)
|
||||
historyItems.value = historyItems.value.filter((row) => normalizeTaskId(row.taskId) !== taskId)
|
||||
delete taskSnapshots.value[taskId]
|
||||
saveTaskSnapshotsToStorage()
|
||||
removeTaskLocally(taskId)
|
||||
} else if (resultId > 0) {
|
||||
await deleteShopMatchHistory(resultId)
|
||||
historyItems.value = historyItems.value.filter((row) => Number(row.resultId || 0) !== resultId)
|
||||
@@ -262,7 +276,14 @@ async function deleteTaskRecord(item: ShopMatchHistoryItem) {
|
||||
throw new Error('缺少可删除的任务标识')
|
||||
}
|
||||
await Promise.allSettled([loadHistory(), loadCandidates(), loadDashboard()])
|
||||
ElMessage.success('删除成功')
|
||||
} catch (error) {
|
||||
if (taskId > 0 && isTaskMissingError(error)) {
|
||||
removeTaskLocally(taskId)
|
||||
await Promise.allSettled([loadHistory(), loadCandidates(), loadDashboard()])
|
||||
ElMessage.success('任务已在服务端删除,本地记录已同步清理')
|
||||
return
|
||||
}
|
||||
ElMessage.error(error instanceof Error ? error.message : '删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user