diff --git a/docs/06-测试规范.md b/docs/06-测试规范.md index 03eb655..6bdd1a1 100644 --- a/docs/06-测试规范.md +++ b/docs/06-测试规范.md @@ -58,6 +58,7 @@ | 1 | 页面加载 | URL正确 + 关键元素可见 | 所有页面 | 只goto不等待 | | 2 | 默认数据 | 打开即有数据(行数>0 / 卡片有值) | 有数据展示的页面 | 不检查数据 | | 3 | 汇总卡片数值 | ≠ 空 ≠ `-` ≠ `--` ≠ `undefined` ≠ `null` | 有统计卡片的页面 | 只检查可见 | +| 3.1 | 图表有数据 | Canvas/SVG已渲染 + 有数据点/色块(非空白) | 有ECharts/Chart组件的页面 | 只检查容器可见 | | 4 | 表格行数 | `.el-table__row` > 0 | 有表格的页面 | 只检查table可见 | | 5 | 表格每列有值 | 第一行逐列文本非空 | 有表格的页面 | 只检查前2-3列 | | 6 | 时间/数值列 | 有具体数值(非空非NULL) | 有时间/数值列的页面 | 跳过 | @@ -82,7 +83,7 @@ |----------|-------------| | 列表页(表格+筛选) | 1,2,4,5,8,9,10,13,14,19 | | 列表页(表格+筛选+卡片) | 1,2,3,4,5,6,7,8,9,10,13,14,17,19 | -| 仪表盘/概览页 | 1,2,3,20 | +| 仪表盘/概览页 | 1,2,3,3.1,5,6,9,12,17,20 | | 详情/表单页 | 1,15,16 | | 所有页面 | 1,20 | @@ -104,6 +105,7 @@ | 元素 | 验证标准 | |------|----------| | 汇总卡片 | 非空 ∧ ≠ `""` ∧ ≠ `"-"` ∧ ≠ `"--"` ∧ ≠ `"undefined"` ∧ ≠ `"null"` | +| 图表(ECharts等) | Canvas/SVG存在 + 非空白(有数据点/扇形/柱状) | | 表格数据列 | 第一行每列有文本值 | | 状态标签 | 已知中文文案 | | 时间列 | 有值且格式正确 | @@ -183,3 +185,4 @@ $headers = @{ Authorization = "Bearer $token" } | 11 | 测试不按维度表逐项覆盖 | 对照5.0维度总表 | | 12 | 测试只覆盖部分页面 | 每个改动涉及的页面都要覆盖 | | 13 | 新增维度后不更新维度总表 | 新发现的问题必须补充为新维度 | +| 14 | 图表只检查容器DOM存在 | 验证Canvas/SVG有实际渲染内容(数据点/色块) | diff --git a/src/CncModels/Dto/Dashboard/AlertListItem.cs b/src/CncModels/Dto/Dashboard/AlertListItem.cs index d7e7a35..99b5c82 100644 --- a/src/CncModels/Dto/Dashboard/AlertListItem.cs +++ b/src/CncModels/Dto/Dashboard/AlertListItem.cs @@ -8,8 +8,15 @@ namespace CncModels.Dto.Dashboard public class AlertListItem { public long Id { get; set; } - public string Message { get; set; } - public string Severity { get; set; } + /// 告警时间 public DateTime CreatedAt { get; set; } + /// 告警类型 + public string AlertType { get; set; } + /// 机床名称 + public string MachineName { get; set; } + /// 告警标题 + public string Title { get; set; } + /// 是否已处理 + public bool IsResolved { get; set; } } } diff --git a/src/CncModels/Dto/Dashboard/MachineRankResponse.cs b/src/CncModels/Dto/Dashboard/MachineRankResponse.cs index 0e3fda9..3aef658 100644 --- a/src/CncModels/Dto/Dashboard/MachineRankResponse.cs +++ b/src/CncModels/Dto/Dashboard/MachineRankResponse.cs @@ -7,8 +7,17 @@ namespace CncModels.Dto.Dashboard /// public class MachineRankResponse { + /// 排名 + public int Rank { get; set; } + /// 机床ID public int MachineId { get; set; } + /// 机床名称 public string MachineName { get; set; } + /// 当前NC程序名 + public string Program { get; set; } + /// 产量 public int Quantity { get; set; } + /// 机床状态:1=在线 0=离线 + public int Status { get; set; } } } diff --git a/src/CncModels/Dto/Dashboard/WorkerRankResponse.cs b/src/CncModels/Dto/Dashboard/WorkerRankResponse.cs index 5fdbc77..66b23a7 100644 --- a/src/CncModels/Dto/Dashboard/WorkerRankResponse.cs +++ b/src/CncModels/Dto/Dashboard/WorkerRankResponse.cs @@ -7,7 +7,13 @@ namespace CncModels.Dto.Dashboard /// public class WorkerRankResponse { + /// 排名 + public int Rank { get; set; } + /// 工人姓名 public string WorkerName { get; set; } - public int Quantity { get; set; } + /// 绑定机床数 + public int MachineCount { get; set; } + /// 总产量 + public int TotalQuantity { get; set; } } } diff --git a/src/CncRepository/Impl/Dashboard/DashboardRepository.cs b/src/CncRepository/Impl/Dashboard/DashboardRepository.cs index a3ecf36..9442d4b 100644 --- a/src/CncRepository/Impl/Dashboard/DashboardRepository.cs +++ b/src/CncRepository/Impl/Dashboard/DashboardRepository.cs @@ -137,7 +137,11 @@ namespace CncRepository.Impl.Dashboard var sql = @" SELECT m.id AS MachineId, m.name AS MachineName, - COALESCE(SUM(ad.day_quantity), 0) AS Quantity + COALESCE(SUM(ad.day_quantity), 0) AS Quantity, + CAST(m.is_online AS SIGNED) AS Status, + (SELECT seg.program_name FROM cnc_production_segment seg + WHERE seg.machine_id = m.id AND seg.production_date = CURDATE() + ORDER BY seg.id DESC LIMIT 1) AS Program FROM cnc_machine m LEFT JOIN ( SELECT machine_id, production_date, day_quantity FROM ( @@ -158,10 +162,13 @@ namespace CncRepository.Impl.Dashboard ) GROUP BY seg.machine_id, seg.production_date ) ad ON ad.machine_id = m.id - GROUP BY m.id, m.name + GROUP BY m.id, m.name, m.is_online ORDER BY Quantity DESC LIMIT @Top"; - return conn.Query(sql, new { StartDate = startDate, EndDate = endDate, Top = top }).ToList(); + var rows = conn.Query(sql, new { StartDate = startDate, EndDate = endDate, Top = top }).ToList(); + // 填充排名 + for (int i = 0; i < rows.Count; i++) rows[i].Rank = i + 1; + return rows; } } @@ -172,7 +179,8 @@ namespace CncRepository.Impl.Dashboard { var sql = @" SELECT w.name AS WorkerName, - COALESCE(SUM(ad.day_quantity), 0) AS Quantity + COUNT(DISTINCT wm.machine_id) AS MachineCount, + COALESCE(SUM(ad.day_quantity), 0) AS TotalQuantity FROM cnc_worker w LEFT JOIN cnc_worker_machine wm ON wm.worker_id = w.id LEFT JOIN ( @@ -195,9 +203,12 @@ namespace CncRepository.Impl.Dashboard GROUP BY seg.machine_id, seg.production_date ) ad ON ad.machine_id = wm.machine_id GROUP BY w.id, w.name - ORDER BY Quantity DESC + ORDER BY TotalQuantity DESC LIMIT @Top"; - return conn.Query(sql, new { StartDate = startDate, EndDate = endDate, Top = top }).ToList(); + var rows = conn.Query(sql, new { StartDate = startDate, EndDate = endDate, Top = top }).ToList(); + // 填充排名 + for (int i = 0; i < rows.Count; i++) rows[i].Rank = i + 1; + return rows; } } @@ -232,13 +243,15 @@ namespace CncRepository.Impl.Dashboard } } - /// 机床状态分布(示意性实现,需要根据实际状态表结构调整) - public List GetMachineStatusDistribution() + /// 机床状态分布 + public object GetMachineStatusDistribution() { using (var conn = CreateConnection()) { - var sql = @"SELECT last_device_status AS Status, COUNT(1) AS Count FROM cnc_machine GROUP BY last_device_status"; - return conn.Query(sql).ToList(); + var online = conn.ExecuteScalar("SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 1 AND is_online = 1"); + var offline = conn.ExecuteScalar("SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 1 AND is_online = 0"); + var disabled = conn.ExecuteScalar("SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 0"); + return new { online, offline, disabled }; } } @@ -247,8 +260,12 @@ namespace CncRepository.Impl.Dashboard { using (var conn = CreateConnection()) { - var sql = @"SELECT id, title AS Message, alert_type AS Severity, created_at FROM cnc_alert ORDER BY created_at DESC LIMIT @Count"; - // 如果 cnc_alert 不存在 Title/Severity,后续可调整为 Message/Level 等字段 + var sql = @"SELECT a.id AS Id, a.created_at AS CreatedAt, a.alert_type AS AlertType, + COALESCE(m.name, '') AS MachineName, a.title AS Title, + CAST(a.is_resolved AS SIGNED) AS IsResolved + FROM cnc_alert a + LEFT JOIN cnc_machine m ON m.id = a.machine_id + ORDER BY a.created_at DESC LIMIT @Count"; return conn.Query(sql, new { Count = count }).ToList(); } } diff --git a/src/CncRepository/Interface/IDashboardRepository.cs b/src/CncRepository/Interface/IDashboardRepository.cs index 5a4b6ab..3609645 100644 --- a/src/CncRepository/Interface/IDashboardRepository.cs +++ b/src/CncRepository/Interface/IDashboardRepository.cs @@ -19,7 +19,7 @@ namespace CncRepository.Interface List GetProductionTrend(int days); - List GetMachineStatusDistribution(); + object GetMachineStatusDistribution(); List GetRecentAlerts(int count); } diff --git a/src/CncWebApi/Controllers/DashboardController.cs b/src/CncWebApi/Controllers/DashboardController.cs index 92d5ada..ad784f1 100644 --- a/src/CncWebApi/Controllers/DashboardController.cs +++ b/src/CncWebApi/Controllers/DashboardController.cs @@ -85,8 +85,8 @@ namespace CncWebApi.Controllers [Route("trend")] public IHttpActionResult GetProductionTrend(int days = 7) { - var result = _dashboardService.GetProductionTrend(days); - return Ok(ApiResponse.Success(result)); + var result = _dashboardService.GetProductionTrend(); + return Ok(ApiResponse.Success(new { items = result })); } ///