using Model; using Model.Dto.Config; using Model.Entity.Config; using Model.Mapper; using ORM; using Service.Interface.Config; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Service.Implement.Config { /// /// IOT设备管理 服务实现 /// public class DeviceService : IDeviceService { /// /// 分页查询设备列表(支持关键字搜索编号/名称/类型,可按所属产品筛选) /// public async Task>> GetPagedAsync(int pageIndex, int pageSize, RefAsync total, string? keyword, long? productId = null) { try { var list = await SqlSugarContext.DbContext.Queryable() .Where(x => x.IsDel == 0) .WhereIF(!string.IsNullOrWhiteSpace(keyword), x => x.Code.Contains(keyword!) || x.Name.Contains(keyword!) || x.DeviceType.Contains(keyword!)) .WhereIF(productId.HasValue && productId.Value > 0, x => x.ProductId == productId!.Value) .OrderBy(x => x.CreateTime, OrderByType.Desc) .ToPageListAsync(pageIndex, pageSize, total); var dtos = list.ToDtoList(); await FillProductNames(dtos); return Result>.Success(dtos); } catch (Exception ex) { return Result>.Error("查询设备列表失败", ex); } } /// /// 根据 Id 获取设备详情 /// public async Task> GetByIdAsync(long id) { try { var entity = await SqlSugarContext.DbContext.Queryable() .Where(x => x.Id == id && x.IsDel == 0) .FirstAsync(); if (entity == null) return Result.Error("设备不存在或已被删除"); var dto = entity.ToDto(); await FillProductNames(new List { dto }); return Result.Success(dto); } catch (Exception ex) { return Result.Error("查询设备详情失败", ex); } } /// /// 新增设备(校验编号唯一性) /// public async Task AddAsync(IotDeviceDto dto) { if (dto == null || string.IsNullOrWhiteSpace(dto.Code)) return Result.Error("设备编号不能为空"); if (string.IsNullOrWhiteSpace(dto.Name)) return Result.Error("设备名称不能为空"); try { bool exists = await SqlSugarContext.DbContext.Queryable() .AnyAsync(x => x.Code == dto.Code && x.IsDel == 0); if (exists) return Result.Error($"设备编号【{dto.Code}】已存在"); var entity = dto.ToEntity(); entity.CreateTime = DateTime.Now; // 初始离线 entity.OnlineStatus = IotDeviceOnlineStatusEnum.Offline; await SqlSugarContext.DbContext.Insertable(entity).ExecuteCommandAsync(); return Result.Success(); } catch (Exception ex) { return Result.Error("新增设备失败", ex); } } /// /// 修改设备(在线状态等运行字段不允许被前端覆盖) /// public async Task UpdateAsync(IotDeviceDto dto) { var entity = dto?.ToEntity(); if (entity == null || entity.Id <= 0) return Result.Error("设备Id无效"); try { // 编号变更时校验唯一性 bool exists = await SqlSugarContext.DbContext.Queryable() .AnyAsync(x => x.Code == entity.Code && x.IsDel == 0 && x.Id != entity.Id); if (exists) return Result.Error($"设备编号【{entity.Code}】已存在"); await SqlSugarContext.DbContext.Updateable(entity) .IgnoreColumns(x => new { x.CreateTime, x.IsDel, x.OnlineStatus, x.LastCollectTime, x.LastError }) .ExecuteCommandAsync(); return Result.Success(); } catch (Exception ex) { return Result.Error("修改设备失败", ex); } } /// /// 删除设备(软删除:IsDel 置 1) /// public async Task DeleteAsync(long id) { if (id <= 0) return Result.Error("设备Id无效"); try { await SqlSugarContext.DbContext.Updateable() .SetColumns(x => x.IsDel == 1) .Where(x => x.Id == id) .ExecuteCommandAsync(); return Result.Success(); } catch (Exception ex) { return Result.Error("删除设备失败", ex); } } /// /// 分页查询指定设备的日志(设备独享日志) /// public async Task>> GetDeviceLogsAsync(long deviceId, int pageIndex, int pageSize, RefAsync total) { try { var list = await SqlSugarContext.DbContext.Queryable() .Where(x => x.DeviceId == deviceId && x.IsDel == 0) .OrderBy(x => x.LogTime, OrderByType.Desc) .ToPageListAsync(pageIndex, pageSize, total); return Result>.Success(list.ToDtoList()); } catch (Exception ex) { return Result>.Error("查询设备日志失败", ex); } } /// /// 给设备 DTO 填充所属产品的型号/名称(ProductName 展示用) /// private async Task FillProductNames(List dtos) { if (dtos == null || dtos.Count == 0) return; var ids = dtos.Where(x => long.TryParse(x.ProductId, out var pid) && pid > 0) .Select(x => long.Parse(x.ProductId!)).Distinct().ToList(); if (ids.Count == 0) return; var products = await SqlSugarContext.DbContext.Queryable() .Where(x => ids.Contains(x.Id) && x.IsDel == 0) .ToListAsync(); var map = products.ToDictionary(p => p.Id, p => p.Name ?? p.Model); foreach (var d in dtos) { if (long.TryParse(d.ProductId, out var pid) && map.TryGetValue(pid, out var name)) d.ProductName = name; } } } }