From 3248ee4b83c331e6878d6527d1dc70b7849747a8 Mon Sep 17 00:00:00 2001 From: zzm <584337238@qq.com> Date: Sun, 27 Sep 2026 19:12:59 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B2=B3=E5=8D=97=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E7=9A=84=E7=AE=A1=E7=90=86=E5=90=8E=E5=8F=B0ui?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/updata_sql.md | 127 ++++ docs/修改记录.md | 251 ++++++++ promo-ui2/src/api/login/index.ts | 10 +- promo-ui2/src/api/login/types.ts | 7 + .../src/layout/components/ToolHeader.vue | 6 +- promo-ui2/src/store/modules/app.ts | 10 +- promo-ui2/src/views/BusinessManage/index.vue | 50 +- promo-ui2/src/views/CardMerchant/index.vue | 21 +- .../src/views/CommissionReport/index.vue | 40 +- promo-ui2/src/views/Home/index.vue | 567 ++++++++++++------ promo-ui2/src/views/Login/Login.vue | 85 +-- .../src/views/Login/components/LoginForm.vue | 262 +++++++- .../src/views/SubordinateRecharge/index.vue | 13 +- promo-ui2/src/views/subFlow/index.vue | 30 +- .../src/main/resources/application-dev.yml | 6 + .../src/main/resources/application.yml | 8 + ruoyi-ui/.env.development | 2 +- ruoyi-ui/.env.production | 2 +- ruoyi-ui/.env.staging | 2 +- ruoyi-ui/src/assets/styles/skin.scss | 10 +- .../src/views/game/wheel/config/index.vue | 6 +- ruoyi-ui/src/views/index.vue | 535 +++++++++++------ ruoyi-ui/src/views/login.vue | 2 +- ruoyi-ui/src/views/register.vue | 2 +- ruoyi-ui/vue.config.js | 2 +- .../ruoyi/promo/config/PromoWebConfig.java | 4 +- .../contract/request/DevLoginRequest.java | 18 + .../controller/PromoLoginController.java | 30 + .../promo/service/PromoLoginService.java | 8 + .../service/impl/PromoLoginServiceImpl.java | 43 +- .../admin/mapper/TtUpgradeRewardLogMapper.xml | 4 +- 31 files changed, 1605 insertions(+), 558 deletions(-) create mode 100644 skins-promo/src/main/java/com/ruoyi/promo/contract/request/DevLoginRequest.java diff --git a/docs/updata_sql.md b/docs/updata_sql.md index 14bab01..e234e9d 100644 --- a/docs/updata_sql.md +++ b/docs/updata_sql.md @@ -160,6 +160,133 @@ SELECT COUNT(*) FROM sys_role_menu WHERE menu_id=3208; 2. 水位从 0 起步。`enabled=true` 时前几件货会落在收紧档(水位低 → 随机数高),属预期行为; 需要立刻放水用后台「奖池水位 → 注水」。 +## 管理后台按钮级权限补全:`sys_menu` 补 24 行 `F`(按钮)记录 + +**背景**:后台按钮的显隐走前端 `v-hasPermi`(`ruoyi-ui/src/directive/permission/hasPermi.js`), +接口放行走后端 `@PreAuthorize("@ss.hasPermi('...')")`,**两边比对的是同一个 `sys_menu.perms`** +(超管 `user_id=1` 拿 `*:*:*`,其他人拿「已授权菜单行的 `perms` 去重集合」,见 +`ruoyi-framework/.../SysPermissionService.java:55`)。 + +历史遗留:**从 `menu_id` 31xx 段开始,新增页面只建了 `C` 行、没建 `F` 行** +(`F` 行分布:1000 段 61 行、2000 段 18 行、3100 段仅 9 行、3200+ 段 0 行)。 +后果是这些页面的按钮在角色授权树里**根本勾不到** ⇒ 除超管外谁都看不见; +更严重的是部分 **列表/查询接口也会 403**,页面进去是空的。 + +盘点结果:代码在用、但 `sys_menu` 未登记的权限串共 **43 个**。其中 **23 个属于 4 个无菜单入口的孤儿页面** +(`ttOrnaments/boxOpenChance`、`ttBonus/firstRecharge`、`ttWelfare/monthlyRecharges`、`ttReplacementRecord/index` +—— 已核实无菜单、无组件引用、无路由、无接口复用方,**不可达,本期不动**); +**其余 20 个 + 复用组补 4 行 = 24 行**,本次补齐。 + +> 为什么 `menu_id` 用 `3209~3232`:`MAX(menu_id)=3208`(麻将胡了 3200~3207、幸运升级 3208),按顺序往后取。 + +**本次数据库变更 3 处**(2026-09-27 已在库 `henan` 执行): + +| 对象 | 变更 | 说明 | +|---|---|---| +| `sys_menu` | 新增 **24 行** | `menu_id=3209~3232`,`menu_type='F'`,挂到 6 个 C 行下(2035/2038/2086/2092/2123/3118)| +| `sys_menu` | 修正 **3 行** | `menu_id=3160~3162` 的 `parent_id`:`3156`(目录 `M`「流水抽奖」)→ `3157`(页面 `C`「抽奖活动」)。**同属 F 行挂载错误**,不改的话勾「抽奖活动」联动带不到这 3 个按钮 | +| `sys_role_menu` | 新增 **24 行** | 把上述 F 行补授权给「**已授权其父 C 行**」的角色(动态 SQL,执行时按实际授权现状生成)。执行时这些父 C 行**仅 `role_id=104`(测试人员)**已授权 ⇒ 24 行全落给 104(`sys_role_menu` 总行数 222 → 246)| + +> 关于 `3160~3162`:这三个串(`system:turnoverLottery:add/edit/remove`)**当前代码里无人使用** +> (`turnoverLottery/list.vue` 的新增/修改/删除按钮没写 `v-hasPermi`,后端也没有对应 `@PreAuthorize`), +> 所以本次修正只是把菜单树层级摆正、消除「F 行挂在目录下」的隐患,不影响线上行为。 +> 若将来给该页面补按钮权限,直接复用这三个串即可。 + +**变更 SQL**: + +```sql +/* ---- 1. 24 行按钮权限(F)---- */ +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 + /* 奖池详情(ttRoll/prizedetail)—— 该页「删除」按钮历史上绑的就是 admin:prize:edit */ + (3209, '修改奖池', 2038, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:prize:edit', '#', 'admin', NOW(), '', NULL, '奖池详情·修改'), + /* CDK管理(ttRedPack/index)—— 整套新增,此前 0 行 F */ + (3210, '新增红包', 2086, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'skinsback:ttRedPack:add', '#', 'admin', NOW(), '', NULL, 'CDK管理·新增'), + (3211, '删除红包', 2086, 2, '', NULL, NULL, 1, 0, 'F', '0', '0', 'skinsback:ttRedPack:remove', '#', 'admin', NOW(), '', NULL, 'CDK管理·删除'), + (3212, '修改红包', 2086, 3, '', NULL, NULL, 1, 0, 'F', '0', '0', 'skinsback:ttRedPack:edit', '#', 'admin', NOW(), '', NULL, 'CDK管理·修改'), + (3213, '导出红包', 2086, 4, '', NULL, NULL, 1, 0, 'F', '0', '0', 'skinsback:ttRedPack:export', '#', 'admin', NOW(), '', NULL, 'CDK管理·导出'), + (3214, '红包查询', 2086, 5, '', NULL, NULL, 1, 0, 'F', '0', '0', 'skinsback:ttRedPack:query', '#', 'admin', NOW(), '', NULL, 'CDK管理·详情'), + (3215, '红包列表', 2086, 6, '', NULL, NULL, 1, 0, 'F', '0', '0', 'skinsback:ttRedPack:list', '#', 'admin', NOW(), '', NULL, 'CDK管理·列表接口'), + (3216, '红包全部列表', 2086, 7, '', NULL, NULL, 1, 0, 'F', '0', '0', 'skinsback:ttRedPack:listAll', '#', 'admin', NOW(), '', NULL, 'CDK管理·不分页列表接口'), + /* 对战排行榜奖励(ttFight/fightRankingReward)—— 此前 0 行 F */ + (3217, '新增奖励', 2092, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:reward:add', '#', 'admin', NOW(), '', NULL, '对战排行榜奖励·生成'), + (3218, '删除奖励', 2092, 2, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:reward:remove', '#', 'admin', NOW(), '', NULL, '对战排行榜奖励·清空'), + (3219, '修改奖励', 2092, 3, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:reward:edit', '#', 'admin', NOW(), '', NULL, '对战排行榜奖励·修改'), + (3220, '奖励查询', 2092, 4, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:reward:query', '#', 'admin', NOW(), '', NULL, '对战排行榜奖励·详情'), + (3221, '奖励列表', 2092, 5, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:reward:list', '#', 'admin', NOW(), '', NULL, '对战排行榜奖励·列表接口'), + /* 机器人对战配置(ttFight/robotFightConfig)—— 该 C 行下原有 4 行(3119~3122),价格配置这套是漏的,故 order 从 5 起 */ + (3222, '新增价格配置', 3118, 5, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:robotFightPriceConfig:add', '#', 'admin', NOW(), '', NULL, '机器人对战配置·价格配置新增'), + (3223, '删除价格配置', 3118, 6, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:robotFightPriceConfig:remove', '#', 'admin', NOW(), '', NULL, '机器人对战配置·价格配置删除'), + (3224, '修改价格配置', 3118, 7, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:robotFightPriceConfig:edit', '#', 'admin', NOW(), '', NULL, '机器人对战配置·价格配置修改'), + (3225, '价格配置查询', 3118, 8, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:robotFightPriceConfig:query', '#', 'admin', NOW(), '', NULL, '机器人对战配置·价格配置详情'), + (3226, '价格配置列表', 3118, 9, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:robotFightPriceConfig:list', '#', 'admin', NOW(), '', NULL, '机器人对战配置·价格配置列表接口'), + /* 货币列表(ttRechargeList/index)—— 该页只有详情接口校验;列表接口本身无 @PreAuthorize */ + (3227, '货币查询', 2035, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:rechargeList:query', '#', 'admin', NOW(), '', NULL, '货币列表·详情'), + /* 机器人对战分组宝箱(ttFight/robotFightGroupBox) + ⚠️ 复用组:该页前端按钮用 admin:box:{add,edit,remove}、后端接口用 admin:box:{list,query}, + 而这 4 个串原先只挂在 2019「宝箱列表」下 —— 父子联动带不过来, + 所以必须在 2123 下再挂一遍,才能做到「勾这一个页面 = 该页完整可用」。*/ + (3228, '新增分组宝箱', 2123, 1, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:box:add', '#', 'admin', NOW(), '', NULL, '机器人对战分组宝箱·新增(与 2020 同 perms,刻意重复)'), + (3229, '删除分组宝箱', 2123, 2, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:box:remove', '#', 'admin', NOW(), '', NULL, '机器人对战分组宝箱·删除(与 2021 同 perms,刻意重复)'), + (3230, '修改分组宝箱', 2123, 3, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:box:edit', '#', 'admin', NOW(), '', NULL, '机器人对战分组宝箱·修改(与 2022 同 perms,刻意重复)'), + (3231, '分组宝箱查询', 2123, 4, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:box:query', '#', 'admin', NOW(), '', NULL, '机器人对战分组宝箱·详情接口'), + (3232, '分组宝箱列表', 2123, 5, '', NULL, NULL, 1, 0, 'F', '0', '0', 'admin:box:list', '#', 'admin', NOW(), '', NULL, '机器人对战分组宝箱·列表接口(与 2019/3139 同 perms,刻意重复)'); + +/* ---- 2. 授权补齐:把新 F 行补给「已授权其父 C 行」的角色 ---- + 动态写法的好处:不依赖执行时刻的角色授权现状,也不用在角色界面逐个重存。 + 注意:只补 F 行;C 行(页面本身)是否可见仍由业务在「角色管理」里决定。*/ +INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) +SELECT DISTINCT `rm`.`role_id`, `f`.`menu_id` + FROM `sys_menu` `f` + JOIN `sys_role_menu` `rm` ON `rm`.`menu_id` = `f`.`parent_id` + WHERE `f`.`menu_id` BETWEEN 3209 AND 3232 + AND NOT EXISTS (SELECT 1 FROM `sys_role_menu` `x` + WHERE `x`.`role_id` = `rm`.`role_id` AND `x`.`menu_id` = `f`.`menu_id`); + +/* ---- 3. 修正 3 行挂错父节点的 F(3160~3162:目录 3156 → 页面 3157)---- */ +UPDATE `sys_menu` + SET `parent_id` = 3157 + WHERE `menu_id` BETWEEN 3160 AND 3162 + AND `menu_type` = 'F' + AND `parent_id` = 3156; +``` + +**验证**: + +```sql +-- ① 24 行 F 都进去了、且 perms 无重复录入 +SELECT COUNT(*) FROM sys_menu WHERE menu_id BETWEEN 3209 AND 3232 AND menu_type='F'; -- 期望 24 +SELECT perms, COUNT(*) FROM sys_menu WHERE menu_id BETWEEN 3209 AND 3232 + GROUP BY perms HAVING COUNT(*) > 1; -- 期望 0 行(2123 组与 2019 组不同 id,不算重复) + +-- ② 全库 F 行的 parent 必须是指向 C 行的 menu_id(防挂错;本次修掉了 3160~3162 这组) +SELECT f.menu_id, f.menu_name, f.perms, f.parent_id, p.menu_type + FROM sys_menu f LEFT JOIN sys_menu p ON p.menu_id = f.parent_id + WHERE f.menu_type = 'F' AND (p.menu_id IS NULL OR p.menu_type <> 'C'); -- 期望 0 行 + +-- ③ 授权补齐后:每个新 F 行,其父 C 行的每个授权角色都应能查到 +SELECT f.menu_id, f.perms, rm.role_id + FROM sys_menu f + JOIN sys_role_menu rm ON rm.menu_id = f.parent_id + WHERE f.menu_id BETWEEN 3209 AND 3232 + AND NOT EXISTS (SELECT 1 FROM sys_role_menu x + WHERE x.role_id = rm.role_id AND x.menu_id = f.menu_id); -- 期望 0 行 + +-- ④ 端到端:模拟某角色的 perms 集合,确认缺串已消失 +SELECT DISTINCT m.perms FROM sys_menu m + JOIN sys_role_menu rm ON m.menu_id = rm.menu_id + WHERE rm.role_id = <角色ID> AND m.perms IS NOT NULL AND m.perms <> ''; +``` + +**代码侧配套(非 SQL)**:新增 `.workbuddy/verify-perms.cjs`,做「代码在用的权限串 ↔ `sys_menu.perms`」双向差集, +防止后续新增页面再次只建 C 行、漏建 F 行。跑法见脚本头部注释。 + +**注意:权限生效需要用户重新登录**(`permissions` 是登录时从 `/getInfo` 拉取的,存在前端 store 里,不会热更新)。 + +--- + -----------------------对战接口优化-------------------------- SHOW INDEX FROM tt_fight; diff --git a/docs/修改记录.md b/docs/修改记录.md index a41ec19..2db92b0 100644 --- a/docs/修改记录.md +++ b/docs/修改记录.md @@ -7,6 +7,257 @@ --- +## 2026-09-27 + +- **管理后台按钮级权限补全:`sys_menu` 补 24 行 `F` + 防漂移校验脚本** + + **起因**:用户问「管理后台会不会有只有超管能看到、非超管看不见的页面内按钮」。核查结论:**会,而且比按钮更严重**。 + + **机制**:按钮显隐走前端 `v-hasPermi`、接口放行走后端 `@PreAuthorize("@ss.hasPermi(...)")`, + 两边比对的是**同一份 `sys_menu.perms`**;超管(`user_id==1`)拿 `*:*:*` 所以永远看得见。 + ⇒ **某权限串只要在 `sys_menu` 里没有对应行,就永远授权不到任何非超管角色**:按钮看不见、部分列表/详情接口直接 403。 + + **盘出的问题**(代码在用、库里未登记,并集 43 串): + - 4 个孤儿页面(开箱概率 / 首充奖励 / 月度充值 / 换装记录)占 23 串 —— 已核实无菜单、无组件引用、无路由、无接口复用方, + **不可达,本期不动**(手输 URL 也 404,因 RuoYi 路由由 `/getRouters` 动态注册)。 + - 其余 20 串 + `admin:box:*` 复用组补 4 行 = **24 行**,本次补齐。 + - 结构性漂移:**从 `menu_id` 31xx 段起,新增页面只建 `C` 行、不建 `F` 行**(F 行分布:1000 段 61、2000 段 18、3100 段 9、3200+ 段 0)。 + + **改动清单** + 1. `sys_menu` 新增 24 行 `F`(`menu_id 3209~3232`,挂 2035/2038/2086/2092/2123/3118 六个 C 行下)。 + 2. `sys_role_menu` 动态补齐:把新 F 行补给「已授权其父 C 行」的角色(本次实写 24 行,全给 `role_id=104`)。 + 3. `sys_menu` 修正 3 行(`3160~3162`)`parent_id`:目录 `3156` → 页面 `3157`(F 行挂错层级,父子联动带不到)。 + 4. **代码侧配套**:新增 `.workbuddy/verify-perms.cjs` —— 扫前端 `v-hasPermi` + 后端 `@PreAuthorize`, + 与 `sys_menu.perms` 做双向差集 + 校验全库 F 行 parent 必须指向 C 行。非 0 退出码,建议挂 `publish.sh` 前防复发。 + + **验证**:库层 5 项全对(24 行 / 0 重复 / 0 挂错父节点 / 0 未授权 / `role_menu` 222→246); + `node .workbuddy/verify-perms.cjs` ⇒ **ALL_OK 6 passed / 0 failed**。 + + **注意**:① 权限生效需用户**重新登录**(`permissions` 登录时从 `/getInfo` 拉取,不热更新)。 + ② 执行时库内授权已被重排 —— 只有 `role_id=104`(测试人员)持有这些页面,`三恒` 等角色**0 菜单**, + 且多个启用用户(三恒/国荣/s1/zzyzzy123/Fdily)**未分配任何角色**,这是业务配置问题,本次未动。 + + 细节 SQL 见 `docs/updata_sql.md`「管理后台按钮级权限补全」,过程与踩坑见 `.workbuddy/memory/2026-09-27.md`。 + +- **推广后台「佣金明细记录」等 3 张报表右侧留白 → 全列 `width` 改 `min-width`** + + **起因**:用户截图 `promo-ui2/src/views/CommissionReport/index.vue` 的「佣金明细记录」表,说「这里表格填充不满」。 + + **根因**(读 Element Plus 源码定论,不是猜):`element-plus/es/components/table/src/table-layout.mjs:100-171` + 的 `updateColumnsWidth()` 只在 **存在弹性列** 时才把表格撑满容器 + (`flexColumns = flattenColumns.filter(c => !isNumber(c.width))`); + 全列都是数字 `width` 时走 else 分支 ⇒ `bodyWidth = Σ realWidth` ⇒ **表格宽恒等于列宽之和,容器再宽右侧也留白**。 + ⚠️ 关键陷阱:`width="170"` 这种**静态字符串**也会被 `table-column/render-helper.mjs:39` 的 + `parseWidth()`(= `Number.parseInt`)转成数字 170 ⇒ 那是**固定列**; + 反过来只写 `min-width` 时 `setColumnWidth()` 会执行 `column.width = void 0` ⇒ 那才是**弹性列**。 + + **改动清单**(`promo-ui2/src/views/CommissionReport/index.vue`,3 张表共 16 列;另有 6 张表见本节末): + 1. 「佣金明细记录」6 列(本地时间170 / 手机号130 / 该次消费120 / 佣金比例90 / 佣金金额100 / 来源120) + 2. 「佣金日报」5 列(手机号130 / 今日消费120 / 来源120 / 佣金金额120 / 日期130) + 3. 「佣金汇总」5 列(手机号130 / 来源120 / 消费金额120 / 本次佣金120 / 参加游戏次数140) + —— **一律 `width` → `min-width`,数值不变**。选「全列都变弹性」而不是「只挑一列变弹性」: + 弹性的那一列会独吞全部余量(1280 视口下 170px 的时间列会涨到 ≈590px),全列按 min-width 等比摊才均匀。 + 模板顶部加了注释说明为什么不能改回 `width`。脚本/接口/分页/过滤逻辑一行未动。 + + **验证**(3 件,全部 ALL_OK): + - SFC 编译:`node .workbuddy/verify-promo-vue-compile.cjs src/views/CommissionReport/index.vue` ⇒ **ALL_OK 4/0** + (连带跑 Home ⇒ 11/0,未受影响)。 + - 算法级多视口回归:`node .workbuddy/verify-ep-table-stretch.cjs src/views/CommissionReport/index.vue` + ⇒ **ALL_OK 15/0**。1280/1440/1600/1920/2560 五个视口下 3 张表**留白全为 0px、`scrollX` 全 false**。 + - 真产物:`node .workbuddy/check-promo-modules.cjs src/views/CommissionReport/index.vue --has=min-width --prop=min-width:16` + ⇒ **ALL_OK**(用户常驻的 `:4000` dev server 上主模块 200、`"min-width"` prop 恰好 **16** 次、0 处编译错误串)。 + - 全站审计:`node .workbuddy/audit-table-fill-ep.cjs` ⇒ CommissionReport 3 张表从「✗ 不能撑满」转为有弹性列。 + + **新增脚本(3 个,都是 promo-ui2 / Element Plus 侧原先缺的)**: + `.workbuddy/audit-table-fill-ep.cjs`(全站扫「全固定列 ⇒ 留白」)、 + `.workbuddy/verify-ep-table-stretch.cjs`(复现 `updateColumnsWidth` 做多视口定量回归)、 + `.workbuddy/check-promo-modules.cjs`(从 `:4000` 拉真实编译产物做断言)。 + 原有的 `sim-table-width.cjs` / `verify-table-fill.cjs` 只适用 ruoyi-ui(Element UI 2.x),**不要混用**。 + + **注意 / 一并修的另外 6 张**:审计出全站共 **9 张**同样会留白的表,用户拍板「6 张全改」,已一并完成: + `BusinessManage/index.vue` 3 张(招商 Σ1128 / 主播 Σ828 / 普通用户 Σ920,后两张在展开行内)、 + `CardMerchant/index.vue:44`(Σ1210)、`subFlow/index.vue:20`(Σ1570)、`SubordinateRecharge/index.vue:23`(Σ760)。 + - 改法一致:**数据列 `width` → `min-width`**;**「操作」列保持 `width`**(CardMerchant 100、subFlow 120)—— + 操作列固定宽是设计意图,不该被拉宽。BusinessManage 的 `type="expand"` 列也不动(`cellStarts` 强制 48px 固定)。 + - **嵌套子表(BusinessManage 二/三级)**:容器宽度由父级展开行决定,**不能用「视口 − 288」推算**。 + `verify-ep-table-stretch.cjs` 已加 `depth` 判定,嵌套表只做「有没有弹性列」的定性断言,不套用视口断言。 + - **两张宽表仍会横向滚动**(改 min-width 治不了,属列宽总量问题):`CardMerchant` Σ1210 ⇒ 视口 ≤1440 横滚(差 58px); + `subFlow` Σ1570 ⇒ 视口 ≤1600 横滚。**这两个视口下改前改后都是横滚**,未新增;≥1600 / ≥1920 起改为撑满(改前是留白)。 + 若要 1440 也不横滚,得再压列宽(`使用时间/创建时间` 180→165、`卡密` 200→190 之类),本次未做,等确认。 + - 复验:全站审计 **不能撑满 0 / 34**;SFC 编译 **19/0 ALL_OK**;列宽回归 **22/0 ALL_OK**(6 张表 × 视口); + 真产物(`:4000`)4 个文件主模块全 200、`"min-width"` prop 计数 **22 / 8 / 6 / 13** 逐一吻合、0 错误串。 + + ⚠️ **未经浏览器实测**(本机 Chrome 起不来,见 `.workbuddy/memory/theme-skin.md`)⇒ 效果请自己刷 `:4000` 确认。 + +- **修复:幸运升级「水位驱动」因 mapper 里 `SUM(x, 0)` 语法错而整条不可用** + + **现象**:启动日志 `TtUpgradeRewardLogMapper.xml` → `sumRecordTotals` 报 + `java.sql.SQLSyntaxErrorException: ... right syntax to use near '' at line 4`, + 外层 WARN「幸运升级水位驱动初始化失败(不阻断启动,首次拉取时会自动重试)」。 + + **根因**:`TtUpgradeRewardLogMapper.xml` 的 `blankBet` / `blankWin` 两行把外层 `COALESCE(..., 0)` 的写法抄进了 `SUM()` —— + `SUM(CASE WHEN is_blank THEN r.amount_consumed END, 0)`。**`SUM()` 只接受一个参数**,第二个 `, 0` 直接语法错。 + (同文件 `totalBet` / `totalWin` 两行写的是 `CASE WHEN is_blank THEN 0 ELSE ... END`,是对的,可作对照。) + + **改动**:删掉 `SUM(...)` 里多余的 `, 0`(外层 `COALESCE(SUM(...), 0)` 保留,仍是 null-safe)。全仓库仅此一处。 + + **影响面(不是"只是个 WARN")**: + - `ensureInit(false)`(`@PostConstruct` 预热)异常 → Redis 累计量 `KEY_BET/KEY_WIN/KEY_BLANK_*` **从未写入**, + `KEY_INIT_AT` 也没落 ⇒ 每次调用都重新全表扫并再次失败,**水位恒为 0**,水位驱动实际等于停摆。 + - 后台「奖池水位 → 按历史重算」`/recalc` 调 `ensureInit(true)` 且**没有 try/catch** ⇒ 该按钮**必 500**。 + - `calibrationFactor()` 有 try/catch → 失败返回 0 → 回落兜底系数 1.19(这条不受影响)。 + + **验证**:库里实测 `SELECT SUM(CASE WHEN 1 THEN 2 END, 0)` 复现同一 `ERROR 1064`; + 改成 `SUM(CASE WHEN ... END)` 后整条 `sumRecordTotals` 跑通出数。XML 重新解析通过。 + + **上线动作**:`./ry.sh stop` → `mvn clean install`(见 `USER.md` 的「必须 clean install,否则嵌套旧 jar」)→ `./ry.sh start`。 + +- **推广后台登录页新增「开发环境账号密码登录」** + + **起因**:推广后台唯一登录入口是 `/promo/smsLogin`(手机号 + 4 位短信验证码 + 滑块),本地联调要连短信通道、拖滑块; + 后端此前已明确下线账号密码登录(`PromoLoginServiceImpl` 注释:「账号密码登录已下线……避免用密码绕过短信校验被撞库」)。 + + **改动清单**(前后端配合,**默认关闭**): + + 1. **后端新增 `POST /promo/devLogin`**(`@Anonymous`):账号解析直接复用 `createUserToken` 的 `promo_user_` 入口 + ⇒ 推广账号(`tt_user` 的主播/招商/卡商,登录名=手机号)与超管(`promo_admin` 的 `username` 或 `phone_number`) + **都能登录**,区别只是「短信验证码」换成了 `SecurityUtils.matchesPassword` 的 BCrypt 密码校验。 + 账号不存在 / 停用 / 密码错统一返回「账号或密码错误」(防账号枚举,真实原因走 `log.warn`)。 + 2. **开关走配置文件而非数据库**:新增 `promo.dev-login.enabled` —— `application.yml` 默认 `false`,`application-dev.yml` 置 `true`, + 生产 profile 不覆盖 ⇒ 接口恒返回「账号密码登录未开启」,且后台管理员无法误开。 + 3. `PromoWebConfig` 放行 `/promo/devLogin`(维护拦截器不拦登录类接口,与 smsLogin/register 同口径)。 + 4. **前端** `LoginForm.vue` 只在 `import.meta.env.DEV`(即 `pnpm run dev`)下渲染「短信验证码 / 账号密码」切换与密码表单; + 登录成功后复用原有的 `completeLogin` + `enterSystem` 落地流程。`api/login` 增加 `devLoginApi` 与 `DevLoginType`。 + + **验证**:`vue-tsc --noEmit` 改动文件 0 报错(仓库其余 30+ 条为既存错误);`mvn -B -DskipTests compile` ⇒ `BUILD SUCCESS`。 + + **无需数据库变更**:开关是配置文件项,不是 `sys_config`(相对 `promoMaintenance` 的取舍见 `.workbuddy/memory/2026-09-27.md`)。 + + **使用注意**:密码按 BCrypt 校验,测试账号若不知明文,查 `tt_user.remark`(格式 `明文密码:xxx`)或 `promo_admin` 表。 + +- **管理后台首页改排版:11 张等宽统计卡 → 「左窄轨 + 右主区」两栏** + + **起因**:用户反馈首页「排版还是和原来一样,只是改了 UI 的风格」——换肤把配色圆角阴影改了,但骨架仍是 + 「页头 → 卡片网格 → 区块 → 区块」的垂直堆叠模板,要求**排版差异化、风格照旧**。 + + **改动清单**(`ruoyi-ui/src/views/index.vue`,单文件) + 1. **骨架拆两栏**:`grid-template-columns: 300px minmax(0,1fr)` + `align-items:start`。 + - **左窄轨**(`position:sticky; top:16px`,跟随滚动):3 个核心大数字(在线用户 / 总充值 / 总流水,字号 28px) + + 待办区(待处理提货申请 / 提货余额)。待处理 >0 时雏菊金描边 + 数值变色。 + - **右侧主区**:实时 RTP → 「经营数据」紧凑指标带(6 项 `mini-stat`,小图标 + 标签 + 数值)→ 流水统计图 + (顺序按用户看完后的要求定:图表 400px 最高,放最底部滚到底正好)。 + 2. **指标一项不丢**:原 `statCards` 11 项拆成 `railMetrics`(3) + `miniStats`(6) + 待办区硬编码 2 项 = 11。 + 原「图标 + 大数值 + 标签」的等权卡片形态取消,改为「大数字 / 紧凑条」两级,主次拉开。 + 3. **RTP 网格** `repeat(5,1fr)` → `repeat(auto-fit, minmax(160px,1fr))`:右区宽度随屏幕浮动(左轨占了 300px), + 写死 5 列会在 1440 以下挤出 4+1。 + 4. 旧骨架 CSS(`.stat-grid` / `.stat-card` / `.stat-icon` / `.stat-info` / `.stat-arrow`)与 `statCards` computed **一并删除**。 + + **风格**:色板 / 圆角 / 阴影 / 图标浅底规则全部沿用,**未新增任何色值** —— cottagecore 配色纪律不动。 + + **验证**:`node .workbuddy/verify-home-layout.cjs`(新增,cwd=ruoyi-ui)⇒ **ALL_OK 28 条 0 失败** + (含 vue-template-compiler 编译模板、dart-sass 编译样式、新旧骨架核对、区块顺序、指标总数 11、交互绑定未丢); + `node .workbuddy/audit-palette.cjs` ⇒ **离版文件 0/185、离版色值 0 次**; + dev server(`:80`)`/static/js/app.js` ⇒ 200 / 7.1MB / 0 处 `Module build failed`。 + ⚠️ 本机助手拉不起 Chrome(安全策略)⇒ **渲染后实际观感未经实测**,需用户刷新页面肉眼确认。 + + **后续补丁(用户看完截图提的)**:左轨「待处理提货申请 / **提货余额**」那格里,提货余额写的是 `$9259.64` + (**美元符号**),而页面其余金额(总充值 `¥1800`、总流水 `¥0.00`、RTP 投注/奖励 `¥0.00`、经营数据 6 项 `¥…`) + 一律 `¥` ⇒ 统一为 `¥{{ balance }}`(`ruoyi-ui/src/views/index.vue:55`,全站唯一一处 `$` 货币写法,已 grep 确认)。 + `verify-home-layout.cjs` 补 2 条断言(模板内不得出现 `$` 紧跟插值;提货余额那行前缀必须是 `¥`)⇒ 现 **30 条 ALL_OK**。 + 真产物复核(新增 `.workbuddy/check-ruoyi-bundle.cjs`,从 `:80` 拉 `app.js`):编译后为 + `_vm._v("¥" + _vm._s(_vm.balance))`,`$` 版本 0 处。 + +- **推广后台首页改排版:「基本信息 / 5 张返利卡 / 汇总表」三段堆叠 → 「推广工具置顶」** + + **起因**:与上一轮管理端首页同类问题(换肤只改配色,骨架没动)。用户在 3 轮高保真稿里选定 **版本 3 · 推广工具置顶**。 + + **改动清单**(`promo-ui2/src/views/Home/index.vue`,单文件) + 1. **① 我的推广(置顶通栏)**:`hero` 行放**推广链接**(15px 加粗、超长省略、整条可复制)+ 主色「复制链接」按钮(无链接时 `disabled`); + 下面一条虚线分隔的三格:**我的邀请码**(复制 / 修改 / 已修改)、**手机号码**(绑 `phoneNumber`)、**上级邀请码**。 + 2. **② 返利 KPI 横带**(4 格,19px 数字):**累计返利 / 今日返利 / 本周返利 / 累计下级** —— + 全部从已有的 `getGameCommissionData()` 的 `periods` 里取(`总`/`今日`/`本周` 行),**不新增任何接口**。 + 3. **③ 底部两栏** `260px minmax(0,1fr)`:左 = **返利比例**(5 行「玩法名 ⋯⋯ 百分比」点线清单,替掉原来 5 张等宽卡); + 右 = **周期返利汇总**表格(列一项没删,仍是 10 列)。`@media(max-width:1200px)` 收成一栏让表格拿满宽度。 + 4. **④ 账号信息降级到最底部**:用户账号 / 用户类型 / 金币余额 / 积分余额 / 注册时间 / Steam交易链接(6 项)。 + 样式上**做成非卡片**(`background/border` 透明、去阴影),避免和上面的数据抢注意力。 + 5. 旧骨架(`.section` / `.section-title` / `.game-rate-cards` / `.rate-card*`)与那两条**从未命中过**的 + `.el-table__row tr:nth-child(odd)` 伪条纹规则一并删除(Element 的 `stripe` 已负责隔行)。 + 6. 颜色从残留的旧 Element 灰(`#f5f7fa` / `#e4e7ed` / `#303133` / `#67c23a` / `#606266` / `#909399` / `#fafafa` / `#e6a23c`) + 收敛到田园核白名单 —— 该页 scoped 样式是换肤时漏掉的一份。 + + **一字未动的**:`username: userInfo.userName`(改邀请码的**入参**,后端拿它做「只能改自己」校验,与展示用的 `phoneNumber` 语义不同); + 返利比例出处仍是 `getInfo()` 的三个 `*CommissionRate`;表格 10 列 / 弹窗 / 复制 / `onMounted` 双并发加载全部保留。 + + **验证**(新增 2 个脚本) + - `node .workbuddy/verify-promo-home.cjs` ⇒ **ALL_OK 54 条 0 失败**:新骨架 12 项、旧骨架 4 项须绝迹、区块顺序、 + 表格 10 列 / 账号 6 项 / KPI 4 项 / 玩法 5 项齐全、交互绑定 7 项、旧 Element 色 0 处、色值全在白名单、8 组对比度 ≥4.5:1。 + - `node .workbuddy/verify-promo-vue-compile.cjs`(新增,用 promo 自带的 `vue/compiler-sfc` 走 + parse → compileScript → compileTemplate → compileStyle)⇒ **ALL_OK 7 条 0 失败**。 + - `node .workbuddy/verify-home-page.cjs` ⇒ **ALL_OK 5 条 0 失败**(该脚本①的结构性正则随「手机号码」移位已改写为与结构无关的定位)。 + - **真机 dev 产物**(用户的 vite dev server 正在 `:4000` 跑,热更新):`/src/views/Home/index.vue` 的 + style / template / script-setup / main 四个模块全 200,0 处 `Transform failed` / `Internal server error`; + 编译后 15/15 个新骨架选择器都带上了 `[data-v-a763a6ae]` 前缀,旧类名 0 残留。 + + ⚠️ 两点未做实测:**渲染后观感**(本机 Chrome 拉不起来);**窄屏横向滚动** —— 底部两栏时表格可用宽度 ≈ 屏宽-200(侧栏)-80, + 10 列 `min-width` 合计 1090px,**视口 < 约 1600px 时右侧表格会出现横向滚动**(≥1600 正常),已在 `<1200px` 断点收成一栏规避。 + **数据全是 0 是账号本身无下级/无消费所致**,不是渲染问题(`periodData` 的 4 行都在,只是值都为 0.00)。 + + 过程与踩坑见 `.workbuddy/memory/2026-09-27.md`。 + +- **管理后台站点名「河南项目」→「凯科佰娱」(ruoyi-ui)** + + **起因**:用户截图(`localhost/#/index`)圈出左下角 Logo 旁标题与浏览器 tab 标题,要求改成「凯科佰娱」。 + + **定位**:截图端口 80 + hash 路由 ⇒ 是 **`ruoyi-ui`(Vue2 管理后台,`vue.config.js` 默认 port 80)**,不是 promo-ui2(:4000)。 + 站点名只有一个源:`VUE_APP_TITLE`(`.env.*`)。消费方两处 —— + `src/layout/components/Sidebar/Logo.vue:23`(侧栏标题)、`src/App.vue:20-29` 的 `metaInfo.titleTemplate` + (`${路由名} - ${VUE_APP_TITLE}`);`public/index.html` 的 `
查看所有招商及其下属主播、普通用户的汇总数据
+注意:邀请码只能修改一次,请谨慎操作!
+注意:邀请码只能修改一次,请谨慎操作!