Files
crawler-plugin/frontend-vue/src/shared/merge-live-progress.ts
T

60 lines
2.0 KiB
TypeScript

/**
* live progress 合并(Task 144)。
*
* history 条目缺失 file 进度时保留实时缓存(live)进度;live 有值且有效时
* 以 live 为准;history 已可下载(fileReady/downloadUrl 就绪)时不覆盖——
* 结果文件既成,实时进度无意义。纯函数无副作用,入参不修改。
*/
export const FILE_PROGRESS_KEYS = [
'fileProgressPercent',
'fileProgressCurrent',
'fileProgressTotal',
'fileProgressMessage',
'fileReady',
'fileStatus',
] as const
export interface DownloadableItem {
resultId?: number | null
fileReady?: boolean | null
fileStatus?: string | null
downloadUrl?: string | null
}
/**
* 可下载判定(Task 145):有结果记录,且满足其一——
* fileReady=true、downloadUrl 非空、fileStatus 为终态(SUCCESS 可下载结果文件,
* FAILED 可下载错误文件或用于展示错误)。
*/
export function canDownloadItem(item: DownloadableItem | null | undefined): boolean {
if (!item) return false
const ready = item.fileReady || Boolean(item.downloadUrl)
const terminalStatus = item.fileStatus === 'SUCCESS' || item.fileStatus === 'FAILED'
return Boolean(item.resultId && (ready || terminalStatus))
}
/** 有效进度值:仅 fileProgressPercent 需要严格 >0,其余字段非空即可(0 是合法计数)。 */
export function hasMeaningfulProgress(key: string, value: unknown): boolean {
if (value === undefined || value === null) return false
if (key === 'fileProgressPercent' && typeof value === 'number') {
return value > 0
}
return true
}
export function mergeHistoryItemPreservingLiveProgress<T extends Record<string, unknown>>(
history: T,
live: T | undefined,
): T {
if (!live) return history
if (canDownloadItem(history as unknown as DownloadableItem)) return history
const result: Record<string, unknown> = { ...history }
for (const key of FILE_PROGRESS_KEYS) {
const value = (live as Record<string, unknown>)[key]
if (hasMeaningfulProgress(key, value)) {
result[key] = value
}
}
return result as T
}