设备管理模块方法转换为DTO模式,修复long类型接收雪花ID丢失精度的问题

This commit is contained in:
2026-08-28 14:05:16 +08:00
parent 2306fbd36b
commit 24d67baf65
15 changed files with 422 additions and 85 deletions
@@ -0,0 +1,148 @@
using Model;
using Model.Entity.Asset;
using ORM;
using Service.Interface;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace Service.Implement
{
/// <summary>
/// 设备附件服务实现(资产附件管理)
/// </summary>
public class EquipmentAttachmentService : IEquipmentAttachmentService
{
private readonly SqlSugarRepository<EquipmentAttachmentEntity> _repository;
public EquipmentAttachmentService(SqlSugarRepository<EquipmentAttachmentEntity> repository)
{
_repository = repository;
}
/// <summary>
/// 查询指定设备的附件列表(按上传时间倒序)
/// </summary>
public async Task<Result<List<EquipmentAttachmentEntity>>> GetByEquipmentAsync(long equipmentId)
{
try
{
var list = await _repository.Entities
.Where(x => x.EquipmentId == equipmentId && x.IsDel == 0)
.OrderBy(x => x.CreateTime, OrderByType.Desc)
.ToListAsync();
return Result<List<EquipmentAttachmentEntity>>.Success(list);
}
catch (Exception ex)
{
return Result<List<EquipmentAttachmentEntity>>.Error("查询附件列表失败", ex);
}
}
/// <summary>
/// 上传附件(保存文件到 uploads 目录并写入附件记录)
/// </summary>
public async Task<Result<EquipmentAttachmentEntity>> UploadAsync(long equipmentId, Stream stream, string originalFileName, long fileSize,
AttachmentTypeEnum fileType, string? uploader, string? remark, string webRootPath)
{
if (equipmentId <= 0)
{
return Result<EquipmentAttachmentEntity>.Error("设备 Id 无效");
}
if (stream == null || fileSize <= 0)
{
return Result<EquipmentAttachmentEntity>.Error("上传文件为空");
}
try
{
// 按设备分目录存储:uploads/equipment/{equipmentId}/
string relativeDir = Path.Combine("uploads", "equipment", equipmentId.ToString());
string physicalDir = Path.Combine(webRootPath, relativeDir);
if (!Directory.Exists(physicalDir))
{
Directory.CreateDirectory(physicalDir);
}
// 存储文件名:时间戳 + 原扩展名,避免重名与中文路径问题
string ext = Path.GetExtension(originalFileName);
string storedName = $"{DateTime.Now:yyyyMMddHHmmssfff}{ext}";
string physicalPath = Path.Combine(physicalDir, storedName);
using (var fileStream = new FileStream(physicalPath, FileMode.Create))
{
await stream.CopyToAsync(fileStream);
}
var entity = new EquipmentAttachmentEntity
{
EquipmentId = equipmentId,
FileName = originalFileName,
FileType = fileType,
FileExt = ext,
FileUrl = $"/{relativeDir.Replace('\\', '/')}/{storedName}",
FileSize = fileSize,
Uploader = uploader,
Remark = remark,
CreateTime = DateTime.Now
};
await _repository.Context.Insertable(entity).ExecuteCommandAsync();
return Result<EquipmentAttachmentEntity>.Success(entity);
}
catch (Exception ex)
{
return Result<EquipmentAttachmentEntity>.Error("上传附件失败", ex);
}
}
/// <summary>
/// 删除附件(软删除记录并删除物理文件)
/// </summary>
public async Task<Result<bool>> DeleteAsync(long id)
{
if (id <= 0)
{
return Result<bool>.Error("附件 Id 无效");
}
try
{
var attachment = await _repository.Entities
.Where(x => x.Id == id && x.IsDel == 0)
.FirstAsync();
if (attachment == null)
{
return Result<bool>.Error("附件不存在或已被删除");
}
var result = await _repository.Context.Updateable<EquipmentAttachmentEntity>()
.SetColumns(x => x.IsDel == 1)
.Where(x => x.Id == id)
.ExecuteCommandAsync();
// 删除物理文件(失败不影响记录删除结果)
try
{
string webRoot = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot");
string physicalPath = Path.Combine(webRoot, (attachment.FileUrl ?? string.Empty).TrimStart('/').Replace('/', Path.DirectorySeparatorChar));
if (File.Exists(physicalPath))
{
File.Delete(physicalPath);
}
}
catch
{
// 物理文件删除失败忽略
}
return Result<bool>.Success(result > 0);
}
catch (Exception ex)
{
return Result<bool>.Error("删除附件失败", ex);
}
}
}
}
@@ -0,0 +1,43 @@
using Model;
using Model.Entity.Asset;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace Service.Interface
{
/// <summary>
/// 设备附件服务接口(资产附件管理:分类存储、在线预览)
/// </summary>
public interface IEquipmentAttachmentService
{
/// <summary>
/// 查询指定设备的附件列表(按上传时间倒序)
/// </summary>
/// <param name="equipmentId">设备 Id</param>
/// <returns>返回包含附件列表的 Result</returns>
Task<Result<List<EquipmentAttachmentEntity>>> GetByEquipmentAsync(long equipmentId);
/// <summary>
/// 上传附件(保存文件到 uploads 目录并写入附件记录)
/// </summary>
/// <param name="equipmentId">设备 Id</param>
/// <param name="stream">文件流</param>
/// <param name="originalFileName">原始文件名</param>
/// <param name="fileSize">文件大小(字节)</param>
/// <param name="fileType">文件类型(说明书/合格证/校准证书等)</param>
/// <param name="uploader">上传人</param>
/// <param name="remark">备注</param>
/// <param name="webRootPath">站点静态文件根目录物理路径</param>
/// <returns>返回新增附件记录的 Result</returns>
Task<Result<EquipmentAttachmentEntity>> UploadAsync(long equipmentId, Stream stream, string originalFileName, long fileSize,
AttachmentTypeEnum fileType, string? uploader, string? remark, string webRootPath);
/// <summary>
/// 删除附件(软删除记录并删除物理文件)
/// </summary>
/// <param name="id">附件 Id</param>
/// <returns>返回操作是否成功的 Result</returns>
Task<Result<bool>> DeleteAsync(long id);
}
}