Selaa lähdekoodia

fix(s8): align dashboard data scope to s1-s7 modules

YY968XX 2 viikkoa sitten
vanhempi
commit
c629a40fa2

+ 2 - 0
Web/src/views/aidop/s8/dashboard/S8DashboardPage.vue

@@ -363,9 +363,11 @@ async function loadDimTrends() {
 }
 
 async function loadDetail() {
+	// S8-DASHBOARD-DATA-ALIGN-S1S7-1:看板明细表与 KPI 同口径,仅显示 module_code IN S1-S7。
 	const params: Record<string, any> = {
 		page: detailPage.value,
 		pageSize: detailPageSize.value,
+		onlyS1S7Modules: true,
 	};
 	const filter = currentPanelFilter.value;
 	if (filter.severity) params.severity = filter.severity;

+ 3 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Dto/S8/AdoS8Dtos.cs

@@ -23,6 +23,9 @@ public class AdoS8ExceptionQueryDto
     public string? RecoveredStatus { get; set; }
     /// <summary>规则类型筛选:OUT_OF_RANGE / TIMEOUT / SHORTAGE / 空=不限;通过 source_rule_code join watch_rule.rule_type。</summary>
     public string? RuleType { get; set; }
+    /// <summary>S8-DASHBOARD-DATA-ALIGN-S1S7-1:仅返回 module_code IN S1-S7 的异常;看板明细表传 true 与 KPI 口径对齐。
+    /// 默认 false 以保证异常列表页(/aidop/s8/exceptions)行为不变。</summary>
+    public bool? OnlyS1S7Modules { get; set; }
     public int Page { get; set; } = 1;
     public int PageSize { get; set; } = 20;
 }

+ 7 - 17
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/S8DashboardCellDataService.cs

@@ -53,8 +53,10 @@ public class S8DashboardCellDataService : ITransient
         var effectiveDeptGroupBy = !string.IsNullOrWhiteSpace(q.DeptGroupBy) ? q.DeptGroupBy! : cfg.DeptGroupBy;
 
         // 取事实数据
+        // S8-DASHBOARD-DATA-ALIGN-S1S7-1:统一只统计 module_code IN S1-S7;不依赖 SceneCode 派生模块。
         var events = await _exRep.AsQueryable()
             .Where(e => e.TenantId == q.TenantId && e.FactoryId == q.FactoryId && !e.IsDeleted)
+            .Where(e => S8ModuleCode.All.Contains(e.ModuleCode))
             .Where(e => e.CreatedAt >= from && e.CreatedAt < to)
             .Select(e => new EvtRow
             {
@@ -121,25 +123,13 @@ public class S8DashboardCellDataService : ITransient
         };
     }
 
-    // S8-SCENE-MIGRATE-RUNTIME-CODE-S1S7-1:DOMAIN_x 改为 S1–S7 多 scene OR;
-    // 同时保留旧复合 scene 兼容(27 行历史 active exception 在 HISTORY-CLEANUP 之前仍引用)
+    // S8-DASHBOARD-DATA-ALIGN-S1S7-1:DOMAIN_x 统一按 ModuleCode 归类(不再依赖 SceneCode 与 legacy 复合场景)。
+    // 上游 events 已过滤 module_code IN S1-S7,此处仅按业务域切片
     private static IEnumerable<EvtRow> ApplyAggregateScope(List<EvtRow> events, string? scope) => scope switch
     {
-        "DOMAIN_DELIVERY"   => events.Where(e =>
-            e.SceneCode == S8SceneCode.S1
-            || e.SceneCode == S8SceneCode.S7
-            || e.SceneCode == S8SceneCode.S1S7Delivery),
-        "DOMAIN_PRODUCTION" => events.Where(e =>
-            e.SceneCode == S8SceneCode.S2
-            || e.SceneCode == S8SceneCode.S6
-            || e.SceneCode == S8SceneCode.S2S6Production
-            || e.SceneCode == "S2S6_QUALITY"),
-        "DOMAIN_SUPPLY"     => events.Where(e =>
-            e.SceneCode == S8SceneCode.S3
-            || e.SceneCode == S8SceneCode.S4
-            || e.SceneCode == S8SceneCode.S5
-            || e.SceneCode == S8SceneCode.S3S5Supply
-            || e.SceneCode == S8SceneCode.S4Purchase),
+        "DOMAIN_DELIVERY"   => events.Where(e => e.ModuleCode == "S1" || e.ModuleCode == "S7"),
+        "DOMAIN_PRODUCTION" => events.Where(e => e.ModuleCode == "S2" || e.ModuleCode == "S6"),
+        "DOMAIN_SUPPLY"     => events.Where(e => e.ModuleCode == "S3" || e.ModuleCode == "S4" || e.ModuleCode == "S5"),
         "ALL"               => events,
         _                   => events,
     };

