|
|
@@ -107,6 +107,16 @@ public class AiSmartCleanService {
|
|
|
* @param fileInfos 前端上传页那棵树(根节点带 children=sheet)
|
|
|
*/
|
|
|
public SmartCleanVO submit(Long caseId, Long userId, List<FileInfo> fileInfos) {
|
|
|
+ return submit(caseId, userId, fileInfos, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 受理批次并立即返回,后台跑完整流程。
|
|
|
+ *
|
|
|
+ * @param autoGovern 智能入口为 true:清洗完成后自动治理,忽略「同时治理」配置;
|
|
|
+ * 自主入口为 false:按治理配置执行
|
|
|
+ */
|
|
|
+ public SmartCleanVO submit(Long caseId, Long userId, List<FileInfo> fileInfos, boolean autoGovern) {
|
|
|
if (caseId == null) {
|
|
|
throw new ServerException("未打开案件,无法智能清洗");
|
|
|
}
|
|
|
@@ -137,7 +147,7 @@ public class AiSmartCleanService {
|
|
|
// 必须一开始就放同步容器:判定阶段多个虚拟线程会并发 addReview。
|
|
|
// 若这里放裸 ArrayList,下方 computeIfAbsent 的同步工厂永远不会生效
|
|
|
reviewItems.put(batchId, java.util.Collections.synchronizedList(new ArrayList<>()));
|
|
|
- startAsync(() -> CaseContextHolder.runWith(caseId, userId, () -> run(batchId, caseId, usable)));
|
|
|
+ startAsync(() -> CaseContextHolder.runWith(caseId, userId, () -> run(batchId, caseId, usable, autoGovern)));
|
|
|
return new SmartCleanVO(batchId, AiCleanStageEnum.JUDGING.name(), usable.size(), sheetTotal,
|
|
|
matched, Math.max(0, sheetTotal - matched));
|
|
|
}
|
|
|
@@ -196,7 +206,7 @@ public class AiSmartCleanService {
|
|
|
* 智能清洗的 doClean 各趟都是静默的(见 {@code dispatchExistingByLevel}),
|
|
|
* 因此这一步是全链路唯一的终态出口 —— 纯 AI/无既有清洗的批次也靠它让前端完成跳转。
|
|
|
*/
|
|
|
- private void pushTerminal(Long caseId, Long batchId) {
|
|
|
+ private void pushTerminal(Long caseId, Long batchId, boolean autoGovern) {
|
|
|
try {
|
|
|
Long userId = CaseContextHolder.getUserId();
|
|
|
if (userId == null) {
|
|
|
@@ -249,7 +259,7 @@ public class AiSmartCleanService {
|
|
|
sseService.sendSee(userId, new SseDTO(103, 100, "AI 清洗流程完成",
|
|
|
new SeeDataDTO(0, 0, vo)));
|
|
|
}
|
|
|
- if (governConfService.hasGovern()) {
|
|
|
+ if (autoGovern || governConfService.hasGovern()) {
|
|
|
sseService.sendSee(userId, new SseDTO(102, 100, "[数据治理]开始数据治理!",
|
|
|
new SeeDataDTO(0, 0)));
|
|
|
}
|
|
|
@@ -264,6 +274,10 @@ public class AiSmartCleanService {
|
|
|
* 后台主流程:判定(并发)→ 一次 doClean → AI 自建表入库 → 终态
|
|
|
*/
|
|
|
void run(Long batchId, Long caseId, List<FileInfo> roots) {
|
|
|
+ run(batchId, caseId, roots, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ void run(Long batchId, Long caseId, List<FileInfo> roots, boolean autoGovern) {
|
|
|
long start = System.currentTimeMillis();
|
|
|
Stats st = new Stats();
|
|
|
try {
|
|
|
@@ -355,7 +369,7 @@ public class AiSmartCleanService {
|
|
|
stage(batchId, finalStage);
|
|
|
// 终态收口(全 SSE):统计 → 状态快照 → 治理宣告;纯 AI/无既有清洗的批次
|
|
|
// 没有 doClean 的完成回调,前端的「完成并跳转统计页」完全依赖这一推
|
|
|
- pushTerminal(caseId, batchId);
|
|
|
+ pushTerminal(caseId, batchId, autoGovern);
|
|
|
// 清洗全部完成:预览阶段动态建的 raw_{sheetId} 临时表已无用,统一清理。
|
|
|
// 融合链路里 doClean 完成回调已清过一次,这里再兜一次纯 AI 批次(没有 doClean 的情况)。
|
|
|
try {
|