Files
webman-buildadmin/docs/36字花-数据库与实施计划.md
2026-05-26 18:44:42 +08:00

494 lines
35 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 「36字花」数据库与实施计划
**文档版本**V1.16
**依据**《36字花 PRD》《业务流程说明书》《后端系统规格书》及现有表 `user`
**目标**:明确分阶段落地步骤、需新建表、两表适配方向与可执行验证清单。
**DDL 脚本(可执行)**[database/dfw_36zihua_schema_v1.sql](../database/dfw_36zihua_schema_v1.sql)
内含:新建 `channel` 表,及 `user` / `admin` / `admin_group``ALTER` 语句,以及新建表完整 `CREATE TABLE`(字段级 `COMMENT` 即字段清单)。
---
## 一、现状与表定位
| 表名 | 当前角色 | 目标角色 |
|------|----------|----------|
| `channel` | 新渠道主表 | **顶级代理渠道分红配置表**:由超管创建,维护分红方式、分红金额、总利润等渠道参数 |
| `user` | 用户coin、channel_id 等) | **C 端玩家主表**:余额与精度、归属代理、流水与风控字段 |
| `admin` | 后台管理员 | **子代理承载表**:顶级代理下级代理放在 `admin`,通过 `invite_code` 管理客户,统一无开奖控制权 |
| `admin_group` | 角色组 | **按渠道隔离**:角色组归属 `channel`,渠道仅管理本渠道角色组 |
### 1.1 全局对局与渠道职责(重要)
与「多渠道」并存的一条硬规则:**对局与开奖全局唯一**,渠道**不**切分牌桌、**不**各自开奖。
| 维度 | 口径 |
|------|------|
| **期号 / 对局** | **全平台共用一套** `game_period`(及全网唯一的当前 `period_no`、同一套状态机)。不存在「每个渠道一局」或「每渠道独立期号表」。 |
| **开奖结果** | **全渠道玩家共享同一期、同一 `result_number`**。所有玩家(无论来自哪个 `channel_id`)压的是**同一场**;避免用户感知「不同入口有不同局、可被渠道操纵」。 |
| **渠道的用途** | `channel``user.channel_id`、注单上的 **`channel_id` 快照**(若有)仅用于 **代理归属、分润、风控与后台数据范围****不**用于生成多套并行对局或独立开奖。 |
| **Redis / 接口** | 当前期倒计时、封盘、算票、开奖号码等 **热状态全局一份**;不得在业务上按渠道维护多套「当前期」或多套开奖结果。**已实现2026-04**`GameHotDataRedis`**`user` 全行、`game_config` 按 key、`game_record`(活跃局 / 按 id / 最新一行)** 以 JSON 缓存在 Redis键前缀 `dfw:v1:`),配置见 `config/game_hot_cache.php``.env-example``GAME_HOT_CACHE_*`;与 `config/cache.php``CACHE_DRIVER`(系统表 `config` 文件缓存)**相互独立**。 |
> **与 DDL 的对应**`game_period` **不设** `channel_id``bet_order.channel_id` 为下单时用户归属快照,不改变「全场一局」语义。详见 §11.5。
---
## 二、分阶段执行计划与「先核心、后细节」顺序
**原则**:先打通 **账号 / 渠道 / 余额与流水 / 最小可演示闭环**,再叠 **玩法细则、自动开奖调度、公告与站内信等展示类能力**。避免一上来就做全量 DDL 与全部后台菜单,导致联调面过大。
### 2.1 总览(与下文 P0P4 对应)
| 阶段 | 目标 | 主要内容 |
|------|------|----------|
| **P0** | 数据地基 | 新建 `channel` 并适配 `user``admin``admin_group`;建立账本类最小表集(金额精度统一) |
| **P1** | 游戏核心 | 期号、注单、开奖、系统配置;**Redis 热点读缓存user / game_config / game_record已落地**;可选 MQ 异步落库等后续增强 |
| **P2** | 资金与风控 | 充提订单、流水账、提现审核、Jackpot / 大额拦截 |
| **P3** | 代理与结算 | 流水占比分桶、级差、联营占成与负结转(表结构 + 跑批骨架) |
| **P4** | 运营与审计 | 公告(含 Pop-out、站内信、后台 RBAC 与操作审计 |
### 2.2 建议先做的:第一批建表(核心路径)
按依赖顺序执行 DDL或 Phinx**优先保证下列表/变更已落地**,其余表可分期补建:
| 顺序 | 类型 | 对象 | 说明 |
|------|------|------|------|
| 1 | 新建 | **`channel`** | 渠道与顶级代理参数;替代历史 `game_channel` 方向 |
| 2 | 适配 | **`user``admin``admin_group`** | `coin` 精度、`channel_id`、邀请码与风控等(见 §四~§六) |
| 3 | 新建 | **`game_config`** | 全局可调参数(局时长、下注窗口等),避免写死 |
| 4 | 新建 | **`user_wallet_record`** | 玩家钱包流水,与余额变更同事务、可审计 |
| 5 | 新建 | **`game_period`**、**`bet_order`** | 最小「一期号 + 注单」闭环;先有表再写状态机与接口 |
**第一批可暂缓的表(归入后续迭代)**`game_bet_auto`(自动托管)、`operation_notice` / `user_notice_read` / `user_site_message`(纯展示与触达)、`game_agent_wallet` 及结算域各表(代理分佣与联营跑批)。
### 2.3 建议先做的:第一批后台菜单(与核心能力对齐)
在 BuildAdmin **`admin_rule`** 中,**优先保证**与下列能力相关的菜单与按钮权限可配置(具体 `component` 路径以仓库为准):
| 优先级 | 菜单能力 | 目的 |
|--------|----------|------|
| 高 | **渠道**、**游戏用户**、**角色组 / 管理员**(含渠道与邀请码相关字段) | 搭好「谁管哪条线、玩家归谁」 |
| 高 | **用户管理 / 用户钱包流水** | 覆盖玩家主数据与账务对账 |
| 高 | **游戏对局 / 压注订单** | 核心玩法与对账入口 |
| 中 | **游戏配置**(侧栏目录名):**常规配置**`game_config` 通用 KV列表默认每页 50 条,不含 `deposit_tier` / `streak_win_reward` / `zi_hua_36_dictionary`)、**连胜奖励**、**充值档位**、**36字花字典** | 运营参数与字典维护 |
| 中 | **充值订单 / 提现订单** | 充提流程管理与审核 |
| 低 | **公告 / 站内信**、**代理结算** 等 | 属 **P3P4**,核心跑通后再接 |
### 2.4 明确放到「细节阶段」的能力(勿阻塞第一期)
下列项依赖 **P1 状态机、定时任务、前端 C 端页面** 较完整后再做,避免与「账号 + 余额 + 最小下注」抢工期:
- **玩法细则**选号上限、连胜倍率、Jackpot 条件等在 `game_config` 与代码中逐步细化即可。
- **自动开奖 / 调度**依赖期号服务、Redis 与可选MQ表结构可先建**调度与算票逻辑后迭代**。
- **游戏公告、强弹窗、站内信展示**:表可后建;**后台编辑 + C 端展示** 属于运营体验增强,放在核心闭环之后。
### 2.5 最小可验收里程碑(建议)
1. **P0 完成**:能创建渠道与子代理管理员,玩家归属正确,`coin``user_wallet_record` 手工或脚本入账可对上。
2. **P1 骨架完成**:能创建期号、写入注单、产生钱包流水(即使开奖仍为**手动或脚本模拟**)。
3. 再推进 **自动流程、充提、公告展示****P3 结算**
### 2.6 本次重构迁移顺序(已执行口径)
1. 新建订单表:`deposit_order``withdraw_order`(带 `order_no` 唯一索引、`user_id/status/create_time` 常用索引)。
2. 硬重命名:`game_user -> user``game_bet_order -> bet_order`
3. 重建菜单与权限目录:`user``order``game``config``record`
4. 新增菜单节点:
- `user/user`
- `order/betOrder``order/depositOrder``order/withdrawOrder`
- `game/period`
- `config/gameConfig``config/ziHuaDictionary`
- `user/userWalletRecord`
5. 清理收口:删除迁移过程中的冗余权限别名规则,仅保留最终模块节点(`user/order/game/config/record`)。
6. 运营模块:`operation_notice``user_notice_read` 表与后台目录 **`operation`**(子菜单 `operation/operationNotice``operation/userNoticeRead`)。
### 2.7 `game_config` 连胜与派彩2026-04 起)
| `config_key` | 说明 |
|--------------|------|
| `streak_win_reward` | JSON`rows[]` 每项含 `streak`110`odds_factor`(与 33 相乘为整段赔率)、`is_jackpot`(是否大奖)。派彩公式:`total_amount × odds_factor × 33`。默认第 10 档 `is_jackpot=true`。 |
| `deposit_tier` | 仍由「充值档位」独立菜单维护,**不出现在**「常规配置」列表。 |
开奖结算后更新 **`user.current_streak`**:本期有中奖注单则 `min(streak_at_bet+1, 10)`,否则 **连胜归 0**(无档位配置)。**中奖 WebSocket同一结算批次**(实现:`GameBetSettleService::publishSettlementWinsAfterCommit`
- 向相关用户推送 **`bet.win`**(小奖/大奖统一;**个人中奖弹窗只认此主题**)。载荷含 `total_win``balance_after``bets[]``is_win=true`,并合并 `current_streak` / `streak_level` / `odds_factor` / **`is_jackpot`**(是否**大奖档**,由 `streak_at_bet` 对应 `streak_win_reward.is_jackpot` 决定,非 `bet.accepted` 的下注时展示含义)。
- 若存在大奖档命中,**再**向公共频道推送 **`jackpot.hit`**`hits[]` 每项含 `user_id`、**`nickname`**、`period_no``total_win``result_number`),供全站跑马灯;**个人弹窗仍以 `bet.win` 为准**。
- **去重**`user.streak` / `wallet.changed` / `jackpot.hit` 使用 `dfw:v1:settle:notify:{period_id}`**`bet.win` 独立** `dfw:v1:ws:betwin:{period_id}:{user_id}`,避免整期 dedup 吞掉中奖推送。
- **补偿**:库内已结算中奖但内存未聚合时,从 `bet_order` 重建并补发;运维可用 `php scripts/republish_bet_win.php`(见移动端草案 §7.1.4)。
- **大奖审核**`win_amount >= jackpot_max_amount` 时注单可先 `status=待审核`,仍推 `bet.win`;后台审核通过后再推一次 `bet.win``approveJackpot`)。
> **派彩期间 `period.tick` 静默规则**:开奖到派彩宽限期结束(`status=payouting`)期间**不再推送 `period.tick`**,避免覆盖中奖动画;本期进入 `finished`/`void` 时各推一帧边界帧每期号每状态去重Redis Key `dfw:v1:ws:tick:boundary:{period_no}:{status}`TTL 300s下一期 `betting` 时恢复每秒推送。详见《36字花-移动端接口设计草案》§7.1.3。
---
## 三、`channel` 设计(替代 `game_channel`
### 3.1 建议保留字段
`id``code`(可作渠道码)、`invite_code``name``status``remark``admin_id``admin_group_id``create_time``update_time`
### 3.2 建议新增或调整(按你确认口径)
| 方向 | 说明 |
|------|------|
| 渠道负责人 | `admin_id`:渠道对应一名管理员(`admin.id`),权限与数据范围以该账号为准;不再单独维护 `top_admin_id` |
| 代理模式参数 | `agent_mode``turnover` 普通刷水 / `affiliate` 联营)、`turnover_share_rate``affiliate_share_rate``affiliate_fee_rate``carryover_balance` |
| 渠道经营指标 | `profit_amount`(精度升级)、`total_profit_amount``commission_pool_amount` |
| 邀请码参数 | 渠道不生成邀请码,邀请码由管理员自动生成并用于注册归属 |
| 代理钱包 | 余额可字段扩展或独立 `game_agent_wallet`(推荐独立表,便于对账) |
### 3.3 注意
`channel` 不承担子代理树结构;子代理层级与邀请码归属下沉到 `admin`。除超管外,渠道管理仅可查看当前管理员归属渠道。
---
## 四、`user` 适配(用户表)
### 4.1 建议保留字段
`id``username` / `phone``password``uuid``head_image``channel_id`(归属渠道)、`status``create_time``update_time`
### 4.2 建议新增或调整
| 方向 | 说明 |
|------|------|
| 金额精度 | `coin` 调整为 **`decimal(18,2)`**(与规格书一致,禁止用浮点存币) |
| 注册与归属 | `invite_code` 或注册时解析 URL 与 `channel.code` 绑定 |
| 提现门槛 | `user.total_deposit_coin` / `user.total_withdraw_coin` / `user.bet_flow_coin` + `game_config.withdraw_bet_flow_ratio`(净充值打码口径,全项目统一) |
| 风控 | 禁止登录 / 禁止下注 / 禁止提现等,可用位标记或独立布尔字段 |
| 连胜持久化 | 可选 `current_streak``last_bet_period_id`;高频仍以 **Redis** 为准DB 作兜底同步 |
| 邮箱 | PRD 支持手机或邮箱注册时,可增加可空字段 `email`(是否唯一索引按产品定) |
---
## 五、`admin` 适配(子代理承载)
| 方向 | 说明 |
|------|------|
| 层级关系 | `parent_admin_id` 表示上级代理 |
| 渠道归属 | `channel_id` 表示该子代理属于哪个顶级渠道 |
| 邀请管理 | `invite_code` 自动生成且全局唯一,用于发展玩家并做归属绑定 |
| 角色标识 | `agent_role`(如 `agent_admin` / `sub_agent` / `staff` |
| 分红设置 | 不再使用 `admin` / `admin_group` 分红字段;统一改为渠道维度结算后按 `channel_admin_share` 二次分配 |
| 开奖权限 | 不在数据层开放给渠道/子代理;开奖权限仅由超管 RBAC 控制 |
### 5.1 分红计算口径(现行)
- 渠道分红:先按 `channel.agent_mode` 计算渠道总佣金
- 管理员分红:再按 `channel_admin_share.share_rate` 对渠道总佣金进行二次分配
- 角色组仅用于权限与数据范围,不再参与金额拆分
---
## 六、`admin_group` 适配(角色组仅归属渠道)
| 方向 | 说明 |
|------|------|
| 渠道归属 | 增加 `channel_id` 字段,角色组只属于一个渠道 |
| 管理边界 | 渠道管理员只能增删改查本渠道 `admin_group` |
| 系统角色组 | `channel_id` 可为空表示系统级(仅超管可见) |
---
## 七、需新建的核心表
表名可按项目命名规范微调,须小写加下划线。
### 7.1 游戏引擎
**对局范围**:与 §1.1 一致——**全平台一套期号**,不按渠道分桌;详见 `game_period``channel_id` 的 DDL。
| 表名 | 用途 |
|------|------|
| `game_period`(或 `game_issue` | **全局**期号、状态机阶段、开奖号码、自动/手动、作废标记(**非**每渠道一局) |
| `bet_order` | 注单:关联全局 `period_id`;可选 `channel_id` 为用户归属快照(分润/查询),**非**独立牌桌 |
| `game_bet_auto`(可选) | 自动托管:剩余局数、选号快照、启停状态(仍挂在全局期号下) |
### 7.2 系统配置
| 表名 | 用途 |
|------|------|
| `game_config`(或统一 `system_config_kv` | 局时长、下注时长、选号上限、赔率步长、Jackpot 参数、RTP 放水、提现倍数与手续费等(须 DB 可配,禁止写死) |
### 7.3 资金与账本(强烈建议)
| 表名 | 用途 |
|------|------|
| **`user_wallet_record`**(原草案名 `user_wallet_ledger`,以 DDL 为准) | **玩家游戏币钱包流水**:充值、提现(含冻结/解冻)、平台划入划出、管理员加扣币、下注、派彩、手续费、作废退款、调账等;金额 **`decimal(18,2)`****只增不改**;与 `user.coin` 变更须同事务 + 条件更新 |
| `deposit_order` | 第三方充值、法币金额、汇率、游戏币到账、回调状态 |
| `withdraw_order` | 提现申请、手续费、审核状态、Jackpot / 大额标记 |
### 7.4 代理与结算
| 表名 | 用途 |
|------|------|
| `agent_settlement_period` | 结算周期、大盘盈亏快照 |
| `agent_commission_record` | 流水占比分桶结果、级差拆分、发放状态 |
| `affiliate_contract`(可选) | 联营契约、占成比例、阶梯条件 |
| `affiliate_carryover`(或与佣金记录合并设计) | 联营负结转余额与流水 |
### 7.5 运营
| 表名 | 用途 |
|------|------|
| `operation_notice` | 公告类型(静默 / Pop-out、内容 |
| `user_notice_read` | 用户已读 / 强弹窗已确认 |
### 7.6 审计(按需)
若现有 `admin_log` 不足以覆盖财务与风控操作,可增补结构化审计表。
### 7.7 冷热分离(中后期)
历史注单与流水检索迁移至 **ElasticSearch 或 ClickHouse**,主库保留近期热数据与归档策略。
---
## 八、验证步骤
### 8.1 数据库与模型
1. DDL 执行后检查:金额字段均为 **`decimal(18,2)`**`channel``user``admin``admin_group`、期号等关联字段有合理索引。
2. 创建测试渠道(顶级)→ 创建子代理 `admin`(设置 `parent_admin_id``channel_id``invite_code`)→ 创建用户并挂载 `channel_id`,链路与后台筛选正常。
3. 扣款更新采用「**条件更新**」语义(如 `WHERE balance >= 扣款额`),压测或单测验证**不出现负余额**。
### 8.1.1 菜单与权限回归(本次新增)
1. 使用超管登录,确认五大目录 `user/order/game/config/record` 可见。
2. 使用普通角色登录,逐项验证按钮权限(`index/add/edit/del/save`)是否与授权一致。
3. 抽查重点页面:
- `user/user`
- `order/depositOrder``order/withdrawOrder``order/betOrder`
- `game/period`
- `config/gameConfig``config/ziHuaDictionary`
- `user/userWalletRecord`
- `operation/operationNotice``operation/userNoticeRead`
4. 验证 `config/ziHuaDictionary` 的读取与保存权限均命中,且仅授权角色可操作。
### 8.2 业务规则(对照 PRD / 业务流程)
| 场景 | 验证要点 |
|------|----------|
| 注册与邀请 | 玩家使用子代理邀请码注册时,先命中 `admin.invite_code`,再落到对应 `channel_id` |
| 子代理权限 | 渠道与子代理账号均无开奖权限;仅超管角色可访问开奖控制接口 |
| 30 秒节奏 | 020s 可下注20s 后拒绝;约 22s 后可查开奖结果 |
| 连胜与跳局 | 连续期号未下注则连胜清零;连赢时本轮总下注不超过上轮总下注 |
| Jackpot | 连胜达阈值且单局下注不低于配置最小额才触发额外大奖 |
| 提现 | 有效投注 ≥ 总充值×配置倍数;最低提现与 0.5% 手续费;大额 / Jackpot 进审核 |
| 灾难恢复 | 模拟期卡在「计算中」,启动退本流程:期作废、本金退回账本 |
#### 8.2.1 后台「游戏实时对局」:运行开关与作废
| 项 | 说明 |
|----|------|
| 配置键 | `game_config.config_key = game_live_runtime_enabled``1` = 运行(默认),`0` = 维护/关闭 |
| 关闭时服务端行为 | **禁止下注**(移动端 **`betPlace`** 返回 `3001`**无进行中局时**定时 **`GamePeriodAutoTicker`** 不创建新期;派彩宽限期结束后的 **`createNextRecordAfterDraw`** 不插入下一期。**当局仍继续****`tickAutoDraw` / `drawResult` / 结算**照常执行,直至本期结束。后台 **`POST /admin/game.Live/runtime``enabled=1`** 时,若 **`hasActiveRecord()` 为假**,则 **`bootstrapPeriodWhenRuntimeEnabled`** 立即插入新一期 |
| 后台快照 `maintenance_ui` | `!game_live_runtime_enabled && !hasActiveRecord()` 时为 `true`:表示**当局已完全结束**(含派彩),此时后台页展示「维护中」并锁定操作区(仅顶部「游戏运行」开关可用);当局尚在 03 状态时为 `false`,倒计时与操作区保持可用直至收尾完成 |
| 作废本局(后台按钮) | 仅当本期为 **下注开放 / 已封盘**`game_record.status``0``1`):将所有 **待开奖** 注单(`bet_order.status = 1`)按 `total_amount` 退回余额并置 `bet_order.status = 3`,写钱包流水 `biz_type = bet_void`;本期 **`game_record.status = 5`**,写入 **`void_reason`**;并 **强制将 `game_live_runtime_enabled` 置为 `0`**。需管理员在后台再次打开「游戏运行」开关后,才恢复下注与后续期次创建 |
| 后台接口 | `POST /admin/game.Live/runtime`body`enabled` 0/1`POST /admin/game.Live/voidPeriod`body`record_id` 可选、`void_reason` 必填) |
| 实时快照 HTTP | `GET /admin/game.Live/snapshot`**只读** `buildSnapshot`,不执行 `recoverLiveRoundState`,避免接口超时;对局自愈/自动开奖由 **`gameLiveTicker`**(每秒 `publishSnapshot`)与 `drawResult` 链路负责 |
| WebSocket | `GET /admin/game.Live/wsConfig` 返回 `ws_url` 与推荐 `subscribe_topics`(含 `admin.live.snapshot``bet.win` 等);`admin.live.snapshot` 由 WS 进程每秒直推(有订阅者时) |
| WS 地址 | `WebSocketConfigHelper``.env``H5_WEBSOCKET_URL``127.0.0.1` 且请求 Host 非本机时自动改用 `ws(s)://{host}/ws/`;生产需 Nginx 将 `/ws/` 反代至 **3131** |
#### 8.2.2 WebSocket 主题与 `bet.win`(联调清单)
| 主题 | 触发 | 移动端 |
|------|------|--------|
| `bet.accepted` | 下注成功 | 扣款确认;`is_jackpot` 为下注时档位 |
| `bet.win` | 开奖结算后中奖 | **中奖弹窗**`is_jackpot` 为大奖档 |
| `jackpot.hit` | 本期有大奖档命中 | 全站公告(可选) |
| `wallet.changed` | 余额变动 | 含 `biz_type=payout` 派彩 |
| `user.streak` | 每期结算后 | 连胜更新 |
详见《36字花-移动端接口设计草案》§7.1.3、§7.1.4。
### 8.3 代理与结算(逻辑就绪后)
1. 构造多代理树与多用户下注,跑一期结算脚本或单元测试纯算法。
2. **大盘亏损**:本期代理分佣为 0。
3. **大盘盈利**:流水占比分桶 + 级差,各级金额之和与线总包一致(可对照文档数值验算)。
4. **联营**:客损为负产生负结转;下期盈利先抵扣再分佣。
### 8.3.1 渠道结算新流程2026-04-23
1. **仅超管可结算**:按渠道结算周期(支持自动任务与手动提前结算)执行渠道结算。
2. **结算即发放**:结算时按 `channel_admin_share` 比例,直接发放到管理员钱包并写入 `admin_wallet_record``commission_income`),同时写 `agent_settlement_period` / `agent_commission_record`
3. **提前结算规则**:手动提前结算后,新的周期起点从本次结算结束时间开始,后续自动周期归入下个结算段。
4. **停用渠道限制**`channel.status != 1` 时,该渠道不再允许玩家注册与登录。
### 8.3.2 后台管理员资金与提现流程2026-04-23
1. **管理员钱包隔离**:新增 `admin_wallet``admin_wallet_record`,与玩家钱包完全隔离。
2. **分红入账**:渠道分红结算后,写管理员钱包入账流水(`commission_income`)。
3. **提现申请**:管理员在个人中心发起提现,金额先冻结(`withdraw_freeze`),生成 `admin_withdraw_order``status=0`)。
4. **渠道超管审核**:仅该渠道顶级角色组(`admin_group.pid=0`)中的管理员可审核本渠道提现单。
5. **审核通过/拒绝**:通过则扣减冻结并累计提现(`withdraw_success`);拒绝则退回可用余额(`withdraw_refund`)。
### 8.4 非功能
- **Redis已落地**
- **热点数据缓存**`app/common/service/GameHotDataRedis.php`,依赖 `webman/redis``config/redis.php`。缓存对象:`user` 行(鉴权与余额类读路径)、`game_config` 行(按 `config_key`)、`game_record`(活跃局、按 id、最新一条。**写库后一致性**:统一经 **`GameHotDataCoordinator`**`afterUserCommitted` / `afterGameConfigKeyCommitted` / `afterGameRecordCommitted`)先 **同步回源**`userReplaceCacheFromDb``gameConfigReplaceFromDb``gameRecordSyncCachesAfterDbWrite`),再视配置将幂等任务写入 **`GameHotDataWriteQueue`**,由进程 **`GameHotDataQueueConsumer`** 批量消化以削峰。互斥:**`GameHotDataLock`** 用于同一用户、同一 `game_config` 键、同一对局记录等资源的并发写串行化(后台钱包加减点、独立配置表单、开奖相关服务、**移动端 `betPlace` 扣款**等与后台共用用户锁)。环境变量 `GAME_HOT_CACHE_*` 控制开关、TTL、队列开关与背压`.env-example``config/game_hot_cache.php`)。
- **规划/增强**(未替代上述):当前期注单池、近 30 期开奖列表缓存、纯 Redis 状态机等,可按压测需求迭代。
- **与 `CACHE_DRIVER`**`config/cache.php` 默认 `file` 仅影响 **系统配置表 `config`**(如 `get_sys_config`**不**控制 `GameHotDataRedis`
- MQ派彩异步消费**幂等**(如 `period_id` + 用户 + 业务单号)。
- API下注、提现等核心接口**限流**生效。
---
## 九、风险与依赖
1. **子代理数据源**:子代理统一在 `admin`,避免在 `channel` 重复建树造成双主数据源。
2. **现有 `profit_amount`decimal(5,2)**:与游戏币 **18,4** 精度不一致,演进时改为 `decimal(18,2)` 或迁移至结算域,避免对账误差。
3. 文档要求 **AI 算票在 Redis 内完成**(演进目标),当前实现以 **MySQL `game_record` + 服务层缓存** 为主;主库仍应避免结算期大范围锁表;账本与注单以事务与幂等为准。
4. **全局对局一致性**:任何需求(多租户展示、渠道后台)均不得引入「按渠道独立期号/独立开奖」;若出现产品歧义,以 **§1.1** 为准,避免公平性质疑与客诉。
---
## 十、相关文档索引
| 文档 | 说明 |
|------|------|
| `docs/36字花prd.md` | 玩法、代理双轨、风控与性能要求 |
| `docs/业务流程.md` | C 端、代理、联营、总控、灾难恢复流程 |
| `docs/后端.md` | 状态机、API、后台模块、安全与精度 |
| `docs/CRUD生成逻辑说明.md` | BuildAdmin CRUD 路径与表名规范 |
| `database/dfw_36zihua_schema_v1.sql` | 具体 DDL字段、索引、注释 |
### 10.1 新建表一览(字段以 SQL 为准)
| 序号 | 表名 | 说明 |
|------|------|------|
| 1 | `game_config` | 动态参数 KV |
| 2 | `game_period` | 期号与状态机 |
| 3 | `bet_order` | 注单 |
| 4 | `game_bet_auto` | 自动托管 |
| 5 | `user_wallet_record` | 玩家游戏币钱包流水(替代旧名 `user_wallet_ledger` |
| 6 | `deposit_order` | 充值订单 |
| 7 | `withdraw_order` | 提现订单 |
| 8 | `game_agent_wallet` | 代理钱包 |
| 9 | `game_agent_wallet_ledger` | 代理钱包流水 |
| 10 | `agent_settlement_period` | 结算周期与大盘快照 |
| 11 | `agent_commission_record` | 代理佣金明细 |
| 12 | `affiliate_contract` | 联营契约 |
| 13 | `affiliate_carryover` | 联营负结转 |
| 14 | `operation_notice` | 运营公告 |
| 15 | `user_notice_read` | 公告已读/确认 |
| 16 | `user_site_message` | 站内信 |
**既有表变更**:新建 `channel` 替代 `game_channel``admin` 增加子代理字段(`parent_admin_id``channel_id``invite_code``agent_role`)用于代理邀请链路管理;`admin_group` 增加 `channel_id` 实现角色组按渠道隔离;`game_user` 已硬重命名为 `user``game_bet_order` 已硬重命名为 `bet_order``user_wallet_record``game_config` 保持现名。
---
**变更记录**
| 版本 | 日期 | 说明 |
|------|------|------|
| V1.0 | 2026-04-14 | 初稿:表适配、新建表清单、验证步骤 |
| V1.1 | 2026-04-14 | 增加可执行 DDL 脚本路径与新建表一览 |
| V1.2 | 2026-04-14 | 修正口径:`game_channel` 仅顶级分红参数,子代理迁移至 `admin` |
| V1.3 | 2026-04-14 | 收敛权限:仅超管可开奖,渠道/子代理仅拉用户 |
| V1.4 | 2026-04-14 | 新建 `channel` 替代 `game_channel``admin_group` 按渠道隔离 |
| V1.5 | 2026-04-15 | 落地 `game_user_wallet_record` 玩家钱包流水表;文档增补字段说明附录;与 DDL 统一命名 |
| V1.6 | 2026-04-15 | 增加「先核心后细节」实施顺序:先建表/菜单清单、可暂缓表与细节阶段能力;修正章节编号(验证步骤改为第八章) |
| V1.7 | 2026-04-15 | 明确「多渠道、单场对局」:全平台共用 `game_period` 与同一开奖;渠道仅归属/分润;附录 `game_period`/`bet_order` 注释对齐 |
| V1.8 | 2026-04-15 | §7.1 游戏引擎表与 §1.1 对齐:显式说明全局期号、`bet_order.channel_id` 仅为归属快照 |
| V1.9 | 2026-04-15 | 落地模块化重构:`game_user->user``game_bet_order->bet_order`;新增 `deposit_order`/`withdraw_order`;后台菜单重组为 `user/order/game/config/record` 五大目录 |
| V1.10 | 2026-04-15 | 完成表名与权限规则收口:`user_wallet_record``game_config` 保持不变;移除冗余 snake alias 菜单规则,文档口径与线上结构一致 |
| V1.11 | 2026-04-16 | 落地运营公告:`operation_notice``user_notice_read` 表与菜单目录 `operation`(运营公告、用户阅读记录) |
| V1.12 | 2026-04-18 | 下注口径:`bet_order` 仅保留 `total_amount`(整笔压注),删除 `unit_amount``pick_count`DDL 与 Phinx 迁移 `20260418270000_bet_order_drop_unit_amount_pick_count` 对齐 |
| V1.14 | 2026-04-20 | 服务端 Redis 热点缓存:`GameHotDataRedis``user` / `game_config` / `game_record``config/game_hot_cache.php``.env-example``GAME_HOT_CACHE_*`;更新 §1.1、§2.1、§8.4、第九章风险与依赖、附录 `user`;与 `CACHE_DRIVER`(系统 `config` 表文件缓存)区分说明 |
| V1.15 | 2026-04-20 | 热点写路径收口:`GameHotDataCoordinator` + `GameHotDataLock` + `GameHotDataWriteQueue` / `GameHotDataQueueConsumer`;文档与实现对齐(替代仅 `*Forget` 描述);移动端 `betPlace` 与后台钱包共用用户互斥锁及 `coin` 乐观更新 |
| V1.16 | 2026-04-23 | 渠道结算改为单阶段口径(仅超管结算,结算即按比例发放管理员钱包并记录操作人)与管理员钱包提现流程(`admin_wallet` / `admin_wallet_record` / `admin_withdraw_order`,渠道顶级组审核) |
---
## 十一、附录:主要表字段说明(与 `database/dfw_36zihua_schema_v1.sql` 同步)
以下为各表**字段含义与使用要点**,便于评审与联调;**以仓库内 DDL 为最终口径**。
### 11.1 `channel`(渠道 / 顶级代理分红参数)
| 字段 | 作用 |
|------|------|
| `id` | 主键 |
| `code` | 渠道标识,业务唯一 |
| `invite_code` | 渠道侧邀请码(与 PRD「邀请码由管理员生成」并存时以产品定义为准 |
| `name` | 渠道名称 |
| `agent_mode` | `turnover` 普通刷水 / `affiliate` 联营,决定分红与契约字段使用方式 |
| `profit_amount` / `total_profit_amount` / `commission_pool_amount` | 经营与分红池快照类金额,**decimal(18,2)** |
| `turnover_share_rate` / `affiliate_share_rate` / `affiliate_fee_rate` | 分红与联营费率类参数 |
| `carryover_balance` | 联营负结转余额(可负) |
| `admin_id` / `admin_group_id` | 渠道负责人(管理员)、渠道绑定的角色组 |
| `status` / `remark` / `create_time` / `update_time` | 状态、备注、时间戳 |
### 11.2 `user`C 端玩家)
| 字段 | 作用 |
|------|------|
| `coin` | 当前游戏币余额,**decimal(18,2)**,更新须条件更新防负余额 |
| `channel_id` | 归属渠道;历史 `game_channel_id` 若仍存在,迁移期注意双写/对照 |
| `register_invite_code` | 注册时邀请码快照,用于审计与归属 |
| `total_deposit_coin` / `total_withdraw_coin` | 累计充值入账、累计提现出账(提现受理时累加);与「净充值」口径配合校验提现门槛 |
| `bet_flow_coin` | 打码量/流水(历史名 `total_valid_bet_coin`2026-04-18 迁移重命名);开奖结算成功时按注单 `total_amount` 1:1 累加,提现门槛 `bet_flow_coin >= (total_deposit_coin - total_withdraw_coin) × withdraw_bet_flow_ratio` |
| `risk_flags` | 风控位(如禁止登录/下注/提现,按位定义) |
| `current_streak` / `last_bet_period_no` | 连胜与期号兜底;**读路径**可通过 **`GameHotDataRedis` 缓存 `user` 行** 降低压力,**写路径**以下注/结算后落库为准,并经 **`GameHotDataCoordinator::afterUserCommitted`** 同步刷新 Redis 与写队列入队 |
| `admin_id` | 归属子代理管理员 |
| 其余 | 账号、头像、状态、时间戳等见 DDL |
### 11.3 `admin` / `admin_group`(子代理与角色组)
| 表/字段 | 作用 |
|---------|------|
| `admin.parent_admin_id` | 子代理上下级 |
| `admin.channel_id` | 所属渠道 |
| `admin.invite_code` | 子代理邀请码,注册归属 |
| `admin.agent_role` | 角色类型(均无开奖权) |
| `admin_group.channel_id` | 角色组归属渠道;`NULL` 可为系统级(仅超管) |
| `channel_admin_share.share_rate` | 渠道内管理员分配比例(百分比,启用项合计=100 |
### 11.4 `game_config`(动态参数)
| 字段 | 作用 |
|------|------|
| `config_key` | 全局唯一键 |
| `config_value` / `value_type` | 参数值及类型(含 JSON |
| `remark` | 说明,禁止业务写死应读此表 |
### 11.5 `game_period` / `bet_order` / `game_bet_auto`
| 表 | 要点 |
|----|------|
| `game_period` | **全平台唯一**期号:`period_no` 全局唯一;`status` 状态机;开奖结果与作废原因。**无 `channel_id` 字段**:对局不按渠道拆分。 |
| `game_play_record`(兼容视图 `bet_order` | 游玩记录关联**全局** `period_id``channel_id` 为**用户/归属快照**,便于分润与查询,**不表示**独立牌桌或独立开奖。`pick_numbers` 为所选号码集合;**`total_amount` 为整笔游玩金额**(命中集合内任一开奖号码即按该金额参与派彩倍率计算)。已移除历史字段 `unit_amount` / `pick_count``idempotency_key` 幂等;金额 **18,4**`win_amount` / `jackpot_extra_amount` |
| `game_bet_auto` | 托管剩余局数、选号快照、抖动时间等;仍挂在**全局**期号下 |
### 11.6 `user_wallet_record`(玩家钱包流水)
| 字段 | 作用 |
|------|------|
| `user_id` | 玩家 `user.id` |
| `channel_id` | **账务发生时**渠道快照,便于按渠道查询与对账;入账逻辑应写入 |
| `biz_type` | 业务类型:`deposit``withdraw``platform_in``platform_out``admin_credit``admin_deduct``bet``payout``fee``void_refund``adjust` 等(字符串枚举,与代码常量一致) |
| `direction` | `1` 入金 / `2` 出金;与 `amount` 恒正配合使用 |
| `amount` | 变动额,**恒正** |
| `balance_before` / `balance_after` | 变动前后余额,对账与审计 |
| `ref_type` / `ref_id` | 关联订单或业务主键(如 `deposit_order``bet_order` |
| `idempotency_key` | 幂等键,防重复记账(唯一索引,允许多 `NULL` |
| `operator_admin_id` | 人工加扣币时的操作者 `admin.id` |
| `remark` | 说明 |
| `create_time` | 流水时间;**本表不设 `update_time`,禁止 UPDATE** |
### 11.7 `deposit_order` / `withdraw_order`
| 表 | 要点 |
|----|------|
| `deposit_order` | 法币、`fx_rate``coin_amount`、网关单号、回调存档 |
| `withdraw_order` | 申请额、手续费、审核与 Jackpot 标记、驳回原因 |
### 11.8 代理钱包与结算域(`game_agent_wallet`、`game_agent_wallet_ledger`、`agent_settlement_period`、`agent_commission_record`、`affiliate_*`
见 DDL 注释:代理余额与流水、结算周期大盘快照、佣金行、联营契约与负结转;金额均为 **decimal(18,2)**,与玩家账本区分职责。
### 11.9 运营与消息(`operation_notice`、`user_notice_read`、`user_site_message`
公告类型(含强弹)、已读确认;站内信与公告分离存储,详见各表 `COMMENT`