-- ============================================================================ -- 乐收赢 · 把「银联收单」目录下的三个**只读**页面补授给租户角色(role_id = 2) -- -- 【本脚本尚未执行】执行由用户做。执行前请先读下面「★ 为什么补」与「★ 你可以否掉哪一条」。 -- -- 交付日期:2026-09-28 -- 背景批次:收银台(扫码收款)页面联调。执行完 `lsy-cashier-menu.sql` 之后, -- 租户角色拿到了「银联收单 → 扫码收款」,但**看不到**同目录下的 -- 支付订单 / 退款记录 / 商户映射 —— 本脚本补上。 -- ============================================================================ -- -- ── ★ 为什么补:三条实测,不是推测 ───────────────────────────────────────── -- -- 1) 活库只读实测(2026-09-28,`GET /system/role/detail/2` 递归遍历): -- 角色 2(租户角色,17 个用户持有)持 54 个菜单,**268/269/270/271/272 一个都没有**; -- 同法量角色 1(管理员角色):120 个菜单,五个 id 全有。 -- ⇒ 两向读数,量具能分辨,不是「查不出来」。 -- -- 2) 文档记的**原本**形态是两个角色都有:`lsy-onboarding-menu.sql:105` 写 -- 「「收付款」目录(id=268)与三个 lsy 兄弟页(269/270/271)**也都授给了两个角色**」。 -- (`lsy-menu.sql` 自己那句「授权给 role_id = 1」是它初版写的,对不上活库现状 —— -- 同一份脚本第 141 行也承认了这一点。) -- ★ 成因**未定,不猜**:可能是有人改过角色配置,也可能是 -- 「角色详情不带授权 ⇒ 抽屉全不勾且保存清空授权」那个缺陷(`1bda59a`,2026-09-28 才修) -- 期间被谁点过一次保存。两种都不改变本脚本要恢复的目标形态。 -- -- 3) 界面文案**要求**租户去那一页:收银台在没有商户号时抛 -- 「该租户未配置商户号,请先在「手工登记商户号」中登记」 -- (`LsyMerchantService.requireByTenant`)。而「手工登记商户号」正是 -- `route_name = 'CollectionMerchant'` 那一页改名后的名字。 -- ⇒ 租户没有这一页时,这句话是**一条死路**:它指的地方租户进不去。 -- -- ── ★ 你可以否掉哪一条 ──────────────────────────────────────────────────── -- -- 前两页(支付订单 / 退款记录)是**纯读**:控制器只有 `GET /page` 与 `GET /{...}`, -- 没有写端点,租户看到的是自己租户的行(实体继承 PaymentTenantBaseEntity,租户拦截器追加条件)。 -- -- **第三页(商户映射)是唯一有写权限的**,所以单独说明,你可以只删这一段: -- · 该页三个端点(page / save / delete)**共用同一个权限串** -- `module_payment:leshouying:merchant:list` ⇒ 授了页面就等于授了新增与删除; -- · 新增时归属被强制取自认证上下文(`LeshouyingMerchantController.save` 里 -- `entity.setTenantId(null)`),请求体里写 tenant_id 无效; -- · `uk_lsy_merchant_mch_no` 是 **mch_no 全局唯一**索引 ⇒ 别人已登记的商户号抢不走。 -- · 残余风险(我认为可接受,但这是判断):租户可以登记一个**尚无人登记**的商户号。 -- 最坏后果是让那个商户号的账户收到本租户顾客的钱(钱进的是对方账户), -- 以及**占位**(该号之后别人登记不了,需管理员 delete 释放)。 -- · 若你不接受这一点:把本文件里 `CollectionMerchant` 那一行从 `pages` 的 VALUES 中删掉再执行, -- 并把上面第 3 条的文案改成「请联系平台管理员开通」。 -- -- ── ★ 幂等 ──────────────────────────────────────────────────────────────── -- -- 末条 INSERT 逐行 `NOT EXISTS`:**重跑不插重复行,也不报错**。 -- 与 `lsy-cashier-menu.sql` 不同,本脚本**不依赖任何 CTE 的非空性** —— -- 三个页面若已被手工删除,本脚本只授它找得到的行,不会去重建页面(重建请重跑 `lsy-menu.sql`, -- 但那份脚本在「目录在、页面被删」时也不会恢复,见它自己的注释)。 -- -- ── ★ 只读核对(执行后跑这三条)──────────────────────────────────────────── -- -- 1) 目录与三个页面在不在、route_name 是什么(锚点用身份,不用会变的 name): -- SELECT id, name, type, route_name, route_path, status -- FROM sys_menu -- WHERE route_name IN ('Collection','CollectionOrder','CollectionRefund','CollectionMerchant') -- ORDER BY id; -- 期望:**4 行**,status 全 '0'。(本次实测 id:268 目录 / 269 / 270 / 271, -- 但 id 不是锚点,别把它当判据。) -- -- 2) 授权行: -- SELECT rm.role_id, m.name, m.permission -- FROM sys_role_menus rm JOIN sys_menu m ON m.id = rm.menu_id -- WHERE m.route_name IN ('Collection','CollectionOrder','CollectionRefund','CollectionMerchant') -- ORDER BY m.id, rm.role_id; -- 期望:role 1 与 role 2 **各 4 行 = 共 8 行**。 -- -- 3) 端到端(界面):以租户账号重新登录 ⇒ 「银联收单」下应出现 4 个页面。 -- ★ 必须**重新登录**:路由与权限来自登录时下发的 user 快照,不重登看不到变化。 -- -- ── ★ 收回 ──────────────────────────────────────────────────────────────── -- -- DELETE FROM sys_role_menus -- WHERE role_id = 2 -- AND menu_id IN (SELECT id FROM sys_menu -- WHERE route_name IN ('Collection','CollectionOrder', -- 'CollectionRefund','CollectionMerchant')); -- ★ 收回**目录行**(`route_name='Collection'`)才是让整块从角色 2 视野里消失的那一下 —— -- `UserService.buildMenuTree` 对「父不在集合里」的子节点是**静默丢弃**(无 else 分支,不报错)。 -- ★ 若只想收回商户映射一页,把上面 IN 列表里的 'CollectionMerchant' 去掉即可; -- 但**不要**连 'Collection' 一起收回,否则另外两页也会一起消失。 -- ============================================================================ -- 目录 + 三个页面,一次算出要授的 menu_id 集合。锚 route_name(身份),不锚 name(标签)。 WITH pages AS ( SELECT id FROM sys_menu WHERE route_name IN ('CollectionOrder', 'CollectionRefund', 'CollectionMerchant') AND type = 2 AND status = '0' UNION ALL SELECT id FROM sys_menu WHERE route_name = 'Collection' AND type = 1 AND status = '0' ) INSERT INTO sys_role_menus (role_id, menu_id) SELECT 2, p.id FROM pages p WHERE NOT EXISTS (SELECT 1 FROM sys_role_menus rm WHERE rm.role_id = 2 AND rm.menu_id = p.id);