Files
danyang-match/docs/P0阻断项修复报告_2026-09-15.md
T
Codex eaf8fdf195 refactor(backend): P0 阻断修复 + 按最新修改时间收敛重复模块与契约
## P0 阻断修复
- 编译:修复实体类与服务类同名导致 Lombok 注解轮次中止的问题
  (MatchmakerService/CounselingService -> *Record),196 个编译错误归零
- 权限矩阵:platform_admin 按设计文档收紧为拒绝 5 项高危权限(不改测试阈值)
- 启动:修复 8 组 MyBatis-Plus 同名 bean 冲突(ConflictingBeanDefinition)
  与 URL 路由歧义(Ambiguous mapping),应用可正常启动

## 模块收敛(裁决规则:以文件修改时间为准)
- messaging 包整体删除,能力迁移至 chat 包
  * 会话列表/详情/未读端点、ConversationDTO、CursorPage
  * 消息游标分页统一为 { items, nextCursor }
- relationship 的 Match/UserRelation entity 与 mapper 合并进 match 包
- MatchmakerUserController 合并进 MatchmakerController,删除冗余 Controller
- 补齐 INV-004:chat sendText 增加双向 Block 校验,拉黑后禁止发送

## 契约对齐
- 红娘服务提交请求兼容前端 { requirement } 字段
- 消息与会话分页契约前后端统一

## 测试
- 迁移 6 个风控用例至 ChatSafetyServiceTest
- 清理 messaging 测试包遗留:6 个真实常量断言归位 chat 包,
  移除 2 个 assertTrue(true) 占位假测试(Block 真实行为已由
  P0FixVerificationTest / RelationshipBlockPriorityPhase08Test 覆盖)
- schema-h2.sql 对齐 PostgreSQL 真实表结构(matches 补列、
  conversation_members 改复合主键)

结果:290 tests, 0 failures, 0 errors, 3 skipped, BUILD SUCCESS
2026-09-15 22:29:26 +08:00

6.1 KiB
Raw Blame History

善缘丹阳 V1.1 — P0 阻断项修复报告

日期:2026-09-15 | 范围:backend | 验证方式:Docker 容器内 Maven 构建 + 全量测试 结论:293 tests / 0 failures / 0 errors / BUILD SUCCESS(修复前:196 个编译错误 + 应用无法启动)


一、最终验证

[INFO] Tests run: 293, Failures: 0, Errors: 0, Skipped: 3
[INFO] BUILD SUCCESS

Spring 应用上下文成功启动 4 次,Failed to load ApplicationContext 归零。 共改动 46 个文件,未提交(保留在工作区待评审)。


二、修复链条(每修一层暴露下一层)

P0-1 编译断裂:196 错误 → 0

根因 说明 处理
同名类冲突导致 Lombok 停摆 MatchmakerService、CounselingService 既是实体又是 Service,javac 因重复定义中止注解处理轮次,Lombok 不生成 getter/setter,引发约 110 个"找不到符号" 实体重命名为 MatchmakerServiceRecord / CounselingServiceRecord(均有显式 @TableName,不影响 DB 映射)
契约缺失 ApiResponse 缺 unauthorized()/forbidden()/notFound()(35 处调用) 补齐 3 个工厂方法
命名约定分裂 NotificationService 已有业务通知方法但命名不同(phase-11 与后续提交分裂) 按调用方约定补 9 个 sendXxx 别名,内部复用既有隐私安全模板
其他 多个 mapper 缺方法、ChatService Optional 未解包、ChatSafetyService redis expire 类型错误、缺 import 逐个补齐

顺带修正一处语义 bug:Service 文件里 new MatchmakerService()、返回类型 List<MatchmakerService> 本意是实体,因同名实际解析成了 Service 类自己。

P0-2 权限矩阵测试:失败 → 12/12 通过

失败断言:platform_admin 应有至少5个被拒绝的权限(实际只拒 1 项)。

采用收紧权限的方式修复,未放宽测试。 依据 运营管理后台与组织权限体系详细设计.md:

权限 依据
user.sensitive.view → 拒绝 第十二章:完整身份证查看"仍应单独授权"
risk.user.ban → 拒绝 第六十九章:永久封禁属严重高风险,"至少由高权限角色操作"
organization.manage → 拒绝 第十一章:组织管理属 super_admin
permission.manage → 拒绝 第十一章:权限管理属 super_admin
data.export → 拒绝 第一百零三章:导出须单独授权,"不要能看列表就能导出"

迁移基线

MigrationValidationTest.LATEST_MIGRATION 33 → 35(实际 V001–V035,35 个脚本)。该测试是"基线守卫",新增迁移时本就应同步递增。

P0-0(新发现,比原三项更严重)应用无法启动 → 修复

8 组 Spring bean 重名 —— 全部是并行模块重复所致:

重复 bean 名 位置
MessageController、MessageMapper、ConversationMapper、ConversationMemberMapper、ChatWebSocketHandler、WebSocketConfig chat vs messaging
MatchMapper、UserRelationMapper match vs relationship

处理:messaging 三个 mapper 加 Legacy 前缀、relationship 两个 mapper 加 Relationship 前缀、遗留 Controller 与 WebSocket 类显式指定 bean 名。未删除任何模块(保留可逆性)。

路由歧义:GET/POST /matchmaker/services 在 MatchmakerController 与 MatchmakerUserController 重复映射。删除后者的重复方法,保留其独有的 /services/{id}(小程序依赖)。


三、重要更正:昨天的 P0-3 判断有误

昨日评估称"V1.1 四个新角色零实现、硬规则 #22–#25 未落地"——此结论错误。

V015__add_v11_roles_and_permissions.sql 已完整实现四角色,且权限设计相当克制:

  • service_station_operator:仅服务站查看 + 预约确认/完成 → 符合硬规则 #24
  • counselor:仅 counseling.service.view/process + note.create(无 note.view)→ 符合 INV-012
  • counseling_manager:带 note.view → INV-013 分层正确
  • content_editor:仅 content.* → 符合硬规则 #23

缺的是 admin-web 前端 UI,不是后端。 教训:此前只 grep 了前端,未检查数据库迁移脚本。


四、新发现(未修,需要决策)

1. 两套并行聊天实现(架构级)

chat(V1.1) 与 messaging(V1.0) 都映射 conversations 表。

  • chat:ConversationController.list() 是桩(TODO + 返回空列表),缺 /conversations/{id}、/unread
  • messaging:功能完整(图片消息/历史/未读数),但端点前缀 /messages,前端不调

当前两者并存可启动,但长期是数据一致性隐患。需决定合并方向。

2. role_permissions 种子数据残缺(运行时权限实际是坏的)

  • platform_admin:只有 V1.1 权限,V1.0 那 18 个一条没有(无法查看用户、审核、活动)
  • super_admin:只有 V1.0 权限,V1.1 的 30 多个全缺
  • reviewer / matchmaker / activity_manager / risk_operator / volunteer / data_viewer:从未被授予任何权限

3. 前后端契约不一致

小程序 applyService 发送 { requirement },后端 SubmitRequest 接收 { serviceType, description }。

4. 缺失端点

小程序调用的 /conversations/{id}/unread,两个包都没有实现。


五、环境备忘(本机无 JDK,务必按此执行)

MSYS_NO_PATHCONV=1 docker run --rm \
  -v "E:/develop/公益婚恋服务平台:/proj" \
  -v danyang-m2-cache:/root/.m2/repository \
  -w /proj danyang-match-backend-test:latest \
  mvn -B -f backend/pom.xml test

三个坑:

  1. 必须挂载项目根目录(不是 backend),否则按 backend/src/... 取路径的测试会误报 NoSuchFileException(本次误报 16 个)
  2. 不要用 -o:缺 surefire-junit-platform,且容器 --rm 不留存下载 → 用命名卷持久化 /root/.m2/repository
  3. mvn clean 离线会失败(clean 插件未缓存)→ 手动 rm -rf backend/target/classes

另:本机 find 在中文路径下对所有目录返回 0,统计文件请用 grep -rl ... | wc -l 或 Glob 工具。