+ 10 - 1
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/S8DashboardService.cs

@@ -1,6 +1,7 @@
 using Admin.NET.Plugin.AiDOP.Entity.S0.Manufacturing;
 using Admin.NET.Plugin.AiDOP.Entity.S0.Warehouse;
 using Admin.NET.Plugin.AiDOP.Entity.S8;
+using Admin.NET.Plugin.AiDOP.Infrastructure.S8;
 
 namespace Admin.NET.Plugin.AiDOP.Service.S8;
 
@@ -25,8 +26,10 @@ public class S8DashboardService : ITransient
         // 看板顶部的"开始/结束日期"通过 beginTime/endTime 透传,与列表的 beginTime/endTime 同语义。
         // BUG-12:补 severity 过滤,与异常列表 API 的 severity 口径一致(精确匹配 LOW/MEDIUM/HIGH/CRITICAL)。
         // BUG-22:REJECTED 状态归入 pending 桶,避免从总数视角"消失";与列表 statusBucket="pending" 同步对齐。
+        // S8-DASHBOARD-DATA-ALIGN-S1S7-1:统一只统计 module_code IN S1-S7;NULL module 的 legacy 行不参与看板 KPI。
         var q = _rep.AsQueryable()
             .Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && !x.IsDeleted)
+            .Where(x => S8ModuleCode.All.Contains(x.ModuleCode))
             .WhereIF(beginTime.HasValue, x => x.CreatedAt >= beginTime!.Value)
             .WhereIF(endTime.HasValue, x => x.CreatedAt <= endTime!.Value)
             .WhereIF(!string.IsNullOrWhiteSpace(severity), x => x.Severity == severity);
@@ -57,6 +60,7 @@ public class S8DashboardService : ITransient
         var from = DateTime.Today.AddDays(-Math.Clamp(days, 1, 90));
         var rows = await _rep.AsQueryable()
             .Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && !x.IsDeleted && x.CreatedAt >= from)
+            .Where(x => S8ModuleCode.All.Contains(x.ModuleCode))
             .Select(x => new { x.CreatedAt })
             .ToListAsync();
 
@@ -71,6 +75,7 @@ public class S8DashboardService : ITransient
     {
         var list = await _rep.AsQueryable()
             .Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && !x.IsDeleted)
+            .Where(x => S8ModuleCode.All.Contains(x.ModuleCode))
             .Select(x => new
             {
                 x.Status,
@@ -151,6 +156,7 @@ public class S8DashboardService : ITransient
 
         var list = await _rep.AsQueryable()
             .Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && !x.IsDeleted)
+            .Where(x => S8ModuleCode.All.Contains(x.ModuleCode))
             .Select(x => new { x.ResponsibleDeptId, x.Status, x.TimeoutFlag })
             .ToListAsync();
 
@@ -186,6 +192,7 @@ public class S8DashboardService : ITransient
 
         var rows = await _rep.AsQueryable()
             .Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && !x.IsDeleted && x.CreatedAt >= from)
