Files
henan-backend/docs/updata_sql.md
T

15 KiB
Raw Blame History

数据库变更台账

数据库改动只写这里:中文标题 + 完整可执行 SQL。不再单独建 docs/*.sql(全量基线除外)。 只记变更 SQL;不写回滚 SQL —— 已执行的条目即为既成事实,要撤销请从本文件的 git 历史取旧版本。 若某条变更依赖尚未执行的前置对象(建表、种子数据等),必须在条目标注清楚,别让后来者踩空。


幸运升级·水位策略简化为「单一目标水位」:sys_config 配置结构变更

背景:上一版把水位策略做成了 4 档波段表(每档 = 水位下界/上界 + 随机数下界/上界), 后台要维护 16 个数、还要保证档间单调且留有重叠,运营难维护也容易配错。本次简化为只填一个「目标水位(%)」: 随机数的中心由目标水位自动反推,取值范围仍由每个饰品自己的「随机数区间」限定 (水位高于目标 → 落点靠近区间下限)。口径推导、换算表、仿真数据与算例见 docs/修改记录.md 的 2026-09-24 条。

本次数据库变更 1 处(2026-09-24 已在库 henan 执行):sys_config.config_key = 'luckyUpgradeWatermark' 的 config_value 由「波段表」改为「目标水位 + 灵敏度」,bands 字段废弃(后端已不再读取,留着不报错)。

⚠️ 前置依赖:本条的 UPDATE 依赖下一节「幸运升级·水位驱动改造」插入的那行 sys_config —— 全新库必须先执行那一条,再执行本条。

⚠️ 同时恢复(代码侧,非 SQL):饰品列表页的「随机数区间」编辑入口重新启用, tt_upgrade_ornaments.luck_section / anchor_luck_section / blank_luck_section 现在必须配置, 且要包含按目标水位推算出的中心值,否则中心被夹在边界上、水位停不到目标值。 ⇒ 下一节里「上线前清空三个区间列」的说法已作废,不要再执行那两条清空 SQL。

变更 SQL:

UPDATE `sys_config`
   SET `config_value` = '{"enabled":true,"targetWatermark":30,"gain":2,"luckyValueMode":"raw"}',
       `remark` = '幸运升级水位策略:目标水位%(平台希望长期维持的净收益比例)、灵敏度 gain、幸运值展示口径 raw/eff。随机数中心 = 100/((1-目标水位/100)*实测标定系数),再由每个饰品的随机数区间限定取值范围;中奖判定恒用 min(概率,75)。enabled=false 逐字节回退固定区间',
       `update_time` = NOW()
 WHERE `config_key` = 'luckyUpgradeWatermark';

字段口径:

字段 含义
enabled true = 按水位动态出随机数;false = 逐字节回退「每个饰品位固定 luck_section」
targetWatermark 目标水位(%):平台希望长期维持的净收益比例。30 ⇒ 长期平均 RTP ≈ 70%
gain 响应灵敏度:水位每偏离目标 1 个点,随机数中心反向调整 gain%。默认 2,后台不展示(调参用)
luckyValueMode 幸运值展示口径:raw(默认,累加前端原始概率)/ eff(累加 min(概率,75));不影响判定

幸运升级·水位驱动改造:水位日志表、拉取记录快照列、水位策略配置与「奖池水位」菜单

背景:幸运升级原来每个饰品位配一套固定幸运区间,随机数永远落在区间内(如 [100,160)), 玩家能看出「每次都要投到 1 倍原价以上才出」。本次改为按全局水位动态决定本轮的随机数区间: 水位 = (Σ下注 − Σ返奖 + 人工调整) / Σ下注(排除白号),水位越高 → 可出的随机数越低。 同时新增后台人工注水/抽水。方案、换算表、口径推导与算例全部汇总在 docs/修改记录.md 的 2026-09-23 条(不另建单独文档)。

本次数据库变更 4 处(2026-09-23 已在库 henan 执行):

对象 变更 说明
tt_upgrade_reward_log 新建表 注水/抽水审计日志,delta 为带符号影响,水位调整额 = SUM(delta)(DB 为真相,Redis 只是短缓存)
tt_upgrade_record 新增 2 列 watermark(本次拉取时的水位%)、round_target(本轮抽到的随机数快照)
sys_config 新增 1 行 config_id=155、config_key='luckyUpgradeWatermark',水位波段表 + 幸运值展示口径;enabled=false 可逐字节回退旧行为
sys_menu / sys_role_menu 各新增 1 / 2 行 menu_id=3208「幸运升级 → 奖池水位」,授权给 role_id 101(三恒)、103(Fdily)

为什么 menu_id 用 3208:3200~3207 是麻将胡了的号段,按顺序往后取,不复用已下架玩法的旧号段。

变更 SQL:

CREATE TABLE IF NOT EXISTS `tt_upgrade_reward_log` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'PK',
  `type` tinyint NOT NULL COMMENT '1注水 2抽水 3重置',
  `amount` decimal(14,2) NOT NULL DEFAULT '0.00' COMMENT '调整金额(绝对值,展示用)',
  `delta` decimal(14,2) NOT NULL DEFAULT '0.00' COMMENT '对水位的带符号影响(注水正/抽水负/重置为抵消值)',
  `watermark_before` decimal(8,2) DEFAULT NULL COMMENT '调整前水位%',
  `watermark_after` decimal(8,2) DEFAULT NULL COMMENT '调整后水位%',
  `operator` varchar(64) DEFAULT NULL COMMENT '操作人',
  `remark` varchar(200) DEFAULT NULL COMMENT '调整原因(必填,前端保证)',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_create` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='幸运升级奖池水位调整日志';

ALTER TABLE `tt_upgrade_record`
  ADD COLUMN `watermark` decimal(8,2) NULL COMMENT '本次拉取时的水位%(1-RTP,排除白号,含人工调整)',
  ADD COLUMN `round_target` int NULL COMMENT '本轮抽到的随机数 fullV 快照';

INSERT INTO `sys_config`
  (`config_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
VALUES
  (155, '幸运升级水位策略', 'luckyUpgradeWatermark',
   '{"enabled":true,"luckyValueMode":"raw","bands":[{"from":-999,"to":10,"vMin":95,"vMax":130},{"from":10,"to":26,"vMin":115,"vMax":150},{"from":26,"to":36,"vMin":75,"vMax":175},{"from":36,"to":999,"vMin":85,"vMax":128}]}',
   'Y', 'admin', NOW(), '', NULL, '幸运升级水位策略:波段表(水位%→随机数区间) + 幸运值展示口径 raw(原始概率)/eff(与判定同口径);中奖判定恒用 min(概率,75)。enabled=false 逐字节回退固定区间');

INSERT INTO `sys_menu`
  (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
VALUES
  (3208, '奖池水位', 2075, 3, 'rewardPool', 'skins/luckyUpgrade/rewardPool/index', NULL, 1, 0, 'C', '0', '0', 'skins:upgrade:pool', 'money', 'admin', NOW(), '', NULL, '幸运升级·奖池水位(全局水位/人工注水抽水/调整历史)');

INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES (101, 3208), (103, 3208);

验证(2026-09-23 实测结果):

SELECT COUNT(*) FROM information_schema.tables
 WHERE table_schema='henan' AND table_name='tt_upgrade_reward_log';                          -- 期望 1,实测 1
SELECT COUNT(*) FROM information_schema.columns
 WHERE table_schema='henan' AND table_name='tt_upgrade_record'
   AND column_name IN ('watermark','round_target');                                          -- 期望 2,实测 2
SELECT COUNT(*) FROM sys_config    WHERE config_key='luckyUpgradeWatermark';                 -- 期望 1,实测 1
SELECT COUNT(*) FROM sys_menu      WHERE menu_id=3208;                                       -- 期望 1,实测 1
SELECT COUNT(*) FROM sys_role_menu WHERE menu_id=3208;                                       -- 期望 2,实测 2

后台左侧「幸运升级」目录下出现「奖池水位」页(/luckyUpgrade/rewardPool)。

注意:水位策略上线后的运营动作

⚠️ 本节第 1 条已被本文件顶部「水位策略简化为单一目标水位」那条取代: luck_section / anchor_luck_section / blank_luck_section 重新成为必填项 (语义 = 随机数的允许取值范围),不要清空;而且要配成**包含「按目标水位推算出的中心值」**的区间。 清空后后端会用兜底区间 [80,160],能用但不受控。

  1. 两个已存在的饰品位(tt_upgrade_ornaments.id 18 / 25)的 luck_section 要清空,才能完全跟随全局波段 —— 已作废,见上方提示。
  2. 水位从 0 起步。enabled=true 时前几件货会落在收紧档(水位低 → 随机数高),属预期行为; 需要立刻放水用后台「奖池水位 → 注水」。

新增「麻将胡了」(mahjong 玩法)的后台菜单、角色授权与维护开关

背景:麻将胡了以「新游戏」类型接入,复用原玫瑰女郎(olympus 玩法)的整套统计口径 —— 消费流水 source=68、奖励流水 source=69、开箱产出 source=15、新游戏返佣费率字段 tt_user.newGameCommissionRate。代码层改动(后端统计链路 + 两个前端)见 docs/修改记录.md; 本条目只记数据库变更。

本次数据库变更 3 张表、共 17 行(2026-09-22 已在库 henan 执行):

表 变更 说明
sys_config 新增 1 行 config_id=154、config_key='mahjongMaintenance',即「麻将胡了维护」开关
sys_menu 新增 8 行 顶级目录 mahjong(menu_id=3200)+ 7 个子页面(3201~3207)
sys_role_menu 新增 8 行 全部授权给 role_id=103

为什么 menu_id 用 3200~3207:3130~3137 是已下架的奥林匹斯旧号段,不复用, 免得数据里「哪段 ID 属于哪个玩法」的对应关系失真。

变更 SQL:

INSERT INTO `sys_menu`
  (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
VALUES
  (3200, '麻将胡了', 0, 6, 'mahjong', '', NULL, 1, 0, 'M', '0', '0', '', 'star', 'admin', NOW(), '', NULL, '麻将胡了游戏后台管理目录'),
  (3201, '箱子配置', 3200, 1, 'box',        'game/mahjong/box/index',        NULL, 1, 0, 'C', '0', '0', 'game:mahjong:box',    'shopping',      'admin', NOW(), '', NULL, '麻将胡了·箱子配置(11 档投注,price ≡ bet)'),
  (3202, '饰品列表', 3200, 2, 'bucket',     'game/mahjong/bucket/index',     NULL, 1, 0, 'C', '0', '0', 'game:mahjong:bucket', 'star',          'admin', NOW(), '', NULL, '麻将胡了·16 档饰品桶定义(0x~500x,只读)'),
  (3203, '回合管理', 3200, 3, 'round',      'game/mahjong/round/index',      NULL, 1, 0, 'C', '0', '0', 'game:mahjong:round',  'documentation', 'admin', NOW(), '', NULL, '麻将胡了·预生成回合池(只读)'),
  (3204, '奖池水位', 3200, 4, 'rewardPool', 'game/mahjong/rewardPool/index', NULL, 1, 0, 'C', '0', '0', 'game:mahjong:pool',   'money',         'admin', NOW(), '', NULL, '麻将胡了·奖池水位(3 身份:普通/主播/白号)'),
  (3205, '玩家记录', 3200, 5, 'record',     'game/mahjong/record/index',     NULL, 1, 0, 'C', '0', '0', 'game:mahjong:record', 'list',          'admin', NOW(), '', NULL, '麻将胡了·玩家游玩记录'),
  (3206, '每日统计', 3200, 6, 'dailywin',   'game/mahjong/dailywin/index',   NULL, 1, 0, 'C', '0', '0', 'game:mahjong:win',    'chart',         'admin', NOW(), '', NULL, '麻将胡了·每日投注/赢奖/RTP 统计'),
  (3207, '奖品管理', 3200, 7, 'prize',      'game/mahjong/prize/index',      NULL, 1, 0, 'C', '0', '0', 'game:mahjong:prize',  'guide',         'admin', NOW(), '', NULL, '麻将胡了·返奖饰品与返奖区间');

INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES
  (103, 3200), (103, 3201), (103, 3202), (103, 3203),
  (103, 3204), (103, 3205), (103, 3206), (103, 3207);

INSERT INTO `sys_config`
  (`config_id`, `config_name`, `config_key`, `config_value`, `config_type`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
VALUES
  (154, '麻将胡了维护', 'mahjongMaintenance', '0', 'Y', 'admin', NOW(), '', NULL, '麻将胡了维护开关 0正常 1维护');

验证(2026-09-22 实测结果):

SELECT COUNT(*) FROM sys_menu      WHERE menu_id BETWEEN 3200 AND 3207;     -- 期望 8,实测 8
SELECT COUNT(*) FROM sys_role_menu WHERE menu_id BETWEEN 3200 AND 3207;     -- 期望 8,实测 8
SELECT COUNT(*) FROM sys_config    WHERE config_key = 'mahjongMaintenance'; -- 期望 1,实测 1

后台左侧出现「麻将胡了」目录(order_num=6),下辖 7 个子页面; 「网站设置」页出现「麻将胡了维护」下拉框(0 正常 / 1 维护)。

前置依赖:麻将胡了的 11 张游戏表(game_mahjong_box / _bucket / _box_bucket / _round / _step / _record / _user / _box_template / _reward_log / _prize_ornament / _prize_range)。

DDL 与种子数据的权威出处是 mahjong-py/schema.sql,不抄进本台账(已拍板:建表只以该文件为权威、直接对库执行)。 该文件可重复执行(CREATE TABLE IF NOT EXISTS + ON DUPLICATE KEY UPDATE),无任何 DROP / DELETE。

执行方式(2026-09-22 已执行):

docker exec -i henan_mysql_db mysql -uroot -p123456 --default-character-set=utf8mb4 -D henan < mahjong-py/schema.sql

落库结果(实测):

表 行数 说明
game_mahjong_box 11 11 档投注,price ≡ bet
game_mahjong_bucket 16 0x ~ 500x
game_mahjong_prize_ornament 12 返奖饰品(沿用玫瑰女郎 id 以维持区间映射)
game_mahjong_prize_range 12 连续覆盖 0.01 ~ 99,999,999
_box_bucket / _round / _step / _record / _user / _box_template / _reward_log 0 空表,等运行期数据
SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema = 'henan' AND table_name LIKE 'game\_mahjong\_%';   -- 期望 11,实测 11

仍需后台操作生成的运行期数据(不是建表,别当成漏建):

  1. game_mahjong_box_bucket 的 528 行配比(16 桶 × 11 箱 × 3 身份)—— 后台 「麻将胡了 → 箱子配置 → 一键重算」(POST /admin/mahjong/box/recalc_all)。空表时挑不到回合。
  2. 每箱×身份的初始奖池水位 —— 后台「奖池水位 → 注水」(¥300 / ¥500 两档需单独注)。