cc 3 dias atrás
pai
commit
fe18a4d102

+ 40 - 16
ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiSmartCleanService.java

@@ -68,7 +68,9 @@ public class AiSmartCleanService {
 
     private final DmService dmService;
 
-    /** 进度与终态全部走 SSE 推送(cmd 103),前端不再轮询状态接口 */
+    /**
+     * 进度与终态全部走 SSE 推送(cmd 103),前端不再轮询状态接口
+     */
     private final SseService sseService;
 
     private final FileInfoMapper fileInfoMapper;
@@ -88,11 +90,15 @@ public class AiSmartCleanService {
     @Value("${zsjz.ai-clean.batch-token-budget:0}")
     private long batchTokenBudget;
 
-    /** 每任务一个虚拟线程,真正的并发上限由闸门控制(与 FileRecognitionService 同一套) */
+    /**
+     * 每任务一个虚拟线程,真正的并发上限由闸门控制(与 FileRecognitionService 同一套)
+     */
     private final ExecutorService executor = Executors.newThreadPerTaskExecutor(
             Thread.ofVirtual().name("ai-clean-", 0).factory());
 
-    /** 待人工明细:判定阶段并发写入 */
+    /**
+     * 待人工明细:判定阶段并发写入
+     */
     private final Map<Long, List<NeedReviewItem>> reviewItems = new ConcurrentHashMap<>();
 
     /**
@@ -119,7 +125,7 @@ public class AiSmartCleanService {
         int sheetTotal = usable.stream()
                 .mapToInt(r -> r.getChildren() == null ? 0 : r.getChildren().size()).sum();
         int matched = (int) usable.stream().flatMap(r -> r.getChildren() == null
-                ? java.util.stream.Stream.<FileInfo>empty() : r.getChildren().stream())
+                        ? java.util.stream.Stream.<FileInfo>empty() : r.getChildren().stream())
                 .filter(s -> s != null && s.getTemplateId() != null).count();
         BatchRef ref = upsertBatch(caseId, batchId, usable.size(), sheetTotal, matched);
         if (!ref.fresh()) {
@@ -143,7 +149,9 @@ public class AiSmartCleanService {
         Thread.startVirtualThread(body);
     }
 
-    /** 前端轮询(兼容旧入口;实时进度已改为 SSE 推送,见 {@link #pushProgress}) */
+    /**
+     * 前端轮询(兼容旧入口;实时进度已改为 SSE 推送,见 {@link #pushProgress})
+     */
     public SmartCleanStatusVO status(Long caseId, Long batchId) {
         AiCleanBatch batch = batchMapper.selectOne(Wrappers.<AiCleanBatch>lambdaQuery()
                 .eq(AiCleanBatch::getCaseId, caseId)
@@ -227,7 +235,9 @@ public class AiSmartCleanService {
 
     // ==================== 后台主流程 ====================
 
-    /** 后台主流程:判定(并发)→ 一次 doClean → AI 自建表入库 → 终态 */
+    /**
+     * 后台主流程:判定(并发)→ 一次 doClean → AI 自建表入库 → 终态
+     */
     void run(Long batchId, Long caseId, List<FileInfo> roots) {
         long start = System.currentTimeMillis();
         Stats st = new Stats();
@@ -371,7 +381,9 @@ public class AiSmartCleanService {
         }
     }
 
-    /** 单表失败:只影响它自己那条 job 与计数,不中断整批 */
+    /**
+     * 单表失败:只影响它自己那条 job 与计数,不中断整批
+     */
     private void fail(Long batchId, PendingAi p, String reason, Stats st) {
         aiCleanService.finish(p.job(), AiCleanStatusEnum.FAIL, reason, System.currentTimeMillis());
         st.failed.incrementAndGet();
@@ -434,7 +446,9 @@ public class AiSmartCleanService {
         return applied;
     }
 
-    /** 把本级的 sheet 挂到根节点<b>浅拷贝</b>上发一趟既有清洗,并等它全部落库 */
+    /**
+     * 把本级的 sheet 挂到根节点<b>浅拷贝</b>上发一趟既有清洗,并等它全部落库
+     */
     private void runCleanPass(List<FileInfo> roots, Map<FileInfo, List<FileInfo>> sheetsByRoot, boolean silent) {
         // 根节点用浅拷贝:不改动前端提交的原始树;两趟各持各的根,互不覆盖
         // (sheet 对象本身仍是同一批引用,瞬态字段只在分组时写一次)
@@ -492,9 +506,9 @@ public class AiSmartCleanService {
 
     /**
      * 建/重置批次。
-     *
-     * @param fresh false 表示上一轮还在跑(非终态),调用方应复用而不是再起一遍 ——
-     *              否则同一批次会有两个线程各自发一次 doClean。
+     * <p>
+     * 表示上一轮还在跑(非终态),调用方应复用而不是再起一遍 ——
+     * 否则同一批次会有两个线程各自发一次 doClean。
      */
     private BatchRef upsertBatch(Long caseId, Long batchId, int fileCount, int sheetTotal, int matched) {
         AiCleanBatch exist = batchMapper.selectOne(batchKey(caseId, batchId));
@@ -545,7 +559,9 @@ public class AiSmartCleanService {
         }
     }
 
-    /** 批次行 + 是否该由本次调用启动后台流程 */
+    /**
+     * 批次行 + 是否该由本次调用启动后台流程
+     */
     private record BatchRef(AiCleanBatch batch, boolean fresh) {
     }
 
@@ -630,7 +646,9 @@ public class AiSmartCleanService {
         private final AtomicInteger aiLoad = new AtomicInteger();
         private final AtomicInteger needReview = new AtomicInteger();
         private final AtomicInteger failed = new AtomicInteger();
-        /** 本轮已消耗的模型 token(判定回写),供批次预算护栏比对 */
+        /**
+         * 本轮已消耗的模型 token(判定回写),供批次预算护栏比对
+         */
         private final AtomicLong tokens = new AtomicLong();
     }
 
@@ -643,7 +661,9 @@ public class AiSmartCleanService {
         executor.shutdownNow();
     }
 
-    /** 一个待判定的 AI 表块 */
+    /**
+     * 一个待判定的 AI 表块
+     */
     private record PendingAi(FileInfo root, FileInfo sheet, AiCleanJob job) {
     }
 
@@ -655,12 +675,16 @@ public class AiSmartCleanService {
                                  String reason) {
     }
 
-    /** 受理响应 */
+    /**
+     * 受理响应
+     */
     public record SmartCleanVO(Long batchId, String stage, int fileCount, int sheetTotal,
                                int matchedCount, int aiSheetCount) {
     }
 
-    /** 轮询响应 */
+    /**
+     * 轮询响应
+     */
     public record SmartCleanStatusVO(String stage, int fileCount, int sheetTotal, int matchedCount,
                                      int aiJudgedCount, int existingHitCount, int aiLoadCount,
                                      int needReviewCount, int failedCount, List<NeedReviewItem> needReview) {