using Admin.NET.Core;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
namespace Admin.NET.Plugin.AiDOP.Infrastructure;
///
/// 将 Ai-DOP 种子菜单 Id 补写到 sys_tenant_menu / sys_role_menu。
/// 解决:SysTenantMenuSeedData 带 IgnoreUpdateSeed,库已存在时新增菜单不会自动进租户/角色;多租户下仅补默认租户会导致其它租户侧栏与菜单管理不可见。
///
public static class AidopMenuLinkSync
{
/// 与框架种子中首条「系统管理员」角色 Id 一致。
private const long SysAdminRoleId = 1300000000101L;
public static void EnsureLinked(IServiceProvider services)
{
using var scope = services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService();
var seedMenus = new global::Admin.NET.Plugin.AiDOP.SysMenuSeedData().HasData().ToList();
var seedMenuIds = seedMenus.Select(m => m.Id).ToHashSet();
var existingMenuIds = db.Queryable()
.Where(m => seedMenuIds.Contains(m.Id))
.Select(m => m.Id)
.ToList()
.ToHashSet();
if (existingMenuIds.Count == 0)
return;
var tenantIds = db.Queryable().Select(t => t.Id).ToList();
if (tenantIds.Count == 0)
return;
var tenantMenuPairs = db.Queryable()
.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();
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()
.Where(rm => seedMenuIds.Contains(rm.MenuId))
.Select(rm => rm.RoleId)
.ToList()
.Distinct()
.ToHashSet();
roleIdsWithAnyAidop.Add(SysAdminRoleId);
var roleMenuPairs = db.Queryable()
.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();
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();
}
}