feat: 实现响应候选模型与私有动作消息结构化

新增响应候选领域模型和结构化私有动作消息,支持响应窗口和候选动作下发。主要变更包括:

- 新增 ResponseActionOption、ResponseActionSeatCandidate 和 ResponseActionWindow 模型
- 扩展 PrivateActionMessage 支持响应候选上下文
- 实现 ResponseActionWindowBuilder 构建弃牌响应候选
- 拆分 GameMessagePublisher 支持回合动作和响应动作消息
- 更新前端原型页展示结构化候选动作
- 新增响应优先级规则文档 RESPONSE_RESOLUTION_RULES.md
This commit is contained in:
hujun
2026-03-20 13:04:59 +08:00
parent 24fce055fd
commit 48da7d4990
20 changed files with 1151 additions and 208 deletions

View File

@@ -44,101 +44,6 @@ Sprint 目标:
## 2. 待做
### S1-05 [功能] 扩展私有动作消息体,支持响应候选下发
## 背景
后续 `HU / GANG / PENG / PASS` 不是任何时刻都可点,必须先有“当前玩家可执行哪些动作”的私有候选列表。现在虽有私有动作主题,但消息体还不足以表达响应窗口和候选动作。
## 目标
把私有动作消息体扩展成可支持:
- 当前可行动作列表
- 候选动作来源
- 响应截止上下文
- 与当前回合/弃牌事件的关联关系
## 范围
- 定义候选动作 DTO
- 定义是否为响应窗口动作
- 定义关联事件 ID 或动作上下文
- 补充前端消费字段说明
## 非范围
- 不在本任务里完成最终 UI 交互
- 不在本任务里实现多人竞争裁决
## 依赖
- `S1-01`
- `S1-02`
- `S1-04`
## 产出物
- 后端私有动作消息模型
- 消息发布说明
- 前端订阅字段适配说明
## 验收标准
- 服务端能向指定用户发送结构化候选动作
- 消息能区分“主动出牌动作”和“被动响应动作”
- 前端收到后无需猜测字段语义
## 验证方式
- 后端:`mvn test`
- 前端:`npm run build`
- 手工:模拟一次弃牌后,检查候选动作消息结构是否完整
### S1-06 [研究] 响应优先级裁决规则澄清
## 背景
在真正实现多人响应之前,必须先统一项目内部的动作优先级和冲突处理规则,否则后端、前端、教学系统会各自假设,后续很容易返工。
## 目标
形成一份明确的规则澄清结果,至少回答:
- `HU / GANG / PENG / PASS` 的优先级顺序
- 多人同时可响应时的裁决方式
- 响应窗口何时打开、何时关闭
- AI 与真人竞争时是否采用同一裁决规则
## 范围
- 梳理当前产品约束
- 梳理实现层需要的最小规则集
- 输出推荐裁决策略
## 非范围
- 不在本任务里直接落代码
## 依赖
- `S1-04`
## 产出物
- 规则澄清文档
- 后续开发任务拆分建议
## 验收标准
- 可以直接指导 `S1-07`
- 后续实现不再需要对优先级做二次猜测
## 验证方式
- 文档评审
- 与主计划、阶段看板、周计划保持一致
### S1-08 [H5] 对局页信息架构与页面拆分方案
## 背景
@@ -222,92 +127,6 @@ Sprint 目标:
- 前端已知道如何接响应候选
- 下一轮 H5 正式页面改造可以直接开始
### S1-04 [功能] 响应候选模型初版
## 背景
要支持 `PENG / GANG / HU / PASS`,系统不能只知道“执行了什么”,还必须知道“现在允许谁做什么”。这个模型是后续优先级裁决、前端动作面板、教学提示的共同基础。
## 目标
定义响应候选模型,能表达:
- 当前响应来源于哪次弃牌或事件
- 哪些玩家可以响应
- 每个玩家可响应哪些动作
- 响应窗口的生命周期
## 范围
- 设计候选动作数据结构
- 设计响应窗口上下文
- 设计与座位、玩家 ID、事件 ID 的关联
## 非范围
- 不在本任务里完成最终竞争裁决实现
## 依赖
- `S1-02`
- `S1-03`
## 产出物
- 后端候选动作模型
- 前后端字段语义说明
## 验收标准
- 候选结构可表达“谁现在能做什么”
- 后续可直接承接 `PASS`
- 前端动作面板无需再自行推导
## 验证方式
- 模型评审
- 后端:`mvn test`
### S1-07 [功能] H5 动作面板字段对齐与占位接入
## 背景
后端一旦开始发送响应候选,前端至少要能消费这些字段并用最小方式展示,否则会形成后端已支持、前端完全不可见的断层。
## 目标
让 H5 原型页先具备读取并展示响应候选字段的占位能力,为后续正式动作面板铺路。
## 范围
- 订阅并解析新的私有动作消息字段
- 在原型页中增加最小占位展示
- 区分“主动动作按钮”和“响应动作按钮”
## 非范围
- 不在本任务里完成正式视觉设计
- 不在本任务里完成多状态动画
## 依赖
- `S1-05`
## 产出物
- 前端字段适配
- H5 原型占位展示
## 验收标准
- 当前原型页能看到候选动作
- 不会影响现有定缺和出牌功能
## 验证方式
- 前端:`npm run build`
- H5 手工:检查候选动作占位区是否出现
---
## 4. 已完成
@@ -397,6 +216,94 @@ Sprint 目标:
- 后续 `S1-04 / S1-05` 可以直接复用事件约定
- `mvn test` 已通过
### S1-04 [功能] 响应候选模型初版
## 已完成内容
- 新增响应候选领域模型:
- `ResponseActionOption`
- `ResponseActionSeatCandidate`
- `ResponseActionWindow`
- `GameSession` 已预留 `pendingResponseActionWindow` 字段,为后续真实响应流程挂载窗口对象做准备
- 新增 `ResponseActionWindowBuilder`,可基于一次弃牌构建候选窗口
- 当前候选规则支持:
- 手里 2 张同牌时生成 `PENG + PASS`
- 手里 3 张同牌时生成 `PENG + GANG + PASS`
- 已补单测验证:
- 有候选时可正确构建多座位响应窗口
- 无候选时返回空结果
## 验收结果
- 后端已经能表达“谁现在可以响应什么”
- `PASS` 已纳入候选动作模型
- 下一步 `S1-05` 可以直接把候选窗口映射到私有动作消息
- `mvn test` 已通过
### S1-05 [功能] 扩展私有动作消息体,支持响应候选下发
## 已完成内容
- `PrivateActionMessage` 已升级为结构化消息,补充字段:
- `actionScope`
- `windowId`
- `triggerEventType`
- `sourceSeatNo`
- `triggerTile`
- `candidates`
- 新增 `PrivateActionCandidate` DTO
- `GameMessagePublisher` 已拆分:
- `publishPrivateTurnActionRequired`
- `publishPrivateResponseActionRequired`
- 当前回合动作消息与响应候选消息已可共用同一消息结构
- 已补消息发布单测,验证 turn / response 两类消息形状
## 验收结果
- 私有动作消息已经能区分“主动回合动作”和“被动响应动作”
- 前端后续无需再猜测候选字段语义
- `mvn test` 已通过
### S1-07 [功能] H5 动作面板字段对齐与占位接入
## 已完成内容
- `App.vue` 已对齐新的私有动作消息结构
- H5 原型页已支持识别:
- `TURN`
- `RESPONSE`
两类动作消息作用域
- 私有动作区已增加候选动作展示占位
- 私有动作区已增加来源座位、目标牌等上下文字段展示
- 已补样式支持候选动作标签展示
## 验收结果
- H5 原型页已经能消费结构化私有动作消息
- 当前定缺和出牌流程未被破坏
- `npm run build` 已通过
### S1-06 [研究] 响应优先级裁决规则澄清
## 已完成内容
- 新增规则澄清文档 `docs/RESPONSE_RESOLUTION_RULES.md`
- 明确了本项目 `V1` 的响应优先级:
- `HU > GANG > PENG > PASS`
- 明确了本项目 `V1` 的同优先级裁决:
- 按出牌者之后最近顺位优先
- 明确了本项目 `V1` 的工程取舍:
- 当前不实现完整 `过水不胡`
- 当前不实现 `一炮多响`
- 明确了公共消息与私有消息的职责边界
- 明确了后续真实响应窗口接入主流程的推荐顺序
## 验收结果
- 后续实现不需要再重新讨论优先级口径
- 裁决器实现已有单一依据
- 文档已纳入 README 与主计划索引
---
## 5. 依赖关系图