From 9e78aa7769ff3794cfa05510c989ae16a50e24d6 Mon Sep 17 00:00:00 2001 From: wuyi Date: Fri, 28 Aug 2026 11:03:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0ORM=E7=9A=84=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E6=B3=A8=E5=85=A5=EF=BC=8C=E6=B7=BB=E5=8A=A0appsettin?= =?UTF-8?q?gs=E7=9A=84gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Asset/EquipmentController.cs | 9 +- IOT_API/DependencyInjection.cs | 8 + IOT_API/Program.cs | 21 -- Service/Implement/Asset/EquipmentService.cs | 260 ++++++++++++++++- Service/Implement/EquipmentService.cs | 266 ------------------ Service/Interface/Asset/IEquipmentService.cs | 61 +++- Service/Interface/IEquipmentService.cs | 65 ----- 7 files changed, 325 insertions(+), 365 deletions(-) delete mode 100644 Service/Implement/EquipmentService.cs delete mode 100644 Service/Interface/IEquipmentService.cs diff --git a/IOT_API/Controllers/Asset/EquipmentController.cs b/IOT_API/Controllers/Asset/EquipmentController.cs index cfd2ea0..fbdd3f0 100644 --- a/IOT_API/Controllers/Asset/EquipmentController.cs +++ b/IOT_API/Controllers/Asset/EquipmentController.cs @@ -1,8 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Model; using Model.Entity.Asset; -using ORM; -using Service.Implement; using Service.Interface; using SqlSugar; using System.Collections.Generic; @@ -20,12 +18,9 @@ namespace IOT_API.Controllers.Asset { private readonly IEquipmentService _equipmentService; - public EquipmentController() + public EquipmentController(IEquipmentService equipmentService) { - // 项目未注册 DI 容器,SqlSugarContext.DbContext 为静态单例,直接实例化服务 - _equipmentService = new EquipmentService( - new SqlSugarRepository(), - new SqlSugarRepository()); + _equipmentService = equipmentService; } /// diff --git a/IOT_API/DependencyInjection.cs b/IOT_API/DependencyInjection.cs index 138e070..9dec826 100644 --- a/IOT_API/DependencyInjection.cs +++ b/IOT_API/DependencyInjection.cs @@ -1,4 +1,6 @@ +using ORM; using Service.Implement; +using SqlSugar; using System.Reflection; namespace WebAPI @@ -15,6 +17,12 @@ namespace WebAPI /// public static IServiceCollection AddBusinessServices(this IServiceCollection services) { + // SqlSugar 客户端:静态单例(SqlSugarScope 线程安全),供仓储及其他需要注入 ISqlSugarClient 的地方使用 + services.AddSingleton(SqlSugarContext.DbContext); + + // 泛型仓储:所有 SqlSugarRepository 统一注册(内部使用 SqlSugarContext.DbContext 静态单例) + services.AddScoped(typeof(SqlSugarRepository<>)); + // Service 项目程序集(接口与实现都在同一个程序集里) Assembly assembly = typeof(BaseService<>).Assembly; diff --git a/IOT_API/Program.cs b/IOT_API/Program.cs index 1eab3c7..f039c2f 100644 --- a/IOT_API/Program.cs +++ b/IOT_API/Program.cs @@ -48,27 +48,6 @@ namespace WebAPI builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); - // ======= Database init start ======= - // Npgsql 时间兼容开关:允许向 PostgreSQL 写入本地时间 DateTime(DateTime.Now) - AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); - - // 从 appsettings.json 读取数据库配置(PostgreSQL) - var dbConfig = builder.Configuration.GetSection("Database"); - DatabaseConfig.InitPostgreSql( - dbConfig["Server"] ?? "localhost", - int.TryParse(dbConfig["Port"], out var port) ? port : 5432, - dbConfig["Database"] ?? "iot", - dbConfig["Uid"] ?? "postgres", - dbConfig["Pwd"] ?? ""); - - // 数据库不存在则创建,并检查连接(租户雪花机器码可按需设置) - DatabaseConfig.SetTenant(10001); - DatabaseConfig.CreateDatabaseAndCheckConnection(createDatabase: true, checkConnection: true); - - // CodeFirst 自动建表:扫描 Model.dll 中所有以 Entity 结尾的类建表/补列 - SqlSugarContext.InitDatabase(); - // ======= Database init end ======= - var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/Service/Implement/Asset/EquipmentService.cs b/Service/Implement/Asset/EquipmentService.cs index f6d87c8..17517ce 100644 --- a/Service/Implement/Asset/EquipmentService.cs +++ b/Service/Implement/Asset/EquipmentService.cs @@ -1,12 +1,266 @@ +using Model; +using Model.Entity.Asset; +using ORM; using Service.Interface; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Service.Implement { /// - /// 设备台账 服务实现 + /// 设备台账服务实现(资产管理) /// - public class EquipmentService : IEquipmentService + public class EquipmentService : BaseService, IEquipmentService { - // TODO: 实现 设备台账 相关方法 + private readonly SqlSugarRepository _statusRecordRepository; + + public EquipmentService(SqlSugarRepository repository, + SqlSugarRepository statusRecordRepository) + : base(repository) + { + _statusRecordRepository = statusRecordRepository; + } + + /// + /// 查询全部设备(过滤已删除数据) + /// + public override async Task>> GetAllAsync() + { + try + { + var list = await _repository.Entities + .Where(x => x.IsDel == 0) + .OrderBy(x => x.CreateTime, OrderByType.Desc) + .ToListAsync(); + return Result>.Success(list); + } + catch (Exception ex) + { + return Result>.Error("查询设备台账失败", ex); + } + } + + /// + /// 分页查询设备台账(支持关键字、分类、状态筛选) + /// + public async Task>> GetPagedAsync(int pageIndex, int pageSize, RefAsync total, + string? keyword, long categoryId = 0, EquipmentStatusEnum? status = null) + { + try + { + var list = await _repository.Entities + .Where(x => x.IsDel == 0) + .WhereIF(!string.IsNullOrWhiteSpace(keyword), + x => x.Code!.Contains(keyword!) || x.Name!.Contains(keyword!)) + .WhereIF(categoryId > 0, x => x.CategoryId == categoryId) + .WhereIF(status.HasValue, x => x.Status == status!.Value) + .OrderBy(x => x.CreateTime, OrderByType.Desc) + .ToPageListAsync(pageIndex, pageSize, total); + total.Value = (int)Math.Ceiling((double)total.Value / pageSize); + return Result>.Success(list); + } + catch (Exception ex) + { + return Result>.Error("分页查询设备台账失败", ex); + } + } + + /// + /// 根据 Id 获取设备台账详情 + /// + public async Task> GetByIdAsync(long id) + { + try + { + var entity = await _repository.Entities + .Where(x => x.Id == id && x.IsDel == 0) + .FirstAsync(); + if (entity == null) + { + return Result.Error("设备不存在或已被删除"); + } + return Result.Success(entity); + } + catch (Exception ex) + { + return Result.Error("查询设备详情失败", ex); + } + } + + /// + /// 新增设备台账(校验编号唯一性,补充创建时间) + /// + public override async Task> InsertAsync(EquipmentEntity entity) + { + if (string.IsNullOrWhiteSpace(entity.Code)) + { + return Result.Error("设备编号不能为空"); + } + try + { + // 设备编号唯一性校验(未删除范围内) + bool exists = await _repository.Entities + .AnyAsync(x => x.Code == entity.Code && x.IsDel == 0); + if (exists) + { + return Result.Error($"设备编号【{entity.Code}】已存在"); + } + + entity.CreateTime = DateTime.Now; + var result = await _repository.Context.Insertable(entity).ExecuteCommandAsync(); + return Result.Success(result > 0); + } + catch (Exception ex) + { + return Result.Error("新增设备失败", ex); + } + } + + /// + /// 更新设备台账 + /// + public async Task> UpdateAsync(EquipmentEntity entity) + { + if (entity.Id <= 0) + { + return Result.Error("设备 Id 无效"); + } + try + { + var old = await _repository.Entities + .Where(x => x.Id == entity.Id && x.IsDel == 0) + .FirstAsync(); + if (old == null) + { + return Result.Error("设备不存在或已被删除"); + } + + // 设备编号变更时校验唯一性 + if (!string.IsNullOrWhiteSpace(entity.Code) && entity.Code != old.Code) + { + bool exists = await _repository.Entities + .AnyAsync(x => x.Code == entity.Code && x.IsDel == 0 && x.Id != entity.Id); + if (exists) + { + return Result.Error($"设备编号【{entity.Code}】已存在"); + } + } + + entity.IsDel = old.IsDel; + entity.CreateTime = old.CreateTime; + entity.UpdateTime = DateTime.Now; + var result = await _repository.Context.Updateable(entity).ExecuteCommandAsync(); + return Result.Success(result > 0); + } + catch (Exception ex) + { + return Result.Error("更新设备失败", ex); + } + } + + /// + /// 软删除设备台账(置 IsDel = 1) + /// + public async Task> DeleteEquipmentAsync(long id) + { + if (id <= 0) + { + return Result.Error("设备 Id 无效"); + } + try + { + var result = await _repository.Context.Updateable() + .SetColumns(x => x.IsDel == 1) + .Where(x => x.Id == id) + .ExecuteCommandAsync(); + return Result.Success(result > 0); + } + catch (Exception ex) + { + return Result.Error("删除设备失败", ex); + } + } + + /// + /// 变更设备状态,并记录状态变更历史(事务保证一致性) + /// + public async Task> ChangeStatusAsync(long equipmentId, EquipmentStatusEnum toStatus, string? operatorName, string? remark) + { + if (equipmentId <= 0) + { + return Result.Error("设备 Id 无效"); + } + try + { + var equipment = await _repository.Entities + .Where(x => x.Id == equipmentId && x.IsDel == 0) + .FirstAsync(); + if (equipment == null) + { + return Result.Error("设备不存在或已被删除"); + } + if (equipment.Status == toStatus) + { + return Result.Error("目标状态与当前状态一致,无需变更"); + } + + var now = DateTime.Now; + var record = new EquipmentStatusRecordEntity + { + EquipmentId = equipmentId, + FromStatus = equipment.Status, + ToStatus = toStatus, + ChangeTime = now, + Operator = operatorName, + Remark = remark, + CreateTime = now + }; + + // 事务:更新设备状态 + 插入状态变更记录 + _repository.BeginTran(); + try + { + equipment.Status = toStatus; + equipment.UpdateTime = now; + await _repository.Context.Updateable(equipment) + .UpdateColumns(x => new { x.Status, x.UpdateTime }) + .ExecuteCommandAsync(); + await _statusRecordRepository.Context.Insertable(record).ExecuteCommandAsync(); + _repository.CommitTran(); + } + catch + { + _repository.RollbackTran(); + throw; + } + + return Result.Success(true); + } + catch (Exception ex) + { + return Result.Error("变更设备状态失败", ex); + } + } + + /// + /// 查询指定设备的状态变更历史记录(按变更时间倒序) + /// + public async Task>> GetStatusRecordsAsync(long equipmentId) + { + try + { + var list = await _statusRecordRepository.Entities + .Where(x => x.EquipmentId == equipmentId && x.IsDel == 0) + .OrderBy(x => x.ChangeTime, OrderByType.Desc) + .ToListAsync(); + return Result>.Success(list); + } + catch (Exception ex) + { + return Result>.Error("查询状态变更记录失败", ex); + } + } } } diff --git a/Service/Implement/EquipmentService.cs b/Service/Implement/EquipmentService.cs deleted file mode 100644 index 025a644..0000000 --- a/Service/Implement/EquipmentService.cs +++ /dev/null @@ -1,266 +0,0 @@ -using Model; -using Model.Entity.Asset; -using ORM; -using Service.Interface; -using SqlSugar; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Service.Implement -{ - /// - /// 设备台账服务实现(资产管理) - /// - public class EquipmentService : BaseService, IEquipmentService - { - private readonly SqlSugarRepository _statusRecordRepository; - - public EquipmentService(SqlSugarRepository repository, - SqlSugarRepository statusRecordRepository) - : base(repository) - { - _statusRecordRepository = statusRecordRepository; - } - - /// - /// 查询全部设备(过滤已删除数据) - /// - public override async Task>> GetAllAsync() - { - try - { - var list = await _repository.Entities - .Where(x => x.IsDel == 0) - .OrderBy(x => x.CreateTime, OrderByType.Desc) - .ToListAsync(); - return Result>.Success(list); - } - catch (Exception ex) - { - return Result>.Error("查询设备台账失败", ex); - } - } - - /// - /// 分页查询设备台账(支持关键字、分类、状态筛选) - /// - public async Task>> GetPagedAsync(int pageIndex, int pageSize, RefAsync total, - string? keyword, long categoryId = 0, EquipmentStatusEnum? status = null) - { - try - { - var list = await _repository.Entities - .Where(x => x.IsDel == 0) - .WhereIF(!string.IsNullOrWhiteSpace(keyword), - x => x.Code!.Contains(keyword!) || x.Name!.Contains(keyword!)) - .WhereIF(categoryId > 0, x => x.CategoryId == categoryId) - .WhereIF(status.HasValue, x => x.Status == status!.Value) - .OrderBy(x => x.CreateTime, OrderByType.Desc) - .ToPageListAsync(pageIndex, pageSize, total); - total.Value = (int)Math.Ceiling((double)total.Value / pageSize); - return Result>.Success(list); - } - catch (Exception ex) - { - return Result>.Error("分页查询设备台账失败", ex); - } - } - - /// - /// 根据 Id 获取设备台账详情 - /// - public async Task> GetByIdAsync(long id) - { - try - { - var entity = await _repository.Entities - .Where(x => x.Id == id && x.IsDel == 0) - .FirstAsync(); - if (entity == null) - { - return Result.Error("设备不存在或已被删除"); - } - return Result.Success(entity); - } - catch (Exception ex) - { - return Result.Error("查询设备详情失败", ex); - } - } - - /// - /// 新增设备台账(校验编号唯一性,补充创建时间) - /// - public override async Task> InsertAsync(EquipmentEntity entity) - { - if (string.IsNullOrWhiteSpace(entity.Code)) - { - return Result.Error("设备编号不能为空"); - } - try - { - // 设备编号唯一性校验(未删除范围内) - bool exists = await _repository.Entities - .AnyAsync(x => x.Code == entity.Code && x.IsDel == 0); - if (exists) - { - return Result.Error($"设备编号【{entity.Code}】已存在"); - } - - entity.CreateTime = DateTime.Now; - var result = await _repository.Context.Insertable(entity).ExecuteCommandAsync(); - return Result.Success(result > 0); - } - catch (Exception ex) - { - return Result.Error("新增设备失败", ex); - } - } - - /// - /// 更新设备台账 - /// - public async Task> UpdateAsync(EquipmentEntity entity) - { - if (entity.Id <= 0) - { - return Result.Error("设备 Id 无效"); - } - try - { - var old = await _repository.Entities - .Where(x => x.Id == entity.Id && x.IsDel == 0) - .FirstAsync(); - if (old == null) - { - return Result.Error("设备不存在或已被删除"); - } - - // 设备编号变更时校验唯一性 - if (!string.IsNullOrWhiteSpace(entity.Code) && entity.Code != old.Code) - { - bool exists = await _repository.Entities - .AnyAsync(x => x.Code == entity.Code && x.IsDel == 0 && x.Id != entity.Id); - if (exists) - { - return Result.Error($"设备编号【{entity.Code}】已存在"); - } - } - - entity.IsDel = old.IsDel; - entity.CreateTime = old.CreateTime; - entity.UpdateTime = DateTime.Now; - var result = await _repository.Context.Updateable(entity).ExecuteCommandAsync(); - return Result.Success(result > 0); - } - catch (Exception ex) - { - return Result.Error("更新设备失败", ex); - } - } - - /// - /// 软删除设备台账(置 IsDel = 1) - /// - public async Task> DeleteEquipmentAsync(long id) - { - if (id <= 0) - { - return Result.Error("设备 Id 无效"); - } - try - { - var result = await _repository.Context.Updateable() - .SetColumns(x => x.IsDel == 1) - .Where(x => x.Id == id) - .ExecuteCommandAsync(); - return Result.Success(result > 0); - } - catch (Exception ex) - { - return Result.Error("删除设备失败", ex); - } - } - - /// - /// 变更设备状态,并记录状态变更历史(事务保证一致性) - /// - public async Task> ChangeStatusAsync(long equipmentId, EquipmentStatusEnum toStatus, string? operatorName, string? remark) - { - if (equipmentId <= 0) - { - return Result.Error("设备 Id 无效"); - } - try - { - var equipment = await _repository.Entities - .Where(x => x.Id == equipmentId && x.IsDel == 0) - .FirstAsync(); - if (equipment == null) - { - return Result.Error("设备不存在或已被删除"); - } - if (equipment.Status == toStatus) - { - return Result.Error("目标状态与当前状态一致,无需变更"); - } - - var now = DateTime.Now; - var record = new EquipmentStatusRecordEntity - { - EquipmentId = equipmentId, - FromStatus = equipment.Status, - ToStatus = toStatus, - ChangeTime = now, - Operator = operatorName, - Remark = remark, - CreateTime = now - }; - - // 事务:更新设备状态 + 插入状态变更记录 - _repository.BeginTran(); - try - { - equipment.Status = toStatus; - equipment.UpdateTime = now; - await _repository.Context.Updateable(equipment) - .UpdateColumns(x => new { x.Status, x.UpdateTime }) - .ExecuteCommandAsync(); - await _statusRecordRepository.Context.Insertable(record).ExecuteCommandAsync(); - _repository.CommitTran(); - } - catch - { - _repository.RollbackTran(); - throw; - } - - return Result.Success(true); - } - catch (Exception ex) - { - return Result.Error("变更设备状态失败", ex); - } - } - - /// - /// 查询指定设备的状态变更历史记录(按变更时间倒序) - /// - public async Task>> GetStatusRecordsAsync(long equipmentId) - { - try - { - var list = await _statusRecordRepository.Entities - .Where(x => x.EquipmentId == equipmentId && x.IsDel == 0) - .OrderBy(x => x.ChangeTime, OrderByType.Desc) - .ToListAsync(); - return Result>.Success(list); - } - catch (Exception ex) - { - return Result>.Error("查询状态变更记录失败", ex); - } - } - } -} diff --git a/Service/Interface/Asset/IEquipmentService.cs b/Service/Interface/Asset/IEquipmentService.cs index 98be808..72b74b1 100644 --- a/Service/Interface/Asset/IEquipmentService.cs +++ b/Service/Interface/Asset/IEquipmentService.cs @@ -1,10 +1,65 @@ +using Model; +using Model.Entity.Asset; +using SqlSugar; +using System.Collections.Generic; +using System.Threading.Tasks; + namespace Service.Interface { /// - /// 设备台账 服务接口 + /// 设备台账服务接口(资产管理) /// - public interface IEquipmentService + public interface IEquipmentService : IBaseService { - // TODO: 定义 设备台账 相关方法 + /// + /// 分页查询设备台账(支持按关键字、分类、状态筛选) + /// + /// 页码(从1开始) + /// 每页数量 + /// 总页数(输出参数) + /// 关键字(模糊匹配设备编号/名称) + /// 设备分类Id(0表示不过滤) + /// 设备状态(null表示不过滤) + /// 返回包含分页数据的 Result + Task>> GetPagedAsync(int pageIndex, int pageSize, RefAsync total, + string? keyword, long categoryId = 0, EquipmentStatusEnum? status = null); + + /// + /// 根据 Id 获取设备台账详情 + /// + /// 主键 Id + /// 返回包含设备详情的 Result + Task> GetByIdAsync(long id); + + /// + /// 更新设备台账 + /// + /// 设备实体(必须包含 Id) + /// 返回操作是否成功的 Result + Task> UpdateAsync(EquipmentEntity entity); + + /// + /// 软删除设备台账(置 IsDel = 1) + /// + /// 主键 Id + /// 返回操作是否成功的 Result + Task> DeleteEquipmentAsync(long id); + + /// + /// 变更设备状态,并记录状态变更历史(事务保证一致性) + /// + /// 设备 Id + /// 目标状态 + /// 操作人 + /// 变更原因/备注 + /// 返回操作是否成功的 Result + Task> ChangeStatusAsync(long equipmentId, EquipmentStatusEnum toStatus, string? operatorName, string? remark); + + /// + /// 查询指定设备的状态变更历史记录(按变更时间倒序) + /// + /// 设备 Id + /// 返回包含状态记录列表的 Result + Task>> GetStatusRecordsAsync(long equipmentId); } } diff --git a/Service/Interface/IEquipmentService.cs b/Service/Interface/IEquipmentService.cs deleted file mode 100644 index 72b74b1..0000000 --- a/Service/Interface/IEquipmentService.cs +++ /dev/null @@ -1,65 +0,0 @@ -using Model; -using Model.Entity.Asset; -using SqlSugar; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Service.Interface -{ - /// - /// 设备台账服务接口(资产管理) - /// - public interface IEquipmentService : IBaseService - { - /// - /// 分页查询设备台账(支持按关键字、分类、状态筛选) - /// - /// 页码(从1开始) - /// 每页数量 - /// 总页数(输出参数) - /// 关键字(模糊匹配设备编号/名称) - /// 设备分类Id(0表示不过滤) - /// 设备状态(null表示不过滤) - /// 返回包含分页数据的 Result - Task>> GetPagedAsync(int pageIndex, int pageSize, RefAsync total, - string? keyword, long categoryId = 0, EquipmentStatusEnum? status = null); - - /// - /// 根据 Id 获取设备台账详情 - /// - /// 主键 Id - /// 返回包含设备详情的 Result - Task> GetByIdAsync(long id); - - /// - /// 更新设备台账 - /// - /// 设备实体(必须包含 Id) - /// 返回操作是否成功的 Result - Task> UpdateAsync(EquipmentEntity entity); - - /// - /// 软删除设备台账(置 IsDel = 1) - /// - /// 主键 Id - /// 返回操作是否成功的 Result - Task> DeleteEquipmentAsync(long id); - - /// - /// 变更设备状态,并记录状态变更历史(事务保证一致性) - /// - /// 设备 Id - /// 目标状态 - /// 操作人 - /// 变更原因/备注 - /// 返回操作是否成功的 Result - Task> ChangeStatusAsync(long equipmentId, EquipmentStatusEnum toStatus, string? operatorName, string? remark); - - /// - /// 查询指定设备的状态变更历史记录(按变更时间倒序) - /// - /// 设备 Id - /// 返回包含状态记录列表的 Result - Task>> GetStatusRecordsAsync(long equipmentId); - } -}