feat: 实现桌面控制组件

This commit is contained in:
JiaJun
2026-04-30 19:04:19 +08:00
parent 36ce93d8d0
commit 9ee681168e
60 changed files with 1246 additions and 247 deletions

View File

@@ -168,7 +168,7 @@
### 2.3 获取当前用户信息
- **POST** `/api/user/profile`
返回参数(金额类字段统一 2 位小数字符串,与 `/api/wallet/balanceSummary` 对齐
返回参数(金额类字段统一 2 位小数字符串,与钱包展示口径一致
**基础档案**
- `uuid`string含义用户对外唯一标识10 位)
@@ -184,13 +184,13 @@
- `create_time`int含义注册时间戳
**资金与提现配额**
- `coin` / `coin_balance`string含义当前余额两字段同值,便于与 `/api/wallet/balanceSummary` 平滑切换
- `coin` / `coin_balance`string含义当前余额两字段同值
- `frozen_balance`string含义冻结余额无冻结场景固定 `0.00`
- `total_deposit_coin`string含义累计充值
- `total_withdraw_coin`string含义累计提现受理后累加
- `bet_flow_coin`string含义打码量/流水;开奖结算后按每注 `total_amount` 1:1 累加)
- `max_withdrawable`string含义**当前允许发起的单笔最大提现金额** = `min(coin_balance, max_withdraw_by_flow)`
- `withdraw_flow`object含义打码量 / 提现配额诊断快照,结构与 `/api/wallet/balanceSummary.withdraw_flow` 一致,此处额外附 `pending_withdraw`
- `withdraw_flow`object含义打码量 / 提现配额诊断快照,此处额外附 `pending_withdraw`
- `ratio`string打码量倍数`0` 表示不限打码)
- `net_deposit`string净充值 = max(0, 累计充值 累计提现)
- `required_bet_flow`string按门槛口径所需打码量纯展示
@@ -247,20 +247,6 @@
- `version`string含义字典版本号前端可用于缓存比对
- `items`:同 `dictionary`含义36字花字典明细
### 3.3 获取最近开奖记录近30期
- **POST** `/api/game/periodHistory`
请求参数:
- `limit`int可选默认 30含义返回最近几期
返回参数:
- `list`array<object>
- `period_no`string含义历史期号
- `result_number`int含义该期开奖结果
- `open_time`int含义开奖时间
---
## 4. 下注与对局模块game/bet
### 4.1 获取当前期详情
@@ -276,19 +262,22 @@
- `result_number`int/null未开奖为 null含义开奖号码
### 4.2 提交下注
- **POST** `/api/game/betPlace`
- 用途:单期手动下注;玩家只需选择**压注号码**与**本笔压注总金额**。开奖只出一个号码,若该号码 ∈ 所选号码集合即视为**中奖**,派彩按整笔 `bet_amount`(落库 `total_amount`× 赔率计算(赔率与连胜倍率见服务端实现)
- **POST** `/api/game/placeBet`(兼容旧路径 `/api/game/betPlace`
- 用途:单期手动下注;玩家传入**压注号码**与**单注金额 `single_bet_amount`**。服务端按 `single_bet_amount × numbers数量` 计算本笔总扣款(落库 `total_amount`,开奖只出一个号码,若该号码 ∈ 所选号码集合即视为中奖
请求参数:
- `period_no`string含义下注目标期号
- `numbers`string含义本次压注号码集合**英文逗号分隔**,如 `1,8,16`;每个号码为 136 的整数,数量不超过 `pick_max_number_count`(同 `lobbyInit.bet_config`),重复号码会去重)
- `bet_amount`string含义**本笔整笔压注金额**> 0;服务端按此金额从余额扣款并写入注单 `total_amount`**不再**按「单号金额 × 号码个数」计算
- `single_bet_amount`string含义**注金额**> 0
- `bet_amount`string兼容字段含义同 `single_bet_amount`
- `idempotency_key`string必填含义防止重复下单
返回参数:
- `order_no`string含义下注订单号
- `period_no`string含义实际落单期号
- `status`string`accepted`/`rejected`,含义:受理结果)
- `single_bet_amount`string含义本次单注金额
- `numbers_count`int含义本次号码数量
- `locked_balance`string可选含义冻结金额
- `balance_after`string含义下单后余额
- `current_streak`int含义下单后连胜快照
@@ -298,9 +287,22 @@
- `3001`:游戏已暂停(`runtime_enabled=false`,后台「游戏实时对局」关闭运行开关或作废本局后未重新开启;与非法流程类错误同段)
- `5000`:系统繁忙;或 **用户 Redis 互斥锁**未获取(与后台钱包/并发写同一用户串行,文案与后台一致:「该用户正在被其他管理员操作(钱包/并发保存),请稍后再试」);或 **`coin` 条件更新**未命中(并发下注/派彩/后台已改余额:「扣款失败:该用户余额已被其他请求修改(如下注、派彩或其他管理员已保存),请刷新后重试」)。
> 说明:一键重复上一注、自动托管开启/停止均由前端控制,客户端在相应时机调用 `/api/game/betPlace` 即可完成,不再提供独立接口。
### 4.3 自动托管
- **POST** `/api/game/autoSpin`
### 4.3 查询我的下注记录最近1个月
请求参数:
- `action`string`start`/`stop`
- `period_no`string`action=start` 时必填)
- `numbers`string`action=start` 时必填,英文逗号分隔)
- `single_bet_amount`string`action=start` 时必填,支持兼容字段 `bet_amount`
- `rounds`int`action=start` 时必填,>=1
返回参数:
- `status`string`scheduled`/`stopped`
- `auto_mode`bool
- `remaining_rounds`int`start` 返回)
### 4.4 查询我的下注记录最近1个月
- **POST** `/api/game/betMyOrders`
请求参数:
@@ -324,29 +326,12 @@
## 5. 钱包与资金模块wallet/finance
### 5.1 获取钱包摘要
- **POST** `/api/wallet/balanceSummary`
返回参数:
- `coin_balance`string含义可用余额等同于 `user.coin`
- `frozen_balance`string含义冻结余额当前系统无冻结场景固定返回 `0.00`
- `withdrawable_balance`string含义可提现余额等同于 `coin_balance`**单笔实际上限以 `max_withdrawable` 为准**
- `max_withdrawable`string含义**当前允许发起的单笔最大提现金额** = min(`coin_balance`, 打码配额余量);客户端直接用于"最大可提 XXX"提示与金额输入上限校验)
- `total_deposit_coin`string含义累计充值币额
- `total_withdraw_coin`string含义累计提现币额提现受理时累加
- `bet_flow_coin`string含义打码量/流水;开奖结算后按每注 `total_amount` 1:1 累加)
- `withdraw_flow`object含义打码量 / 提现配额诊断快照,供前端展示说明与上限推导)
- `ratio`string含义打码量倍数来自 `game_config.withdraw_bet_flow_ratio`,默认 `1.00``0` 表示"不限打码"
- `net_deposit`string含义净充值 = max(0, 累计充值 - 累计提现)
- `required_bet_flow`string含义按门槛口径所需的打码量 = 净充值 × 倍数,纯展示)
- `remaining_bet_flow`string含义按门槛口径还差多少打码量纯展示已达标为 `0.00`
- `eligible`bool含义是否满足整体门槛纯展示实际放行以 `max_withdrawable` 为准)
- `max_withdraw_by_flow`string/null含义仅按打码量折算的单笔可提上限 = max(0, `bet_flow_coin` / `ratio` - `total_withdraw_coin`)`ratio=0` 不限打码时返回 `null`
- `flow_unlimited`bool含义是否处于"不限打码"状态,`ratio=0` 时为 `true`
说明(打码量即提现配额模型):
- 每笔提现按 `withdraw_coin × ratio` 消耗打码配额;`total_withdraw_coin` 已累积历史消耗。
- **单笔最大可提现 `max_withdrawable = min(coin_balance, max_withdraw_by_flow)`**`ratio=0` 时退化为仅受余额约束。
### 5.1 余额同步口径(已移除独立摘要接口)
- 已移除 `/api/wallet/balanceSummary`
- 余额同步来源调整为:
- 下注返回 `placeBet.balance_after`
- WebSocket 推送 `wallet.changed`
- 充值/提现详情接口(如 `depositDetail` / `withdrawDetail`)作为业务单据维度核对
- 倍数 `ratio` 由后台「游戏配置 → `withdraw_bet_flow_ratio`」维护,修改后对新请求立即生效。
- 历史累计类字段(`total_deposit_coin` / `total_withdraw_coin` / `bet_flow_coin`)均为累加语义;若后续审核驳回,回冲逻辑由后台审核流程负责。
@@ -655,114 +640,78 @@
---
## 7. 推送模块webman/push
## 7. WebSocketH5与状态同步
> 用于移动端实时监听对局状态、开奖结果、余额变更与强公告事件。
> 协议与客户端行为对齐 [Pusher Channels](https://pusher.com/docs/channels/library_auth_reference/pusher-websockets-protocol/)webman/push 内置兼容客户端 `push.js`)。
> 参考:[webman/push 官方文档](https://www.workerman.net/doc/webman/plugin/push.html)
> 本版本已移除 webman/push 频道模式H5 前端使用原生 WebSocket 直连HTTP 轮询仅作为弱网兜底。
### 7.1 频道命名与职责(优化版)
### 7.1 WebSocket 连接与消息
| 频道名 | 类型 | 订阅方 | 典型事件 |
|--------|------|--------|----------|
| `private-user-{user.uuid}` | 私有(`private-` 前缀) | 当前登录用户;`{user.uuid}` 与登录态/档案中的 **10 位 `uuid`** 一致 | `bet.accepted``wallet.changed``withdraw.review_required`、定向 `notice.popout` 等 |
| `public-game-period` | 公共 | 所有在线客户端 | `period.tick``period.locked``period.opened` |
| `public-operation-notice` | 公共 | 所有在线客户端 | 全站/渠道级 `notice.popout`(与私有公告二选一或并存,由实现约定) |
- **连接地址**:由服务端配置下发(后台测试页读取 `H5_WEBSOCKET_URL`
- **客户端**:浏览器原生 `WebSocket``ws://` / `wss://`
- **连接时携带参数(建议)**
- URL Query`token`(用户登录态 user-token`auth_token`(接口鉴权)、`device_id`(设备标识)、`lang``zh/en`
- 示例:`wss://ws.example.com/game?token=xxx&auth_token=xxx&device_id=ios_001&lang=zh`
- **连接成功返回(服务端首帧建议)**
- `event``ws.connected`
- `connection_id`:连接唯一标识
- `server_time`:服务器时间戳(秒)
- `heartbeat_interval`:心跳间隔(秒)
- **连接失败返回(建议)**
- `event``ws.error`
- `code`:错误码(如 `1101` 未登录、`1103` 鉴权失败)
- `message`:错误描述
- **建议消息**
- 心跳:`{"action":"ping"}`
- 订阅状态流:`{"action":"subscribe","topics":["period.tick","period.opened"]}`
- 订阅资金流:`{"action":"subscribe","topics":["bet.accepted","wallet.changed"]}`
- 订阅托管流:`{"action":"subscribe","topics":["auto.spin.progress","wallet.changed"]}`
约定说明:
#### 7.1.1 消息协议字段定义(联调口径)
- **用户私有频道一律使用对外标识 `uuid`,不使用数据库主键 `user_id`**,避免与后台、日志、多端展示口径不一致,并降低枚举内网 ID 的风险。
- 名称以 `private-` 开头的频道必须通过 **私有频道鉴权**(见 7.2)成功后才能收到服务端推送。
- `public-*` 可直接订阅,无需鉴权 HTTP 步骤。
- 客户端 -> 服务端:
- `action`:动作名(当前约定 `ping` / `subscribe`
- `topics`:仅 `subscribe` 时必填,表示要订阅的主题列表(数组)
- 服务端 -> 客户端:
- `event`:事件名(如 `period.tick``wallet.changed``jackpot.hit`
- `topic`:所属主题(通常与 `event` 一致;用于前端按主题路由)
- `data`:业务载荷(对象)
- `server_time`:服务端时间戳(秒,倒计时与对时基准)
### 7.2 连接地址与鉴权流程
#### 7.1.2 订阅行为说明
**WebSocket 连接 URL与官方 `push.js` 一致)**
- **仅建立连接不会自动下发全部业务消息**;客户端需要发送 `subscribe` 明确订阅主题。
- 成功订阅后服务端返回:`{"event":"ws.subscribed","topics":[...]}`
- 若未订阅主题,通常只能收到握手首帧(`ws.connected`)和心跳回包(`pong`)。
- 形如:`{websocket_base}/app/{app_key}`
- 示例(本地默认配置见 `config/plugin/webman/push/app.php``ws://127.0.0.1:3131/app/{app_key}`
- 生产环境请改为 `wss://` 与对外域名,并与网关/证书一致。
#### 7.1.3 推送频率与触发规则(当前实现)
**连接建立后的协议步骤(简述)**
- `period.tick`**每秒一次**(用于倒计时、状态同步)。
- `admin.live.snapshot`**每秒一次**(后台实时对局页全量快照)。
- `period.opened` / `period.payout` / `admin.live.opened`:按开奖流程阶段触发(事件触发型,非固定频率)。
- `wallet.changed`:仅在余额发生变更时推送(如下注扣款、充值入账、派彩入账)。
- `jackpot.hit`**仅在本期存在中大奖命中用户时推送**;无命中不推送。
1. 客户端建立 WebSocket服务端下发 `pusher:connection_established`payload 内含 **`socket_id`**(后续鉴权必填)。
2. 订阅 **公共** 频道:发送 `pusher:subscribe``data` 仅含 `channel` 名即可。
3. 订阅 **私有** 频道:
- 客户端向 **鉴权接口** 发起 `POST``Content-Type: application/x-www-form-urlencoded`),表单字段:`channel_name``socket_id`
- 默认鉴权路径为 **`/plugin/webman/push/auth`**(与 `config/plugin/webman/push/app.php``auth` 一致,可随部署调整)。
- 服务端校验「当前登录用户是否允许订阅该 `channel_name`」——对 `private-user-{uuid}` 应校验 **`uuid` 与当前用户一致**,否则返回 `403`
- 鉴权成功返回的 JSON 由 `push.js` 原样作为 `pusher:subscribe``data` 发送(含 `auth` 等字段)。
### 7.1A 后台连接方式(管理端联调)
**与移动端登录态的关系**
- 后台菜单:仅保留一个菜单 `连接服务器websocket`,用于统一联调 WebSocket
- 后台连接入口:
- `/admin/test.GameCurrentStatus/wsConfig`
- 后台页面能力:
- 读取 `ws_url``connect_tip``sample_messages`
- 手动连接/断开 WebSocket
- 手动发送订阅与心跳报文
- 实时查看服务端返回帧内容(用于联调事件格式)
- 客户端在调用鉴权接口时,除 `channel_name` / `socket_id` 外,需携带与 REST API 一致的 **`user-token`(及业务所需的 `auth-token`**,由服务端解析用户身份后再比对 `private-user-{uuid}`
- **不建议**依赖浏览器 Cookie Session 作为唯一依据H5 外还有 App 内嵌、小程序等);若仅沿用框架示例中的 Session需在落地实现中改为 **无状态 token 校验**
### 7.2 HTTP 兜底接口
### 7.3 事件定义(初设)
- 本版本已移除以下兜底接口:`/api/game/currentStatus``/api/game/periodHistory``/api/wallet/balanceSummary`
- 状态与余额统一以 WebSocket 推送为主HTTP 仅保留业务动作/详情查询接口(如 `placeBet``depositDetail``withdrawDetail`)。
| 事件名 | 建议频道 | 说明 |
|--------|----------|------|
| `period.tick` | `public-game-period` | 倒计时广播 |
| `period.locked` | `public-game-period` | 封盘 |
| `period.opened` | `public-game-period` | 开奖完成(中奖号码) |
| `bet.accepted` | `private-user-{uuid}` | 下注成功回执 |
| `bet.settled` | `private-user-{uuid}` | **每期每用户一条**:该局开奖对该用户全部注单的汇总(`total_win_amount``order_count``hit_order_count``result_number``balance_after`;不再按单笔注单重复推送) |
| `wallet.changed` | `private-user-{uuid}` | 余额变化(中奖派彩入账等;`reason=payout` 等) |
| `notice.popout` | `public-operation-notice``private-user-{uuid}` | 强公告(按业务选择广播或定向) |
| `withdraw.review_required` | `private-user-{uuid}` | 提现进入审核 |
### 7.3 一致性规则
### 7.4 消息形态(客户端解析)
连接上收到的单帧一般为 JSON常见两类
- 协议类:`event``pusher:connection_established``pusher_internal:subscription_succeeded` 等。
- 业务类:`event` 为业务事件名,`channel` 为频道名,`data` 为负载(可能为字符串化的 JSON客户端需 `JSON.parse` 一次)。
业务负载示例(与初设一致,字段以实际实现为准):
```json
{
"event": "period.opened",
"channel": "public-game-period",
"data": {
"period_no": "20260416001",
"result_number": 18,
"open_time": 1776326400
}
}
```
### 7.5 降级与一致性
- 推送仅作 **体验增强**:断线、弱网时客户端仍应以 **HTTP 轮询/用户主动刷新**(如 `/api/game/periodCurrent``/api/wallet/balanceSummary`)为准。
- 同一业务状态以 **服务端落库与接口查询** 为最终一致;推送到达顺序不保证与业务因果严格一致,需客户端幂等与去重(可带 `period_no` / `order_no` / 时间戳)。
### 7.6 使用 Apipost 调试 WebSocket 与私有频道
Apipostv7+)支持 **WebSocket**:新建请求 → 选择 **WebSocket** → 类型选 **Raw**。私有频道遵循「先拿 `socket_id` → 再 HTTP 鉴权 → 再发 `pusher:subscribe`」,与 `vendor/webman/push/src/push.js` 行为一致。
**A. 仅调试公共频道(如 `public-game-period`**
1. 启动 webman 与 push 进程,确认 `config/plugin/webman/push/app.php``websocket``app_key`
2. 在 Apipost 中 WebSocket URL 填:`ws://127.0.0.1:3131/app/{app_key}`(将 `{app_key}` 换成配置中的真实值)。
3. 点击连接,在消息面板应收到一帧 `pusher:connection_established`,从中取出 `socket_id`(公共订阅可不依赖后续步骤,但便于对照协议)。
4. 在发送框填入一行 JSON勿带代码块标记并发送
`{"event":"pusher:subscribe","data":{"channel":"public-game-period"}}`
5. 成功时随后会收到 `pusher_internal:subscription_succeeded`;之后服务端向该频道 `trigger` 的事件会出现在消息列表中。
**B. 调试用户私有频道 `private-user-{uuid}`**
1. 同上先连接,从首帧解析出 **`socket_id`**。
2. 新建 **HTTP** 请求:`POST http://{你的HTTP入口}/plugin/webman/push/auth`
- Header`Content-Type: application/x-www-form-urlencoded`
- Bodyx-www-form-urlencoded`channel_name=private-user-{替换为真实uuid}&socket_id={上一步的socket_id}`
- 若鉴权已接入 `user-token`,请在 Header 中一并带上与移动端一致的 **`user-token`**(及 `auth-token` 等),否则会得到 `403` 或无效签名。
3. 将接口返回的 **JSON 正文**(整段)作为 `pusher:subscribe``data`:在 Apipost WebSocket 发送
`{"event":"pusher:subscribe","data": <上一步响应 JSON 对象>}`
注意:`push.js` 会把鉴权返回与 `channel` 字段合并后再发送;若手搓 JSON需保证与官方协议一致`auth` 字段)。
4. 订阅成功后即可在消息面板等待该私有频道上的业务事件。
**说明**:若仅做协议连通性验证,可暂时使用服务端对鉴权接口的占位实现;**上线前**必须落实「`channel_name` 与当前用户 `uuid` 匹配」校验,避免越权订阅。
- 倒计时以服务端下发时间为准,不信任本地时钟累计。
- 下注成功后以 `placeBet` 返回的 `balance_after` 为准,并等待 `wallet.changed` 同步。
- WebSocket 断线后立即重连并重新订阅主题,不再依赖 `currentStatus/periodHistory/balanceSummary` 回补。
---
@@ -772,13 +721,10 @@ Apipostv7+)支持 **WebSocket**:新建请求 → 选择 **WebSocket** →
1. `GET /api/v1/authToken?secret=xxx&timestamp=xxx&device_id=xxx&signature=xxx` 获取 `auth-token`
2. `POST /api/user/login` 登录(请求头带 `auth-token`
3. `POST /api/game/lobbyInit` 拉首页初始化(请求头带 `auth-token`
3. 建立 webman/push 连接并订阅:
- `public-game-period`
- `private-user-{user.uuid}``uuid` 取自登录/档案接口,与 7.1 一致)
4. 收到 `period.tick` 实时刷新倒计时
5. 用户下注调用 `POST /api/game/betPlace`
6. 监听 `bet.accepted` + `wallet.changed` 更新下注结果和余额
7. 监听 `period.opened` 渲染开奖动画并刷新开奖记录
4. 建立 WebSocketH5连接发送订阅消息监听状态流
5. 用户下注调用 `POST /api/game/placeBet`
6. 下单后以 `placeBet.balance_after``wallet.changed` 同步余额
7. 断线或页面回前台时,重连 WebSocket 并重新订阅主题回补实时状态
## 8.2 充值到下注到提现闭环
1. 拉取档位:`POST /api/finance/depositTierList`(玩家选择一档,并记下该档 `channels[].code`
@@ -786,8 +732,8 @@ Apipostv7+)支持 **WebSocket**:新建请求 → 选择 **WebSocket** →
- 返回 `paid=false``status=pending`、**非空 `pay_url`**:客户端在 WebView/浏览器中打开 `pay_url``GET /api/finance/depositMockPayPage`);用户在模拟页点击确认后,由 `POST /api/finance/depositMockNotify` 完成入账,或轮询 `depositDetail` / 等 `wallet.changed` 再刷新余额
- 未来接真实第三方:将 `pay_url` 换为真网关,入账仅在支付平台 **异步通知** 中调用 `DepositSettlement::settle`(与当前 `depositMockNotify` 路径一致)
3. 客户端可选轮询 `POST /api/finance/depositDetail` 兜底确认状态;入账成功后会收到 `wallet.changed`
4. 下注:`POST /api/game/betPlace`
5. 派彩后收到 `wallet.changed`
4. 下注:`POST /api/game/placeBet`
5. 监听余额:`wallet.changed`(或按订单详情接口核对)
6. 查询流水:`POST /api/wallet/recordList`
7. 提现:`POST /api/finance/withdrawCreate`(即时冻结 `user.coin` 与写出 `withdraw` 流水) -> `POST /api/finance/withdrawDetail`
@@ -799,22 +745,20 @@ Apipostv7+)支持 **WebSocket**:新建请求 → 选择 **WebSocket** →
---
## 9. 游戏时序流程图(接口 + 推送
## 9. 游戏时序流程图(WebSocket + HTTP兜底
```mermaid
flowchart TD
A[用户登录 /api/user/login] --> B[拉初始化 /api/game/lobbyInit]
B --> C[连接webman/push并订阅频道]
C --> D[收到 period.tick 倒计时]
D --> E{0-20秒下注期?}
E -- 是 --> F[提交下注 /api/game/betPlace]
F --> G[推送 bet.accepted + wallet.changed]
E -- 否 --> H[进入封盘状态 period.locked]
H --> I[服务端算票与开奖]
I --> J[推送 period.opened]
J --> K[客户端开奖动画与结果展示]
K --> L[客户端刷新开奖记录 /api/game/periodHistory]
L --> D
B --> C[连接 WebSocket 并订阅主题]
C --> D{0-20秒下注期?}
D -- 是 --> E[提交下注 /api/game/placeBet]
E --> F[等待 wallet.changed 同步余额]
D -- 否 --> G[进入封盘与开奖阶段]
G --> H[服务端算票与开奖]
H --> I[WebSocket 推送状态变化]
I --> J[断线重连并重新订阅]
J --> C
```
---
@@ -874,7 +818,7 @@ flowchart TD
1. **登录方式**:仅账号密码,还是要短信/邮箱验证码?
2. **提现收款类型**:首版只做银行卡,还是同时支持电子钱包/加密地址?
3. **自动托管**:是否首期上线;若不上线可先隐藏 `auto-bet` 接口。
4. **push事件最小集**:是否先只上 `period.tick``period.opened``wallet.changed` 三类
4. **WebSocket 主题定义**:状态流、资金流、托管流的 topic 与消息体是否按本文固定
5. **错误码规范**:是否已有公司统一错误码表;若有需对齐替换本草案码段。
确认后可进入下一步:按该文档落地 controller + validate + service + 路由。

View File

@@ -103,7 +103,7 @@
- 各种纯函数派生逻辑
- 包括格子 view model、倒计时、公告筛选、趋势计算、下注汇总等
#### [src/features/game/shared/index.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/index.ts)
#### [src/features/game/shared/untils.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/index.ts)
新增内容:
-`shared` 子模块统一导出
@@ -114,7 +114,7 @@
- 并进一步按模块拆为子目录:
- `src/store/auth`
- `src/store/game`
- `src/features/game/model/index.ts` 现在仅作为过渡导出层,用于维持 `features/game` 对外接口不变
- `src/features/game/model/untils.ts` 现在仅作为过渡导出层,用于维持 `features/game` 对外接口不变
#### [src/store/game/game-round-store.ts](/Users/jiaunun/Desktop/36-character-flower/src/store/game/game-round-store.ts)
新增内容:
@@ -138,20 +138,20 @@
- 认证相关 store
- 原有 `auth-store` 已归入 `auth` 子目录
#### [src/store/auth/index.ts](/Users/jiaunun/Desktop/36-character-flower/src/store/auth/index.ts)
#### [src/store/auth/untils.ts](/Users/jiaunun/Desktop/36-character-flower/src/store/auth/index.ts)
说明:
- 统一导出认证模块 store
#### [src/store/game/index.ts](/Users/jiaunun/Desktop/36-character-flower/src/store/game/index.ts)
#### [src/store/game/untils.ts](/Users/jiaunun/Desktop/36-character-flower/src/store/game/index.ts)
说明:
- 统一导出游戏模块 store
#### [src/store/index.ts](/Users/jiaunun/Desktop/36-character-flower/src/store/index.ts)
#### [src/store/untils.ts](/Users/jiaunun/Desktop/36-character-flower/src/store/index.ts)
新增内容:
- 统一导出 `src/store` 下各模块
- 当前包括 `auth``game`
#### [src/features/game/model/index.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/model/index.ts)
#### [src/features/game/model/untils.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/model/index.ts)
新增内容:
- 作为过渡导出层,继续对 `features/game` 暴露游戏 store
@@ -167,7 +167,7 @@
- 包括 bootstrap、round feed、announcement 的响应映射
- 提供 `getMockGameBootstrap()` 用于当前阶段 UI 接线
#### [src/features/game/api/index.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/api/index.ts)
#### [src/features/game/api/untils.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/api/index.ts)
新增内容:
-`api` 子模块统一导出
@@ -230,13 +230,13 @@
- 桌面端游戏页壳层
- 负责多栏编排
#### [src/features/game/components/index.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/components/index.ts)
#### [src/features/game/components/untils.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/components/index.ts)
新增内容:
- 对组件模块统一导出
### 3.8 游戏入口与总导出
#### [src/features/game/entry/game-route-page.tsx](/Users/jiaunun/Desktop/36-character-flower/src/features/game/entry/game-route-page.tsx)
#### [src/features/game/entry/entry-page.tsx](/Users/jiaunun/Desktop/36-character-flower/src/features/game/entry/game-route-page.tsx)
新增内容:
- 游戏路由页适配层
- 负责:
@@ -247,7 +247,7 @@
- 接公告弹窗、自动托管遮罩
- 使用 i18n 文案
#### [src/features/game/index.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/index.ts)
#### [src/features/game/untils.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/index.ts)
新增内容:
-`game` 功能模块统一导出
@@ -262,7 +262,7 @@
### 4.1 基础常量与全局信息
#### [src/constants/index.ts](/Users/jiaunun/Desktop/36-character-flower/src/constants/index.ts)
#### [src/constants/untils.ts](/Users/jiaunun/Desktop/36-character-flower/src/constants/index.ts)
修改内容:
- 将应用名称从通用模板名改为 `36字花`
- 更新默认描述文案
@@ -325,7 +325,7 @@
### 5.1 修复 `/$lang/game` 的循环更新错误
涉及文件:
- [src/features/game/entry/game-route-page.tsx](/Users/jiaunun/Desktop/36-character-flower/src/features/game/entry/game-route-page.tsx)
- [src/features/game/entry/entry-page.tsx](/Users/jiaunun/Desktop/36-character-flower/src/features/game/entry/game-route-page.tsx)
修复内容:
- 之前直接把会返回新引用的派生 selector 传给 Zustand hook导致 React 触发无限更新
@@ -336,7 +336,7 @@
### 5.2 清理页面里的硬编码双语判断
涉及文件:
- [src/features/game/entry/game-route-page.tsx](/Users/jiaunun/Desktop/36-character-flower/src/features/game/entry/game-route-page.tsx)
- [src/features/game/entry/entry-page.tsx](/Users/jiaunun/Desktop/36-character-flower/src/features/game/entry/game-route-page.tsx)
- [src/routes/$lang/route.tsx](/Users/jiaunun/Desktop/36-character-flower/src/routes/%24lang/route.tsx)
- [src/locales/zh-CN/common.ts](/Users/jiaunun/Desktop/36-character-flower/src/locales/zh-CN/common.ts)
- [src/locales/en-US/common.ts](/Users/jiaunun/Desktop/36-character-flower/src/locales/en-US/common.ts)