S8NotificationLayerService.cs 4.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using Admin.NET.Core;
  2. using Admin.NET.Plugin.AiDOP.Entity.S8;
  3. using Admin.NET.Plugin.AiDOP.Infrastructure;
  4. using Admin.NET.Plugin.AiDOP.Infrastructure.S8;
  5. namespace Admin.NET.Plugin.AiDOP.Service.S8;
  6. public class S8NotificationLayerService : ITransient
  7. {
  8. private readonly SqlSugarRepository<AdoS8NotificationLayer> _rep;
  9. private readonly SqlSugarRepository<SysRole> _roleRep;
  10. public S8NotificationLayerService(
  11. SqlSugarRepository<AdoS8NotificationLayer> rep,
  12. SqlSugarRepository<SysRole> roleRep)
  13. {
  14. _rep = rep;
  15. _roleRep = roleRep;
  16. }
  17. public async Task<List<AdoS8NotificationLayer>> ListAsync(long tenantId, long factoryId) =>
  18. await _rep.AsQueryable()
  19. .Where(x => x.TenantId == tenantId && x.FactoryId == factoryId)
  20. .ToListAsync();
  21. public async Task<List<object>> GetRoleOptionsAsync()
  22. {
  23. var roles = await _roleRep.AsQueryable()
  24. .Where(x => (x.Id >= 1329908000101L && x.Id <= 1329908000107L) || x.Id == 1300000000101L)
  25. .OrderBy(x => x.Id)
  26. .Select(x => new { value = x.Code, label = x.Name })
  27. .ToListAsync();
  28. return roles.Cast<object>().ToList();
  29. }
  30. // S8-TENANT-FACTORY-P0-CLOSURE-1:归属一律由服务端可信作用域盖章,忽略 body.TenantId / body.FactoryId。
  31. public async Task<AdoS8NotificationLayer> CreateAsync(AdoS8NotificationLayer body, S8TrustedScope scope)
  32. {
  33. if (string.IsNullOrWhiteSpace(body.SceneCode) || string.IsNullOrWhiteSpace(body.Severity) || string.IsNullOrWhiteSpace(body.LevelCode))
  34. throw new S8BizException("场景、严重度、层级必填");
  35. if (string.IsNullOrWhiteSpace(body.TargetRoleIds))
  36. throw new S8BizException("目标角色必填");
  37. if (string.IsNullOrWhiteSpace(body.NotifyChannel))
  38. throw new S8BizException("通知渠道至少选一个");
  39. // S8-SEVERITY-FOLLOW-SERIOUS-STANDARDIZE-EXEC-1:归一为 FOLLOW/SERIOUS 后再校验/写入。
  40. body.Severity = S8SeverityCode.Normalize(body.Severity);
  41. body.TenantId = scope.TenantId;
  42. body.FactoryId = scope.FactoryId;
  43. var exists = await _rep.AsQueryable()
  44. .AnyAsync(x => x.TenantId == body.TenantId && x.FactoryId == body.FactoryId &&
  45. x.SceneCode == body.SceneCode && x.Severity == body.Severity && x.LevelCode == body.LevelCode);
  46. if (exists) throw new S8BizException("同场景+严重度+层级已存在");
  47. body.Id = 0;
  48. body.CreatedAt = DateTime.Now;
  49. return await _rep.InsertReturnEntityAsync(body);
  50. }
  51. // S8-TENANT-FACTORY-P0-CLOSURE-1:按 Id + 可信作用域绑行;越权 Id 视为不存在,归属不可被 body 改写。
  52. public async Task<AdoS8NotificationLayer> UpdateAsync(long id, AdoS8NotificationLayer body, S8TrustedScope scope)
  53. {
  54. var e = await LoadScopedAsync(id, scope);
  55. if (string.IsNullOrWhiteSpace(body.SceneCode) || string.IsNullOrWhiteSpace(body.Severity) || string.IsNullOrWhiteSpace(body.LevelCode))
  56. throw new S8BizException("场景、严重度、层级必填");
  57. if (string.IsNullOrWhiteSpace(body.TargetRoleIds))
  58. throw new S8BizException("目标角色必填");
  59. if (string.IsNullOrWhiteSpace(body.NotifyChannel))
  60. throw new S8BizException("通知渠道至少选一个");
  61. // S8-SEVERITY-FOLLOW-SERIOUS-STANDARDIZE-EXEC-1:归一为 FOLLOW/SERIOUS 后再校验/写入。
  62. body.Severity = S8SeverityCode.Normalize(body.Severity);
  63. var exists = await _rep.AsQueryable()
  64. .AnyAsync(x => x.Id != id && x.TenantId == e.TenantId && x.FactoryId == e.FactoryId &&
  65. x.SceneCode == body.SceneCode && x.Severity == body.Severity && x.LevelCode == body.LevelCode);
  66. if (exists) throw new S8BizException("同场景+严重度+层级已存在");
  67. body.Id = id;
  68. body.TenantId = e.TenantId;
  69. body.FactoryId = e.FactoryId;
  70. body.CreatedAt = e.CreatedAt;
  71. body.UpdatedAt = DateTime.Now;
  72. await _rep.UpdateAsync(body);
  73. return body;
  74. }
  75. // S8-TENANT-FACTORY-P0-CLOSURE-1:删除必须先按可信作用域绑行,禁止裸 DeleteByIdAsync(id)。
  76. public async Task DeleteAsync(long id, S8TrustedScope scope)
  77. {
  78. var e = await LoadScopedAsync(id, scope);
  79. await _rep.DeleteByIdAsync(e.Id);
  80. }
  81. private async Task<AdoS8NotificationLayer> LoadScopedAsync(long id, S8TrustedScope scope) =>
  82. await _rep.AsQueryable()
  83. .Where(x => x.Id == id && x.TenantId == scope.TenantId && x.FactoryId == scope.FactoryId)
  84. .FirstAsync() ?? throw new S8NotFoundException();
  85. }