设备管理模块Entity添加和controller

This commit is contained in:
2026-08-28 10:40:28 +08:00
parent 9b852e5c95
commit 3e3341dd19
11 changed files with 994 additions and 8 deletions
@@ -0,0 +1,141 @@
using Microsoft.AspNetCore.Mvc;
using Model;
using Model.Entity.Asset;
using ORM;
using Service.Implement;
using Service.Interface;
using SqlSugar;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace IOT_API.Controllers.Asset
{
/// <summary>
/// 资产管理 - 设备台账控制器
/// </summary>
[Route("api/Equipment")] //资产管理模块下的设备管理接口
[ApiController]
public class EquipmentController : ControllerBase
{
private readonly IEquipmentService _equipmentService;
public EquipmentController()
{
// 项目未注册 DI 容器,SqlSugarContext.DbContext 为静态单例,直接实例化服务
_equipmentService = new EquipmentService(
new SqlSugarRepository<EquipmentEntity>(),
new SqlSugarRepository<EquipmentStatusRecordEntity>());
}
/// <summary>
/// 设备列表(分页查询,支持关键字/分类/状态筛选)
/// </summary>
/// <param name="pageIndex">页码(从1开始,默认1</param>
/// <param name="pageSize">每页数量(默认10</param>
/// <param name="keyword">关键字(模糊匹配设备编号/名称)</param>
/// <param name="categoryId">设备分类Id0表示不过滤)</param>
/// <param name="status">设备状态(不传表示不过滤)</param>
[HttpGet("list")]
public async Task<Result<List<EquipmentEntity>>> GetList(int pageIndex = 1, int pageSize = 10,
string? keyword = null, long categoryId = 0, EquipmentStatusEnum? status = null)
{
RefAsync<int> total = 0;
var result = await _equipmentService.GetPagedAsync(pageIndex, pageSize, total, keyword, categoryId, status);
Response.Headers["X-Total-Count"] = total.Value.ToString();
return result;
}
/// <summary>
/// 查询全部设备(不分页,供下拉选择等场景使用)
/// </summary>
[HttpGet("all")]
public async Task<Result<List<EquipmentEntity>>> GetAll()
{
return await _equipmentService.GetAllAsync();
}
/// <summary>
/// 设备详情
/// </summary>
/// <param name="id">设备主键 Id</param>
[HttpGet("{id}")]
public async Task<Result<EquipmentEntity>> GetById(long id)
{
return await _equipmentService.GetByIdAsync(id);
}
/// <summary>
/// 新增设备
/// </summary>
/// <param name="entity">设备实体</param>
[HttpPost]
public async Task<Result<bool>> Add([FromBody] EquipmentEntity entity)
{
return await _equipmentService.InsertAsync(entity);
}
/// <summary>
/// 修改设备
/// </summary>
/// <param name="id">设备主键 Id</param>
/// <param name="entity">设备实体</param>
[HttpPut("{id}")]
public async Task<Result<bool>> Update(long id, [FromBody] EquipmentEntity entity)
{
entity.Id = id;
return await _equipmentService.UpdateAsync(entity);
}
/// <summary>
/// 删除设备(软删除)
/// </summary>
/// <param name="id">设备主键 Id</param>
[HttpDelete("{id}")]
public async Task<Result<bool>> Delete(long id)
{
return await _equipmentService.DeleteEquipmentAsync(id);
}
/// <summary>
/// 变更设备状态(同步记录状态变更历史)
/// </summary>
/// <param name="id">设备主键 Id</param>
/// <param name="request">状态变更请求</param>
[HttpPost("{id}/status")]
public async Task<Result<bool>> ChangeStatus(long id, [FromBody] ChangeStatusRequest request)
{
return await _equipmentService.ChangeStatusAsync(id, request.Status, request.Operator, request.Remark);
}
/// <summary>
/// 查询设备状态变更历史记录
/// </summary>
/// <param name="id">设备主键 Id</param>
[HttpGet("{id}/status-records")]
public async Task<Result<List<EquipmentStatusRecordEntity>>> GetStatusRecords(long id)
{
return await _equipmentService.GetStatusRecordsAsync(id);
}
}
/// <summary>
/// 状态变更请求体
/// </summary>
public class ChangeStatusRequest
{
/// <summary>
/// 目标状态
/// </summary>
public EquipmentStatusEnum Status { get; set; }
/// <summary>
/// 操作人
/// </summary>
public string? Operator { get; set; }
/// <summary>
/// 变更原因/备注
/// </summary>
public string? Remark { get; set; }
}
}
+29 -7
View File
@@ -1,4 +1,5 @@
using Common;
using ORM;
using System.Text.Json;
namespace WebAPI
@@ -7,33 +8,54 @@ namespace WebAPI
{
public static void Main(string[] args)
{
// ======= 崩溃转储:未处理异常时自动生成 MiniDump =======
// ======= תδ쳣ʱԶ MiniDump =======
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
//记录dump文件
//¼dumpļ
Exception ex = e.ExceptionObject as Exception;
MiniDump.TryDump($"dumps\\Error_{DateTime.Now:yyyy-MM-dd HH-mm-ss-ms}.dmp", MiniDump.Option.WithFullMemory, ex);
};
// ======= 崩溃转储结束 =======
// ======= ת =======
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// ======= 核心配置开始 =======
// ======= ÿʼ =======
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString;
// 3. 属性命名策略保持原样(不强制转为驼峰)
// 3. ԱԭǿתΪշ壩
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
// ======= 核心配置结束 =======
// ======= ý =======
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// ======= Database init start =======
// Npgsql 时间兼容开关:允许向 PostgreSQL 写入本地时间 DateTimeDateTime.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.
@@ -43,7 +65,7 @@ namespace WebAPI
app.UseSwaggerUI();
}
// 注意:如果上位机只支持 http 请求,现场部署时你可能需要根据实际情况注释掉下面这行 Https 重定向
// עλֻ֧ http ֳʱҪʵע͵ Https ض
app.UseHttpsRedirection();
app.UseAuthorization();
+8 -1
View File
@@ -5,5 +5,12 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"Database": {
"Server": "localhost",
"Port": 5432,
"Database": "iot",
"Uid": "postgres",
"Pwd": "postgres"
}
}
@@ -0,0 +1,55 @@
using SqlSugar;
namespace Model.Entity.Asset
{
/// <summary>
/// 设备附件(资产附件管理:文件上传,支持按文件类型筛选与预览)
/// </summary>
public class EquipmentAttachmentEntity : BaseEntity
{
/// <summary>
/// 设备Id(关联 EquipmentEntity.Id
/// </summary>
public long EquipmentId { get; set; }
/// <summary>
/// 文件名称
/// </summary>
[SugarColumn(Length = 200)]
public string? FileName { get; set; }
/// <summary>
/// 文件类型(使用说明书/合格证明/校准证书/保养卡/合同扫描件/验收照片等)
/// </summary>
public AttachmentTypeEnum FileType { get; set; }
/// <summary>
/// 文件扩展名(如 .pdf、.jpg
/// </summary>
[SugarColumn(Length = 20)]
public string? FileExt { get; set; }
/// <summary>
/// 文件存储地址(上传后存储的相对路径)
/// </summary>
[SugarColumn(Length = 200)]
public string? FileUrl { get; set; }
/// <summary>
/// 文件大小(字节)
/// </summary>
public long FileSize { get; set; }
/// <summary>
/// 上传人
/// </summary>
[SugarColumn(Length = 50)]
public string? Uploader { get; set; }
/// <summary>
/// 备注
/// </summary>
[SugarColumn(Length = 500)]
public string? Remark { get; set; }
}
}
@@ -0,0 +1,43 @@
using SqlSugar;
namespace Model.Entity.Asset
{
/// <summary>
/// 设备分类(资产分类:支持按实验室/楼层/部门/位置/产品等多级树形分类,可按类型筛选展示)
/// </summary>
public class EquipmentCategoryEntity : BaseEntity
{
/// <summary>
/// 父级分类Id0表示顶级)
/// </summary>
public long ParentId { get; set; }
/// <summary>
/// 分类名称
/// </summary>
[SugarColumn(Length = 100)]
public string? Name { get; set; }
/// <summary>
/// 分类编码
/// </summary>
[SugarColumn(Length = 50)]
public string? Code { get; set; }
/// <summary>
/// 层级(1级、2级……,便于树形展示与筛选)
/// </summary>
public int Level { get; set; } = 1;
/// <summary>
/// 排序号
/// </summary>
public int Sort { get; set; }
/// <summary>
/// 备注
/// </summary>
[SugarColumn(Length = 500)]
public string? Remark { get; set; }
}
}
+229
View File
@@ -0,0 +1,229 @@
using SqlSugar;
namespace Model.Entity.Asset
{
/// <summary>
/// 设备台账(资产台账)
/// </summary>
public class EquipmentEntity : BaseEntity
{
#region
/// <summary>
/// 设备编号(唯一)
/// </summary>
[SugarColumn(Length = 50)]
public string? Code { get; set; }
/// <summary>
/// 设备名称
/// </summary>
[SugarColumn(Length = 100)]
public string? Name { get; set; }
/// <summary>
/// 设备分类Id(关联 EquipmentCategoryEntity.Id
/// </summary>
public long CategoryId { get; set; }
/// <summary>
/// 设备类型(实验室/楼层/部门/位置/产品/自定义等分类维度下的类型名称,冗余便于展示)
/// </summary>
[SugarColumn(Length = 100)]
public string? Type { get; set; }
/// <summary>
/// 设备品牌
/// </summary>
[SugarColumn(Length = 100)]
public string? Brand { get; set; }
/// <summary>
/// 设备型号
/// </summary>
[SugarColumn(Length = 100)]
public string? Model { get; set; }
/// <summary>
/// 规格参数
/// </summary>
[SugarColumn(Length = 200)]
public string? Specifications { get; set; }
/// <summary>
/// 制造商(设备制造商)
/// </summary>
[SugarColumn(Length = 100)]
public string? Manufacturer { get; set; }
/// <summary>
/// 供应商(资产供应商)
/// </summary>
[SugarColumn(Length = 100)]
public string? Supplier { get; set; }
/// <summary>
/// 设备图片地址(图片上传后存储的相对路径)
/// </summary>
[SugarColumn(Length = 200)]
public string? ImageUrl { get; set; }
/// <summary>
/// 二维码编号(一物一码)
/// </summary>
[SugarColumn(Length = 50)]
public string? QrCode { get; set; }
/// <summary>
/// 设备描述
/// </summary>
[SugarColumn(ColumnDataType = "text")]
public string? Description { get; set; }
#endregion
#region 使///
/// <summary>
/// 使用部门名称(资产使用部门)
/// </summary>
[SugarColumn(Length = 100)]
public string? Department { get; set; }
/// <summary>
/// 存放位置(实验室/楼层/房间等位置信息)
/// </summary>
[SugarColumn(Length = 200)]
public string? Location { get; set; }
/// <summary>
/// 责任人(资产责任人)
/// </summary>
[SugarColumn(Length = 50)]
public string? ResponsiblePerson { get; set; }
/// <summary>
/// 责任人联系电话(资产责任人电话)
/// </summary>
[SugarColumn(Length = 30)]
public string? ContactPhone { get; set; }
/// <summary>
/// 保管人
/// </summary>
[SugarColumn(Length = 50)]
public string? Custodian { get; set; }
#endregion
#region
/// <summary>
/// 购置日期
/// </summary>
public DateTime? PurchaseDate { get; set; }
/// <summary>
/// 购置价格(资产购置价格)
/// </summary>
[SugarColumn(DecimalDigits = 2, Length = 18)]
public decimal? PurchasePrice { get; set; }
/// <summary>
/// 保修到期日期(资产保修到期)
/// </summary>
public DateTime? WarrantyExpireDate { get; set; }
#endregion
#region /使/
/// <summary>
/// 验收日期(资产验收日期)
/// </summary>
public DateTime? AcceptanceDate { get; set; }
/// <summary>
/// 启用日期(资产启用日期)
/// </summary>
public DateTime? EnableDate { get; set; }
/// <summary>
/// 使用年限(资产使用年限,单位:年)
/// </summary>
public int? ServiceLifeYears { get; set; }
/// <summary>
/// 报废日期(资产报废日期)
/// </summary>
public DateTime? ScrapDate { get; set; }
#endregion
#region 使
/// <summary>
/// 设备当前状态(状态流转记录见 EquipmentStatusRecordEntity
/// </summary>
public EquipmentStatusEnum Status { get; set; } = EquipmentStatusEnum.PendingAcceptance;
#endregion
#region //
/// <summary>
/// 校准状态(正常/超期)
/// </summary>
public ComplianceStatusEnum CalibrationStatus { get; set; } = ComplianceStatusEnum.Normal;
/// <summary>
/// 上次校准日期(校准日期)
/// </summary>
public DateTime? LastCalibrationDate { get; set; }
/// <summary>
/// 下次校准到期日期(用于判断是否超期)
/// </summary>
public DateTime? NextCalibrationDate { get; set; }
/// <summary>
/// 检定日期
/// </summary>
public DateTime? InspectionDate { get; set; }
/// <summary>
/// 下次检定到期日期(用于判断是否超期)
/// </summary>
public DateTime? NextInspectionDate { get; set; }
/// <summary>
/// 保养状态(正常/超期)
/// </summary>
public ComplianceStatusEnum MaintenanceStatus { get; set; } = ComplianceStatusEnum.Normal;
/// <summary>
/// 上次保养日期(保养日期)
/// </summary>
public DateTime? LastMaintenanceDate { get; set; }
/// <summary>
/// 下次保养到期日期(保养周期到期,用于判断是否超期)
/// </summary>
public DateTime? NextMaintenanceDate { get; set; }
#endregion
#region
/// <summary>
/// 备注
/// </summary>
[SugarColumn(Length = 500)]
public string? Remark { get; set; }
/// <summary>
/// 创建人
/// </summary>
[SugarColumn(Length = 50)]
public string? CreateBy { get; set; }
/// <summary>
/// 更新人(修改人)
/// </summary>
[SugarColumn(Length = 50)]
public string? UpdateBy { get; set; }
/// <summary>
/// 更新时间(修改时间)
/// </summary>
public DateTime? UpdateTime { get; set; }
#endregion
}
}
+110
View File
@@ -0,0 +1,110 @@
namespace Model.Entity.Asset
{
/// <summary>
/// 设备状态(设备状态管理:待验收 → 使用中 → 已借出 → 闲置 → 维修中 → 已停用 → 待处置 → 已处置 → 入库)
/// </summary>
public enum EquipmentStatusEnum
{
/// <summary>
/// 待验收
/// </summary>
PendingAcceptance = 1,
/// <summary>
/// 使用中
/// </summary>
InUse = 2,
/// <summary>
/// 已借出
/// </summary>
Borrowed = 3,
/// <summary>
/// 闲置
/// </summary>
Idle = 4,
/// <summary>
/// 维修中
/// </summary>
Repairing = 5,
/// <summary>
/// 已停用
/// </summary>
Suspended = 6,
/// <summary>
/// 待处置
/// </summary>
PendingDisposal = 7,
/// <summary>
/// 已处置
/// </summary>
Disposed = 8,
/// <summary>
/// 入库
/// </summary>
InStorage = 9
}
/// <summary>
/// 合规状态(设备合规管理:校准状态、保养状态)
/// </summary>
public enum ComplianceStatusEnum
{
/// <summary>
/// 正常
/// </summary>
Normal = 1,
/// <summary>
/// 超期
/// </summary>
Overdue = 2
}
/// <summary>
/// 附件文件类型(设备附件管理:文件类型筛选)
/// </summary>
public enum AttachmentTypeEnum
{
/// <summary>
/// 使用说明书
/// </summary>
UserManual = 1,
/// <summary>
/// 合格证明
/// </summary>
Certificate = 2,
/// <summary>
/// 校准证书
/// </summary>
CalibrationCertificate = 3,
/// <summary>
/// 保养卡
/// </summary>
MaintenanceCard = 4,
/// <summary>
/// 合同扫描件
/// </summary>
Contract = 5,
/// <summary>
/// 验收照片
/// </summary>
AcceptancePhoto = 6,
/// <summary>
/// 其他
/// </summary>
Other = 99
}
}
@@ -0,0 +1,42 @@
using SqlSugar;
namespace Model.Entity.Asset
{
/// <summary>
/// 设备台账状态记录(设备状态管理:状态变更历史记录,并可按时间筛选查询)
/// </summary>
public class EquipmentStatusRecordEntity : BaseEntity
{
/// <summary>
/// 设备Id(关联 EquipmentEntity.Id
/// </summary>
public long EquipmentId { get; set; }
/// <summary>
/// 变更前状态
/// </summary>
public EquipmentStatusEnum FromStatus { get; set; }
/// <summary>
/// 变更后状态
/// </summary>
public EquipmentStatusEnum ToStatus { get; set; }
/// <summary>
/// 状态变更时间
/// </summary>
public DateTime ChangeTime { get; set; }
/// <summary>
/// 操作人
/// </summary>
[SugarColumn(Length = 50)]
public string? Operator { get; set; }
/// <summary>
/// 变更原因/备注
/// </summary>
[SugarColumn(Length = 500)]
public string? Remark { get; set; }
}
}
+6
View File
@@ -74,6 +74,12 @@ namespace ORM
string DBPath = Path.Combine(folder, "SQL.db");
DbConnectionString =$@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog={DBPath};Integrated Security=True;";
}
public static void InitPostgreSql(string Server, int Port, string Database, string Uid, string Pwd)
{
DbConnectionType = DbType.PostgreSQL;
DbConnectionString =
$"Host={Server};Port={Port};Database={Database};Username={Uid};Password={Pwd};";
}
#endregion
/// <summary>
/// 设置数据库连接字符串(可手动覆盖)
+266
View File
@@ -0,0 +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
{
/// <summary>
/// 设备台账服务实现(资产管理)
/// </summary>
public class EquipmentService : BaseService<EquipmentEntity>, IEquipmentService
{
private readonly SqlSugarRepository<EquipmentStatusRecordEntity> _statusRecordRepository;
public EquipmentService(SqlSugarRepository<EquipmentEntity> repository,
SqlSugarRepository<EquipmentStatusRecordEntity> statusRecordRepository)
: base(repository)
{
_statusRecordRepository = statusRecordRepository;
}
/// <summary>
/// 查询全部设备(过滤已删除数据)
/// </summary>
public override async Task<Result<List<EquipmentEntity>>> GetAllAsync()
{
try
{
var list = await _repository.Entities
.Where(x => x.IsDel == 0)
.OrderBy(x => x.CreateTime, OrderByType.Desc)
.ToListAsync();
return Result<List<EquipmentEntity>>.Success(list);
}
catch (Exception ex)
{
return Result<List<EquipmentEntity>>.Error("查询设备台账失败", ex);
}
}
/// <summary>
/// 分页查询设备台账(支持关键字、分类、状态筛选)
/// </summary>
public async Task<Result<List<EquipmentEntity>>> GetPagedAsync(int pageIndex, int pageSize, RefAsync<int> 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<List<EquipmentEntity>>.Success(list);
}
catch (Exception ex)
{
return Result<List<EquipmentEntity>>.Error("分页查询设备台账失败", ex);
}
}
/// <summary>
/// 根据 Id 获取设备台账详情
/// </summary>
public async Task<Result<EquipmentEntity>> GetByIdAsync(long id)
{
try
{
var entity = await _repository.Entities
.Where(x => x.Id == id && x.IsDel == 0)
.FirstAsync();
if (entity == null)
{
return Result<EquipmentEntity>.Error("设备不存在或已被删除");
}
return Result<EquipmentEntity>.Success(entity);
}
catch (Exception ex)
{
return Result<EquipmentEntity>.Error("查询设备详情失败", ex);
}
}
/// <summary>
/// 新增设备台账(校验编号唯一性,补充创建时间)
/// </summary>
public override async Task<Result<bool>> InsertAsync(EquipmentEntity entity)
{
if (string.IsNullOrWhiteSpace(entity.Code))
{
return Result<bool>.Error("设备编号不能为空");
}
try
{
// 设备编号唯一性校验(未删除范围内)
bool exists = await _repository.Entities
.AnyAsync(x => x.Code == entity.Code && x.IsDel == 0);
if (exists)
{
return Result<bool>.Error($"设备编号【{entity.Code}】已存在");
}
entity.CreateTime = DateTime.Now;
var result = await _repository.Context.Insertable(entity).ExecuteCommandAsync();
return Result<bool>.Success(result > 0);
}
catch (Exception ex)
{
return Result<bool>.Error("新增设备失败", ex);
}
}
/// <summary>
/// 更新设备台账
/// </summary>
public async Task<Result<bool>> UpdateAsync(EquipmentEntity entity)
{
if (entity.Id <= 0)
{
return Result<bool>.Error("设备 Id 无效");
}
try
{
var old = await _repository.Entities
.Where(x => x.Id == entity.Id && x.IsDel == 0)
.FirstAsync();
if (old == null)
{
return Result<bool>.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<bool>.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<bool>.Success(result > 0);
}
catch (Exception ex)
{
return Result<bool>.Error("更新设备失败", ex);
}
}
/// <summary>
/// 软删除设备台账(置 IsDel = 1)
/// </summary>
public async Task<Result<bool>> DeleteEquipmentAsync(long id)
{
if (id <= 0)
{
return Result<bool>.Error("设备 Id 无效");
}
try
{
var result = await _repository.Context.Updateable<EquipmentEntity>()
.SetColumns(x => x.IsDel == 1)
.Where(x => x.Id == id)
.ExecuteCommandAsync();
return Result<bool>.Success(result > 0);
}
catch (Exception ex)
{
return Result<bool>.Error("删除设备失败", ex);
}
}
/// <summary>
/// 变更设备状态,并记录状态变更历史(事务保证一致性)
/// </summary>
public async Task<Result<bool>> ChangeStatusAsync(long equipmentId, EquipmentStatusEnum toStatus, string? operatorName, string? remark)
{
if (equipmentId <= 0)
{
return Result<bool>.Error("设备 Id 无效");
}
try
{
var equipment = await _repository.Entities
.Where(x => x.Id == equipmentId && x.IsDel == 0)
.FirstAsync();
if (equipment == null)
{
return Result<bool>.Error("设备不存在或已被删除");
}
if (equipment.Status == toStatus)
{
return Result<bool>.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<bool>.Success(true);
}
catch (Exception ex)
{
return Result<bool>.Error("变更设备状态失败", ex);
}
}
/// <summary>
/// 查询指定设备的状态变更历史记录(按变更时间倒序)
/// </summary>
public async Task<Result<List<EquipmentStatusRecordEntity>>> 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<List<EquipmentStatusRecordEntity>>.Success(list);
}
catch (Exception ex)
{
return Result<List<EquipmentStatusRecordEntity>>.Error("查询状态变更记录失败", ex);
}
}
}
}
+65
View File
@@ -0,0 +1,65 @@
using Model;
using Model.Entity.Asset;
using SqlSugar;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Service.Interface
{
/// <summary>
/// 设备台账服务接口(资产管理)
/// </summary>
public interface IEquipmentService : IBaseService<EquipmentEntity>
{
/// <summary>
/// 分页查询设备台账(支持按关键字、分类、状态筛选)
/// </summary>
/// <param name="pageIndex">页码(从1开始)</param>
/// <param name="pageSize">每页数量</param>
/// <param name="total">总页数(输出参数)</param>
/// <param name="keyword">关键字(模糊匹配设备编号/名称)</param>
/// <param name="categoryId">设备分类Id0表示不过滤)</param>
/// <param name="status">设备状态(null表示不过滤)</param>
/// <returns>返回包含分页数据的 Result</returns>
Task<Result<List<EquipmentEntity>>> GetPagedAsync(int pageIndex, int pageSize, RefAsync<int> total,
string? keyword, long categoryId = 0, EquipmentStatusEnum? status = null);
/// <summary>
/// 根据 Id 获取设备台账详情
/// </summary>
/// <param name="id">主键 Id</param>
/// <returns>返回包含设备详情的 Result</returns>
Task<Result<EquipmentEntity>> GetByIdAsync(long id);
/// <summary>
/// 更新设备台账
/// </summary>
/// <param name="entity">设备实体(必须包含 Id</param>
/// <returns>返回操作是否成功的 Result</returns>
Task<Result<bool>> UpdateAsync(EquipmentEntity entity);
/// <summary>
/// 软删除设备台账(置 IsDel = 1)
/// </summary>
/// <param name="id">主键 Id</param>
/// <returns>返回操作是否成功的 Result</returns>
Task<Result<bool>> DeleteEquipmentAsync(long id);
/// <summary>
/// 变更设备状态,并记录状态变更历史(事务保证一致性)
/// </summary>
/// <param name="equipmentId">设备 Id</param>
/// <param name="toStatus">目标状态</param>
/// <param name="operatorName">操作人</param>
/// <param name="remark">变更原因/备注</param>
/// <returns>返回操作是否成功的 Result</returns>
Task<Result<bool>> ChangeStatusAsync(long equipmentId, EquipmentStatusEnum toStatus, string? operatorName, string? remark);
/// <summary>
/// 查询指定设备的状态变更历史记录(按变更时间倒序)
/// </summary>
/// <param name="equipmentId">设备 Id</param>
/// <returns>返回包含状态记录列表的 Result</returns>
Task<Result<List<EquipmentStatusRecordEntity>>> GetStatusRecordsAsync(long equipmentId);
}
}