|
|
@@ -216,17 +216,17 @@
|
|
|
import type { FileInfo } from '@/types/api';
|
|
|
import {
|
|
|
clearImportProgress,
|
|
|
- clearLegacyTaskLogStorage,
|
|
|
getActiveImportProgress,
|
|
|
getCleanFlowSource,
|
|
|
getImportProgressEventSource,
|
|
|
- getTaskLogMemory,
|
|
|
+ getTaskLogSnapshot,
|
|
|
resetImportProgressRuntimeState,
|
|
|
saveImportProgress,
|
|
|
- saveTaskLogMemory,
|
|
|
+ saveTaskLogSnapshot,
|
|
|
setImportProgressEventSource,
|
|
|
useImportProgressRuntimeState,
|
|
|
type TaskLogItem,
|
|
|
+ type TaskLogStatus,
|
|
|
} from './importProgressSession';
|
|
|
|
|
|
const { prefixCls } = useDesign('case-clean-progress');
|
|
|
@@ -264,10 +264,12 @@
|
|
|
} = useImportProgressRuntimeState();
|
|
|
const sseMessages = ref<string[]>([]);
|
|
|
/**
|
|
|
- * 处理日志:清洗 + 治理统一成一条时间线,只保存在模块内存里。
|
|
|
- * 进度页与导入文件页可以互相切换回看;刷新/关闭页面即丢失,不落 localStorage。
|
|
|
+ * 处理日志:清洗 + 治理统一成一条时间线。
|
|
|
+ * 实时写模块状态供页面渲染,同时按案件/批次落一份 localStorage 快照,
|
|
|
+ * 完成后结果页仍可回看(见 importProgressSession 的 TaskLogSnapshot)。
|
|
|
*/
|
|
|
const taskLog = ref<TaskLogItem[]>([]);
|
|
|
+ const taskLogStatus = ref<TaskLogStatus>('running');
|
|
|
const taskLogBatchId = ref('');
|
|
|
const governFailed = ref(false);
|
|
|
let taskLogSeq = 0;
|
|
|
@@ -456,6 +458,7 @@
|
|
|
const batchId = currentCleanBatchId.value || refreshCurrentCleanBatchId();
|
|
|
if (taskLogBatchId.value && batchId && batchId !== taskLogBatchId.value) {
|
|
|
taskLog.value = [];
|
|
|
+ taskLogStatus.value = 'running';
|
|
|
governFailed.value = false;
|
|
|
}
|
|
|
taskLogBatchId.value = batchId || taskLogBatchId.value;
|
|
|
@@ -469,7 +472,7 @@
|
|
|
if (taskLog.value.length > 200) {
|
|
|
taskLog.value.length = 200;
|
|
|
}
|
|
|
- saveTaskLogMemory(taskLog.value, taskLogBatchId.value, getCurrentCaseId());
|
|
|
+ persistTaskLog();
|
|
|
};
|
|
|
|
|
|
const findBatchId = (items?: FileInfo[] | null): string => {
|
|
|
@@ -504,6 +507,76 @@
|
|
|
return currentCleanBatchId.value;
|
|
|
};
|
|
|
|
|
|
+ /** 把当前日志序列落一份快照:完成后进度快照会清掉,但任务日志仍可在结果页回看 */
|
|
|
+ const persistTaskLog = (status: TaskLogStatus = taskLogStatus.value) => {
|
|
|
+ const caseId = getCurrentCaseId();
|
|
|
+ if (!caseId) return;
|
|
|
+
|
|
|
+ const batchId = taskLogBatchId.value || currentCleanBatchId.value || refreshCurrentCleanBatchId() || '';
|
|
|
+ const updatedAt = Date.now();
|
|
|
+ taskLogStatus.value = status;
|
|
|
+ saveTaskLogSnapshot({
|
|
|
+ caseId: String(caseId),
|
|
|
+ batchId,
|
|
|
+ status,
|
|
|
+ logs: taskLog.value,
|
|
|
+ successCount: successCount.value,
|
|
|
+ failCount: failCount.value,
|
|
|
+ updatedAt,
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 刷新恢复执行中的页面时,把同一批次已产生的日志接回来 */
|
|
|
+ const restoreTaskLog = () => {
|
|
|
+ const snapshot = getTaskLogSnapshot(getCurrentCaseId());
|
|
|
+ if (!snapshot) return;
|
|
|
+
|
|
|
+ const currentBatch = currentCleanBatchId.value || refreshCurrentCleanBatchId();
|
|
|
+ if (currentBatch && snapshot.batchId && snapshot.batchId !== currentBatch) return;
|
|
|
+
|
|
|
+ taskLog.value = snapshot.logs.slice();
|
|
|
+ taskLogBatchId.value = snapshot.batchId;
|
|
|
+ taskLogStatus.value = snapshot.status;
|
|
|
+ if (snapshot.status === 'failed') {
|
|
|
+ governFailed.value = true;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 完成 / 失败后刷新进度页:进度快照已在完成时清掉,但任务日志快照还在。
|
|
|
+ * 同一批次的终态直接恢复成结果视图,避免刷新后又重新跑一遍清洗。
|
|
|
+ */
|
|
|
+ const restoreCompletedTaskLog = () => {
|
|
|
+ const snapshot = getTaskLogSnapshot(getCurrentCaseId());
|
|
|
+ if (!snapshot || (snapshot.status !== 'completed' && snapshot.status !== 'failed')) return false;
|
|
|
+
|
|
|
+ const currentBatch = currentCleanBatchId.value || refreshCurrentCleanBatchId();
|
|
|
+ if (currentBatch && snapshot.batchId && snapshot.batchId !== currentBatch) return false;
|
|
|
+
|
|
|
+ taskLog.value = snapshot.logs.slice();
|
|
|
+ taskLogBatchId.value = snapshot.batchId;
|
|
|
+ taskLogStatus.value = snapshot.status;
|
|
|
+ currentCleanBatchId.value = snapshot.batchId || currentCleanBatchId.value;
|
|
|
+ successCount.value = snapshot.successCount ?? successCount.value;
|
|
|
+ failCount.value = snapshot.failCount ?? failCount.value;
|
|
|
+ cleanStatsSnapshot.value = {
|
|
|
+ ...cleanStatsSnapshot.value,
|
|
|
+ success: snapshot.successCount,
|
|
|
+ fail: snapshot.failCount,
|
|
|
+ };
|
|
|
+
|
|
|
+ const hasGovernLogs = snapshot.logs.some((item) => item.text.includes('[数据治理]'));
|
|
|
+ shouldRunGovernAfterClean.value = hasGovernLogs;
|
|
|
+ governTaskStarted.value = hasGovernLogs;
|
|
|
+ governTaskFinished.value = hasGovernLogs && snapshot.status === 'completed';
|
|
|
+ governFailed.value = snapshot.status === 'failed';
|
|
|
+ cleanTaskStarted.value = true;
|
|
|
+ cleanTaskFinished.value = true;
|
|
|
+ activeStep.value = 2;
|
|
|
+ progress.value = 100;
|
|
|
+ return true;
|
|
|
+ };
|
|
|
+
|
|
|
const handleViewLog = () => {
|
|
|
refreshCurrentCleanBatchId();
|
|
|
logModalOpen.value = true;
|
|
|
@@ -708,6 +781,7 @@
|
|
|
activeStep.value = 2;
|
|
|
governTaskFinished.value = true;
|
|
|
closeSse();
|
|
|
+ persistTaskLog('completed');
|
|
|
clearImportProgress(getCurrentCaseId());
|
|
|
safeEmitImportRefresh();
|
|
|
if (!governCompleteNotified.value) {
|
|
|
@@ -749,6 +823,7 @@
|
|
|
governFailed.value = true;
|
|
|
progress.value = 100;
|
|
|
addTaskLog(`[数据治理]${message}`);
|
|
|
+ persistTaskLog('failed');
|
|
|
closeSse();
|
|
|
createMessage.error(message);
|
|
|
}
|
|
|
@@ -811,7 +886,9 @@
|
|
|
const message = String(payload.message || '').trim();
|
|
|
if (/治理失败|治理异常/.test(message)) {
|
|
|
governFailed.value = true;
|
|
|
+ taskLogStatus.value = 'failed';
|
|
|
progress.value = 100;
|
|
|
+ persistTaskLog('failed');
|
|
|
closeSse();
|
|
|
createMessage.error(message || '数据治理失败,请查看任务日志');
|
|
|
return;
|
|
|
@@ -1143,6 +1220,7 @@
|
|
|
*/
|
|
|
watch(isComplete, (done) => {
|
|
|
if (!done) return;
|
|
|
+ persistTaskLog(governFailed.value ? 'failed' : 'completed');
|
|
|
const unable = isFused.value ? (aiStage.value?.needReviewCount ?? 0) : 0;
|
|
|
if (unable > 0) {
|
|
|
createMessage.warning(`另有 ${unable} 个表 AI 无法清洗,详情见处理日志;可用「手动清洗」处理。`);
|
|
|
@@ -1328,14 +1406,15 @@
|
|
|
};
|
|
|
|
|
|
const initializeProgress = async () => {
|
|
|
- // 任务日志在模块内存里:进度页与导入文件页可来回查看;刷新/关闭页面自然丢失
|
|
|
- const cachedTaskLog = getTaskLogMemory(undefined, getCurrentCaseId());
|
|
|
- taskLog.value = cachedTaskLog.logs;
|
|
|
- taskLogBatchId.value = cachedTaskLog.batchId;
|
|
|
+ // 每次进入都先清掉上一次留在组件里的任务日志,再按快照恢复
|
|
|
+ taskLog.value = [];
|
|
|
+ taskLogBatchId.value = '';
|
|
|
+ taskLogStatus.value = 'running';
|
|
|
governFailed.value = false;
|
|
|
- clearLegacyTaskLogStorage();
|
|
|
|
|
|
if (restoreImportProgress()) {
|
|
|
+ // 刷新恢复:把同一批次已产生的清洗/治理日志接回来,避免页面空白
|
|
|
+ restoreTaskLog();
|
|
|
// 刷新恢复:智能入口仍强制自动治理,避免旧快照把治理开关带回配置值
|
|
|
if (isSmartFlowEntry()) {
|
|
|
shouldRunGovernAfterClean.value = true;
|
|
|
@@ -1351,6 +1430,12 @@
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // 完成/失败后刷新:进度快照已清,但任务日志快照还在,直接恢复结果视图
|
|
|
+ if (restoreCompletedTaskLog()) {
|
|
|
+ closeSse();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
resetImportProgressRuntimeState();
|
|
|
|
|
|
await loadGovernSwitch();
|
|
|
@@ -1371,7 +1456,6 @@
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
clearCompletionFallbackTimer();
|
|
|
- // 日志保留在模块内存里供导入文件页回看;不落 localStorage,刷新/关闭页面即丢失
|
|
|
if (isComplete.value) {
|
|
|
closeSse();
|
|
|
} else {
|