# WorkOrderServiceImpl.saveCustomWorkOrder 中 domain_request 分支梳理 > 目标:把 `saveCustomWorkOrder` 里 `if (WorkOrderEnums.Type.domain_request.name().equals(workList.getType()))` 这一支的整体链路、分支条件、以及涉及的库表操作梳理清楚(包含精确/泛域名、批量/非批量两条线),用于后续重构前的理解与拆分。 --- ## 0. 入口位置与范围 入口方法: - `WorkOrderServiceImpl.saveCustomWorkOrder(…)` `cdn-service/src/main/java/com/cmcc/cdn/platform/selfservice/order/WorkOrderServiceImpl.java:2634` 本文聚焦分支: - `WorkOrderServiceImpl.saveCustomWorkOrder` 中 `if (WorkOrderEnums.Type.domain_request.name().equals(workList.getType())) { … }` `WorkOrderServiceImpl.java:2664` --- ## 1. saveCustomWorkOrder 的前置校验(进入 domain_request 分支之前) ### 1.1 登录态与企业操作权限校验 - 登录态为空直接失败:`WorkOrderServiceImpl.java:2635-2637` - 校验当前用户是否能操作 `workList.enterprise`: - 读取当前用户可操作的企业列表:`enterpriseService.getNewCustomDisplay(SecurityUserUtil.getId())` - 若 `workList.enterprise != 当前登录企业` 且也不在可操作企业列表里:抛错 `WorkOrderServiceImpl.java:2638-2643` 涉及表:这里主要是服务查询,具体表在 `enterpriseService` 内部(本文不展开)。 ### 1.2 企业信息读取(用于后续显示/通知等) - 通过 `enterpriseInfoDao.findByEnterpriseId(workList.getEnterprise())` 拿企业名称 `WorkOrderServiceImpl.java:2646-2649` > `enterprise_info`(推断)被读;实际表名需以 `EnterpriseInfo` 实体为准。 ### 1.3 CP 角色分支:配置校验 + model 文案拼接 如果当前登录角色为企业账号(CP): - `checkOrderConfig(workList)` 校验姓名/手机号/邮箱格式 `WorkOrderServiceImpl.java:2650-2652` `WorkOrderServiceImpl.java:3038-3049` - `workList.model` 解析成文案(`CustomOrderEnums.ModelVO`) `WorkOrderServiceImpl.java:2652-2658` ### 1.4 附件数量限制 - `workList.md5List`(通用附件)最多 5 个 `WorkOrderServiceImpl.java:2660-2662` --- ## 2. domain_request 分支总览(主流程) 核心代码范围: - `WorkOrderServiceImpl.java:2664-2734` 整体顺序可以理解为: 1. 企业惩戒复核(联合惩戒黑名单) 2. 调 `DomainOrderService.handleWithDomainOrder` 生成/更新域名配置需求工单(含写库) 3. 若是修改重提:清理历史“信安附件 file_info + 工单附件关联 log_file_resource”冗余 4. 重建本次提交的附件关联(log_file_resource) 5. 绑定工单-企业关系(worker_order_enterprise) 6. 触发信安/备案号校验与流程流转(WorkOrderManager) 7. 拼 domainInfo / enterpriseInfo 写入 request header(疑似用于后续启动 BPM 或审计) 8. 特殊:若工单已落 BPM 且为新建(非修改),则覆盖工单下一处理人 下面按步骤拆开。 --- ## 3. Step 1:联合惩戒复核(企业是否被惩戒) - `recheckEnterprisePunishmentStatus(info)` `WorkOrderServiceImpl.java:2665-2666` 方法本体:`WorkOrderServiceImpl.java:2753-2772` 逻辑要点: - info 不存在:仅 warn,不阻断(`2754-2757`) - 调用 BBoss 联合惩戒查询:`bBossInteractiveService.queryJointPunish(enterpriseInfo.getEcId())`(`2759`) - 若响应失败或已惩戒:抛 `PlatformException` 阻断(`2761-2771`) 库表:无直接 DB 写入(是外部接口/服务调用)。 --- ## 4. Step 2:创建/修改域名配置需求工单(核心入库点) ### 4.1 是否修改重提 - `boolean isModify = Objects.nonNull(workList.getId());` `WorkOrderServiceImpl.java:2667` > 这里的 `workList.id` 代表 **work_order.id(运营总表主键)**。 ### 4.2 调用 DomainOrderService.handleWithDomainOrder(★主入口) - `ConfigureDomainOrderPO domainOrderPO = domainOrderService.handleWithDomainOrder(workList, modelStr);` `WorkOrderServiceImpl.java:2669` 该方法位置: - `DomainOrderService.handleWithDomainOrder(…)` `cdn-service/src/main/java/com/cmcc/cdn/platform/selfservice/order/DomainOrderService.java:2569` #### 4.2.1 handleWithDomainOrder:域名规模/泛域名/迁移工单校验 - 单次 add/delete 的域名数上限(配置项 `MAX_DOMAIN_ADD_SIZE`,默认 100) `DomainOrderService.java:2570-2574` - 域名存在性校验(域名表或工单表): `domainStateService.checkDomainExist(domains, workList.getCode(), workList.getRequirement())` `DomainOrderService.java:2576-2580` - 新增(add)时泛域名包含关系校验(泛域名之间、与系统已有泛域名) `DomainOrderService.java:2587-2596` - 删除(delete)时校验不能存在未完成的域名迁移工单 `domainMigrateService.judgeUnCompleteDomainMigRateOrder(domains)` `DomainOrderService.java:2598-2609` - 省份“全国(33)”展开为 31 省 `DomainOrderService.java:2612-2617` - 非 delete 时:BSS/THIRD/WEB 来源企业必须上传信安附件 `DomainOrderService.java:2625-2632` 最后落到: - `return checkAndSaveConfigDomain(workList, modelStr);` `DomainOrderService.java:2633` #### 4.2.2 checkAndSaveConfigDomain:批量/非批量分流、重复工单校验、入域名表 入口: - `DomainOrderService.checkAndSaveConfigDomain(…)` `DomainOrderService.java:2328` 关键分支: 1. 批量单要求必须有 `fileId`(批量附件) - 若 `isBatch=true`,把 `fileId` fallback 为 `secInfoFileId[0]`(存在明显历史兼容) `DomainOrderService.java:2333-2338` 2. 非批量必须有 speedList;删除时还校验域名状态 `DomainOrderService.java:2339-2351` 3. 修改重提场景:允许同域名的“进行中工单”只排除自己 - 查询 `configure_list + speed_configure_domain` 的进行中工单: `orderRepository.findByDomainAndStatusIsNot(domain, Finish)` `DomainOrderService.java:2354-2373` - `DomainOrderRepository.findByDomainAndStatusIsNot` 是 native join(见库表章节) 4. 直播产品不支持冲突域名(cpDomain)场景 `DomainOrderService.java:2393-2397` 然后真正保存工单子表(configure_list): - `ConfigureDomainOrderPO domainOrderPO = saveConfigureDomain(workList, modelStr);` `DomainOrderService.java:2398` 并且在 `domain_request + requirement=CREATE` 情况下,会把域名落到域名配置表: - 批量:从 `batch_self_domain` 生成 `self_service_domain_config` `DomainOrderService.java:2406-2444` - 非批量:从 `speed_configure_domain` 生成 `self_service_domain_config` `DomainOrderService.java:2445-2481` > 这一步是 **“域名入域名表”** 的关键点:`selfServiceDomainConfigDao.saveAll(…)`。 --- ## 5. Step 2.3 saveConfigureDomain:work_order / configure_list / 关联表写入(非常关键) 入口: - `DomainOrderService.saveConfigureDomain(…)` `DomainOrderService.java:509` ### 5.1 “workList.type == domain_request” vs “最终写入 work_order.type” 这里有一个容易踩坑的点: - `saveCustomWorkOrder` 的分支条件看的是 `workList.getType()`(前端传参) - 但 `saveConfigureDomain` 内部会根据是否 CP 账号改写实际工单类型: - `cpFlag=true` ⇒ `workType = WorkOrderEnums.Type.configure` - 否则 `workType = WorkOrderEnums.Type.domain_request` `DomainOrderService.java:510-513` 也就是说:**同样走 domain_request 分支,落库可能是 configure 或 domain_request 两种工单类型**(看当前登录角色)。 ### 5.2 修改重提(isModify)的认定 - `isModify = workList.id != null && workType == domain_request` `DomainOrderService.java:514-515` - 修改时: - 读取旧 `work_order`:`workOrderService.findById(workList.getId())`(`516`) - 用新的域名列表覆盖 `work_order.details`(`517-521`) - 同时记录旧的 speedDomains,稍后删除旧关联行 `DomainOrderService.java:565-575` ### 5.3 非批量新建:work_order 复用/创建 & 工单号生成 非批量 `!isBatch` 时: - 通过 `customService.getWorkOrder(workType, domains, enterprise)` 获取/复用 `work_order` `DomainOrderService.java:523-528` - 如果 `workOrder` 为空且不是 delete:生成 code - domain_request:调用 `workOrderService.getWorkOrderCode(domain_request)` `DomainOrderService.java:534-536` - configure:随机 16 位并保证不重复 `DomainOrderService.java:537-543` ### 5.4 信安附件内容校验(重要:精确/泛域名都在这里做一致性校验) - 非 delete 时做校验:`checkUnitInfomation(workList, workOrder.getCode())` `DomainOrderService.java:545-548` 方法本体: - `DomainOrderService.checkUnitInfomation(WorkOrderVO, workId)` `DomainOrderService.java:372` 关键点: - 海外产品(ProdTypeEnum.isOverseas)且是 domain_request:跳过信安附件校验 `DomainOrderService.java:373-377` - 读取信安 Excel(从 `secInfoFileId[0]`)解析为对象: `excelUtil.convertToObjectFromExcel(…)` `DomainOrderService.java:379-384` - 信安信息不允许泛域名(domain 以 `*` 开头直接抛错) `DomainOrderService.java:385-389` - 若是泛域名(EXTENSIVEDOMAIN): - 校验上传信安域名与页面 subdomain 列表一一对应、备案号一致 `DomainOrderService.java:391-403` - 若是精确域名(非 EXTENSIVE): - 校验上传信安域名与页面 speedList 一一对应、备案号一致 `DomainOrderService.java:404-416` - 校验域名未在域名表中存在:`selfServiceDomainConfigDao.findByDomain(domain)` `DomainOrderService.java:420-426` - 给每条信安记录打上 `informaionId = workId`(这里的 workId 实际是工单 code) `DomainOrderService.java:427-429` > 这里的校验是“前端页面填写信息”与“上传信安模板内容”的强一致校验,是后续重构时最容易拆坏的点。 ### 5.5 生成 ConfigureDomainOrderPO 并保存(configure_list) - 非批量:用 `ConfigureDomainOrderPO.createDomainOrderPO(…)` 构造 `DomainOrderService.java:579-583` 对应实体表:`configure_list`(`ConfigureDomainOrderPO.java:40-41`) - 批量:走 `createConfigureDomainOrderPOFromBatchDomainFile(…)` `DomainOrderService.java:577-579` 批量域名表: - `BatchSelfDomainPO` => `batch_self_domain` `BatchSelfDomainPO.java:32-33` 关联的“加速域名明细”表: - `SpeedConfigureDomainPO` => `speed_configure_domain` `SpeedConfigureDomainPO.java:26-27` ### 5.6 泛域名(EXTENSIVEDOMAIN):子域名入库(sub_domain + join 表) 如果 `workList.domainType == EXTENSIVEDOMAIN`: - 校验每个子域名必须属于该泛域名后缀 - `domainOrderPO.setSubDomains(…)` 存子域名列表(SubDomainPO) `DomainOrderService.java:611-625` 子域名表: - `sub_domain`(`SubDomainPO.java:20-21`) join 表: - `work_order_domain_request_sub`(在 `ConfigureDomainOrderPO` 的 `@JoinTable` 上) `ConfigureDomainOrderPO.java:139-145` ### 5.7 修改重提:删除旧 speed_configure_domain - 若 `preSpeedDomains` 非空:`speedConfigureDomainDao.deleteAll(preSpeedDomains)` `DomainOrderService.java:629-633` ### 5.8 保存 configure_list + 追加 domain_history 记录 - `ConfigureDomainOrderPO p = orderRepository.save(domainOrderPO);` `DomainOrderService.java:635` - domain_history:至少写 1 条 - 修改重提:`Button.submit` `DomainOrderService.java:637-640` - 普通新建:result 为 null `DomainOrderService.java:641-643` 此外(非海外 + 创建单)还会写一条“控制信安信息显示/校验状态”的记录: - `DomainHistoryPO.create(p.getId(), false, false, submit)` `DomainOrderService.java:651-654` --- ## 6. Step 3:修改重提时的“历史附件清理”(file_info + log_file_resource) 回到 `WorkOrderServiceImpl.saveCustomWorkOrder`: 如果 `isModify=true`: 1. 查旧 configure_list(通过 work_order.id)拿 orgEnterId: - `ConfigureDomainOrderPO orgPo = orderRepository.findByWorkOrderId(workList.getId()).orElse(null);` - `orgEnterId = orgPo.getTenantId();` `WorkOrderServiceImpl.java:2671-2672` 2. 删除历史信安附件(file_info)冗余: - `deleteHistoryFileInfo(workList, domainOrderPOId)` `WorkOrderServiceImpl.java:2676` 方法:`WorkOrderServiceImpl.java:3660-3683` 其删除策略: - 新提交的 `secInfoFileId` 为空则不删 - 查当前工单关联的 log_file_resource,取 `fileContentType == security_info` 的 md5 列表 - `oldMd5.removeAll(newSecInfoFileId)` 得到“旧有但本次未再使用”的 md5 - `fileInfoDao.findByMd5In(oldMd5)` 并 `fileInfoDao.deleteAll(…)` `WorkOrderServiceImpl.java:3663-3679` 涉及表: - `file_info`(`FileInfoPO.java:30-31`) - `log_file_resource` 1. 清空该 configure_list 下的所有附件关联: - `logFileResourceRepository.deleteAllByOrderId(domainOrderPOId)` `WorkOrderServiceImpl.java:2678-2682` repository:`LogFileResourceRepository.deleteAllByOrderId` `LogFileResourceRepository.java:147-149` --- ## 7. Step 4:重建本次提交的附件关联(log_file_resource) 无论新建还是修改,都会重新生成附件关联: ### 7.1 md5List(最多 5 个) - `logOrderService.saveFilesToTable(domainOrderPO.getId(), workList.getMd5List(), WorkOrderEnums.Type.configure);` `WorkOrderServiceImpl.java:2684-2685` `LogOrderService.saveFilesToTable(…)`: - 对 list 中每个 md5 插入 `LogFileResource(type, md5, orderId)` `LogOrderService.java:761-772` ### 7.2 fileId(单文件,标记 domain_config) - `logOrderService.saveFiles([LogFileResource.create(…, FileContentTypeEnum.domain_config)])` `WorkOrderServiceImpl.java:2686-2689` ### 7.3 secInfoFileId(信安附件,标记 security_info) - 遍历每个 md5,插入 `LogFileResource(…, FileContentTypeEnum.security_info)` `WorkOrderServiceImpl.java:2690-2697` LogFileResource 说明: - repository 的 SQL 指向 `log_file_resource`。 - 字段 `md5` 注释说明“是 mongodb_Id 值,不是文件 md5 值”(非常重要) `LogFileResource.java:51` --- ## 8. Step 5:绑定工单与企业关系(worker_order_enterprise) - `workOrderService.setNewWorkOrderEnterpriseForDR(workOrderId, newEnterpriseId, orgEnterpriseId)` `WorkOrderServiceImpl.java:2698-2701` 方法位置: - `WorkOrderServiceImpl.setNewWorkOrderEnterpriseForDR(…)` `WorkOrderServiceImpl.java:1183-1209` 逻辑: - 若 `orgEnterpriseId` 不为空(修改工单)且企业变更: - 查 `worker_order_enterprise` 记录并更新 `enterpriseId/enterpriseType` `WorkOrderServiceImpl.java:1185-1196` - 否则(新建): - 插入一条新的 `WorkOrderEnterprise` `WorkOrderServiceImpl.java:1197-1208` 表: - `worker_order_enterprise`(注意表名是 worker_order_enterprise) `WorkOrderEnterprise.java:22-23` --- ## 9. Step 6:触发信安/备案号校验与流程流转(WorkOrderManager) - `workOrderManager.handleDomainConfigXinAnInfo(SecurityUserUtil.getId(), domainOrderPO.getId());` `WorkOrderServiceImpl.java:2702-2703` 方法位置: - `WorkOrderManager.handleDomainConfigXinAnInfo(…)` `WorkOrderManager.java:58-92` 核心逻辑(只说需求类相关): 1. 读 configure_list: - `orderRepository.findById(orderId)` `WorkOrderManager.java:59` 2. 若 operateType == CREATE: - 海外产品:直接 `updateNextCheckUserInOrderSubmit(…)` 并返回 `WorkOrderManager.java:62-67` - 非海外:先刷新备案号/一致性状态: - `domainOrderService.updateCheckedIcpInfo(po)` `WorkOrderManager.java:68` - 如果 `checkDomainIcpEqual(po)` 为 true:`uploadInformation(po)`(同步信安系统) `WorkOrderManager.java:71-73` - 最后如果仍然 `checkDomainIcpEqual(po)` 为 true:进入流转 `domainOrderService.updateNextCheckUserInOrderSubmit(…)` `WorkOrderManager.java:83-85` 3. 若 operateType != CREATE:直接 `updateNextCheckUserInOrderSubmit(…)` `WorkOrderManager.java:86-88` --- ## 10. Step 7:拼 domainInfo/enterpriseInfo 写入请求头(包含精确+批量域名) 代码位置: - `WorkOrderServiceImpl.java:2704-2726` 逻辑: 1. 先从 `domainOrderPO.getSpeedDomains()` 拿域名(对应 `speed_configure_domain`) `WorkOrderServiceImpl.java:2706-2708` 2. 如果 `domainOrderPO.getBatchId() != null`: - 查 `batch_self_domain`:`batchSelfDomainDao.findByBatchId(domainOrderPO.getBatchId())` `WorkOrderServiceImpl.java:2709-2713` - 把批量域名也加入 domains 3. domains 去重(Set) `WorkOrderServiceImpl.java:2716-2719` 4. 拼成 `"a.com,b.com"` 写入 header: - `req.putHeader("domainInfo", "…")` - `req.putHeader("enterpriseInfo", domainOrderPO.getTenantId())` `WorkOrderServiceImpl.java:2720-2726` --- ## 11. Step 8:BPM 已存在且是新建(非修改)时的特殊“下一处理人覆盖” 代码: - `WorkOrderServiceImpl.java:2726-2733` 条件: - `BpmTaskPO bpmTaskPO = bpmTaskDao.findByCode(domainOrderPO.getWorkOrder().getCode());` - `if (bpmTaskPO != null && !isModify) { … }` 动作: - `WorkOrder workOrder = workOrderRepository.findByMyId(domainOrderPO.getId());` `WorkOrderServiceImpl.java:2728` > 这里传入的是 `domainOrderPO.getId()`(configure_list.id),但方法名 `findByMyId` 从语义上更像查 work_order.id。后续重构/排雷建议重点确认。 然后: - `orderDao.findByEcId(enter.get().getEcId())` 找到 BBoss 侧订单 - 取 `currentUserId` 找用户,设置为工单审批人: - `workOrder.setApprovingUser(users);` - `workOrderRepository.save(workOrder);` `WorkOrderServiceImpl.java:2729-2733` 涉及表(推断/部分不在本文展开): - `bpm_task`(`bpmTaskDao`) - `work_order`(`workOrderRepository`) - `bboss order` 相关表(`orderDao`/`OrderInfo`) --- ## 12. 涉及库表与操作一览(按“表 -> 操作 -> 代码点”) ### 12.1 work_order(运营总表) - 新建/复用/修改 details、设置 code、corpName、省份信息、审批人等 `DomainOrderService.saveConfigureDomain`:`DomainOrderService.java:523-563`、`679-698` - 设置下一审批人(dealer/approvingUser/userTemp) `DomainOrderService.updateNextCheckUserInOrderSubmit`:`DomainOrderService.java:1130-1168` ### 12.2 configure_list(域名配置需求工单子表) - 保存 configure_list 主记录 `DomainOrderService.saveConfigureDomain`:`DomainOrderService.java:635` - 保存备案号查询结果 recordNumber(非批量) `DomainOrderService.updateCheckedIcpInfo`:`DomainOrderService.java:977-982` 实体: - `ConfigureDomainOrderPO` => `configure_list` `ConfigureDomainOrderPO.java:40-41` ### 12.3 speed_configure_domain(工单加速域名明细) - 新建:由 `ConfigureDomainOrderPO.createDomainOrderPO` 生成并随 configure_list 保存 `DomainOrderService.java:579-583` - 修改重提:删除旧的 speedDomains 记录 `speedConfigureDomainDao.deleteAll(preSpeedDomains)` `DomainOrderService.java:629-633` 实体: - `SpeedConfigureDomainPO` => `speed_configure_domain` `SpeedConfigureDomainPO.java:26-27` ### 12.4 batch_self_domain(批量域名明细) - 批量新建时写入(saveBatchDomains / saveAll) `DomainOrderService.createConfigureDomainOrderPOFromBatchDomainFile`:`DomainOrderService.java:721-723` - ICP 查询后回写 recordNumber/icpEquals `DomainOrderService.updateCheckedIcpInfo`:`DomainOrderService.java:934-963` - saveCustomWorkOrder 用于拼装 domainInfo(按 batchId 查询) `WorkOrderServiceImpl.java:2709-2713` 实体: - `BatchSelfDomainPO` => `batch_self_domain` `BatchSelfDomainPO.java:32-33` ### 12.5 self_service_domain_config(域名配置表/域名主表) - domain_request 且 requirement=CREATE 时:把域名插入域名表(批量/非批量两条线) `DomainOrderService.checkAndSaveConfigDomain`:`DomainOrderService.java:2400-2481` - ICP 查询后更新 legal(合法性) `DomainOrderService.updateCheckedIcpInfo`:`DomainOrderService.java:954-955`、`975-976`、`988-989` 实体: - `SelfServiceDomainConfigPO` => `self_service_domain_config` `SelfServiceDomainConfigPO.java:79-80` ### 12.6 domain_history(域名配置需求工单历史) - 保存初始/提交记录、IC P 校验控制记录等 `DomainOrderService.saveConfigureDomain`:`DomainOrderService.java:636-654` - ICP 校验完成标记 `DomainOrderService.updateCheckedIcpInfo`:`DomainOrderService.java:992-999`、`956-962` - 异常时写 msg(WorkOrderManager 捕获 uploadInformation 异常) `WorkOrderManager.java:75-78` 实体: - `DomainHistoryPO` => `domain_history` `DomainHistoryPO.java:21-22` ### 12.7 log_file_resource(工单附件关联表) - 修改重提时:按 orderId(configure_list.id)清空 `logFileResourceRepository.deleteAllByOrderId(domainOrderPOId)` `WorkOrderServiceImpl.java:2678-2682` - 新建附件关联: - md5List:`LogOrderService.saveFilesToTable` `WorkOrderServiceImpl.java:2684-2685` / `LogOrderService.java:761-772` - fileId(domain_config):`WorkOrderServiceImpl.java:2686-2689` - secInfoFileId(security_info):`WorkOrderServiceImpl.java:2690-2697` ### 12.8 file_info(信安附件内容落库) - 修改重提时:根据“旧的安全信息 md5 列表”删除 file_info 记录 `WorkOrderServiceImpl.deleteHistoryFileInfo`:`WorkOrderServiceImpl.java:3660-3679` 实体: - `FileInfoPO` => `file_info` `FileInfoPO.java:30-31` ### 12.9 worker_order_enterprise(工单-企业关系映射) - 新建工单:插入映射 - 修改且企业变更:更新映射 `WorkOrderServiceImpl.setNewWorkOrderEnterpriseForDR`:`WorkOrderServiceImpl.java:1183-1209` 实体: - `WorkOrderEnterprise` => `worker_order_enterprise` `WorkOrderEnterprise.java:22-23` ### 12.10 sub_domain / work_order_domain_request_sub(泛域名子域名) - EXTENSIVEDOMAIN 时保存子域名集合(SubDomainPO) - join 表:`work_order_domain_request_sub`(配置在 ConfigureDomainOrderPO 上) `ConfigureDomainOrderPO.java:139-145` `SubDomainPO.java:20-21` --- ## 13. 重构前建议你重点“标注/解耦”的风险点(仅提示,不做重构方案) 1. **domain_request 分支里实际落库的工单类型可能是 configure 或 domain_request** 根因:`saveConfigureDomain` 的 `cpFlag ? configure : domain_request` `DomainOrderService.java:510-513` 2. **修改重提的附件清理策略**:同时删 `log_file_resource` + `file_info`,并且 `LogFileResource.md5` 实际是 mongodb_id `WorkOrderServiceImpl.java:2673-2682`、`3660-3679`、`LogFileResource.java:51` 3. **BPM 存在时覆盖审批人** 的取数链路(`workOrderRepository.findByMyId(domainOrderPO.getId())`)参数语义可疑 `WorkOrderServiceImpl.java:2726-2733`