+            .Where(x => S8ModuleCode.All.Contains(x.ModuleCode))
             .Select(x => new
             {
                 x.CreatedAt,
@@ -247,7 +254,9 @@ public class S8DashboardService : ITransient
 
     public async Task<List<AdoS8Exception>> GetQuickExceptionsAsync(long tenantId, long factoryId, string mode)
     {
-        var q = _rep.AsQueryable().Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && !x.IsDeleted);
+        var q = _rep.AsQueryable()
+            .Where(x => x.TenantId == tenantId && x.FactoryId == factoryId && !x.IsDeleted)
+            .Where(x => S8ModuleCode.All.Contains(x.ModuleCode));
         var ordered = mode switch
         {
             "high-priority" => q.OrderBy(x => x.PriorityScore, OrderByType.Desc),

+ 3 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/S8ExceptionService.cs

@@ -46,6 +46,9 @@ public class S8ExceptionService : ITransient
             .WhereIF(!string.IsNullOrWhiteSpace(q.Severity), (e, sc, wr) => e.Severity == q.Severity)
             .WhereIF(!string.IsNullOrWhiteSpace(q.SceneCode), (e, sc, wr) => e.SceneCode == q.SceneCode)
             .WhereIF(!string.IsNullOrWhiteSpace(q.ModuleCode), (e, sc, wr) => e.ModuleCode == q.ModuleCode)
+            // S8-DASHBOARD-DATA-ALIGN-S1S7-1:看板明细表传 OnlyS1S7Modules=true 时与 KPI 口径对齐;
+            // 异常列表页不传该参数,行为保持不变(仍可见 NULL module 的 legacy 行)。
+            .WhereIF(q.OnlyS1S7Modules == true, (e, sc, wr) => S8ModuleCode.All.Contains(e.ModuleCode))
             .WhereIF(q.DeptId.HasValue, (e, sc, wr) => e.ResponsibleDeptId == q.DeptId!.Value || e.OccurrenceDeptId == q.DeptId!.Value)
             .WhereIF(q.TimeoutFlag.HasValue, (e, sc, wr) => e.TimeoutFlag == q.TimeoutFlag!.Value)
             .WhereIF(q.BeginTime.HasValue, (e, sc, wr) => e.CreatedAt >= q.BeginTime!.Value)

+ 5 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/S8MonitoringService.cs

@@ -26,8 +26,11 @@ public class S8MonitoringService : ITransient
     /// </summary>
     public async Task<AdoS8OrderGridDto> GetOrderGridAsync(long tenantId = 1, long factoryId = 1)
     {
+        // S8-DASHBOARD-DATA-ALIGN-S1S7-1:统一统计基准 module_code IN S1-S7;
+        // module_code IS NULL 的 legacy/demo 行不参与大屏聚合(不依赖 scene_code、不映射 legacy scene)。
         var events = await _rep.AsQueryable()
             .Where(e => e.TenantId == tenantId && e.FactoryId == factoryId && !e.IsDeleted)
+            .Where(e => S8ModuleCode.All.Contains(e.ModuleCode))
             .Select(e => new
             {
                 e.ModuleCode,
@@ -187,6 +190,8 @@ public class S8MonitoringService : ITransient
     {
         var query = _rep.AsQueryable()
             .Where(e => e.TenantId == q.TenantId && e.FactoryId == q.FactoryId && !e.IsDeleted)
+            // S8-DASHBOARD-DATA-ALIGN-S1S7-1:统一统计基准 module_code IN S1-S7。
+            .Where(e => S8ModuleCode.All.Contains(e.ModuleCode))
             .WhereIF(!string.IsNullOrWhiteSpace(q.SceneCode), e => e.SceneCode == q.SceneCode)
             .WhereIF(!string.IsNullOrWhiteSpace(q.ModuleCode), e => e.ModuleCode == q.ModuleCode)
             .WhereIF(q.BizDateFrom.HasValue, e => e.CreatedAt >= q.BizDateFrom!.Value)