import type { Task } from './types' import { label, phaseText, quantityText, unitText } from './state' export interface CollectionControlEvidence { collectionMode?: string | null accountPaused?: boolean blockingReason?: string | null } export function collectionControlState(task: Task | null | undefined, evidence: CollectionControlEvidence = {}) { if (task && ['SUCCEEDED', 'FAILED', 'DEAD', 'ABORTED'].includes(task.taskStatus)) return null const reasons = [task?.blockingReason, evidence.blockingReason] const text = evidence.collectionMode === 'OFF' || reasons.includes('COLLECTION_OFF') ? '采集已关闭' : evidence.accountPaused || reasons.includes('ACCOUNT_PAUSED') ? '已暂停' : reasons.includes('EXECUTION_DISABLED') ? '执行未启用' : null if (!text) return null // A control switch alone cannot establish that an already running attempt has stopped. const running = Boolean(task && ['RUNNING', 'APPLYING'].includes(task.taskStatus)) return { text, running, summary: running ? `${text === '采集已关闭' ? '已关闭' : text} · 执行中` : text } } export function isNormalContinuation(task: Task | null | undefined) { const attempt = task?.latestAttempt return task?.taskStatus === 'RETRY_WAIT' && attempt?.status === 'YIELDED' && task.latestAttemptNo != null && task.latestAttemptNo > 0 && attempt.attemptNo === task.latestAttemptNo && task.attemptCount === task.latestAttemptNo && !attempt.errorCode && !attempt.failureSummary } export function taskStateText(task: Task | null | undefined, evidence: CollectionControlEvidence = {}) { if (!task) return '尚无任务' const control = collectionControlState(task, evidence) if (control) return control.summary if (isNormalContinuation(task)) return '本批已完成,等待续采' const states: Record = { WAITING_SOURCE: '等待数据准备', WAITING_UPSTREAM: '等待数据准备', READY: '等待执行', QUEUED: '等待执行', WAITING: '等待执行', RUNNING: '正在执行', RETRY_WAIT: '等待重试', YIELDED: '本批已完成,等待续采', DEAD: '已停止,需处理', SUCCEEDED: '执行完成', FAILED: '执行失败' } return states[task.taskStatus] ?? label(task.taskStatus) } export function taskProgressText(task: Task | null | undefined) { if (!task) return '尚无任务' if (['WAITING_SOURCE', 'WAITING_UPSTREAM'].includes(task.taskStatus)) return '尚未开始,等待数据准备' if (task.attemptCount === 0 && ['READY', 'QUEUED', 'WAITING'].includes(task.taskStatus)) return '尚未开始,等待执行' const progress = task.progress if (!progress?.phase) return task.taskStatus === 'SUCCEEDED' ? '本任务执行完成' : '当前进度尚未提供' const phase = phaseText(progress.phase) if (progress.completed == null || !progress.unit || progress.unit === 'NONE') return phase const amount = `${quantityText(progress.completed)}${unitText(progress.unit)}` if (!progress.totalKnown || progress.total == null) return `${phase},已处理 ${amount},总量尚未确定` const total = Number(progress.total), completed = Number(progress.completed) const percent = Number.isFinite(total) && Number.isFinite(completed) && total > 0 && completed >= 0 && completed <= total ? `(${Math.floor(completed / total * 1000) / 10}%,当前阶段)` : '' return `${phase},已处理 ${quantityText(progress.completed)} / ${quantityText(progress.total)}${unitText(progress.unit)}${percent}` } export function taskCompletionText(task: Task | null | undefined) { if (!task) return '—' if (task.resultPublicationState === 'PUBLISHED' || task.resultPublicationState === 'REUSED') return '结果已可用' if (task.taskStatus === 'SUCCEEDED') return '执行完成,结果尚未发布' if (['DEAD', 'FAILED', 'ABORTED'].includes(task.taskStatus)) return '已停止,需先处理异常' return '完成时间暂无法预计' }