using Admin.NET.Core; using Admin.NET.Plugin.AiDOP.Entity; using Admin.NET.Plugin.AiDOP.Infrastructure; namespace Admin.NET.Plugin.AiDOP.SmartOps; /// /// 提交前校验正式审批角色在当前租户可解析,禁止静默跳过。 /// public sealed class SmartOpsImprovementApproverGuard : ITransient { private readonly ISqlSugarClient _db; public SmartOpsImprovementApproverGuard(ISqlSugarClient db) => _db = db; public async Task EnsureResolvableAsync(AdoSmartOpsImprovementPlan plan) { var tenantId = plan.TenantId ?? 0; SmartOpsTrustedScopeRules.EnsureBusinessTenant(tenantId); var route = SmartOpsImprovementApprovalRules.ResolveRoute(plan); var missing = new List(); foreach (var code in SmartOpsImprovementApprovalRules.RequiredRoleCodes(route)) { var role = await _db.Queryable() .ClearFilter() .FirstAsync(r => r.TenantId == tenantId && r.Code == code && r.Status == StatusEnum.Enable); var label = SmartOpsImprovementApprovalRules.RoleName(code); if (role == null) { missing.Add($"{label}({code})角色不存在或已停用"); continue; } var userIds = await _db.Queryable() .ClearFilter() .Where(x => x.RoleId == role.Id) .Select(x => x.UserId) .ToListAsync(); var hasMember = userIds.Count > 0 && await _db.Queryable() .ClearFilter() .AnyAsync(u => userIds.Contains(u.Id) && u.TenantId == tenantId && u.Status == StatusEnum.Enable); if (!hasMember) missing.Add($"{label}({code})没有启用成员"); } if (missing.Count > 0) throw Oops.Oh("无可解析审批人,已拒绝提交:" + string.Join(";", missing)); } }