diff --git a/frontend/src/views/dashboard/DashboardPage.vue b/frontend/src/views/dashboard/DashboardPage.vue
index bc55f64..46046df 100644
--- a/frontend/src/views/dashboard/DashboardPage.vue
+++ b/frontend/src/views/dashboard/DashboardPage.vue
@@ -33,7 +33,7 @@
采集服务
-
+
ⓘ
diff --git a/frontend/src/views/machine/MachineListPage.vue b/frontend/src/views/machine/MachineListPage.vue
index 766560b..b4f8f9f 100644
--- a/frontend/src/views/machine/MachineListPage.vue
+++ b/frontend/src/views/machine/MachineListPage.vue
@@ -49,6 +49,7 @@
{{ row.isOnline ? '在线' : '离线' }}
+ {{ row.lastPingLatency }}ms
diff --git a/src/CncCollector/Core/CollectWorker.cs b/src/CncCollector/Core/CollectWorker.cs
index 7d1cc58..b7d4450 100644
--- a/src/CncCollector/Core/CollectWorker.cs
+++ b/src/CncCollector/Core/CollectWorker.cs
@@ -216,6 +216,7 @@ namespace CncCollector.Core
///
/// Ping每台机床的IP地址,更新各自的在线状态(并行执行)
+ /// 每台机床连续Ping 4次,取平均值作为延迟
///
private void PingAllMachines()
{
@@ -232,26 +233,32 @@ namespace CncCollector.Core
if (machines.Count == 0) return;
- // 并行Ping所有机床(超时2秒/台)
- var results = new ConcurrentDictionary();
+ // 并行Ping所有机床(每台4次取平均,超时2秒/次)
+ var results = new ConcurrentDictionary(); // machineId → 平均延迟(ms),-1表示离线
var tasks = machines.Select(m => Task.Run(() =>
{
- results[m.Id] = PingHost(m.Ip);
+ results[m.Id] = PingHostAvg(m.Ip, 4);
})).ToArray();
- Task.WaitAll(tasks, Math.Min(machines.Count * 3000, 30000));
+ Task.WaitAll(tasks, Math.Min(machines.Count * 12000, 120000));
- // 按在线/离线分组批量更新
- var onlineIds = results.Where(kv => kv.Value).Select(kv => kv.Key).ToList();
- var offlineIds = results.Where(kv => !kv.Value).Select(kv => kv.Key).ToList();
+ // 按在线/离线分组
+ var onlineIds = results.Where(kv => kv.Value >= 0).Select(kv => kv.Key).ToList();
+ var offlineIds = results.Where(kv => kv.Value < 0).Select(kv => kv.Key).ToList();
using (var conn = new MySqlConnection(_businessConnStr))
{
- if (onlineIds.Count > 0)
- conn.Execute(@"UPDATE cnc_machine SET last_ping_time = NOW(), updated_at = NOW() WHERE id IN @Ids",
- new { Ids = onlineIds });
+ // 只更新在线机床的 last_ping_time 和 last_ping_latency
+ foreach (var kv in results.Where(kv => kv.Value >= 0))
+ {
+ conn.Execute(@"UPDATE cnc_machine SET last_ping_time = NOW(), last_ping_latency = @Latency, updated_at = NOW() WHERE id = @Id",
+ new { Id = kv.Key, Latency = kv.Value });
+ }
+ // 离线机床:清空延迟,不更新 last_ping_time
if (offlineIds.Count > 0)
- conn.Execute(@"UPDATE cnc_machine SET last_ping_time = NOW(), updated_at = NOW() WHERE id IN @Ids",
+ {
+ conn.Execute(@"UPDATE cnc_machine SET last_ping_latency = NULL, updated_at = NOW() WHERE id IN @Ids",
new { Ids = offlineIds });
+ }
}
_log.Info($"Ping完成(地址={_address.Name}):在线{onlineIds.Count}台,离线{offlineIds.Count}台");
@@ -263,22 +270,39 @@ namespace CncCollector.Core
}
///
- /// Ping指定主机地址(超时2秒)
+ /// Ping指定主机地址,连续ping count次取平均延迟(ms)。离线返回-1
///
- private bool PingHost(string host)
+ private int PingHostAvg(string host, int count = 4)
{
try
{
+ long totalMs = 0;
+ int successCount = 0;
using (var ping = new Ping())
{
- var reply = ping.Send(host, 2000);
- return reply.Status == IPStatus.Success;
+ for (int i = 0; i < count; i++)
+ {
+ try
+ {
+ var reply = ping.Send(host, 2000);
+ if (reply.Status == IPStatus.Success)
+ {
+ totalMs += reply.RoundtripTime;
+ successCount++;
+ }
+ }
+ catch
+ {
+ // 单次失败忽略
+ }
+ }
}
+ return successCount > 0 ? (int)(totalMs / successCount) : -1;
}
catch (Exception ex)
{
_log.Debug($"Ping失败(主机={host}): {ex.Message}");
- return false;
+ return -1;
}
}
diff --git a/src/CncModels/Dto/Machine/MachineDetailResponse.cs b/src/CncModels/Dto/Machine/MachineDetailResponse.cs
index fa3bf77..c38b313 100644
--- a/src/CncModels/Dto/Machine/MachineDetailResponse.cs
+++ b/src/CncModels/Dto/Machine/MachineDetailResponse.cs
@@ -18,6 +18,8 @@ namespace CncModels.Dto.Machine
public string IpAddress { get; set; }
public bool IsEnabled { get; set; }
public bool IsOnline { get; set; }
+ /// 最近Ping延迟(ms)
+ public int? LastPingLatency { get; set; }
public int? WorkerId { get; set; }
public string WorkerName { get; set; }
public string LastProgramName { get; set; }
diff --git a/src/CncModels/Dto/Machine/MachineListItem.cs b/src/CncModels/Dto/Machine/MachineListItem.cs
index 79d5b94..f08d007 100644
--- a/src/CncModels/Dto/Machine/MachineListItem.cs
+++ b/src/CncModels/Dto/Machine/MachineListItem.cs
@@ -18,6 +18,8 @@ namespace CncModels.Dto.Machine
public string IpAddress { get; set; }
public bool IsEnabled { get; set; }
public bool IsOnline { get; set; }
+ /// 最近Ping延迟(ms)
+ public int? LastPingLatency { get; set; }
public int? WorkerId { get; set; }
public string WorkerName { get; set; }
public string LastProgramName { get; set; }
diff --git a/src/CncModels/Entity/Machine.cs b/src/CncModels/Entity/Machine.cs
index d1c7917..384425f 100644
--- a/src/CncModels/Entity/Machine.cs
+++ b/src/CncModels/Entity/Machine.cs
@@ -34,6 +34,9 @@ namespace CncModels.Entity
/// 最近Ping时间(在线状态由 last_ping_time 实时计算)
public DateTime? LastPingTime { get; set; }
+ /// 最近Ping延迟(ms),4次平均值
+ public int? LastPingLatency { get; set; }
+
/// 最近采集时间
public DateTime? LastCollectTime { get; set; }
diff --git a/src/CncRepository/Impl/Dashboard/DashboardRepository.cs b/src/CncRepository/Impl/Dashboard/DashboardRepository.cs
index aace741..d13d674 100644
--- a/src/CncRepository/Impl/Dashboard/DashboardRepository.cs
+++ b/src/CncRepository/Impl/Dashboard/DashboardRepository.cs
@@ -44,12 +44,11 @@ namespace CncRepository.Impl.Dashboard
) all_days";
/// 汇总卡片数据
- public DashboardSummaryResponse GetSummary(int onlineTimeout = 300)
+ public DashboardSummaryResponse GetSummary()
{
using (var conn = CreateConnection())
{
- var onlineCount = conn.ExecuteScalar(@"SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 1 AND last_ping_time IS NOT NULL AND last_ping_time >= NOW() - INTERVAL @OnlineTimeout SECOND",
- new { OnlineTimeout = onlineTimeout });
+ var onlineCount = conn.ExecuteScalar(@"SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 1 AND last_ping_time IS NOT NULL AND last_ping_time >= NOW() - INTERVAL 20 SECOND");
var totalMachines = conn.ExecuteScalar(@"SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 1");
// 今日总产量:直接从产量分段实时计算(今日一定没有日终汇总)
var todayProduction = conn.ExecuteScalar(@"
@@ -121,7 +120,7 @@ namespace CncRepository.Impl.Dashboard
}
/// 机床排行
- public List GetMachineRank(DateTime startDate, DateTime endDate, int top, int onlineTimeout = 300, string sortOrder = "desc")
+ public List GetMachineRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc")
{
// 排序方向白名单校验,防止SQL注入
var orderBy = string.Equals(sortOrder, "asc", StringComparison.OrdinalIgnoreCase) ? "ASC" : "DESC";
@@ -131,7 +130,7 @@ namespace CncRepository.Impl.Dashboard
SELECT m.id AS MachineId,
m.name AS MachineName,
COALESCE(SUM(ad.day_quantity), 0) AS Quantity,
- (CASE WHEN m.is_enabled = 1 AND m.last_ping_time IS NOT NULL AND m.last_ping_time >= NOW() - INTERVAL @OnlineTimeout SECOND THEN 1 ELSE 0 END) AS Status,
+ (CASE WHEN m.last_ping_time IS NOT NULL AND m.last_ping_time >= NOW() - INTERVAL 20 SECOND THEN 1 ELSE 0 END) 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
@@ -158,7 +157,7 @@ namespace CncRepository.Impl.Dashboard
GROUP BY m.id, m.name, m.is_enabled, m.last_ping_time
ORDER BY Quantity {orderBy}
LIMIT @Top";
- var rows = conn.Query(sql, new { StartDate = startDate, EndDate = endDate, Top = top, OnlineTimeout = onlineTimeout }).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;
@@ -239,14 +238,12 @@ namespace CncRepository.Impl.Dashboard
}
/// 机床状态分布
- public object GetMachineStatusDistribution(int onlineTimeout = 300)
+ public object GetMachineStatusDistribution()
{
using (var conn = CreateConnection())
{
- var online = conn.ExecuteScalar("SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 1 AND last_ping_time IS NOT NULL AND last_ping_time >= NOW() - INTERVAL @OnlineTimeout SECOND",
- new { OnlineTimeout = onlineTimeout });
- var offline = conn.ExecuteScalar("SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 1 AND (last_ping_time IS NULL OR last_ping_time < NOW() - INTERVAL @OnlineTimeout SECOND)",
- new { OnlineTimeout = onlineTimeout });
+ var online = conn.ExecuteScalar("SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 1 AND last_ping_time IS NOT NULL AND last_ping_time >= NOW() - INTERVAL 20 SECOND");
+ var offline = conn.ExecuteScalar("SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 1 AND (last_ping_time IS NULL OR last_ping_time < NOW() - INTERVAL 20 SECOND)");
var disabled = conn.ExecuteScalar("SELECT COUNT(1) FROM cnc_machine WHERE is_enabled = 0");
return new { online, offline, disabled };
}
diff --git a/src/CncRepository/Impl/MachineRepository.cs b/src/CncRepository/Impl/MachineRepository.cs
index 2ddd711..0ff4846 100644
--- a/src/CncRepository/Impl/MachineRepository.cs
+++ b/src/CncRepository/Impl/MachineRepository.cs
@@ -17,22 +17,22 @@ namespace CncRepository.Impl
public MachineRepository(string connectionString) : base(connectionString) { }
/// 机床SELECT列映射模板(snake_case列名 → PascalCase属性名)
- /// 在线判断SQL片段:已启用且最近Ping在超时阈值内视为在线。参数 @OnlineTimeout
- private const string OnlineExpr = "(CASE WHEN is_enabled = 1 AND last_ping_time IS NOT NULL AND last_ping_time >= NOW() - INTERVAL @OnlineTimeout SECOND THEN 1 ELSE 0 END)";
+ /// 在线判断SQL片段:last_ping_time在20秒内视为在线
+ private const string OnlineExpr = "(CASE WHEN last_ping_time IS NOT NULL AND last_ping_time >= NOW() - INTERVAL 20 SECOND THEN 1 ELSE 0 END)";
- private const string SelectColumns = @"id as Id, device_code as DeviceCode, name as Name, workshop_id as WorkshopId, collect_address_id as CollectAddressId, ip_address as IpAddress, brand_id as BrandId, is_enabled as IsEnabled, {0} as IsOnline, last_ping_time as LastPingTime, last_collect_time as LastCollectTime, last_device_status as LastDeviceStatus, last_run_status as LastRunStatus, last_program_name as LastProgramName, last_part_count as LastPartCount, last_operate_mode as LastOperateMode, last_machining_status as LastMachiningStatus, created_at as CreatedAt, updated_at as UpdatedAt";
+ private const string SelectColumns = @"id as Id, device_code as DeviceCode, name as Name, workshop_id as WorkshopId, collect_address_id as CollectAddressId, ip_address as IpAddress, brand_id as BrandId, is_enabled as IsEnabled, {0} as IsOnline, last_ping_time as LastPingTime, last_ping_latency as LastPingLatency, last_collect_time as LastCollectTime, last_device_status as LastDeviceStatus, last_run_status as LastRunStatus, last_program_name as LastProgramName, last_part_count as LastPartCount, last_operate_mode as LastOperateMode, last_machining_status as LastMachiningStatus, created_at as CreatedAt, updated_at as UpdatedAt";
- public Machine GetById(int id, int onlineTimeout = 300)
+ public Machine GetById(int id)
{
using (var conn = CreateConnection())
{
var cols = string.Format(SelectColumns, OnlineExpr);
var sql = $"SELECT {cols} FROM cnc_machine WHERE id = @Id";
- return conn.QuerySingleOrDefault(sql, new { Id = id, OnlineTimeout = onlineTimeout });
+ return conn.QuerySingleOrDefault(sql, new { Id = id });
}
}
- public MachineDetailResponse GetDetailById(int id, int onlineTimeout = 300)
+ public MachineDetailResponse GetDetailById(int id)
{
using (var conn = CreateConnection())
{
@@ -42,7 +42,8 @@ namespace CncRepository.Impl
m.brand_id as BrandId, b.brand_name as BrandName,
m.ip_address as IpAddress,
m.is_enabled as IsEnabled,
- (CASE WHEN m.is_enabled = 1 AND m.last_ping_time IS NOT NULL AND m.last_ping_time >= NOW() - INTERVAL @OnlineTimeout SECOND THEN 1 ELSE 0 END) as IsOnline,
+ (CASE WHEN m.last_ping_time IS NOT NULL AND m.last_ping_time >= NOW() - INTERVAL 20 SECOND THEN 1 ELSE 0 END) as IsOnline,
+ m.last_ping_latency as LastPingLatency,
w.id as WorkerId, w.name as WorkerName,
m.last_program_name as LastProgramName, m.last_collect_time as LastCollectTime
FROM cnc_machine m
@@ -51,17 +52,16 @@ namespace CncRepository.Impl
LEFT JOIN cnc_worker_machine wm ON m.id = wm.machine_id
LEFT JOIN cnc_worker w ON wm.worker_id = w.id
WHERE m.id = @Id";
- return conn.QuerySingleOrDefault(sql, new { Id = id, OnlineTimeout = onlineTimeout });
+ return conn.QuerySingleOrDefault(sql, new { Id = id });
}
}
- public PagedResult GetList(MachineQuery query, int onlineTimeout = 300)
+ public PagedResult GetList(MachineQuery query)
{
using (var conn = CreateConnection())
{
var where = " WHERE 1=1";
var p = new DynamicParameters();
- p.Add("OnlineTimeout", onlineTimeout);
if (!string.IsNullOrWhiteSpace(query.Keyword))
{
where += " AND (m.name LIKE @Keyword OR m.device_code LIKE @Keyword)";
@@ -75,9 +75,9 @@ namespace CncRepository.Impl
if (query.IsOnline.HasValue)
{
if (query.IsOnline.Value == 1)
- where += " AND m.is_enabled = 1 AND m.last_ping_time IS NOT NULL AND m.last_ping_time >= NOW() - INTERVAL @OnlineTimeout SECOND";
+ where += " AND m.last_ping_time IS NOT NULL AND m.last_ping_time >= NOW() - INTERVAL 20 SECOND";
else
- where += " AND (m.is_enabled = 0 OR m.last_ping_time IS NULL OR m.last_ping_time < NOW() - INTERVAL @OnlineTimeout SECOND)";
+ where += " AND (m.last_ping_time IS NULL OR m.last_ping_time < NOW() - INTERVAL 20 SECOND)";
}
if (query.BrandId.HasValue)
{
@@ -87,7 +87,8 @@ namespace CncRepository.Impl
var limit = query.PageSize;
var offset = query.Offset;
var sql = @"SELECT m.id as Id, m.device_code as DeviceCode, m.name as Name, m.workshop_id as WorkshopId, ws.name as WorkshopName, m.collect_address_id as CollectAddressId, m.brand_id as BrandId, b.brand_name as BrandName, m.ip_address as IpAddress, m.is_enabled as IsEnabled,
- (CASE WHEN m.is_enabled = 1 AND m.last_ping_time IS NOT NULL AND m.last_ping_time >= NOW() - INTERVAL @OnlineTimeout SECOND THEN 1 ELSE 0 END) as IsOnline,
+ (CASE WHEN m.last_ping_time IS NOT NULL AND m.last_ping_time >= NOW() - INTERVAL 20 SECOND THEN 1 ELSE 0 END) as IsOnline,
+ m.last_ping_latency as LastPingLatency,
m.last_program_name as LastProgramName, m.last_collect_time as LastCollectTime, w.id as WorkerId, w.name as WorkerName
FROM cnc_machine m
LEFT JOIN cnc_workshop ws ON m.workshop_id = ws.id
@@ -157,33 +158,33 @@ namespace CncRepository.Impl
}
}
- public Machine GetByDeviceCode(string deviceCode, int onlineTimeout = 300)
+ public Machine GetByDeviceCode(string deviceCode)
{
using (var conn = CreateConnection())
{
var cols = string.Format(SelectColumns, OnlineExpr);
var sql = $"SELECT {cols} FROM cnc_machine WHERE device_code = @DeviceCode";
- return conn.QuerySingleOrDefault(sql, new { DeviceCode = deviceCode, OnlineTimeout = onlineTimeout });
+ return conn.QuerySingleOrDefault(sql, new { DeviceCode = deviceCode });
}
}
- public List GetEnabledByAddressId(int collectAddressId, int onlineTimeout = 300)
+ public List GetEnabledByAddressId(int collectAddressId)
{
using (var conn = CreateConnection())
{
var cols = string.Format(SelectColumns, OnlineExpr);
var sql = $"SELECT {cols} FROM cnc_machine WHERE collect_address_id = @CollectAddressId AND is_enabled = 1";
- return conn.Query(sql, new { CollectAddressId = collectAddressId, OnlineTimeout = onlineTimeout }).ToList();
+ return conn.Query(sql, new { CollectAddressId = collectAddressId }).ToList();
}
}
- public List GetEnabledOnline(int onlineTimeout = 300)
+ public List GetEnabledOnline()
{
using (var conn = CreateConnection())
{
var cols = string.Format(SelectColumns, OnlineExpr);
- var sql = $"SELECT {cols} FROM cnc_machine WHERE is_enabled = 1 AND last_ping_time IS NOT NULL AND last_ping_time >= NOW() - INTERVAL @OnlineTimeout SECOND";
- return conn.Query(sql, new { OnlineTimeout = onlineTimeout }).ToList();
+ var sql = $"SELECT {cols} FROM cnc_machine WHERE is_enabled = 1 AND last_ping_time IS NOT NULL AND last_ping_time >= NOW() - INTERVAL 20 SECOND";
+ return conn.Query(sql).ToList();
}
}
diff --git a/src/CncRepository/Interface/IDashboardRepository.cs b/src/CncRepository/Interface/IDashboardRepository.cs
index e5ae9bf..5e1c8c1 100644
--- a/src/CncRepository/Interface/IDashboardRepository.cs
+++ b/src/CncRepository/Interface/IDashboardRepository.cs
@@ -9,17 +9,17 @@ namespace CncRepository.Interface
///
public interface IDashboardRepository
{
- DashboardSummaryResponse GetSummary(int onlineTimeout = 300);
+ DashboardSummaryResponse GetSummary();
List GetWorkshopProduction(DateTime startDate, DateTime endDate);
- List GetMachineRank(DateTime startDate, DateTime endDate, int top, int onlineTimeout = 300, string sortOrder = "desc");
+ List GetMachineRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc");
List GetWorkerRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc");
List GetProductionTrend(int days);
- object GetMachineStatusDistribution(int onlineTimeout = 300);
+ object GetMachineStatusDistribution();
List GetRecentAlerts(int count);
}
diff --git a/src/CncRepository/Interface/IMachineRepository.cs b/src/CncRepository/Interface/IMachineRepository.cs
index 3cf81c6..f831fcf 100644
--- a/src/CncRepository/Interface/IMachineRepository.cs
+++ b/src/CncRepository/Interface/IMachineRepository.cs
@@ -10,17 +10,17 @@ namespace CncRepository.Interface
///
public interface IMachineRepository
{
- Machine GetById(int id, int onlineTimeout = 300);
- MachineDetailResponse GetDetailById(int id, int onlineTimeout = 300);
- PagedResult GetList(MachineQuery query, int onlineTimeout = 300);
+ Machine GetById(int id);
+ MachineDetailResponse GetDetailById(int id);
+ PagedResult GetList(MachineQuery query);
int Create(Machine entity);
bool Update(Machine entity);
bool Delete(int id);
int BatchDelete(List ids);
bool ToggleEnabled(int id);
- Machine GetByDeviceCode(string deviceCode, int onlineTimeout = 300);
- List GetEnabledByAddressId(int collectAddressId, int onlineTimeout = 300);
- List GetEnabledOnline(int onlineTimeout = 300);
+ Machine GetByDeviceCode(string deviceCode);
+ List GetEnabledByAddressId(int collectAddressId);
+ List GetEnabledOnline();
void UpdateLastCollect(int id, Machine entity);
/// 设置机床所属的采集地址
void SetCollectAddress(int machineId, int? collectAddressId);
diff --git a/src/CncService/Impl/DashboardService.cs b/src/CncService/Impl/DashboardService.cs
index 7e74ec8..f7dd673 100644
--- a/src/CncService/Impl/DashboardService.cs
+++ b/src/CncService/Impl/DashboardService.cs
@@ -27,18 +27,10 @@ namespace CncService.Impl
_serviceChecker = serviceChecker;
}
- /// 从sys_config读取online_timeout,默认300秒
- private int GetOnlineTimeout()
- {
- var cfg = _sysConfigRepository.GetByKey("online_timeout");
- if (cfg != null && int.TryParse(cfg.ConfigValue, out var val) && val > 0) return val;
- return 300;
- }
-
///
public DashboardSummaryResponse GetSummary()
{
- return _dashboardRepository.GetSummary(GetOnlineTimeout());
+ return _dashboardRepository.GetSummary();
}
///
@@ -54,7 +46,7 @@ namespace CncService.Impl
{
var s = startDate ?? DateTime.Today;
var e = endDate ?? DateTime.Today;
- return _dashboardRepository.GetMachineRank(s, e, top, GetOnlineTimeout(), sortOrder);
+ return _dashboardRepository.GetMachineRank(s, e, top, sortOrder);
}
///
@@ -74,7 +66,7 @@ namespace CncService.Impl
///
public object GetMachineStatusDistribution()
{
- return _dashboardRepository.GetMachineStatusDistribution(GetOnlineTimeout());
+ return _dashboardRepository.GetMachineStatusDistribution();
}
///
@@ -83,12 +75,20 @@ namespace CncService.Impl
return _dashboardRepository.GetRecentAlerts(count);
}
+ /// 从sys_config读取heartbeat_interval,计算心跳超时阈值(间隔×3)
+ private int GetHeartbeatTimeout()
+ {
+ var cfg = _sysConfigRepository.GetByKey("heartbeat_interval");
+ if (cfg != null && int.TryParse(cfg.ConfigValue, out var val) && val > 0)
+ return val * 3;
+ return 30; // 默认10秒间隔 × 3 = 30秒
+ }
+
///
public object GetCollectorStatus()
{
- var latest = _collectorHeartbeatRepository.GetLatest("collector-service");
- // 心跳超时阈值:90秒(3个心跳间隔,采集服务默认每30秒上报一次)
- const int heartbeatTimeoutSeconds = 90;
+ var latest = _collectorHeartbeatRepository.GetLatest("CncCollector");
+ int heartbeatTimeoutSeconds = GetHeartbeatTimeout();
bool heartbeatRunning = false;
long heartbeatUptime = 0;
diff --git a/tests/CncService.Tests/DashboardServiceTests.cs b/tests/CncService.Tests/DashboardServiceTests.cs
index 922ad96..cba34a9 100644
--- a/tests/CncService.Tests/DashboardServiceTests.cs
+++ b/tests/CncService.Tests/DashboardServiceTests.cs
@@ -12,12 +12,12 @@ namespace CncService.Tests
// Fake repositories to isolate DashboardService.GetCollectorStatus tests
public class FakeDashboardRepository : IDashboardRepository
{
- public DashboardSummaryResponse GetSummary(int something) => new DashboardSummaryResponse();
+ public DashboardSummaryResponse GetSummary() => new DashboardSummaryResponse();
public List GetWorkshopProduction(DateTime startDate, DateTime endDate) => new List();
- public List GetMachineRank(DateTime startDate, DateTime endDate, int top, int something, string sortOrder = "desc") => new List();
+ public List GetMachineRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc") => new List();
public List GetWorkerRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc") => new List();
public List GetProductionTrend(int days) => new List();
- public object GetMachineStatusDistribution(int something) => new object();
+ public object GetMachineStatusDistribution() => new object();
public List GetRecentAlerts(int count) => new List();
}