| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- using Admin.NET.Core;
- using Microsoft.Extensions.DependencyInjection;
- using SqlSugar;
- namespace Admin.NET.Plugin.AiDOP.Infrastructure;
- /// <summary>
- /// 将 Ai-DOP 种子菜单 Id 补写到 <c>sys_tenant_menu</c> / <c>sys_role_menu</c>。
- /// 解决:<c>SysTenantMenuSeedData</c> 带 IgnoreUpdateSeed,库已存在时新增菜单不会自动进租户/角色;多租户下仅补默认租户会导致其它租户侧栏与菜单管理不可见。
- /// </summary>
- public static class AidopMenuLinkSync
- {
- /// <summary>与框架种子中首条「系统管理员」角色 Id 一致。</summary>
- private const long SysAdminRoleId = 1300000000101L;
- private const long LegacyMaterialSubstitutionMenuId = 1329003000005L;
- private const long DeprecatedMaterialSubstitutionMenuId = 1329002000004L;
- public static void EnsureLinked(IServiceProvider services)
- {
- using var scope = services.CreateScope();
- var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
- NormalizeMaterialSubstitutionMenu(db);
- NormalizeS1OrderWorkOrderParents(db);
- var seedMenus = new global::Admin.NET.Plugin.AiDOP.SysMenuSeedData().HasData().ToList();
- var seedMenuIds = seedMenus.Select(m => m.Id).ToHashSet();
- var existingMenuIds = db.Queryable<SysMenu>()
- .Where(m => seedMenuIds.Contains(m.Id))
- .Select(m => m.Id)
- .ToList()
- .ToHashSet();
- if (existingMenuIds.Count == 0)
- return;
- var tenantIds = db.Queryable<SysTenant>().Select(t => t.Id).ToList();
- if (tenantIds.Count == 0)
- return;
- var tenantMenuPairs = db.Queryable<SysTenantMenu>()
- .Where(tm => tenantIds.Contains(tm.TenantId) && seedMenuIds.Contains(tm.MenuId))
- .Select(tm => new { tm.TenantId, tm.MenuId })
- .ToList()
- .Select(x => (x.TenantId, x.MenuId))
- .ToHashSet();
- var tenantRows = new List<SysTenantMenu>();
- foreach (var tid in tenantIds)
- {
- foreach (var menu in seedMenus)
- {
- if (!existingMenuIds.Contains(menu.Id))
- continue;
- if (tenantMenuPairs.Contains((tid, menu.Id)))
- continue;
- tenantRows.Add(new SysTenantMenu
- {
- Id = CommonUtil.GetFixedHashCode("" + tid + menu.Id, 1300000000000),
- TenantId = tid,
- MenuId = menu.Id
- });
- }
- }
- if (tenantRows.Count > 0)
- db.Insertable(tenantRows).ExecuteCommand();
- // 已为任一 Ai-DOP 种子菜单授权的角色,补全新增子菜单;并始终包含默认租户系统管理员角色。
- var roleIdsWithAnyAidop = db.Queryable<SysRoleMenu>()
- .Where(rm => seedMenuIds.Contains(rm.MenuId))
- .Select(rm => rm.RoleId)
- .ToList()
- .Distinct()
- .ToHashSet();
- roleIdsWithAnyAidop.Add(SysAdminRoleId);
- var roleMenuPairs = db.Queryable<SysRoleMenu>()
- .Where(rm => roleIdsWithAnyAidop.Contains(rm.RoleId) && seedMenuIds.Contains(rm.MenuId))
- .Select(rm => new { rm.RoleId, rm.MenuId })
- .ToList()
- .Select(x => (x.RoleId, x.MenuId))
- .ToHashSet();
- var roleRows = new List<SysRoleMenu>();
- foreach (var roleId in roleIdsWithAnyAidop)
- {
- foreach (var menu in seedMenus)
- {
- if (!existingMenuIds.Contains(menu.Id))
- continue;
- if (roleMenuPairs.Contains((roleId, menu.Id)))
- continue;
- roleRows.Add(new SysRoleMenu
- {
- Id = menu.Id + (roleId % 1300000000000),
- RoleId = roleId,
- MenuId = menu.Id
- });
- }
- }
- if (roleRows.Count > 0)
- db.Insertable(roleRows).ExecuteCommand();
- }
- private static void NormalizeMaterialSubstitutionMenu(ISqlSugarClient db)
- {
- var deprecatedMenuId = DeprecatedMaterialSubstitutionMenuId;
- var legacyMenuId = LegacyMaterialSubstitutionMenuId;
- var legacyMenu = db.Queryable<SysMenu>()
- .First(m => m.Id == legacyMenuId);
- if (legacyMenu != null)
- {
- legacyMenu.Title = "物料替代";
- legacyMenu.Path = "/aidop/s0/manufacturing/material-substitution";
- legacyMenu.Name = "aidopS0MfgMaterialSubstitution";
- legacyMenu.Component = "/aidop/s0/manufacturing/MaterialSubstitutionList";
- legacyMenu.Remark = "S0 物料替代";
- db.Updateable(legacyMenu)
- .UpdateColumns(m => new { m.Title, m.Path, m.Name, m.Component, m.Remark })
- .ExecuteCommand();
- }
- var deprecatedExists = db.Queryable<SysMenu>().Any(m => m.Id == deprecatedMenuId);
- if (!deprecatedExists)
- return;
- db.Deleteable<SysUserMenu>().Where(x => x.MenuId == deprecatedMenuId).ExecuteCommand();
- db.Deleteable<SysRoleMenu>().Where(x => x.MenuId == deprecatedMenuId).ExecuteCommand();
- db.Deleteable<SysTenantMenu>().Where(x => x.MenuId == deprecatedMenuId).ExecuteCommand();
- db.Deleteable<SysMenu>().Where(x => x.Id == deprecatedMenuId).ExecuteCommand();
- }
- /// <summary>
- /// 将 S1「订单管理」「工单管理」升级为目录并修正 path/name;
- /// 「产销协同看板」单独菜单路径为 /aidop/s1/SalesKanBan;
- /// 「工单下达」父级须为工单管理目录 1322000000004(历史错误曾挂到 0005)。
- /// </summary>
- private static void NormalizeS1OrderWorkOrderParents(ISqlSugarClient db)
- {
- const long orderMgmtId = 1322000000003L;
- const long workOrderMgmtId = 1322000000004L;
- const long salesKanBanMenuId = 1322000000005L;
- const long workOrderDispatchMenuId = 1322000000106L;
- var orderMgmt = db.Queryable<SysMenu>().First(m => m.Id == orderMgmtId);
- if (orderMgmt != null)
- {
- orderMgmt.Type = MenuTypeEnum.Dir;
- orderMgmt.Component = "Layout";
- orderMgmt.Path = "/aidop/s1/order-mgmt";
- orderMgmt.Name = "aidopS1OrderMgmt";
- orderMgmt.Icon = "ele-Folder";
- db.Updateable(orderMgmt)
- .UpdateColumns(m => new { m.Type, m.Component, m.Path, m.Name, m.Icon })
- .ExecuteCommand();
- }
- var workOrderMgmt = db.Queryable<SysMenu>().First(m => m.Id == workOrderMgmtId);
- if (workOrderMgmt != null)
- {
- workOrderMgmt.Type = MenuTypeEnum.Dir;
- workOrderMgmt.Component = "Layout";
- workOrderMgmt.Path = "/aidop/s1/workorder-mgmt";
- workOrderMgmt.Name = "aidopS1WorkOrderMgmt";
- workOrderMgmt.Icon = "ele-Folder";
- db.Updateable(workOrderMgmt)
- .UpdateColumns(m => new { m.Type, m.Component, m.Path, m.Name, m.Icon })
- .ExecuteCommand();
- }
- var salesKanBan = db.Queryable<SysMenu>().First(m => m.Id == salesKanBanMenuId);
- if (salesKanBan != null)
- {
- salesKanBan.Type = MenuTypeEnum.Menu;
- salesKanBan.Component = "/aidop/kanban/s1";
- salesKanBan.Path = "/aidop/s1/SalesKanBan";
- salesKanBan.Name = "aidopS1003";
- salesKanBan.Icon = "ele-DataAnalysis";
- db.Updateable(salesKanBan)
- .UpdateColumns(m => new { m.Type, m.Component, m.Path, m.Name, m.Icon })
- .ExecuteCommand();
- }
- var dispatch = db.Queryable<SysMenu>().First(m => m.Id == workOrderDispatchMenuId);
- if (dispatch != null)
- {
- var needFix = dispatch.Pid != workOrderMgmtId
- || dispatch.Path != "/aidop/s1/workorder-mgmt/dispatch";
- if (needFix)
- {
- dispatch.Pid = workOrderMgmtId;
- dispatch.Path = "/aidop/s1/workorder-mgmt/dispatch";
- db.Updateable(dispatch)
- .UpdateColumns(m => new { m.Pid, m.Path })
- .ExecuteCommand();
- }
- }
- }
- }
|