- .agents/skills 25 件全量 frontmatter 规范化与评审修入(含 prompt-governance 大修);.claude/skills 7 件薄壳按双层方案①落位 - 新增 skill:agentic-seat-context-design(agentic 席位与 context 工程设计基线,2026-07-05 探索蒸馏) - 设计波三件落档:复杂游戏北极星件(W-NSTAR 终审稿待拍)/黄金模板规格件(W-TPL 定稿待批)/生成侧过程蒸馏回路(W-GENLOG 骨架) - protocol/在飞板/作战清单/数据飞轮 SoT/契约 prompts 索引同步;breakout 九门证据刷新 - .gitignore 补 /localagents.md 真实忽略行(该文件自声明绝不提交,此前声明未被机器执行) - 刻意不入库:nacos-data/ 与 _tier2-gen、c2v-*、amgen-* 生成产物(可重生成,忽略行格式待拍) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
15 KiB
name, description
| name | description |
|---|---|
| add-business-module | 当在 game-cloud 后端新增一个 game-module 业务模块时使用:-api 契约 + -server 实现的双 Maven 结构、controller/service/dal 分层、错误码独占段、Flyway 迁移、两处装配、单测/集成测试与契约同步的标准步骤及踩坑表。 |
新增业务模块操作手册(add-business-module)
蒸馏来源:
docs/architecture/架构/README.md(§2 后端模块地图 / §4.1 编码规范 / §11 模块开发 Checklist)、docs/architecture/架构/README.md(§7.10 扩展性 / SPI)。 适用:在game-cloud后端新增一个game-module-{name}业务模块(如 pay / trade / community / ip / biz / ad,或后续新模块)。 配套:工程规范见../rules/engineering-conventions.md;可靠性/数据隔离红线见../rules/security-and-reliability.md;模块全景见../knowledge/product-and-architecture.md;契约先行见./contract-first-development.md;任务协议见../workflows/ai-development-protocol.md。
目标
把一个新业务能力沉淀为标准 Huijing 风格的双 Maven 模块(-api + -server),可被 huijing-server 单体加载、对外暴露 /app-api/** 与 /admin-api/** 接口、有库表迁移与测试、契约同步给前端。产出后即可被前端联调、被其他模块通过 Feign 调用。
样板:
game-module-project是已编译+单测验证的活样板,照抄它(结构/分层/注释/错误码/单测)即可。 全局接线已就绪:HuijingServerApplication的组件扫描 +@MapperScan+application.yaml的 type-aliases 已通配覆盖整个com.wanxiang.huijing.game.module,新模块无需改 Application/yaml,只需在huijing-server/pom.xml加本模块-server依赖(步骤 5)。端前缀/app-api·/admin-api由框架按controller.app·controller.admin包名自动添加,Controller 里@RequestMapping只写/{模块}。
前置
- 已读
../knowledge/product-and-architecture.md,确认该能力确实需要新模块(多数 MVP 需求在既有模块加子包即可,见模块架构文档 §4 遗漏分析的判断方式)。 - 中间件(MySQL/Redis/Nacos/RocketMQ)已自托管 mini-infra,连接信息见
docs/内网凭据与端点.md;本地跑 Flyway 与集成测试的 Testcontainers 仍依赖 Docker。 - 已在模块速查表(开发团队版 §2.2)与错误码段位表(开发团队版 §4.1)为新模块预留了模块编号与错误码段。(两版《系统概要设计》——"开发团队版"/"技术决策版"——已归档
_archive,节号按历史读;现行规范见../rules/engineering-conventions.md与docs/architecture/README.md)
模块物理结构(以 project 为样板)
新模块拆成两个 Maven 子模块:-api(契约,被别人引用)与 -server(实现,只本模块用)。
game-module-{name}/
├── game-module-{name}-api/ # 契约层:可被其他模块依赖
│ └── src/main/java/com/wanxiang/huijing/game/module/{name}/
│ ├── api/ # Feign 接口(供别的模块同步调用)
│ ├── dto/ # 模块间传输对象 DTO
│ ├── enums/ # 枚举(状态/类型)
│ └── enums/ErrorCodeConstants.java # 本模块错误码常量(独占一段)
│
└── game-module-{name}-server/ # 实现层:只本模块内部使用
└── src/main/java/com/wanxiang/huijing/game/module/{name}/
├── controller/admin/ # 后台接口(运营/管理员,/admin/{name}/**)
│ └── vo/ # admin 端 VO(ReqVO/RespVO/PageReqVO)
├── controller/app/ # 产品端接口(创作者/玩家,/app/{name}/**)
│ └── vo/ # app 端 VO
├── service/ # 业务逻辑(@Transactional 只加这里)
├── dal/mysql/ # Mapper 接口 + DO(数据库映射对象)
├── dal/dataobject/ # DO(与表字段一一对应)
├── convert/ # DO ↔ VO/DTO 转换器(MapStruct)
├── job/ # 定时任务(如对账/聚合/清理)
└── mq/consumer/ # RocketMQ 消费者(幂等消费)—— RocketMQ 已自托管 mini-infra;单体内跨模块通知仍优先同进程 -api notify-push,真跨进程/异步才上 RocketMQ(见下方坑表)
└── src/main/resources/
└── db/migration/ # Flyway 迁移脚本 V{x.y.z}__{desc}.sql
└── src/test/java/... # 单元测试 + 集成测试
包名固定
com.wanxiang.huijing.game.module.{name}.{层}(开发团队版 §4.1)。-api只放契约,禁止放实现/DO/Mapper;-server禁止被其他业务模块依赖。
步骤清单(照做)
| # | 步骤 | 关键动作 | 验证 |
|---|---|---|---|
| 1 | 建模块 | 复制 project 的 -api/-server 两个 pom 改 artifactId;-server 依赖本模块 -api + 需要的他模块 -api |
mvn -pl game-module-{name}-server compile 通过 |
| 2 | -api 定义契约 |
写 DTO/枚举/Feign 接口/ErrorCodeConstants;先于 -server 完成,前端据此定义 TS 类型 |
契约同步进 contracts/api-schemas/{name}.yaml |
| 3 | -server 实现分层 |
按 controller(admin/app)→service→dal(DO+Mapper)→convert 落地;MQ/job 按需加 | 单元测试覆盖 service |
| 4 | Flyway 迁移 | -server 的 db/migration/ 下新建 V{x.y.z}__{desc}.sql,如 V1.0.0__create_game_{name}.sql;只新增不改旧文件 |
mvn flyway:migrate -pl game-module-{name}-server 成功 |
| 5 | 装配=两处(缺任一 compile/启动失败,Wave4 实测) | ① root game-cloud/pom.xml 的 <modules> 加 <module>game-module-{name}</module>(聚合定义,缺则 mvn -pl game-module-{name} … 报「找不到父 pom 聚合」);② huijing-server/pom.xml 加 game-module-{name}-server 依赖(单体把模块编进 JAR,缺则启动无此模块、Swagger 无分组) |
mvn -pl huijing-server -am compile 通过 + 启动后 Swagger 见分组 |
| 6 | 模块配置(Nacos 已部署 mini-infra) | 如有模块级配置(开关/阈值/外部 API key):Nacos 已自托管 mini-infra,模块级配置可入 Nacos 配置集;简单静态项也可走本地配置文件/环境变量。 | Nacos 控制台可见 / 配置项生效 |
| 7 | 单元测试(Service) | XxxServiceImplTest 继承 BaseMockitoUnitTest(纯 Mockito,无需 DB/Docker,照抄 project 的 ProjectServiceImplTest);需真实 DB 才用 BaseDbUnitTest(集成阶段)。注意:mock/verify BaseMapper.insert/updateById 用 any(XxxDO.class) 消歧,裸 any() 会因重载报错;verify(...).updateById(argThat(...)) 须显式标 lambda 参数类型 argThat((XxxDO d) -> …),否则同样重载歧义致 testCompile 失败(Wave4 biz 实测踩坑) |
mvn -pl game-module-{name}/game-module-{name}-server test 绿 |
| 8 | 集成测试(Controller+DB) | XxxServiceIntegrationTest,Testcontainers 自动起 MySQL/Redis;覆盖核心 API |
mvn verify -pl game-module-{name}-server -Pintegration 绿 |
| 9 | Swagger/Knife4j 验证 | 启动 huijing-server,开 http://localhost:48080/doc.html 确认接口与字段自动生成正确 |
doc.html 可见新模块分组 |
| 10 | 更新文档 | 更新开发团队版 §2.2 模块速查表 + ../knowledge/product-and-architecture.md 模块清单/依赖 |
文档与代码一致 |
| 11 | 通知前端 | 给前端 Swagger 地址 + 示例 curl(含鉴权头);契约变更走 ./contract-first-development.md |
前端可联调 |
API 路径规范:/{端前缀}/{模块}/{资源}/{动作},端前缀框架自动加。/app-api/** 走用户 Token,/admin-api/** 走管理员权限。Controller 里 @RequestMapping("/{name}") 只写模块名,最终对外即 POST /app-api/{name}/xxx、GET /admin-api/{name}/page。
错误码段位规则
每个模块独占一段 9 位错误码,避免冲突(详见 ../rules/engineering-conventions.md)。已分配段(开发团队版 §4.1):
| 段位 | 模块 |
|---|---|
1-001-xxx-xxx |
system |
1-002-xxx-xxx |
infra |
1-100-xxx-xxx |
project |
1-101-xxx-xxx |
aigc |
1-102-xxx-xxx |
runtime |
1-103-xxx-xxx |
feed |
1-104~1-112 |
续段(telemetry/ad/trade/studio/compliance…)+ Wave4:community=1-107、biz=1-110(已落地);完整映射以 engineering-conventions.md / contracts/README.md §四 为权威 |
错误码常量集中写在 -api 的 ErrorCodeConstants.java,用 Huijing ServiceException + 错误码枚举抛出(不要裸抛 RuntimeException)。
完整 Checklist(可勾选)
- 已确认确需新模块(而非在既有模块加子包)
- 创建
game-module-{name}-api与game-module-{name}-server两个 Maven 模块 -api中定义 VO/DTO 入口、枚举、Feign 接口、ErrorCodeConstants(独占错误码段)-server中建controller/admin/+controller/app/+service/+dal/mysql/+convert/(按需job/、mq/consumer/)- 编写 Flyway 迁移
V{x.y.z}__{desc}.sql(只新增,不改旧迁移) - 装配两处:root
game-cloud/pom.xml<modules>注册<module>+huijing-server/pom.xml引入-server依赖 - 模块级配置(如有):Nacos 已自托管 mini-infra,可入 Nacos 配置集;简单静态项也可走本地配置/环境变量
- 单元测试(Service 层)通过
- 集成测试(Controller + DB,Testcontainers)通过
- Swagger(Knife4j)
doc.html验证 API 文档自动生成 - 更新开发团队版 §2.2 模块速查表 +
../knowledge/product-and-architecture.md - 通知前端:附 Swagger 地址 + 示例 curl
- 契约文件
contracts/api-schemas/{name}.yaml已同步并提交 git
常见坑
| 坑 | 后果 | 正确做法 |
|---|---|---|
| 改 Huijing framework 层源码 | 升级 Huijing 时冲突、不可维护 | 不改 framework 层,走 SPI/扩展点(如 PayChannel/AdProvider/ConversionAdapter SPI,见技术决策版 §7.10) |
| 自己写 SQL 做数据隔离 | 创作者能看到别人的项目/资产 | 用 Huijing DataPermission(数据权限)做隔离,"创作者只看自己的"(技术决策版 §7.4) |
| 审核流自己写状态流转 | 流程僵硬、无法可视化配置 | 审核/发布/下架走 bpm(Flowable) 工作流驱动(开发团队版 §2.2 project 依赖 bpm) |
-server 被别的模块依赖 |
编译耦合、循环依赖 | 跨模块只依赖对方 -api;单体装配下注入 -api 接口实际走提供方 -server 内的 @RestController @Primary 本地实现 = 同进程调用、与调用方同一 @Transactional(B2 实证:telemetry 统计→quality→feed.upsertRank 同事务原子,异常整批回滚);拆微服务后退化为 Feign 远程调用、事务边界改变,须按 rules 补幂等/补偿;异步用 RocketMQ |
单体装配下 -api 的 @FeignClient 代理与本地实现 bean 二义性 |
Spring 启动失败(OpenFeign 默认注册 primary bean,与本地 @Primary 实现冲突) |
提供方本地实现标 @RestController @Primary;个别仍冲突的(M1 实证:4 个 CommonApi)给 @FeignClient 补 primary = false(修法见 commit d7fac90) |
| 跨模块「通知/事件」直接上 MQ | 单体内过度设计、调试链路长、RocketMQ 重依赖 | MVP 单体内跨模块通知优先「同进程 -api notify-push」(Wave4 community 范式):通知方建 XxxNotifyApi(@Primary 本地实现),上游在本地事务提交后调用 + try-catch 吞异常仅记 error log(通知失败不回滚业务/不中断循环);通知由无鉴权线程(定时任务/回调)触发写库时,入口注入 LoginUser(id=0)+finally clearContext 防审计列 NOT NULL 撞 500(范本 telemetry/community)。真异步/跨进程才上 MQ |
@Transactional 加在 Controller 或范围过大 |
长事务、锁竞争 | 只加在 Service 层,范围尽量小(开发团队版 §4.1) |
| 修改已存在的 Flyway 迁移文件 | flyway validate 失败、CI 阻断 |
新建迁移补偿,绝不改旧文件(开发团队版 §9) |
| 单元测试连真实 DB | 测试慢、不稳定 | 业务逻辑用 Mock;真需要 DB 用集成测试 + Testcontainers |
select * / 大表无索引查询 |
慢查询、性能事故 | 必须指定字段;大表查询必须命中索引(开发团队版 §4.1) |
| 「运营赋值类」资金(admin 赋余额/补偿)混进业务收益流水表 | 污染营收报表 gross/net 聚合 + 破坏对账锚点 | 另建专用流水表(trade U2:game_trade_grant,独立 uk_biz_no 幂等行),账户余额仍走原子增(balance += amount, total_income += amount 守恒 balance+frozen+total_withdraw=total_income);流水写入 + 余额增同 @Transactional,先写流水行(uk 防并发)再增余额,余额增 0 行抛错回滚(禁「流水已记、余额未增」半态)。范本 AccountServiceImpl.grant |
| 「一用户一态」聚合域(订阅/会员)按每次操作建新行 | uk_user 撞键 / 状态分散难查 | 一行一用户 upsert(uk_user,首建 insert / 已有 CAS 续期);幂等键内联在行(last_grant_biz_no,同 bizNo 不重复延长 = 重试安全),区别于流水域的独立 uk_biz_no 行;续期叠加 新到期=max(now,旧expire)+时长(不丢未用时长,已过期从 now 起算);CAS(WHERE expire_time=读时快照)防并发 lost-update,miss 回查重试有限轮次(禁死循环)。范本 SubscriptionServiceImpl |
| 「有效期/过期态」依赖定时 job 物化 status 列 | 无 cron / 定时 job 未接时过期态不准 | 有效性以 expire_time>now 查询时实时回算(effectiveStatus/active 在 Convert 层算),落库 status 仅初始态 + 后续物化预留;不依赖定时 job 也能正确反映过期。范本 TradeConvert.toSubscriptionVO |