feat(service): CncService层完整实现 - 12接口+12实现,编译通过
- Interface: 12个服务接口(IAuthService/IDashboardService/IBrandService/ICollectAddressService/IMachineService/IWorkshopService/IWorkerService/IProductionService/IAlertService/IScreenService/ISystemLogService/ICollectDataService) - Impl: 12个服务实现(构造函数注入Repository+参数校验+DTO转换+业务逻辑) - 登录: BCrypt密码验证+HS256 JWT生成 - 仪表盘: 7项统计+采集服务心跳检测 - 品牌: CRUD+复制+16标准字段 - 机床/车间/员工: CRUD+唯一性校验+绑定管理 - 产量: 分页查询+汇总+修正审计 - 告警: 分页+单条/批量处理+统计 - 大屏: 卡片配置+筛选条件管理 - 采集数据: 原始记录分页+最新记录 - 系统日志: 分页查询 - 添加BCrypt.Net-Next 4.0.3 NuGet包main
parent
fc7d350c3d
commit
fd40475271
@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CncService.Interface;
|
||||||
|
using CncModels.Dto.Alert;
|
||||||
|
using CncModels.Dto;
|
||||||
|
using CncModels.Constants;
|
||||||
|
using CncRepository.Interface;
|
||||||
|
|
||||||
|
namespace CncService.Impl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 告警管理实现
|
||||||
|
/// </summary>
|
||||||
|
public class AlertService : IAlertService
|
||||||
|
{
|
||||||
|
private readonly IAlertRepository _alertRepository;
|
||||||
|
|
||||||
|
public AlertService(IAlertRepository alertRepository)
|
||||||
|
{
|
||||||
|
_alertRepository = alertRepository ?? throw new ArgumentNullException(nameof(alertRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public PagedResult<AlertListItem> GetList(AlertQuery query)
|
||||||
|
{
|
||||||
|
if (query == null) throw new BusinessException(ErrorCode.BadRequest, "查询参数不能为空");
|
||||||
|
return _alertRepository.GetList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Resolve(long id)
|
||||||
|
{
|
||||||
|
if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的告警ID");
|
||||||
|
return _alertRepository.Resolve(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int BatchResolve(List<long> ids)
|
||||||
|
{
|
||||||
|
if (ids == null || ids.Count == 0) throw new BusinessException(ErrorCode.BadRequest, "无效的ID列表");
|
||||||
|
return _alertRepository.BatchResolve(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public AlertStatisticsResponse GetStatistics()
|
||||||
|
{
|
||||||
|
return _alertRepository.GetStatistics();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,101 @@
|
|||||||
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using BCrypt.Net;
|
||||||
|
using CncModels.Constants;
|
||||||
|
using CncModels.Dto.Login;
|
||||||
|
using CncService.Interface;
|
||||||
|
using CncService;
|
||||||
|
using CncRepository.Interface;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace CncService.Impl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 登录认证实现
|
||||||
|
/// </summary>
|
||||||
|
public class AuthService : IAuthService
|
||||||
|
{
|
||||||
|
private readonly ISysConfigRepository _sysConfigRepository;
|
||||||
|
private readonly string _jwtSecret;
|
||||||
|
|
||||||
|
public AuthService(ISysConfigRepository sysConfigRepository, string jwtSecret)
|
||||||
|
{
|
||||||
|
_sysConfigRepository = sysConfigRepository ?? throw new ArgumentNullException(nameof(sysConfigRepository));
|
||||||
|
_jwtSecret = jwtSecret ?? throw new ArgumentNullException(nameof(jwtSecret));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public LoginResponse Login(LoginRequest request)
|
||||||
|
{
|
||||||
|
if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数错误");
|
||||||
|
// 读取管理员用户名与哈希
|
||||||
|
var userCfg = _sysConfigRepository.GetByKey("admin_username");
|
||||||
|
var pwdCfg = _sysConfigRepository.GetByKey("admin_password_hash");
|
||||||
|
|
||||||
|
var usernameStored = userCfg?.ConfigValue;
|
||||||
|
var passwordHash = pwdCfg?.ConfigValue;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(usernameStored) || string.IsNullOrWhiteSpace(passwordHash))
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCode.BadRequest, "用户名或密码错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.Equals(request.Username, usernameStored, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCode.BadRequest, "用户名或密码错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证密码
|
||||||
|
if (!BCrypt.Net.BCrypt.Verify(request.Password ?? string.Empty, passwordHash))
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCode.BadRequest, "用户名或密码错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过期时间
|
||||||
|
int expiresIn = (request.RememberMe ?? false) ? 24 * 3600 : 8 * 3600;
|
||||||
|
|
||||||
|
// 生成简易 JWT
|
||||||
|
var token = GenerateJwtToken(request.Username, expiresIn);
|
||||||
|
|
||||||
|
return new LoginResponse
|
||||||
|
{
|
||||||
|
Token = token,
|
||||||
|
ExpiresIn = expiresIn
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateJwtToken(string username, int expiresInSeconds)
|
||||||
|
{
|
||||||
|
// Header
|
||||||
|
const string headerJson = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
|
||||||
|
long exp = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + expiresInSeconds;
|
||||||
|
// Payload
|
||||||
|
string payloadJson = $"{{\"sub\":\"admin\",\"name\":\"{Escape(username)}\",\"exp\":{exp}}}";
|
||||||
|
|
||||||
|
string header = Base64UrlEncode(Encoding.UTF8.GetBytes(headerJson));
|
||||||
|
string payload = Base64UrlEncode(Encoding.UTF8.GetBytes(payloadJson));
|
||||||
|
string unsigned = header + "." + payload;
|
||||||
|
|
||||||
|
// Signature
|
||||||
|
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_jwtSecret)))
|
||||||
|
{
|
||||||
|
var sig = hmac.ComputeHash(Encoding.UTF8.GetBytes(unsigned));
|
||||||
|
string signature = Base64UrlEncode(sig);
|
||||||
|
return unsigned + "." + signature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Escape(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input)) return string.Empty;
|
||||||
|
return input.Replace("\\", "\\\\").Replace("\"", "\\\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Base64UrlEncode(byte[] input)
|
||||||
|
{
|
||||||
|
var base64 = Convert.ToBase64String(input);
|
||||||
|
return base64.Replace("+", "-").Replace("/", "_").TrimEnd('=');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,172 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using CncModels.Dto.Brand;
|
||||||
|
using CncModels.Entity;
|
||||||
|
using CncRepository.Interface;
|
||||||
|
using CncService.Interface;
|
||||||
|
using CncService;
|
||||||
|
using CncModels.Constants;
|
||||||
|
|
||||||
|
namespace CncService.Impl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 品牌模板实现
|
||||||
|
/// </summary>
|
||||||
|
public class BrandService : IBrandService
|
||||||
|
{
|
||||||
|
private readonly IBrandRepository _brandRepository;
|
||||||
|
private readonly IBrandFieldMappingRepository _mappingRepository;
|
||||||
|
private readonly ICollectAddressRepository _collectAddressRepository;
|
||||||
|
|
||||||
|
public BrandService(IBrandRepository brandRepository,
|
||||||
|
IBrandFieldMappingRepository mappingRepository,
|
||||||
|
ICollectAddressRepository collectAddressRepository)
|
||||||
|
{
|
||||||
|
_brandRepository = brandRepository;
|
||||||
|
_mappingRepository = mappingRepository;
|
||||||
|
_collectAddressRepository = collectAddressRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BrandListItem> GetList()
|
||||||
|
{
|
||||||
|
var brands = _brandRepository.GetAll();
|
||||||
|
return brands.Select(b => new BrandListItem
|
||||||
|
{
|
||||||
|
Id = b.Id,
|
||||||
|
BrandName = b.BrandName,
|
||||||
|
DeviceField = b.DeviceField,
|
||||||
|
TagsPath = b.TagsPath,
|
||||||
|
IsEnabled = b.IsEnabled,
|
||||||
|
FieldCount = _brandRepository.GetFieldMappingCount(b.Id)
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BrandDetailResponse GetById(int id)
|
||||||
|
{
|
||||||
|
var brand = _brandRepository.GetById(id);
|
||||||
|
if (brand == null) throw new BusinessException(ErrorCode.NotFound, "品牌不存在");
|
||||||
|
|
||||||
|
var mappings = _mappingRepository.GetByBrandId(id);
|
||||||
|
var detail = new BrandDetailResponse
|
||||||
|
{
|
||||||
|
Id = brand.Id,
|
||||||
|
BrandName = brand.BrandName,
|
||||||
|
DeviceField = brand.DeviceField,
|
||||||
|
TagsPath = brand.TagsPath,
|
||||||
|
IsEnabled = brand.IsEnabled,
|
||||||
|
FieldCount = mappings?.Count ?? 0,
|
||||||
|
Mappings = mappings?.Select(m => new BrandFieldMappingDto
|
||||||
|
{
|
||||||
|
StandardField = m.StandardField,
|
||||||
|
FieldName = m.FieldName,
|
||||||
|
MatchBy = m.MatchBy,
|
||||||
|
DataType = m.DataType,
|
||||||
|
IsRequired = m.IsRequired
|
||||||
|
}).ToList() ?? new List<BrandFieldMappingDto>()
|
||||||
|
};
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Create(CreateBrandRequest request)
|
||||||
|
{
|
||||||
|
if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数错误");
|
||||||
|
// 验证唯一性
|
||||||
|
if (_brandRepository.GetAll().Any(b => string.Equals(b.BrandName, request.BrandName, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCode.Conflict, "品牌名称已存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
var entity = new Brand
|
||||||
|
{
|
||||||
|
BrandName = request.BrandName,
|
||||||
|
DeviceField = request.DeviceField,
|
||||||
|
TagsPath = request.TagsPath,
|
||||||
|
IsEnabled = 1,
|
||||||
|
CreatedAt = DateTime.Now,
|
||||||
|
UpdatedAt = DateTime.Now
|
||||||
|
};
|
||||||
|
return _brandRepository.Create(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Update(int id, UpdateBrandRequest request)
|
||||||
|
{
|
||||||
|
var brand = _brandRepository.GetById(id);
|
||||||
|
if (brand == null) throw new BusinessException(ErrorCode.NotFound, "品牌不存在");
|
||||||
|
if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数错误");
|
||||||
|
|
||||||
|
brand.BrandName = request.BrandName ?? brand.BrandName;
|
||||||
|
brand.DeviceField = request.DeviceField ?? brand.DeviceField;
|
||||||
|
brand.TagsPath = request.TagsPath ?? brand.TagsPath;
|
||||||
|
brand.UpdatedAt = DateTime.Now;
|
||||||
|
|
||||||
|
return _brandRepository.Update(brand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Delete(int id)
|
||||||
|
{
|
||||||
|
var brand = _brandRepository.GetById(id);
|
||||||
|
if (brand == null) throw new BusinessException(ErrorCode.NotFound, "品牌不存在");
|
||||||
|
|
||||||
|
// 删除前检查是否有关联的采集地址
|
||||||
|
var countCollectAddress = _collectAddressRepository.GetList(new CncModels.Dto.CollectAddress.CollectAddressQuery { BrandId = id }).Total;
|
||||||
|
if (countCollectAddress > 0) return false;
|
||||||
|
|
||||||
|
return _brandRepository.Delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ToggleEnabled(int id)
|
||||||
|
{
|
||||||
|
return _brandRepository.ToggleEnabled(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Copy(int id)
|
||||||
|
{
|
||||||
|
var brand = _brandRepository.GetById(id);
|
||||||
|
if (brand == null) throw new BusinessException(ErrorCode.NotFound, "品牌不存在");
|
||||||
|
|
||||||
|
var newBrand = new Brand
|
||||||
|
{
|
||||||
|
BrandName = brand.BrandName + "_Copy",
|
||||||
|
DeviceField = brand.DeviceField,
|
||||||
|
TagsPath = brand.TagsPath,
|
||||||
|
IsEnabled = brand.IsEnabled,
|
||||||
|
CreatedAt = DateTime.Now,
|
||||||
|
};
|
||||||
|
int newBrandId = _brandRepository.Create(newBrand);
|
||||||
|
|
||||||
|
// 复制字段映射
|
||||||
|
var mappings = _mappingRepository.GetByBrandId(id);
|
||||||
|
if (mappings != null && mappings.Count > 0)
|
||||||
|
{
|
||||||
|
var newMappings = mappings.Select(m => new BrandFieldMapping
|
||||||
|
{
|
||||||
|
BrandId = newBrandId,
|
||||||
|
StandardField = m.StandardField,
|
||||||
|
FieldName = m.FieldName,
|
||||||
|
MatchBy = m.MatchBy,
|
||||||
|
DataType = m.DataType,
|
||||||
|
IsRequired = m.IsRequired,
|
||||||
|
CreatedAt = DateTime.Now
|
||||||
|
}).ToList();
|
||||||
|
_mappingRepository.BatchCreate(newBrandId, newMappings);
|
||||||
|
}
|
||||||
|
return newBrandId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<StandardFieldResponse> GetStandardFields()
|
||||||
|
{
|
||||||
|
// 硬编码的16个标准字段示例
|
||||||
|
var list = new List<StandardFieldResponse>();
|
||||||
|
for (int i = 1; i <= 16; i++)
|
||||||
|
{
|
||||||
|
list.Add(new StandardFieldResponse
|
||||||
|
{
|
||||||
|
StandardField = $"Field{i}",
|
||||||
|
Description = $"标准字段描述{i}"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using CncModels.Dto;
|
||||||
|
using CncModels.Dto.CollectAddress;
|
||||||
|
using CncRepository.Interface;
|
||||||
|
using CncService.Interface;
|
||||||
|
using CncService;
|
||||||
|
using CncModels.Entity;
|
||||||
|
|
||||||
|
namespace CncService.Impl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 采集地址实现
|
||||||
|
/// </summary>
|
||||||
|
public class CollectAddressService : ICollectAddressService
|
||||||
|
{
|
||||||
|
private readonly ICollectAddressRepository _collectAddressRepository;
|
||||||
|
private readonly IMachineRepository _machineRepository;
|
||||||
|
private readonly IBrandRepository _brandRepository;
|
||||||
|
|
||||||
|
public CollectAddressService(ICollectAddressRepository collectAddressRepository,
|
||||||
|
IMachineRepository machineRepository,
|
||||||
|
IBrandRepository brandRepository)
|
||||||
|
{
|
||||||
|
_collectAddressRepository = collectAddressRepository;
|
||||||
|
_machineRepository = machineRepository;
|
||||||
|
_brandRepository = brandRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PagedResult<CollectAddressListItem> GetList(CollectAddressQuery query)
|
||||||
|
{
|
||||||
|
return _collectAddressRepository.GetList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CollectAddressDetailResponse GetById(int id)
|
||||||
|
{
|
||||||
|
var detail = _collectAddressRepository.GetById(id);
|
||||||
|
if (detail == null) throw new BusinessException(CncModels.Constants.ErrorCode.NotFound, "采集地址不存在");
|
||||||
|
string brandName = null;
|
||||||
|
var brand = _brandRepository.GetById(detail.BrandId);
|
||||||
|
if (brand != null) brandName = brand.BrandName;
|
||||||
|
// 直接映射到输出 DTO
|
||||||
|
return new CollectAddressDetailResponse
|
||||||
|
{
|
||||||
|
Id = detail.Id,
|
||||||
|
Name = detail.Name,
|
||||||
|
Url = detail.Url,
|
||||||
|
BrandId = detail.BrandId,
|
||||||
|
BrandName = brandName,
|
||||||
|
CollectInterval = detail.CollectInterval,
|
||||||
|
IsEnabled = detail.IsEnabled
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Create(CreateCollectAddressRequest request)
|
||||||
|
{
|
||||||
|
if (request == null) throw new CncService.BusinessException(CncModels.Constants.ErrorCode.BadRequest, "请求参数错误");
|
||||||
|
if (_brandRepository.GetById(request.BrandId) == null) throw new CncService.BusinessException(CncModels.Constants.ErrorCode.NotFound, "品牌不存在");
|
||||||
|
var entity = new CollectAddress
|
||||||
|
{
|
||||||
|
Name = request.Name,
|
||||||
|
Url = request.Url,
|
||||||
|
BrandId = request.BrandId,
|
||||||
|
CollectInterval = request.CollectInterval,
|
||||||
|
IsEnabled = 1,
|
||||||
|
CreatedAt = DateTime.Now,
|
||||||
|
UpdatedAt = DateTime.Now
|
||||||
|
};
|
||||||
|
return _collectAddressRepository.Create(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Update(int id, UpdateCollectAddressRequest request)
|
||||||
|
{
|
||||||
|
var address = _collectAddressRepository.GetById(id);
|
||||||
|
if (address == null) throw new CncService.BusinessException(CncModels.Constants.ErrorCode.NotFound, "采集地址不存在");
|
||||||
|
if (request == null) throw new CncService.BusinessException(CncModels.Constants.ErrorCode.BadRequest, "请求参数错误");
|
||||||
|
|
||||||
|
address.Name = request.Name ?? address.Name;
|
||||||
|
address.Url = request.Url ?? address.Url;
|
||||||
|
address.BrandId = (request.BrandId != 0) ? request.BrandId : address.BrandId;
|
||||||
|
address.CollectInterval = (request.CollectInterval != 0) ? request.CollectInterval : address.CollectInterval;
|
||||||
|
address.UpdatedAt = DateTime.Now;
|
||||||
|
return _collectAddressRepository.Update(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Delete(int id)
|
||||||
|
{
|
||||||
|
// 检查关联机床数量
|
||||||
|
if (_collectAddressRepository.GetMachineCount(id) > 0) return false;
|
||||||
|
return _collectAddressRepository.Delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ToggleEnabled(int id)
|
||||||
|
{
|
||||||
|
return _collectAddressRepository.ToggleEnabled(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using CncService.Interface;
|
||||||
|
using CncModels.Dto;
|
||||||
|
using CncModels.Entity;
|
||||||
|
using CncModels.Constants;
|
||||||
|
using CncRepository.Interface;
|
||||||
|
|
||||||
|
namespace CncService.Impl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 采集数据查询实现
|
||||||
|
/// </summary>
|
||||||
|
public class CollectDataService : ICollectDataService
|
||||||
|
{
|
||||||
|
private readonly ICollectRawRepository _collectRawRepository;
|
||||||
|
|
||||||
|
public CollectDataService(ICollectRawRepository collectRawRepository)
|
||||||
|
{
|
||||||
|
_collectRawRepository = collectRawRepository ?? throw new ArgumentNullException(nameof(collectRawRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public PagedResult<CollectRaw> GetRawByAddress(int addressId, int page, int pageSize)
|
||||||
|
{
|
||||||
|
if (addressId <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的地址ID");
|
||||||
|
if (page <= 0) throw new BusinessException(ErrorCode.BadRequest, "页码无效");
|
||||||
|
if (pageSize <= 0) throw new BusinessException(ErrorCode.BadRequest, "页大小无效");
|
||||||
|
return _collectRawRepository.GetByAddressId(addressId, page, pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public CollectRaw GetLatestRaw(int addressId)
|
||||||
|
{
|
||||||
|
if (addressId <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的地址ID");
|
||||||
|
return _collectRawRepository.GetLatestByAddressId(addressId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CncModels.Dto.Dashboard;
|
||||||
|
using CncRepository.Interface;
|
||||||
|
using CncService.Interface;
|
||||||
|
|
||||||
|
namespace CncService.Impl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 仪表盘实现
|
||||||
|
/// </summary>
|
||||||
|
public class DashboardService : IDashboardService
|
||||||
|
{
|
||||||
|
private readonly IDashboardRepository _dashboardRepository;
|
||||||
|
private readonly ICollectorHeartbeatRepository _collectorHeartbeatRepository;
|
||||||
|
|
||||||
|
public DashboardService(IDashboardRepository dashboardRepository,
|
||||||
|
ICollectorHeartbeatRepository collectorHeartbeatRepository)
|
||||||
|
{
|
||||||
|
_dashboardRepository = dashboardRepository ?? throw new ArgumentNullException(nameof(dashboardRepository));
|
||||||
|
_collectorHeartbeatRepository = collectorHeartbeatRepository ?? throw new ArgumentNullException(nameof(collectorHeartbeatRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public DashboardSummaryResponse GetSummary()
|
||||||
|
{
|
||||||
|
return _dashboardRepository.GetSummary();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public List<WorkshopProductionResponse> GetWorkshopProduction(DateTime? startDate, DateTime? endDate)
|
||||||
|
{
|
||||||
|
var s = startDate ?? DateTime.Today;
|
||||||
|
var e = endDate ?? DateTime.Today;
|
||||||
|
return _dashboardRepository.GetWorkshopProduction(s, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public List<MachineRankResponse> GetMachineRank(DateTime? startDate, DateTime? endDate, int top = 10)
|
||||||
|
{
|
||||||
|
var s = startDate ?? DateTime.Today;
|
||||||
|
var e = endDate ?? DateTime.Today;
|
||||||
|
return _dashboardRepository.GetMachineRank(s, e, top);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public List<WorkerRankResponse> GetWorkerRank(DateTime? startDate, DateTime? endDate, int top = 10)
|
||||||
|
{
|
||||||
|
var s = startDate ?? DateTime.Today;
|
||||||
|
var e = endDate ?? DateTime.Today;
|
||||||
|
return _dashboardRepository.GetWorkerRank(s, e, top);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public object GetProductionTrend(int days = 7)
|
||||||
|
{
|
||||||
|
return _dashboardRepository.GetProductionTrend(days);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public object GetMachineStatusDistribution()
|
||||||
|
{
|
||||||
|
return _dashboardRepository.GetMachineStatusDistribution();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public List<AlertListItem> GetRecentAlerts(int count = 5)
|
||||||
|
{
|
||||||
|
return _dashboardRepository.GetRecentAlerts(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public object GetCollectorStatus()
|
||||||
|
{
|
||||||
|
var latest = _collectorHeartbeatRepository.GetLatest("collector-service");
|
||||||
|
bool isRunning = latest != null && latest.LastCollectTime.HasValue &&
|
||||||
|
(DateTime.Now - latest.LastCollectTime.Value).TotalMinutes < 5;
|
||||||
|
return new { IsRunning = isRunning, LastCollectTime = latest?.LastCollectTime };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CncService.Interface;
|
||||||
|
using CncModels.Dto;
|
||||||
|
using CncModels.Dto.Machine;
|
||||||
|
using CncModels.Entity;
|
||||||
|
using CncModels.Constants;
|
||||||
|
using CncRepository.Interface;
|
||||||
|
|
||||||
|
namespace CncService.Impl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 机床管理实现
|
||||||
|
/// </summary>
|
||||||
|
public class MachineService : IMachineService
|
||||||
|
{
|
||||||
|
private readonly IMachineRepository _machineRepository;
|
||||||
|
private readonly ICollectAddressRepository _addressRepository;
|
||||||
|
private readonly IWorkerMachineRepository _workerMachineRepository;
|
||||||
|
private readonly IBrandRepository _brandRepository;
|
||||||
|
|
||||||
|
public MachineService(
|
||||||
|
IMachineRepository machineRepository,
|
||||||
|
ICollectAddressRepository addressRepository,
|
||||||
|
IWorkerMachineRepository workerMachineRepository,
|
||||||
|
IBrandRepository brandRepository)
|
||||||
|
{
|
||||||
|
_machineRepository = machineRepository ?? throw new ArgumentNullException(nameof(machineRepository));
|
||||||
|
_addressRepository = addressRepository ?? throw new ArgumentNullException(nameof(addressRepository));
|
||||||
|
_workerMachineRepository = workerMachineRepository ?? throw new ArgumentNullException(nameof(workerMachineRepository));
|
||||||
|
_brandRepository = brandRepository ?? throw new ArgumentNullException(nameof(brandRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public PagedResult<MachineListItem> GetList(MachineQuery query)
|
||||||
|
{
|
||||||
|
if (query == null) throw new BusinessException(ErrorCode.BadRequest, "查询参数不能为空");
|
||||||
|
return _machineRepository.GetList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public MachineDetailResponse GetById(int id)
|
||||||
|
{
|
||||||
|
if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的机床ID");
|
||||||
|
var machine = _machineRepository.GetById(id);
|
||||||
|
if (machine == null) throw new BusinessException(ErrorCode.NotFound, "机床未找到");
|
||||||
|
|
||||||
|
var detail = new MachineDetailResponse
|
||||||
|
{
|
||||||
|
Id = machine.Id,
|
||||||
|
DeviceCode = machine.DeviceCode,
|
||||||
|
Name = machine.Name,
|
||||||
|
WorkshopId = machine.WorkshopId,
|
||||||
|
CollectAddressId = machine.CollectAddressId,
|
||||||
|
BrandId = machine.BrandId,
|
||||||
|
IpAddress = machine.IpAddress,
|
||||||
|
IsEnabled = machine.IsEnabled,
|
||||||
|
IsOnline = machine.IsOnline,
|
||||||
|
LastProgramName = machine.LastProgramName,
|
||||||
|
LastCollectTime = machine.LastCollectTime
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取绑定工人信息
|
||||||
|
var binding = _workerMachineRepository.GetByMachineId(id);
|
||||||
|
if (binding != null)
|
||||||
|
{
|
||||||
|
detail.WorkerId = binding.WorkerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int Create(CreateMachineRequest request)
|
||||||
|
{
|
||||||
|
if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数不能为空");
|
||||||
|
if (string.IsNullOrWhiteSpace(request.DeviceCode)) throw new BusinessException(ErrorCode.BadRequest, "设备编码不能为空");
|
||||||
|
// 唯一性校验
|
||||||
|
var existing = _machineRepository.GetByDeviceCode(request.DeviceCode);
|
||||||
|
if (existing != null) throw new BusinessException(ErrorCode.Conflict, "设备编码已存在");
|
||||||
|
|
||||||
|
var entity = new Machine
|
||||||
|
{
|
||||||
|
DeviceCode = request.DeviceCode,
|
||||||
|
Name = request.Name,
|
||||||
|
WorkshopId = request.WorkshopId,
|
||||||
|
CollectAddressId = request.CollectAddressId,
|
||||||
|
BrandId = request.BrandId,
|
||||||
|
IpAddress = request.IpAddress,
|
||||||
|
IsEnabled = 1,
|
||||||
|
IsOnline = 0,
|
||||||
|
CreatedAt = DateTime.Now,
|
||||||
|
UpdatedAt = DateTime.Now
|
||||||
|
};
|
||||||
|
return _machineRepository.Create(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Update(int id, UpdateMachineRequest request)
|
||||||
|
{
|
||||||
|
if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的机床ID");
|
||||||
|
if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数不能为空");
|
||||||
|
var entity = _machineRepository.GetById(id);
|
||||||
|
if (entity == null) throw new BusinessException(ErrorCode.NotFound, "机床未找到");
|
||||||
|
|
||||||
|
entity.Name = request.Name ?? entity.Name;
|
||||||
|
entity.WorkshopId = request.WorkshopId;
|
||||||
|
entity.CollectAddressId = request.CollectAddressId;
|
||||||
|
entity.BrandId = request.BrandId;
|
||||||
|
entity.IpAddress = request.IpAddress ?? entity.IpAddress;
|
||||||
|
entity.UpdatedAt = DateTime.Now;
|
||||||
|
return _machineRepository.Update(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Delete(int id)
|
||||||
|
{
|
||||||
|
if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的机床ID");
|
||||||
|
// 解绑工人
|
||||||
|
_workerMachineRepository.DeleteByMachineId(id);
|
||||||
|
return _machineRepository.Delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool ToggleEnabled(int id)
|
||||||
|
{
|
||||||
|
if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的机床ID");
|
||||||
|
return _machineRepository.ToggleEnabled(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CncService.Interface;
|
||||||
|
using CncModels.Dto;
|
||||||
|
using CncModels.Dto.Production;
|
||||||
|
using CncModels.Entity;
|
||||||
|
using CncModels.Constants;
|
||||||
|
using CncRepository.Interface;
|
||||||
|
|
||||||
|
namespace CncService.Impl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 产量管理实现
|
||||||
|
/// </summary>
|
||||||
|
public class ProductionService : IProductionService
|
||||||
|
{
|
||||||
|
private readonly IDailyProductionRepository _dailyProductionRepository;
|
||||||
|
private readonly IProductionSegmentRepository _productionSegmentRepository;
|
||||||
|
private readonly IProductionAdjustmentRepository _productionAdjustmentRepository;
|
||||||
|
|
||||||
|
public ProductionService(
|
||||||
|
IDailyProductionRepository dailyProductionRepository,
|
||||||
|
IProductionSegmentRepository productionSegmentRepository,
|
||||||
|
IProductionAdjustmentRepository productionAdjustmentRepository)
|
||||||
|
{
|
||||||
|
_dailyProductionRepository = dailyProductionRepository ?? throw new ArgumentNullException(nameof(dailyProductionRepository));
|
||||||
|
_productionSegmentRepository = productionSegmentRepository ?? throw new ArgumentNullException(nameof(productionSegmentRepository));
|
||||||
|
_productionAdjustmentRepository = productionAdjustmentRepository ?? throw new ArgumentNullException(nameof(productionAdjustmentRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public PagedResult<DailyProductionListItem> GetList(ProductionQuery query)
|
||||||
|
{
|
||||||
|
if (query == null) throw new BusinessException(ErrorCode.BadRequest, "查询参数不能为空");
|
||||||
|
return _dailyProductionRepository.GetList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public DailySummaryResponse GetSummary(DateTime? date, int? workshopId)
|
||||||
|
{
|
||||||
|
var targetDate = date ?? DateTime.Today;
|
||||||
|
var total = _dailyProductionRepository.GetTotalByDateRange(targetDate, targetDate, workshopId);
|
||||||
|
return new DailySummaryResponse
|
||||||
|
{
|
||||||
|
TotalQuantity = (int)total,
|
||||||
|
MachineCount = 0,
|
||||||
|
NormalCount = 0,
|
||||||
|
OfflineCount = 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public decimal GetTotalByDateRange(DateTime startDate, DateTime endDate, int? workshopId)
|
||||||
|
{
|
||||||
|
return _dailyProductionRepository.GetTotalByDateRange(startDate, endDate, workshopId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Adjust(ProductionAdjustRequest request)
|
||||||
|
{
|
||||||
|
if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数不能为空");
|
||||||
|
decimal newValue;
|
||||||
|
decimal.TryParse(request.NewValue, out newValue);
|
||||||
|
var entity = new ProductionAdjustment
|
||||||
|
{
|
||||||
|
TargetTable = request.TargetTable,
|
||||||
|
TargetId = request.TargetId,
|
||||||
|
FieldName = request.FieldName,
|
||||||
|
OldValue = null,
|
||||||
|
NewValue = newValue,
|
||||||
|
Reason = request.Reason,
|
||||||
|
OperatorIp = "",
|
||||||
|
CreatedAt = DateTime.Now
|
||||||
|
};
|
||||||
|
_productionAdjustmentRepository.Create(entity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using CncService.Interface;
|
||||||
|
using CncModels.Dto;
|
||||||
|
using CncModels.Dto.Log;
|
||||||
|
using CncModels.Constants;
|
||||||
|
using CncRepository.Interface;
|
||||||
|
|
||||||
|
namespace CncService.Impl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 系统日志实现
|
||||||
|
/// </summary>
|
||||||
|
public class SystemLogService : ISystemLogService
|
||||||
|
{
|
||||||
|
private readonly ISystemLogRepository _systemLogRepository;
|
||||||
|
|
||||||
|
public SystemLogService(ISystemLogRepository systemLogRepository)
|
||||||
|
{
|
||||||
|
_systemLogRepository = systemLogRepository ?? throw new ArgumentNullException(nameof(systemLogRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public PagedResult<SystemLogListItem> GetList(SystemLogQuery query)
|
||||||
|
{
|
||||||
|
if (query == null) throw new BusinessException(ErrorCode.BadRequest, "查询参数不能为空");
|
||||||
|
return _systemLogRepository.GetList(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using CncService.Interface;
|
||||||
|
using CncModels.Dto;
|
||||||
|
using CncModels.Dto.Worker;
|
||||||
|
using CncModels.Entity;
|
||||||
|
using CncModels.Constants;
|
||||||
|
using CncRepository.Interface;
|
||||||
|
|
||||||
|
namespace CncService.Impl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 员工管理实现
|
||||||
|
/// </summary>
|
||||||
|
public class WorkerService : IWorkerService
|
||||||
|
{
|
||||||
|
private readonly IWorkerRepository _workerRepository;
|
||||||
|
private readonly IWorkerMachineRepository _workerMachineRepository;
|
||||||
|
private readonly IMachineRepository _machineRepository;
|
||||||
|
|
||||||
|
public WorkerService(
|
||||||
|
IWorkerRepository workerRepository,
|
||||||
|
IWorkerMachineRepository workerMachineRepository,
|
||||||
|
IMachineRepository machineRepository)
|
||||||
|
{
|
||||||
|
_workerRepository = workerRepository ?? throw new ArgumentNullException(nameof(workerRepository));
|
||||||
|
_workerMachineRepository = workerMachineRepository ?? throw new ArgumentNullException(nameof(workerMachineRepository));
|
||||||
|
_machineRepository = machineRepository ?? throw new ArgumentNullException(nameof(machineRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public PagedResult<WorkerListItem> GetList(WorkerQuery query)
|
||||||
|
{
|
||||||
|
if (query == null) throw new BusinessException(ErrorCode.BadRequest, "查询参数不能为空");
|
||||||
|
return _workerRepository.GetList(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public WorkerDetailResponse GetById(int id)
|
||||||
|
{
|
||||||
|
if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
|
||||||
|
var w = _workerRepository.GetById(id);
|
||||||
|
if (w == null) throw new BusinessException(ErrorCode.NotFound, "员工未找到");
|
||||||
|
|
||||||
|
var bindings = _workerMachineRepository.GetByWorkerId(id);
|
||||||
|
var machineNames = new List<string>();
|
||||||
|
foreach (var b in bindings)
|
||||||
|
{
|
||||||
|
var m = _machineRepository.GetById(b.MachineId);
|
||||||
|
if (m != null) machineNames.Add(m.Name ?? m.DeviceCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WorkerDetailResponse
|
||||||
|
{
|
||||||
|
Id = w.Id,
|
||||||
|
Code = w.Code,
|
||||||
|
Name = w.Name,
|
||||||
|
IsEnabled = w.IsEnabled,
|
||||||
|
MachineCount = bindings.Count,
|
||||||
|
MachineNames = string.Join(", ", machineNames)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public int Create(CreateWorkerRequest request)
|
||||||
|
{
|
||||||
|
if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数不能为空");
|
||||||
|
if (string.IsNullOrWhiteSpace(request.Code)) throw new BusinessException(ErrorCode.BadRequest, "工号不能为空");
|
||||||
|
// 唯一性校验
|
||||||
|
var existing = _workerRepository.GetByCode(request.Code);
|
||||||
|
if (existing != null) throw new BusinessException(ErrorCode.Conflict, "工号已存在");
|
||||||
|
|
||||||
|
var entity = new Worker
|
||||||
|
{
|
||||||
|
Name = request.Name,
|
||||||
|
Code = request.Code,
|
||||||
|
IsEnabled = 1,
|
||||||
|
CreatedAt = DateTime.Now,
|
||||||
|
UpdatedAt = DateTime.Now
|
||||||
|
};
|
||||||
|
return _workerRepository.Create(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Update(int id, UpdateWorkerRequest request)
|
||||||
|
{
|
||||||
|
if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
|
||||||
|
if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数不能为空");
|
||||||
|
var entity = _workerRepository.GetById(id);
|
||||||
|
if (entity == null) throw new BusinessException(ErrorCode.NotFound, "员工未找到");
|
||||||
|
|
||||||
|
entity.Name = request.Name ?? entity.Name;
|
||||||
|
entity.UpdatedAt = DateTime.Now;
|
||||||
|
return _workerRepository.Update(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Delete(int id)
|
||||||
|
{
|
||||||
|
if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
|
||||||
|
// 解绑所有机床
|
||||||
|
_workerMachineRepository.DeleteByWorkerId(id);
|
||||||
|
return _workerRepository.Delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool ToggleEnabled(int id)
|
||||||
|
{
|
||||||
|
if (id <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的员工ID");
|
||||||
|
return _workerRepository.ToggleEnabled(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool BindMachine(int workerId, int machineId)
|
||||||
|
{
|
||||||
|
if (workerId <= 0 || machineId <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的参数");
|
||||||
|
// 检查是否已绑定
|
||||||
|
var existing = _workerMachineRepository.GetByMachineId(machineId);
|
||||||
|
if (existing != null) throw new BusinessException(ErrorCode.Conflict, "该机床已绑定其他工人");
|
||||||
|
_workerMachineRepository.Create(workerId, machineId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool UnbindMachine(int workerId, int machineId)
|
||||||
|
{
|
||||||
|
if (workerId <= 0 || machineId <= 0) throw new BusinessException(ErrorCode.BadRequest, "无效的参数");
|
||||||
|
return _workerMachineRepository.DeleteByMachineId(machineId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CncModels.Dto.Alert;
|
||||||
|
using CncModels.Dto;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
public interface IAlertService
|
||||||
|
{
|
||||||
|
PagedResult<AlertListItem> GetList(AlertQuery query);
|
||||||
|
bool Resolve(long id);
|
||||||
|
int BatchResolve(List<long> ids);
|
||||||
|
AlertStatisticsResponse GetStatistics();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
using CncModels.Dto.Login;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 登录认证服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IAuthService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 管理员登录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">登录请求参数</param>
|
||||||
|
/// <returns>登录响应(包含 JWT Token 及有效期)</returns>
|
||||||
|
LoginResponse Login(LoginRequest request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using CncModels.Dto.Brand;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 品牌模板服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IBrandService
|
||||||
|
{
|
||||||
|
List<BrandListItem> GetList();
|
||||||
|
BrandDetailResponse GetById(int id);
|
||||||
|
int Create(CreateBrandRequest request);
|
||||||
|
bool Update(int id, UpdateBrandRequest request);
|
||||||
|
bool Delete(int id);
|
||||||
|
bool ToggleEnabled(int id);
|
||||||
|
int Copy(int id);
|
||||||
|
List<StandardFieldResponse> GetStandardFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
using CncModels.Dto;
|
||||||
|
using CncModels.Dto.CollectAddress;
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 采集地址服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface ICollectAddressService
|
||||||
|
{
|
||||||
|
PagedResult<CollectAddressListItem> GetList(CollectAddressQuery query);
|
||||||
|
CollectAddressDetailResponse GetById(int id);
|
||||||
|
int Create(CreateCollectAddressRequest request);
|
||||||
|
bool Update(int id, UpdateCollectAddressRequest request);
|
||||||
|
bool Delete(int id);
|
||||||
|
bool ToggleEnabled(int id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
using CncModels.Dto;
|
||||||
|
using CncModels.Entity;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 采集数据查询服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface ICollectDataService
|
||||||
|
{
|
||||||
|
/// <summary>按地址ID分页查询原始采集记录</summary>
|
||||||
|
PagedResult<CollectRaw> GetRawByAddress(int addressId, int page, int pageSize);
|
||||||
|
|
||||||
|
/// <summary>获取最新采集记录</summary>
|
||||||
|
CollectRaw GetLatestRaw(int addressId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CncModels.Dto.Dashboard;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 仪表盘服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IDashboardService
|
||||||
|
{
|
||||||
|
DashboardSummaryResponse GetSummary();
|
||||||
|
|
||||||
|
List<WorkshopProductionResponse> GetWorkshopProduction(DateTime? startDate, DateTime? endDate);
|
||||||
|
|
||||||
|
List<MachineRankResponse> GetMachineRank(DateTime? startDate, DateTime? endDate, int top = 10);
|
||||||
|
|
||||||
|
List<WorkerRankResponse> GetWorkerRank(DateTime? startDate, DateTime? endDate, int top = 10);
|
||||||
|
|
||||||
|
object GetProductionTrend(int days = 7);
|
||||||
|
|
||||||
|
object GetMachineStatusDistribution();
|
||||||
|
|
||||||
|
List<AlertListItem> GetRecentAlerts(int count = 5);
|
||||||
|
|
||||||
|
object GetCollectorStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CncModels.Dto.Machine;
|
||||||
|
using CncModels.Dto;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 机床管理服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IMachineService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 分页查询机床列表
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">查询条件</param>
|
||||||
|
/// <returns>分页结果</returns>
|
||||||
|
PagedResult<MachineListItem> GetList(MachineQuery query);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据ID获取机床详情
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">机床ID</param>
|
||||||
|
/// <returns>机床详情</returns>
|
||||||
|
MachineDetailResponse GetById(int id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新增机床
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">创建参数</param>
|
||||||
|
/// <returns>新建机床的ID</returns>
|
||||||
|
int Create(CreateMachineRequest request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 编辑机床信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">机床ID</param>
|
||||||
|
/// <param name="request">修改参数</param>
|
||||||
|
/// <returns>是否更新成功</returns>
|
||||||
|
bool Update(int id, UpdateMachineRequest request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除机床并解绑相关工人
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">机床ID</param>
|
||||||
|
/// <returns>是否删除成功</returns>
|
||||||
|
bool Delete(int id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 启用或禁用机床
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">机床ID</param>
|
||||||
|
/// <returns>是否切换成功</returns>
|
||||||
|
bool ToggleEnabled(int id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CncModels.Dto;
|
||||||
|
using CncModels.Dto.Production;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 产量管理服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IProductionService
|
||||||
|
{
|
||||||
|
/// <summary>分页查询产量记录</summary>
|
||||||
|
PagedResult<DailyProductionListItem> GetList(ProductionQuery query);
|
||||||
|
|
||||||
|
/// <summary>获取日汇总统计</summary>
|
||||||
|
DailySummaryResponse GetSummary(DateTime? date, int? workshopId);
|
||||||
|
|
||||||
|
/// <summary>获取日期范围总产量</summary>
|
||||||
|
decimal GetTotalByDateRange(DateTime startDate, DateTime endDate, int? workshopId);
|
||||||
|
|
||||||
|
/// <summary>产量修正</summary>
|
||||||
|
bool Adjust(ProductionAdjustRequest request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using CncModels.Dto.Screen;
|
||||||
|
using CncModels.Dto.ScreenConfig;
|
||||||
|
using CncModels.Entity;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 大屏配置服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IScreenService
|
||||||
|
{
|
||||||
|
/// <summary>获取大屏汇总数据</summary>
|
||||||
|
ScreenSummaryResponse GetSummary();
|
||||||
|
|
||||||
|
/// <summary>获取所有卡片配置</summary>
|
||||||
|
List<ScreenConfig> GetConfigs();
|
||||||
|
|
||||||
|
/// <summary>更新卡片配置</summary>
|
||||||
|
bool UpdateConfig(ScreenConfig entity);
|
||||||
|
|
||||||
|
/// <summary>获取筛选项列表</summary>
|
||||||
|
List<ScreenFilter> GetFilters(string screenKey);
|
||||||
|
|
||||||
|
/// <summary>创建筛选项</summary>
|
||||||
|
int CreateFilter(ScreenFilter entity);
|
||||||
|
|
||||||
|
/// <summary>更新筛选项</summary>
|
||||||
|
bool UpdateFilter(ScreenFilter entity);
|
||||||
|
|
||||||
|
/// <summary>删除筛选项</summary>
|
||||||
|
bool DeleteFilter(int id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CncModels.Dto.Log;
|
||||||
|
using CncModels.Dto;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
public interface ISystemLogService
|
||||||
|
{
|
||||||
|
PagedResult<SystemLogListItem> GetList(SystemLogQuery query);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CncModels.Dto.Worker;
|
||||||
|
using CncModels.Dto;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
public interface IWorkerService
|
||||||
|
{
|
||||||
|
PagedResult<WorkerListItem> GetList(WorkerQuery query);
|
||||||
|
WorkerDetailResponse GetById(int id);
|
||||||
|
int Create(CreateWorkerRequest request);
|
||||||
|
bool Update(int id, UpdateWorkerRequest request);
|
||||||
|
bool Delete(int id);
|
||||||
|
bool ToggleEnabled(int id);
|
||||||
|
bool BindMachine(int workerId, int machineId);
|
||||||
|
bool UnbindMachine(int workerId, int machineId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using CncModels.Dto.Settings;
|
||||||
|
using CncModels.Entity;
|
||||||
|
|
||||||
|
namespace CncService.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 车间管理服务接口
|
||||||
|
/// </summary>
|
||||||
|
public interface IWorkshopService
|
||||||
|
{
|
||||||
|
/// <summary>获取车间列表</summary>
|
||||||
|
List<WorkshopListItem> GetList(string keyword);
|
||||||
|
|
||||||
|
/// <summary>按ID获取车间</summary>
|
||||||
|
Workshop GetById(int id);
|
||||||
|
|
||||||
|
/// <summary>新增车间</summary>
|
||||||
|
int Create(CreateWorkshopRequest request);
|
||||||
|
|
||||||
|
/// <summary>编辑车间</summary>
|
||||||
|
bool Update(int id, UpdateWorkshopRequest request);
|
||||||
|
|
||||||
|
/// <summary>删除车间</summary>
|
||||||
|
bool Delete(int id);
|
||||||
|
|
||||||
|
/// <summary>启停车间</summary>
|
||||||
|
bool ToggleEnabled(int id);
|
||||||
|
|
||||||
|
/// <summary>获取车间下机床数量</summary>
|
||||||
|
int GetMachineCount(int workshopId);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue