You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
haoliang-net/src/CncRepository/Impl/MachineRepository.cs

299 lines
15 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Collections.Generic;
using System.Linq;
using Dapper;
using CncModels.Entity;
using CncModels.Dto;
using CncModels.Dto.Machine;
using CncRepository.Base;
using CncRepository.Interface;
namespace CncRepository.Impl
{
/// <summary>
/// 机床实现
/// </summary>
public class MachineRepository : BusinessRepository, IMachineRepository
{
public MachineRepository(string connectionString) : base(connectionString) { }
/// <summary>机床SELECT列映射模板snake_case列名 → PascalCase属性名</summary>
/// <summary>在线判断SQL片段last_ping_time在20秒内视为在线</summary>
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_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)
{
using (var conn = CreateConnection())
{
var cols = string.Format(SelectColumns, OnlineExpr);
var sql = $"SELECT {cols} FROM cnc_machine WHERE id = @Id";
return conn.QuerySingleOrDefault<Machine>(sql, new { Id = id });
}
}
public MachineDetailResponse GetDetailById(int id)
{
using (var conn = CreateConnection())
{
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.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
LEFT JOIN cnc_workshop ws ON m.workshop_id = ws.id
LEFT JOIN cnc_brand b ON m.brand_id = b.id
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<MachineDetailResponse>(sql, new { Id = id });
}
}
public PagedResult<MachineListItem> GetList(MachineQuery query)
{
using (var conn = CreateConnection())
{
var where = " WHERE 1=1";
var p = new DynamicParameters();
if (!string.IsNullOrWhiteSpace(query.Keyword))
{
where += " AND (m.name LIKE @Keyword OR m.device_code LIKE @Keyword)";
p.Add("Keyword", $"%{query.Keyword}%");
}
if (query.WorkshopId.HasValue)
{
where += " AND m.workshop_id = @WorkshopId";
p.Add("WorkshopId", query.WorkshopId.Value);
}
if (query.IsOnline.HasValue)
{
if (query.IsOnline.Value == 1)
where += " AND m.last_ping_time IS NOT NULL AND m.last_ping_time >= NOW() - INTERVAL 20 SECOND";
else
where += " AND (m.last_ping_time IS NULL OR m.last_ping_time < NOW() - INTERVAL 20 SECOND)";
}
if (query.BrandId.HasValue)
{
where += " AND m.brand_id = @BrandId";
p.Add("BrandId", query.BrandId.Value);
}
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.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
LEFT JOIN cnc_brand b ON m.brand_id = b.id
LEFT JOIN cnc_worker_machine wm ON m.id = wm.machine_id
LEFT JOIN cnc_worker w ON wm.worker_id = w.id" + where + @" ORDER BY m.id DESC LIMIT @Limit OFFSET @Offset";
p.Add("Limit", limit);
p.Add("Offset", offset);
var totalSql = @"SELECT COUNT(*) FROM cnc_machine m" + where + @"";
var total = conn.ExecuteScalar<int>(totalSql, p);
var items = conn.Query<MachineListItem>(sql, p).ToList();
return new PagedResult<MachineListItem>
{
Items = items,
Total = total,
Page = query.Page,
PageSize = limit
};
}
}
public int Create(Machine entity)
{
using (var conn = CreateConnection())
{
var sql = @"INSERT INTO cnc_machine (device_code, name, workshop_id, collect_address_id, ip_address, brand_id, is_enabled, created_at, updated_at)
VALUES (@DeviceCode, @Name, @WorkshopId, @CollectAddressId, @IpAddress, @BrandId, @IsEnabled, @CreatedAt, @UpdatedAt);
SELECT LAST_INSERT_ID();";
return conn.QuerySingle<int>(sql, entity);
}
}
public bool Update(Machine entity)
{
using (var conn = CreateConnection())
{
var sql = @"UPDATE cnc_machine SET device_code = @DeviceCode, name = @Name, workshop_id = @WorkshopId, collect_address_id = @CollectAddressId, ip_address = @IpAddress, brand_id = @BrandId, is_enabled = @IsEnabled, updated_at = @UpdatedAt, last_program_name = @LastProgramName, last_collect_time = @LastCollectTime, last_device_status = @LastDeviceStatus, last_run_status = @LastRunStatus, last_machining_status = @LastMachiningStatus WHERE id = @Id";
return conn.Execute(sql, entity) > 0;
}
}
public bool Delete(int id)
{
using (var conn = CreateConnection())
{
var sql = @"DELETE FROM cnc_machine WHERE id = @Id";
return conn.Execute(sql, new { Id = id }) > 0;
}
}
public int BatchDelete(List<int> ids)
{
if (ids == null || ids.Count == 0) return 0;
using (var conn = CreateConnection())
{
var sql = @"DELETE FROM cnc_machine WHERE id IN @Ids";
return conn.Execute(sql, new { Ids = ids });
}
}
public bool ToggleEnabled(int id)
{
using (var conn = CreateConnection())
{
var sql = @"UPDATE cnc_machine SET is_enabled = CASE WHEN is_enabled = 1 THEN 0 ELSE 1 END, updated_at = NOW() WHERE id = @Id";
return conn.Execute(sql, new { Id = id }) > 0;
}
}
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<Machine>(sql, new { DeviceCode = deviceCode });
}
}
public List<Machine> 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<Machine>(sql, new { CollectAddressId = collectAddressId }).ToList();
}
}
public List<Machine> 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 20 SECOND";
return conn.Query<Machine>(sql).ToList();
}
}
public void UpdateLastCollect(int id, Machine entity)
{
using (var conn = CreateConnection())
{
var sql = @"UPDATE cnc_machine SET last_collect_time = @LastCollectTime, last_program_name = @LastProgramName, last_machining_status = @LastMachiningStatus, updated_at = NOW() WHERE id = @Id";
var param = new
{
Id = id,
LastCollectTime = entity.LastCollectTime,
LastProgramName = entity.LastProgramName,
LastMachiningStatus = entity.LastMachiningStatus
};
conn.Execute(sql, param);
}
}
public void SetCollectAddress(int machineId, int? collectAddressId)
{
using (var conn = CreateConnection())
{
conn.Execute("UPDATE cnc_machine SET collect_address_id = @AddressId, updated_at = NOW() WHERE id = @Id",
new { Id = machineId, AddressId = collectAddressId });
}
}
/// <inheritdoc/>
public MachineCollectRecordItem GetLatestCollectRecord(int machineId)
{
using (var conn = CreateConnection())
{
string sql = @"SELECT DATE_FORMAT(cr.collect_time, '%Y-%m-%d %H:%i:%s') AS CollectTime,
cr.program_name AS ProgramName, cr.part_count AS PartCount, cr.run_status AS RunStatus
FROM cnc_collect_record cr
WHERE cr.machine_id = @MachineId
ORDER BY cr.collect_time DESC LIMIT 1";
return conn.QuerySingleOrDefault<MachineCollectRecordItem>(sql, new { MachineId = machineId });
}
}
/// <inheritdoc/>
public List<MachineTodayProdItem> GetTodayProduction(int machineId)
{
using (var conn = CreateConnection())
{
// 优先从已汇总的日产量表取
string dpSql = @"SELECT program_name AS ProgramName, CAST(total_quantity AS SIGNED) AS Quantity,
total_run_time AS RunTime, total_cutting_time AS CuttingTime
FROM cnc_daily_production
WHERE machine_id = @MachineId AND production_date = CURDATE()";
var dpItems = conn.Query<MachineTodayProdItem>(dpSql, new { MachineId = machineId }).AsList();
if (dpItems.Count > 0) return dpItems;
// 没有汇总数据则从分段表实时计算
string segSql = @"SELECT seg.program_name AS ProgramName,
CAST(SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity
ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) AS SIGNED) AS Quantity,
NULL AS RunTime, NULL AS CuttingTime
FROM cnc_production_segment seg
WHERE seg.machine_id = @MachineId AND seg.production_date = CURDATE()
GROUP BY seg.program_name";
return conn.Query<MachineTodayProdItem>(segSql, new { MachineId = machineId }).AsList();
}
}
/// <inheritdoc/>
public List<MachineTrendItem> GetProductionTrend(int machineId, int days = 7)
{
using (var conn = CreateConnection())
{
// 优先从日产量表取近N天数据
string sql = @"SELECT DATE_FORMAT(dp.production_date, '%Y-%m-%d') AS Date,
CAST(SUM(dp.total_quantity) AS SIGNED) AS Quantity
FROM cnc_daily_production dp
WHERE dp.machine_id = @MachineId
AND dp.production_date >= DATE_SUB(CURDATE(), INTERVAL @Days DAY)
GROUP BY dp.production_date
ORDER BY dp.production_date";
var items = conn.Query<MachineTrendItem>(sql, new { MachineId = machineId, Days = days - 1 }).AsList();
if (items.Count > 0) return items;
// 没有汇总数据则从分段表实时计算
string segSql = @"SELECT DATE_FORMAT(seg.production_date, '%Y-%m-%d') AS Date,
CAST(SUM(CASE WHEN seg.is_settled=1 THEN seg.quantity
ELSE COALESCE(seg.end_part_count, seg.start_part_count) - seg.start_part_count END) AS SIGNED) AS Quantity
FROM cnc_production_segment seg
WHERE seg.machine_id = @MachineId
AND seg.production_date >= DATE_SUB(CURDATE(), INTERVAL @Days DAY)
GROUP BY seg.production_date
ORDER BY seg.production_date";
return conn.Query<MachineTrendItem>(segSql, new { MachineId = machineId, Days = days - 1 }).AsList();
}
}
/// <inheritdoc/>
public List<MachineCollectRecordItem> GetRecentCollectRecords(int machineId, int limit = 20)
{
using (var conn = CreateConnection())
{
string sql = @"SELECT DATE_FORMAT(cr.collect_time, '%Y-%m-%d %H:%i:%s') AS CollectTime,
cr.program_name AS ProgramName, cr.part_count AS PartCount, cr.run_status AS RunStatus
FROM cnc_collect_record cr
WHERE cr.machine_id = @MachineId
ORDER BY cr.collect_time DESC LIMIT @Limit";
return conn.Query<MachineCollectRecordItem>(sql, new { MachineId = machineId, Limit = limit }).AsList();
}
}
}
}