# OARMS 研究与发现记录 --- ## 逐模块检查结果(2026-05-21) ### BS-1 大屏管理 — 检查完成 **检查范围**: 10 个 Java 文件 + 2 个 SQL 文件 #### L1 接口存在性 联调指南 14 个接口全部存在,路由精确匹配。 ✅ | 接口 | 路径 | 状态 | |------|------|------| | POST /query | ✅ | | | GET /detail | ✅ | | | POST /save | ✅ | | | POST /update | ✅ | | | POST /remove | ✅ | | | GET /options | ✅ | | | GET /district/list | ✅ | | | POST /toggle-status | ✅ | | | GET /check-code | ✅ | | | GET /check-address | ✅ | | | GET /export | ✅ | | | POST /import | ✅ | | | GET /import-template | ✅ | | | GET /histories | ✅ | | #### L2 参数一致性 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 1 | `queryList(ScreenQuery query)` POST 方法缺少 `@RequestBody`,前端发 JSON body 时参数为空 | **P0** | Controller:47 | | 2 | `save(ScreenSaveReq req)` POST 方法缺少 `@RequestBody` | **P0** | Controller:71 | | 3 | `update(ScreenSaveReq req)` POST 方法缺少 `@RequestBody` | **P0** | Controller:83 | | 4 | `remove(String id)` POST 方法未使用 `@RequestBody Map`,id 无法从 JSON body 获取 | **P1** | Controller:95 | | 5 | `toggleStatus(String id, Integer status)` POST 方法缺少参数绑定注解 | **P1** | Controller:144 | > 说明:无 @RequestBody 时 Spring 从 query string / form data 绑定,前端 Axios 发 JSON body 会收不到数据。e2e 测试通过是因为测试脚本用了 query params。 #### L3 返回值一致性 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 6 | `save()` 返回 `RestResult.ok()` 未携带新建实体 ID,前端无法获取新记录 ID | **P1** | ServiceImpl:93-98 | | 7 | ScreenDetailVO 的 createTime/updateTime 使用 `Date` 类型,ScreenHistoryEntity 的 changedAt 使用 `LocalDateTime`,类型不一致 | **P2** | VO:94-97, HistoryEntity:41 | | 8 | histories 返回的 snapshotData 是 CLOB(JSON) 字符串,前端需 JSON.parse,无提示 | **P2** | ServiceImpl:253 | #### L4 DTO-DB 映射 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 9 | ScreenEntity 缺少 `@DS("master")` 注解,开发指南约定必须标注 | **P2** | ScreenEntity:23 | | 10 | ScreenHistoryEntity 缺少 `@DS("master")` 注解 | **P2** | ScreenHistoryEntity:25 | 其余 @TableField 与 DDL 列名完全对应,类型映射正确。 ✅ #### L5 数据完整性 - DDL 文件存在 ✅ - 初始数据 8 条 ✅ - DM8 已建表 ✅ #### L6 代码规范 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 11 | Controller 全部方法缺少 `log.info("[OK] ...")` 日志 | **P3** | Controller 全文件 | | 12 | `AssertUtils.isNotNull(entity, "大屏信息不存在")` 第二个 String 参数会被当作 varargs 的第二个对象检查,不会作为错误消息显示 | **P3** | ServiceImpl:106 | | 13 | IScreenService 所有方法返回 RestResult,Service 层与 HTTP 响应格式耦合 | **P3** | IScreenService 全文件 | | 14 | update() 中 `BeanUtils.copyProperties(req, entity)` 会用 req 中 null 字段覆盖 entity 已有值 | **P2** | ServiceImpl:107 | #### 问题汇总 | 严重程度 | 数量 | |---------|------| | P0 阻塞 | 3 | | P1 严重 | 2 | | P2 一般 | 5 | | P3 建议 | 3 | | **合计** | **13** | --- ### LB-1 法律法规 — 检查完成 **检查范围**: 7 个 Java 文件 + 2 个 SQL 文件 #### L1 接口存在性 联调指南 9 个接口全部存在,路由精确匹配。 ✅ #### L2 参数一致性 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 1 | `queryList` POST 缺少 `@RequestBody`(同 BS-1 模式) | **P0** | Controller:44 | | 2 | `save` POST 缺少 `@RequestBody` | **P0** | Controller:68 | | 3 | `update` POST 缺少 `@RequestBody` | **P0** | Controller:80 | | 4 | `remove(String id)` POST 缺少参数绑定 | **P1** | Controller:92 | | 5 | `repeal(String id)` POST 缺少参数绑定 | **P1** | Controller:109 | Query 字段与联调指南一致 ✅。SaveReq 字段与联调指南一致 ✅。 #### L3 返回值一致性 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 6 | `save()` 未返回新建实体 ID | **P1** | ServiceImpl:69-74 | 直接返回 Entity 而非 VO,与联调指南定义一致 ✅。 #### L4 DTO-DB 映射 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 7 | LawClauseEntity 缺少 `@DS("master")` | **P2** | Entity:24 | 其余 @TableField 与 DDL 列名完全对应,类型映射正确 ✅。 #### L5 数据完整性 DDL ✅、初始数据 5 条 ✅、DM8 建表 ✅ #### L6 代码规范 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 8 | **`repeal()` 设置 `effectiveStatus=0`,但 DDL 定义废止应为 2(1=有效,2=废止)** | **P1** | ServiceImpl:121 | | 9 | `update()` BeanUtils.copyProperties null 字段覆盖 | **P2** | ServiceImpl:83 | | 10 | Controller 全部方法缺少 `log.info("[OK]")` | **P3** | Controller 全文件 | | 11 | `publishDate` 的 @JsonFormat 使用硬编码 `"yyyy-MM-dd"`,应使用 `DateUtil.DATE_DEFAULT_FORMAT` | **P3** | Entity:50, SaveReq:57 | | 12 | `AssertUtils.isNotNull(entity, "msg")` message 参数不生效 | **P3** | ServiceImpl:82,120 | #### 问题汇总 | 严重程度 | 数量 | |---------|------| | P0 阻塞 | 3 | | P1 严重 | 3 | | P2 一般 | 2 | | P3 建议 | 3 | | **合计** | **11** | --- ### MR-1 监测规则 — 检查完成 **检查范围**: 12 个 Java 文件 + 2 个 SQL 文件 #### L1 接口存在性 联调指南 11 个接口全部存在,路由精确匹配。 ✅ #### L2 参数一致性 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 1 | `queryList` POST 缺少 `@RequestBody`(同 BS-1 模式) | **P0** | Controller:44 | | 2 | `save` POST 缺少 `@RequestBody` | **P0** | Controller:68 | | 3 | `update` POST 缺少 `@RequestBody` | **P0** | Controller:80 | | 4 | `remove(String id)` POST 缺少参数绑定 | **P1** | Controller:92 | | 5 | `toggleStatus(String id, Integer status)` POST 缺少参数绑定 | **P1** | Controller:105 | Query 字段与联调指南一致 ✅。SaveReq 字段与联调指南一致 ✅。 #### L3 返回值一致性 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 6 | `save()` 未返回新建实体 ID | **P1** | ServiceImpl:126-143 | | 7 | `scopeDistricts` 为 CLOB(JSON) 字符串,`getEnabledRules` 直接返回 String,前端需 JSON.parse | **P2** | ServiceImpl:253 | | 8 | `queryList` 返回的 VO 中 `lawClauses`/`histories` 为 null(仅 detail 填充) | **P3** | ServiceImpl:72-76 | #### L4 DTO-DB 映射 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 9 | MonitoringRuleEntity 缺少 `@DS("master")` | **P2** | Entity:21 | 其余 @TableField 与 DDL 列名完全对应 ✅。scopeDistricts CLOB → String 映射正确 ✅。 #### L5 数据完整性 DDL ✅(3 张表)、初始数据 9 条 ✅、DM8 建表 ✅ #### L6 代码规范 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 10 | 操作历史 `operator` 硬编码为 `"系统管理员"`,未从登录用户获取 | **P2** | ServiceImpl:141,172,202,227 | | 11 | `update()` BeanUtils.copyProperties null 字段覆盖 | **P2** | ServiceImpl:159 | | 12 | `remove()` 先删除操作历史再新增一条删除记录,产生孤儿历史数据 | **P3** | ServiceImpl:192-202 | | 13 | `buildSnapshot()` 手动拼接 JSON 字符串,字段值含引号时会破坏 JSON 格式 | **P3** | ServiceImpl:341-354 | | 14 | Controller 全部方法缺少 `log.info("[OK]")` | **P3** | Controller 全文件 | | 15 | `AssertUtils.isNotNull(entity, "msg")` message 参数不生效 | **P3** | ServiceImpl:151,182,213 | #### 问题汇总 | 严重程度 | 数量 | |---------|------| | P0 阻塞 | 3 | | P1 严重 | 2 | | P2 一般 | 4 | | P3 建议 | 6 | | **合计** | **15** | --- ### AM-1 录屏设置 — 检查完成 **检查范围**: 7 个 Java 文件 + 1 个 DDL 文件 #### L1 接口存在性 联调指南 7 个接口全部存在 ✅ #### L2 参数一致性 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 1 | `queryList`/`save`/`update` POST 缺少 `@RequestBody`(同前模块模式) | **P0** | Controller:44,68,80 | | 2 | `remove(String id)` / `toggleStatus(String id, Integer status)` POST 缺少参数绑定 | **P1** | Controller:92,109 | Query/SaveReq 字段与联调指南一致 ✅。save() 有录屏时长/频率范围校验、大屏唯一性校验、时间范围校验 ✅。 #### L3 返回值一致性 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 3 | `save()` 未返回新建实体 ID | **P1** | ServiceImpl:110 | #### L4 DTO-DB 映射 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 4 | RecordingConfigEntity 缺少 `@DS("master")` | **P2** | Entity:21 | #### L5 数据完整性 DDL ✅、无初始数据(符合预期)✅、DM8 建表 ✅ #### L6 代码规范 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 5 | `update()` BeanUtils.copyProperties null 字段覆盖 | **P2** | ServiceImpl:156 | | 6 | Controller 缺少 `log.info("[OK]")` | **P3** | Controller 全文件 | | 7 | `AssertUtils.isNotNull(entity, "msg")` message 不生效 | **P3** | ServiceImpl:91,119 | #### 问题汇总: P0×1, P1×2, P2×2, P3×2 = **7** --- ### AM-2 随机录屏 — 检查完成 **检查范围**: 7 个 Java 文件 + 1 个 DDL 文件 #### L1 接口存在性 联调指南 2 个接口全部存在 ✅(query + detail) #### L2 参数一致性 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 1 | `queryList` POST 缺少 `@RequestBody` | **P0** | Controller:42 | Query 字段与联调指南一致 ✅。90 天查询范围限制已实现 ✅。 #### L3/L4/L5 - detail 返回 Map(含 alerts 子列表)✅ - 跨模块查询(ScreenMapper 两步关联)✅ - DDL ✅、无初始数据 ✅、DM8 ✅ - Entity 缺少 `@DS("master")` → **P2** #### L6 代码规范 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 2 | Entity 缺少 `@DS("master")` | **P2** | RecordingTaskEntity | | 3 | Controller 缺少 `log.info("[OK]")` | **P3** | Controller 全文件 | #### 问题汇总: P0×1, P2×1, P3×1 = **3** --- ### AM-3 广告画面监控 — 检查完成 **检查范围**: 6 个 Java 文件 + 1 个 DDL 文件 #### L1 接口存在性 联调指南 4 个接口全部存在 ✅(query, detail, start, judge) #### L2 参数一致性 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 1 | `queryList` POST 缺少 `@RequestBody` | **P0** | Controller:41 | | 2 | `judgeMonitor(MonitorJudgeReq req)` POST 缺少 `@RequestBody` | **P0** | Controller:77 | | 3 | `startMonitor(String id)` POST 缺少参数绑定 | **P1** | Controller:65 | Query 字段与联调指南一致 ✅。默认过滤已判定记录(monitorStatus < 3)✅。 #### L3 返回值一致性 - 直接返回 Entity,与联调指南一致 ✅ #### L4 DTO-DB 映射 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 4 | MonitorRecordEntity 缺少 `@DS("master")` | **P2** | Entity | #### L5 数据完整性 DDL ✅、无初始数据 ✅、DM8 ✅ #### L6 代码规范 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 5 | `autoCreateEvidence()` 用 try-catch 吞掉异常,取证创建失败但监控判定仍成功,导致数据不一致 | **P2** | ServiceImpl:148-176 | | 6 | Controller 缺少 `log.info("[OK]")` | **P3** | Controller 全文件 | | 7 | `AssertUtils.isNotNull` message 不生效 | **P3** | ServiceImpl:101,126 | #### 问题汇总: P0×2, P1×1, P2×2, P3×2 = **7** --- ### CW-1 固化取证 — 检查完成 **检查范围**: 7 个 Java 文件 + 1 个 DDL 文件 #### L1 接口存在性 联调指南 5 个接口全部存在 ✅ #### L2/L3/L4/L5/L6 汇总 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 1 | `queryList`/`save` POST 缺少 `@RequestBody` | **P0** | Controller:43,67 | | 2 | `save()` 未返回新建实体 ID | **P1** | ServiceImpl:144 | | 3 | EvidenceRecordEntity 缺少 `@DS("master")` | **P2** | Entity:25 | | 4 | download/play 返回占位路径(TODO 对接文件存储系统) | **P2** | ServiceImpl:161,174 | | 5 | Controller 缺少 `log.info("[OK]")` | **P3** | Controller 全文件 | | 6 | `AssertUtils.isNotNull` message 不生效 | **P3** | ServiceImpl:132,156,168 | DTO-DB 映射正确 ✅。@JsonFormat 使用 DateUtil 常量 ✅。@DSTransactional 正确使用 ✅。 `AssertUtils.isTrue` 正确使用 `BaseResultCode.PARAM_IS_INVALID` ✅。 #### 问题汇总: P0×1, P1×1, P2×2, P3×2 = **6** --- ### CW-2 规则关联 — 检查完成 **检查范围**: 5 个 Java 文件 + 1 个 DDL 文件 #### L1 接口存在性 联调指南 2 个接口全部存在 ✅ #### 汇总 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 1 | `relate` POST 缺少 `@RequestBody` | **P0** | Controller:53 | | 2 | Entity 缺少 `@DS("master")` | **P2** | Entity | | 3 | `associatedBy` 硬编码 `"系统管理员"` | **P2** | ServiceImpl:103 | | 4 | Controller 缺少 `log.info("[OK]")` | **P3** | Controller 全文件 | `AssertUtils.isTrue` 正确使用 `BaseResultCode` ✅。跨模块校验(证据状态、规则有效性)完整 ✅。 #### 问题汇总: P0×1, P2×2, P3×1 = **4** --- ### CW-3 线索生成 — 检查完成 **检查范围**: 8 个 Java 文件 + 1 个 DDL 文件 #### L1 接口存在性 联调指南 5 个接口全部存在 ✅ #### L2/L3/L4/L6 汇总 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 1 | `queryList` POST 缺少 `@RequestBody` | **P0** | Controller:43 | | 2 | `generateClue(String evidenceId)` POST 缺少参数绑定 | **P1** | Controller:67 | | 3 | `generateClue()` 未返回新建线索 ID | **P1** | ServiceImpl:222 | | 4 | `statusSummary()` 仅统计状态 1-2,遗漏 3(处理中) 和 4(已办结) | **P1** | ServiceImpl:244-253 | | 5 | `relatedRules`/`relatedLawClauses` 为 CLOB(JSON) 字符串,前端需 JSON.parse | **P2** | ServiceImpl:181,183 | | 6 | Entity 缺少 `@DS("master")` | **P2** | Entity | | 7 | `generatedBy` 硬编码 `"系统管理员"` | **P2** | ServiceImpl:191 | | 8 | `aggregateRuleInfo()` N+1 查询(循环内 selectById) | **P2** | ServiceImpl:276-287 | | 9 | `buildRulesJson`/`buildLawClausesJson` 手动拼 JSON(字段值含引号会破坏格式) | **P3** | ServiceImpl:293-355 | | 10 | Controller 缺少 `log.info("[OK]")` | **P3** | Controller 全文件 | #### 问题汇总: P0×1, P1×3, P2×4, P3×2 = **10** --- ### CW-4 线索转办 — 检查完成 **检查范围**: 14 个 Java 文件 + 1 个 DDL 文件 #### L1 接口存在性 联调指南 13 个接口全部存在 ✅ #### L2/L3/L4/L6 汇总 | # | 问题 | 严重程度 | 位置 | |---|------|---------|------| | 1 | 6 个 POST 接口缺少 `@RequestBody`(query/submit/pending-clues.query/status-update/urge/withdraw) | **P0** | Controller:51,75,105,123,129,135 | | 2 | `submitTransfer()` 未返回转办记录 ID | **P1** | ServiceImpl:175 | | 3 | 2 个 Entity 缺少 `@DS("master")` | **P2** | Entity | | 4 | `transferPerson` 硬编码 `"系统管理员"` | **P2** | ServiceImpl:152 | | 5 | `departmentList`/`personList` 返回硬编码模拟数据(TODO 对接组织架构) | **P2** | ServiceImpl:198-231 | | 6 | `queryList` 列表查询存在 N+1(每条记录 selectById 查线索编码) | **P2** | ServiceImpl:81-84 | | 7 | Controller 缺少 `log.info("[OK]")` | **P3** | Controller 全文件 | | 8 | `AssertUtils.isNotNull` message 不生效 | **P3** | ServiceImpl:139,293,335,378 | 状态流转校验完整(transferred→processing→completed/failed)✅。撤回回退线索状态 ✅。`@DSTransactional` 正确使用 ✅。 #### 问题汇总: P0×1, P1×1, P2×5, P3×2 = **9** --- ## 全模块检查总结 | 模块 | P0 | P1 | P2 | P3 | 合计 | |------|----|----|----|----|------| | BS-1 大屏管理 | 3 | 2 | 5 | 3 | 13 | | LB-1 法律法规 | 3 | 3 | 2 | 3 | 11 | | MR-1 监测规则 | 3 | 2 | 4 | 6 | 15 | | AM-1 录屏设置 | 1 | 2 | 2 | 2 | 7 | | AM-2 随机录屏 | 1 | 0 | 1 | 1 | 3 | | AM-3 广告监控 | 2 | 1 | 2 | 2 | 7 | | CW-1 固化取证 | 1 | 1 | 2 | 2 | 6 | | CW-2 规则关联 | 1 | 0 | 2 | 1 | 4 | | CW-3 线索生成 | 1 | 3 | 4 | 2 | 10 | | CW-4 线索转办 | 1 | 1 | 5 | 2 | 9 | | **合计** | **17** | **15** | **29** | **24** | **85** | ### 跨模块共性问题(高频模式) #### 模式 1:POST 接口缺少 @RequestBody(P0,影响全部模块) 所有模块的 POST 接口(query/save/update 等)均缺少 `@RequestBody` 注解。前端使用 Axios 发送 JSON body 时参数全部为空。 **修复方案**:统一在所有 POST 接口的对象参数前添加 `@RequestBody`。对于简单参数(String id, Integer status)使用 `@RequestBody Map` 或 `@RequestParam`。 #### 模式 2:save() 不返回新建实体 ID(P1,影响 7 个模块) 所有新增接口返回 `RestResult.ok()` 而非 `RestResult.ok(entity.getId())`。前端无法获取新创建记录的 ID。 #### 模式 3:Entity 缺少 @DS("master")(P2,影响全部 10 个模块) 所有 Entity 仅标注 `@TableName(schema = "OARMS")` 但缺少 `@DS("master")`。因 master 为 primary 数据源暂时不影响运行,但不符合开发规范。 #### 模式 4:操作人硬编码(P2,影响 MR-1/CW-2/CW-3/CW-4) 所有写入操作的操作人(operator/generatedBy/transferPerson/associatedBy)硬编码为 `"系统管理员"`,未从登录用户获取。 #### 模式 5:手动拼接 JSON 字符串(P3,影响 MR-1/CW-3) `buildSnapshot`/`buildRulesJson`/`buildLawClausesJson` 使用 StringBuilder 拼接 JSON,字段值含特殊字符时会破坏格式。应使用 JSON 库序列化。 #### 模式 6:Controller 缺少日志(P3,影响全部模块) 所有 Controller 方法未按规范输出 `log.info("[OK] ...")` 日志。 #### 模式 7:BeanUtils.copyProperties null 覆盖(P2,影响 5 个模块) update 方法中 `BeanUtils.copyProperties(req, entity)` 会用 req 中的 null 字段覆盖 entity 的已有值。 --- ## 代码结构发现 ### 模块对应关系(计划 vs 实际) | 计划阶段 | 计划模块 | SQL DDL | SQL 初始数据 | Java 代码层 | 状态 | |----------|----------|---------|-------------|-------------|------| | Phase 1 | BS-1 大屏基础信息管理 | ✅ V1.0.0__BS_screen_ddl.sql | ✅ V1.0.0__BS_screen_init_data.sql | ✅ screen (Entity/Query/Req/VO/Mapper/Service/Controller) | ✅ 完成 | | Phase 2 | LB-1 法律法规管理 | ✅ V2.0.0__LB_law_ddl.sql | ✅ V2.0.0__LB_law_init_data.sql | ✅ law (Entity/Query/Req/Mapper/Service/Controller) | ✅ 完成 | | Phase 3 | MR-1 监测规则管理 | ✅ V6.0.0__MR_monitoring_rule_ddl.sql | ✅ V6.0.0__MR_monitoring_rule_init_data.sql | ✅ rule (Entity×3/Query/Req/VO/Mapper×3/Service/Controller) | ✅ 完成 | | Phase 4 | AM-1 录屏设置管理 | ✅ V3.0.0__AM_recording_config_ddl.sql | ❌ 无初始数据 | ✅ monitor.config (Entity/Query/Req/Mapper/Service/Controller) | ✅ 完成 | | Phase 5 | AM-2 随机录屏 | ✅ V4.0.0__AM_recording_task_ddl.sql | ❌ 无初始数据 | ✅ monitor.task (Entity×2/Query/Mapper×2/Service/Controller) | ✅ 完成 | | Phase 6 | AM-3 广告画面监控 | ✅ V5.0.0__AM_monitor_record_ddl.sql | ❌ 无初始数据 | ✅ monitor.record (Entity/Query/Req/Mapper/Service/Controller) | ✅ 完成 | | Phase 7 | CW-1 固化取证 | ✅ V7.0.0__CW_evidence_ddl.sql | ❌ 无初始数据 | ✅ evidence.record (Entity×2/Query/Req/VO/Mapper×2/Service/Controller) | ✅ 完成 | | Phase 8 | CW-2 规则关联 | ✅ V8.0.0__CW_evidence_rule_relation_ddl.sql | ❌ 无初始数据 | ✅ evidence.relation (Entity/Query/Req/Mapper/Service/Controller) | ✅ 完成 | | Phase 9 | CW-3 线索生成 | ✅ V9.0.0__CW_monitoring_clue_ddl.sql | ❌ 无初始数据 | ✅ evidence.clue (Entity×2/Query/VO/Mapper×2/Service/Controller) | ✅ 完成 | | Phase 10 | CW-4 线索转办 | ✅ V10.0.0__CW_clue_transfer_ddl.sql | ❌ 无初始数据 | ✅ evidence.transfer (Entity×2/Query/Req/VO/Mapper×2/Service/Controller) | ✅ 完成 | ### 关键发现 1. **SQL 版本号与计划阶段不一致**: SQL 文件版本号 (V1~V10) 与计划阶段 (Phase 1~10) 顺序不同。MR-1 监测规则在计划中是 Phase 3,但 SQL 编号为 V6。这不影响功能,但说明 SQL 文件是按模块类别分组而非按依赖顺序编号。 2. **无 Mapper XML 文件**: 所有模块使用 MyBatis-Plus 注解方式,没有 XML mapper 文件,这是正常的。 3. **初始数据**: 仅 BS-1、LB-1、MR-1 有初始数据 SQL,其余模块无需预置数据(合理)。 4. **编译状态**: 代码已通过 git commit `c06a4e5` 提交,commit 信息为 "feat: OARMS 全模块后端代码 + DM8 数据库适配"。 ### 技术栈确认 - 框架: Spring Boot + MyBatis-Plus - 数据库: DM8(达梦数据库),版本 `--03134283914-20220901-168571-20009` - 权限: Sa-Token(StpInterfaceImpl 存在) - 项目结构: modules/{模块}/{子模块}/{layer} ### 数据源架构决策(2026-05-18) 项目配置了两个数据源,共用同一 DM8 实例 `172.22.80.70:15236`: | 数据源名 | Schema | 用途 | 决策 | |----------|--------|------|------| | `master` | OARMS | 业务数据(全部 17 张业务表) | 保留 | | `youfool` | YOUFOOL | 框架 restLog(接口访问日志),`RestLogServiceImpl` 硬编码 `@DS("youfool")` | 保留 | **决策**: 保持现状,不合并。框架代码不可修改,youfool 数据源是框架层强制依赖。 ### PRD vs 后端代码覆盖分析(2026-05-18) #### 比对方法 读取每个模块的 `S4-API设计.md`,逐条对照后端 Controller 中实际定义的接口。 #### 整体结论 - **10 个模块全部有基础 CRUD 后端代码**(Entity/Mapper/Service/Controller) - **路径命名风格不一致**:后端统一用单数名词(`/api/screen`),PRD 用复数(`/api/screens`) - **HTTP 方法不一致**:后端几乎全用 POST,PRD 规范使用 RESTful 风格(PUT/DELETE) - **高级功能接口大量缺失** #### 逐模块覆盖详情 ##### BS-1 大屏基础信息管理 | PRD 接口 | 功能 | 后端状态 | |----------|------|---------| | POST /api/screens/query | 列表查询 | ✅ | | POST /api/screens | 新增 | ✅ (路径 /api/screen/save) | | PUT /api/screens/{id} | 编辑 | ✅ (路径 /api/screen/update) | | GET /api/screens/{id} | 详情 | ✅ (路径 /api/screen/detail) | | DELETE /api/screens/{id} | 删除 | ✅ (路径 /api/screen/remove) | | PUT /api/screens/{id}/status | 状态变更 | ❌ 未实现 | | GET /api/screens/export | 导出 | ❌ 未实现 | | POST /api/screens/import | 批量导入 | ❌ 未实现 | | GET /api/screens/import-template | 下载导入模板 | ❌ 未实现 | | GET /api/screens/{id}/histories | 历史版本列表 | ❌ 未实现 | | GET /api/screens/check-code | 编码唯一校验 | ❌ 未实现 | | GET /api/screens/check-address | 地址唯一校验 | ❌ 未实现 | ##### LB-1 法律法规管理 | PRD 接口 | 功能 | 后端状态 | |----------|------|---------| | POST /api/law-clauses/query | 列表查询 | ✅ | | POST /api/law-clauses | 新增 | ✅ (路径 /api/law-clause/save) | | PUT /api/law-clauses/{id} | 编辑 | ✅ (路径 /api/law-clause/update) | | GET /api/law-clauses/{id} | 详情 | ✅ (路径 /api/law-clause/detail) | | DELETE /api/law-clauses/{id} | 删除 | ✅ (路径 /api/law-clause/remove) | | PUT /api/law-clauses/{id}/repeal | 废止条款 | ❌ 未实现 | | GET /api/law-clauses/check-clause-number | 条款号唯一校验 | ❌ 未实现 | | GET /api/law-clauses/effective | 已生效条款列表 | ❌ 未实现 | ##### MR-1 监测规则管理 | PRD 接口 | 功能 | 后端状态 | |----------|------|---------| | POST /api/monitoring-rules/query | 列表查询 | ✅ | | POST /api/monitoring-rules | 新增 | ✅ | | PUT /api/monitoring-rules/{id} | 编辑 | ✅ (POST /update) | | GET /api/monitoring-rules/{id} | 详情 | ✅ (GET /detail) | | DELETE /api/monitoring-rules/{id} | 删除 | ✅ (POST /remove) | | PUT /api/monitoring-rules/{id}/toggle-status | 切换启用状态 | ✅ (POST /toggle-status) | | GET /api/monitoring-rules/check-name | 名称唯一校验 | ✅ | | GET /api/monitoring-rules/enabled | 已启用规则列表 | ✅ | | GET /api/monitoring-rules/{id}/histories | 操作历史 | ❌ 未实现(详情接口已含历史) | | POST /api/monitoring-rules/export | 导出Excel | ❌ 未实现 | ##### AM-1 录屏设置管理 | PRD 接口 | 功能 | 后端状态 | |----------|------|---------| | POST /api/recording-configs/query | 列表查询 | ✅ | | POST /api/recording-configs | 新增 | ✅ | | PUT /api/recording-configs/{id} | 编辑 | ✅ (POST /update) | | GET /api/recording-configs/{id} | 详情 | ✅ | | PUT /api/recording-configs/{id}/status | 状态变更 | ❌ 未实现 | | GET /api/screens/available | 可配置大屏列表 | ✅ (路径不同) | ##### AM-2 随机录屏 | PRD 接口 | 功能 | 后端状态 | |----------|------|---------| | POST /api/recording-tasks/query | 列表查询 | ✅ | | GET /api/recording-tasks/{id} | 详情 | ✅ | ##### AM-3 广告画面监控 | PRD 接口 | 功能 | 后端状态 | |----------|------|---------| | POST /api/monitor-records/query | 列表查询 | ✅ | | GET /api/monitor-records/{id} | 详情 | ✅ | | PUT /api/monitor-records/{id}/start | 开始监控 | ✅ | | PUT /api/monitor-records/{id}/judge | 监控判定 | ✅ | ##### CW-1 固化取证 | PRD 接口 | 功能 | 后端状态 | |----------|------|---------| | POST /api/evidence-records/query | 列表查询 | ✅ | | GET /api/evidence-records/{id} | 详情 | ✅ | | POST /api/evidence-records | 保存取证 | ✅ | | GET /api/evidence-records/{id}/status-history | 状态历史 | ❌ 未实现(详情接口已含) | | GET /api/evidence-records/{id}/download | 下载地址 | ❌ 未实现 | | GET /api/evidence-records/{id}/play | 播放地址 | ❌ 未实现 | ##### CW-2 规则关联 | PRD 接口 | 功能 | 后端状态 | |----------|------|---------| | GET /api/evidence-rule-relations | 查询已关联规则 | ✅ | | POST /api/evidence-rule-relations | 关联规则 | ✅ | ##### CW-3 线索生成 | PRD 接口 | 功能 | 后端状态 | |----------|------|---------| | POST /api/monitoring-clues/query | 列表查询 | ✅ | | GET /api/monitoring-clues/{id} | 详情 | ✅ | | POST /api/monitoring-clues | 生成线索 | ✅ | | GET /api/evidence-records/{id}/clue-preview | 线索预览 | ❌ 未实现 | | GET /api/monitoring-clues/status-summary | 状态统计 | ❌ 未实现 | ##### CW-4 线索转办 | PRD 接口 | 功能 | 后端状态 | |----------|------|---------| | POST /api/clue-transfer/query | 转办记录列表 | ✅ | | GET /api/clue-transfer/{id} | 转办详情 | ✅ | | POST /api/clue-transfer/submit | 提交转办 | ✅ | | GET /api/clue-transfer/districts | 区域列表 | ❌ 未实现 | | GET /api/clue-transfer/districts/{code}/departments | 部门列表 | ❌ 未实现 | | GET /api/clue-transfer/departments/{id}/persons | 人员列表 | ❌ 未实现 | | GET /api/clue-transfer/clues/{id}/disposal-feedback | 处置反馈 | ❌ 未实现 | #### 缺失接口汇总 > 注:下表中标记 ❌ 的接口已在 2026-05-18 的"缺失接口补齐"和"CW-4 完善"中全部实现。此表保留作为历史对照。 | 类别 | 原缺失数 | 当前状态 | |------|---------|---------| | 导入/导出/模板下载 | 3 | ✅ 已补齐 | | 唯一性校验 | 2 | ✅ 已补齐 | | 状态变更/废止 | 2 | ✅ 已补齐 | | 历史版本 | 1 | ✅ 已补齐 | | 文件下载/播放 | 2 | ✅ 已补齐 | | 级联选择 | 3 | ✅ 已补齐 | | 线索预览/统计 | 2 | ✅ 已补齐 | | 处置反馈 | 1 | ✅ 已补齐 | | CW-4 业务闭环 | 6 | ✅ 已补齐(pending-clues/status-update/urge/withdraw/operation-logs) | --- ### PRD vs 后端代码详细差异分析(2026-05-18 更新) > 基础 CRUD 和 P0-P3 补齐接口均已实现并通过端到端测试。以下仅列出**仍然存在的差异**。 #### 一、风格差异(不影响功能) | 项目 | PRD 要求 | 后端实现 | 影响 | |------|---------|---------|------| | 路径命名 | 复数名词 `/api/screens` | 单数名词 `/api/screen` | 不影响 | | HTTP 方法 | RESTful(PUT/DELETE) | 统一 POST | 不影响 | | 状态枚举值 | 字符串 "RECORDING"/"COMPLETED" | 数字 1/2/3 | 不影响 | | 分页默认大小 | 20 条/页 | 10 条/页 | 不影响 | | API 前缀 | 部分 PRD 要求 `/api/cw/` | 无 `/cw/` 前缀 | 不影响 | #### 二、缺失的业务逻辑(需补充) ##### AM-1 录屏设置 - **唯一性校验**:PRD 要求同一大屏只能有一条配置,后端未在 save/update 中校验 - **时间范围校验**:PRD 要求录屏时间必须在广告播放时间段内,后端未实现 ##### AM-2 随机录屏 - **查询条件缺失**:缺少 `district`(区域)和 `screenName`(大屏名称模糊匹配)筛选条件 - **时间范围限制**:PRD 要求最大查询范围不超过 90 天,后端未限制 ##### AM-3 广告画面监控 - **查询条件缺失**:缺少时间范围(start_time/end_time)、监控人员(monitor_person)筛选 - **默认状态过滤**:PRD 要求默认只查询未归档记录,后端未实现 - **并发控制**:PRD 要求同一记录只能由一人监控,后端未实现 - **自动联动**:PRD 要求判定为违法时自动触发 CW-1 取证流程,后端未实现 ##### CW-1 固化取证 - **状态历史独立接口**:PRD 要求 `GET /evidence-records/{id}/status-history`,当前详情接口已含但无独立入口 - **关联上下文接口**:PRD 要求 `GET /monitor-records/{id}/evidence-context`(来源监控记录关联信息),后端未实现 ##### CW-2 规则关联 - **搜索可关联规则**:PRD 要求搜索可关联的监测规则列表,当前只能在 MR-1 的 enabled 接口获取 ##### CW-3 线索生成 - **线索生成日志**:PRD 要求 `GET /monitoring-clues/{id}/generation-logs`,后端未实现独立接口 - **广告主补充**:PRD 要求线索确认时可补充广告主信息,后端 generate 接口未支持 #### 三、缺失的通用功能 | 功能 | 涉及模块 | 说明 | |------|---------|------| | 权限控制 | 全部 | PRD 定义了市局/区局角色数据范围过滤,后端未实现 | | 关联对象返回 | AM-1/2/3, CW-1 | PRD 要求返回 screen_info/config_info/video_info 嵌套对象,后端返回平铺字段 | | 状态中文名 | 全部 | PRD 要求返回 `xxx_text` 中文字段(如 task_status_text),后端未实现 | | 归档标志 | AM-3 | PRD 要求 archive_flag 字段区分已归档/未归档,后端无此字段 | #### 四、CW-4 已超出 PRD 的实现 以下接口为后端主动扩展,PRD 中未要求但已实现: | 接口 | 说明 | |------|------| | POST /api/clue-transfer/status-update | 外部系统回调状态流转 | | POST /api/clue-transfer/urge | 催办 | | POST /api/clue-transfer/withdraw | 撤回 | | GET /api/clue-transfer/pending-clues/query | 待转办线索列表 | | GET /api/clue-transfer/pending-clues/detail | 待转办线索详情 | | GET /api/clue-transfer/operation-logs | 操作日志独立查询 | ### 框架 API 发现(2026-05-18 编译修复过程中) #### SuperEntity(框架基类) - **位置**: `com.chinaweal.youfool.framework.springboot.mybatis.plus.SuperEntity` - **不是泛型类**,直接 `extends SuperEntity` 即可 - 提供字段: `createBy`, `createTime`, `updateBy`, `updateTime`, `createName`, `updateName` - 自动填充策略: INSERT 时填充 createBy/createTime, INSERT_UPDATE 时填充 updateBy/updateTime #### AssertUtils(断言工具) - **位置**: `com.chinaweal.youfool.framework.springboot.common.util.AssertUtils` - `isTrue(boolean, ResultCode, Object... params)` — 第二个参数是 ResultCode 枚举,不是 String - `isNotNull(Object...)` — 无消息参数版本,使用 BaseResultCode.PARAM_NOT_COMPLETE - `isNotBlank(String...)` — 无消息参数版本,使用 BaseResultCode.PARAM_IS_BLANK - `isNotBlank(String, String)` — 带消息参数的重载(varargs 导致编译通过) #### RestResult(统一返回) - **位置**: `com.chinaweal.youfool.framework.springboot.rest.RestResult` - `ok()` / `ok(T data)` — 成功返回 - `error(ResultCode)` / `error(ResultCode, String msg)` / `error(ResultCode, T data)` — 错误返回 - **没有 `fail()` 方法**,统一使用 `error()` #### BaseResultCode(常用错误码) - `SUCCESS` — 成功 - `PARAM_IS_INVALID` — 参数无效 - `PARAM_NOT_COMPLETE` — 参数不完整 - `PARAM_IS_BLANK` — 参数为空