AidopMenuLinkSync.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using Admin.NET.Core;
  2. using Microsoft.Extensions.DependencyInjection;
  3. using SqlSugar;
  4. namespace Admin.NET.Plugin.AiDOP.Infrastructure;
  5. /// <summary>
  6. /// 将 Ai-DOP 种子菜单 Id 补写到 <c>sys_tenant_menu</c> / <c>sys_role_menu</c>。
  7. /// 解决:<c>SysTenantMenuSeedData</c> 带 IgnoreUpdateSeed,库已存在时新增菜单不会自动进租户/角色;多租户下仅补默认租户会导致其它租户侧栏与菜单管理不可见。
  8. /// </summary>
  9. public static class AidopMenuLinkSync
  10. {
  11. /// <summary>与框架种子中首条「系统管理员」角色 Id 一致。</summary>
  12. private const long SysAdminRoleId = 1300000000101L;
  13. public static void EnsureLinked(IServiceProvider services)
  14. {
  15. using var scope = services.CreateScope();
  16. var db = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
  17. var seedMenus = new global::Admin.NET.Plugin.AiDOP.SysMenuSeedData().HasData().ToList();
  18. var seedMenuIds = seedMenus.Select(m => m.Id).ToHashSet();
  19. var existingMenuIds = db.Queryable<SysMenu>()
  20. .Where(m => seedMenuIds.Contains(m.Id))
  21. .Select(m => m.Id)
  22. .ToList()
  23. .ToHashSet();
  24. if (existingMenuIds.Count == 0)
  25. return;
  26. var tenantIds = db.Queryable<SysTenant>().Select(t => t.Id).ToList();
  27. if (tenantIds.Count == 0)
  28. return;
  29. var tenantMenuPairs = db.Queryable<SysTenantMenu>()
  30. .Where(tm => tenantIds.Contains(tm.TenantId) && seedMenuIds.Contains(tm.MenuId))
  31. .Select(tm => new { tm.TenantId, tm.MenuId })
  32. .ToList()
  33. .Select(x => (x.TenantId, x.MenuId))
  34. .ToHashSet();
  35. var tenantRows = new List<SysTenantMenu>();
  36. foreach (var tid in tenantIds)
  37. {
  38. foreach (var menu in seedMenus)
  39. {
  40. if (!existingMenuIds.Contains(menu.Id))
  41. continue;
  42. if (tenantMenuPairs.Contains((tid, menu.Id)))
  43. continue;
  44. tenantRows.Add(new SysTenantMenu
  45. {
  46. Id = CommonUtil.GetFixedHashCode("" + tid + menu.Id, 1300000000000),
  47. TenantId = tid,
  48. MenuId = menu.Id
  49. });
  50. }
  51. }
  52. if (tenantRows.Count > 0)
  53. db.Insertable(tenantRows).ExecuteCommand();
  54. // 已为任一 Ai-DOP 种子菜单授权的角色,补全新增子菜单;并始终包含默认租户系统管理员角色。
  55. var roleIdsWithAnyAidop = db.Queryable<SysRoleMenu>()
  56. .Where(rm => seedMenuIds.Contains(rm.MenuId))
  57. .Select(rm => rm.RoleId)
  58. .ToList()
  59. .Distinct()
  60. .ToHashSet();
  61. roleIdsWithAnyAidop.Add(SysAdminRoleId);
  62. var roleMenuPairs = db.Queryable<SysRoleMenu>()
  63. .Where(rm => roleIdsWithAnyAidop.Contains(rm.RoleId) && seedMenuIds.Contains(rm.MenuId))
  64. .Select(rm => new { rm.RoleId, rm.MenuId })
  65. .ToList()
  66. .Select(x => (x.RoleId, x.MenuId))
  67. .ToHashSet();
  68. var roleRows = new List<SysRoleMenu>();
  69. foreach (var roleId in roleIdsWithAnyAidop)
  70. {
  71. foreach (var menu in seedMenus)
  72. {
  73. if (!existingMenuIds.Contains(menu.Id))
  74. continue;
  75. if (roleMenuPairs.Contains((roleId, menu.Id)))
  76. continue;
  77. roleRows.Add(new SysRoleMenu
  78. {
  79. Id = menu.Id + (roleId % 1300000000000),
  80. RoleId = roleId,
  81. MenuId = menu.Id
  82. });
  83. }
  84. }
  85. if (roleRows.Count > 0)
  86. db.Insertable(roleRows).ExecuteCommand();
  87. }
  88. }