| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- -- ============================================================================
- -- 1.0.435:修复 1.0.433 引入的角色授权回归 —— 按钮权限挂载点选错导致父菜单被丢
- --
- -- 回归现象(RUNTIME VERIFIED):
- -- UATAdminA 打开 /aidop/s5/inventory/stock-query 返回 404;
- -- 其菜单树里「库存查询」消失,同级其余 5 个页面均在。
- -- 实测 UAT_FUNCTION_USER(838258976469061) 的 SysRoleMenu 已无 MenuId=1329015030003,
- -- 而对照租户 B 的同名角色仍有。
- --
- -- 根因(CODE VERIFIED,SysMenuService.cs:468-486 角色授权树「已勾选」计算):
- -- foreach (var id in menuIds) {
- -- if (是按钮) continue;
- -- var children = menuList.ToChildList(..., id, false);
- -- if (children.Count == 0 || children.All(u => menuIds.Contains(u.Id))) continue;
- -- exceptList.Add(id); // 有子节点但未全部持有 → 从「已勾选」中排除
- -- }
- -- 1.0.433 把 6 个按钮权限挂在「库存查询」(1329015030003) 下。该菜单原本是**叶子**
- -- (children.Count==0,永不排除);挂上按钮后,业务角色一个按钮都不持有
- -- → children.All(...) 为假 → 「库存查询」被排除出已勾选集合。
- -- 前端 editRole.vue:118-120 提交的是 checkedKeys ∪ halfCheckedKeys:
- -- 它既不在已勾选(被排除),其子节点又全未勾选(不构成半选)
- -- → 管理员下一次保存该角色时它被 GrantRoleMenu 全量覆盖删除。
- -- 祖先目录(库存数据 / S5 物料仓储 / Ai-DOP)因仍有其他已勾选子节点而处于**半选**,
- -- 得以幸存,所以只丢了这一条。
- -- 注:该「已勾选」计算用 GetSugarQueryableAndTenantId(0),**不按租户过滤**,
- -- 因此 1.0.433 只授权给 AIDOP 租户的按钮,同样会影响 UAT 租户角色的勾选态。
- --
- -- 修复方案:
- -- ① 新建**隐藏管理目录**「库存冷链入站(管理)」挂在 S5 物料仓储下,
- -- 6 个按钮权限改挂到它下面 → 「库存查询」恢复为叶子,永不再被排除。
- -- 新目录不授予任何业务角色 → 不在任何业务角色的 menuIds 中 → 排除循环不会遍历到它。
- -- 其父节点 S5 物料仓储 仍有多个已授权子节点(实测「持有 S5 目录却不持有其任何子节点」
- -- 的角色数 = 0),故各角色对该目录仍为半选,不受影响。
- -- ② 恢复 UAT_FUNCTION_USER 丢失的「库存查询」授权(精确到单租户单角色单菜单)。
- --
- -- 明确不做:不改任何按钮权限的 Permission 名、不改租户级授权范围、
- -- 不给任何业务角色新增管理权限、不使用 GrantMenu 全量覆盖、不按 RoleCode 跨租户处理。
- --
- -- 幂等:INSERT 带 NOT EXISTS;UPDATE 带目标状态限定,重复执行影响行数为 0。
- -- ============================================================================
- -- ---------------------------------------------------------------------------
- -- 1. 新建隐藏管理目录(按钮权限的专用挂载点)
- -- ---------------------------------------------------------------------------
- INSERT INTO SysMenu (Id, Pid, Type, Name, Title, Icon,
- IsIframe, IsHide, IsKeepAlive, IsAffix, OrderNo, Status, Remark, CreateTime)
- SELECT 1329015030100, 1321000006000, 1, 'aidopS5InvInboundAdmin', '库存冷链入站(管理)', 'ele-Menu',
- 0, 1, 1, 0, 900, 1,
- 'S5 冷链入站管理权限点的专用挂载目录(隐藏)。刻意独立成节点:SysMenuService 的角色授权树会把「有子节点但未全部持有」的菜单排除出已勾选,若把按钮挂到业务页面下,会导致该页面在下次角色保存时被删除(见 1.0.433 回归)。',
- NOW()
- FROM DUAL
- WHERE NOT EXISTS (SELECT 1 FROM SysMenu WHERE Id = 1329015030100);
- -- ---------------------------------------------------------------------------
- -- 2. 6 个按钮权限改挂到该隐藏目录(原挂在「库存查询」1329015030003 下)
- -- ---------------------------------------------------------------------------
- UPDATE SysMenu
- SET Pid = 1329015030100, UpdateTime = NOW()
- WHERE Type = 3
- AND Pid = 1329015030003
- AND Permission IN (
- 's5InventoryInbound:bootstrap',
- 's5InventoryInbound:run-once',
- 's5InventoryInbound:reconcile',
- 's5InventoryInbound:transform-std',
- 's5InventoryInbound:transform-inventory-std',
- 's5InventoryInbound:daily-recon');
- -- ---------------------------------------------------------------------------
- -- 3. 管理租户(AIDOP)对该隐藏目录的租户级授权(与 1.0.433 的按钮授权保持同一租户)
- -- ---------------------------------------------------------------------------
- INSERT INTO SysTenantMenu (Id, TenantId, MenuId)
- SELECT (SELECT IFNULL(MAX(Id), 0) + 1 FROM SysTenantMenu tm2),
- t.Id, 1329015030100
- FROM SysTenant t
- JOIN SysOrg o ON o.Id = t.OrgId
- WHERE o.Code = 'AIDOP' AND t.Status = 1
- AND EXISTS (SELECT 1 FROM SysMenu WHERE Id = 1329015030100)
- AND NOT EXISTS (
- SELECT 1 FROM SysTenantMenu tm
- WHERE tm.TenantId = t.Id AND tm.MenuId = 1329015030100)
- LIMIT 1;
- -- ---------------------------------------------------------------------------
- -- 4. 恢复被回归删除的「库存查询」角色授权(精确单租户单角色单菜单)
- -- TenantId 838257186181189 / RoleId 838258976469061 / MenuId 1329015030003
- -- ---------------------------------------------------------------------------
- INSERT INTO SysRoleMenu (Id, RoleId, MenuId)
- SELECT (SELECT IFNULL(MAX(Id), 0) + 1 FROM SysRoleMenu rm2), r.Id, m.Id
- FROM SysRole r
- JOIN SysMenu m ON m.Id = 1329015030003 AND m.Type = 2 AND m.Status = 1
- WHERE r.Id = 838258976469061
- AND r.TenantId = 838257186181189
- AND r.Status = 1
- AND EXISTS (
- SELECT 1 FROM SysTenantMenu t
- WHERE t.TenantId = r.TenantId AND t.MenuId = m.Id)
- AND NOT EXISTS (
- SELECT 1 FROM SysRoleMenu x
- WHERE x.RoleId = r.Id AND x.MenuId = m.Id);
|