Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d77feb67f7 | ||
|
|
3e3341dd19 |
@@ -1,14 +1,142 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
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 WebAPI.Controllers
|
||||
namespace IOT_API.Controllers.Asset
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备台账
|
||||
/// 资产管理 - 设备台账控制器
|
||||
/// </summary>
|
||||
[Route("api/Equipment")] //资产管理模块下的设备管理接口
|
||||
[ApiController]
|
||||
[Route("api/asset/equipment")]
|
||||
public class EquipmentController : ControllerBase
|
||||
{
|
||||
// TODO: 实现 设备台账 相关接口
|
||||
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">设备分类Id(0表示不过滤)</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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,27 @@ 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.
|
||||
|
||||
@@ -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>
|
||||
/// 父级分类Id(0表示顶级)
|
||||
/// </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; }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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">设备分类Id(0表示不过滤)</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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user