494 lines
35 KiB
Markdown
494 lines
35 KiB
Markdown
# 「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 总览(与下文 P0~P4 对应)
|
||
|
||
| 阶段 | 目标 | 主要内容 |
|
||
|------|------|----------|
|
||
| **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字花字典** | 运营参数与字典维护 |
|
||
| 中 | **充值订单 / 提现订单** | 充提流程管理与审核 |
|
||
| 低 | **公告 / 站内信**、**代理结算** 等 | 属 **P3~P4**,核心跑通后再接 |
|
||
|
||
### 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`(1~10)、`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 秒节奏 | 0–20s 可下注,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`:表示**当局已完全结束**(含派彩),此时后台页展示「维护中」并锁定操作区(仅顶部「游戏运行」开关可用);当局尚在 0–3 状态时为 `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`。
|