diff --git a/Src/Dlhis.Basic/WorkGrids/Controllers/EFenceController.cs b/Src/Dlhis.Basic/WorkGrids/Controllers/EFenceController.cs new file mode 100644 index 00000000..2c45c3fc --- /dev/null +++ b/Src/Dlhis.Basic/WorkGrids/Controllers/EFenceController.cs @@ -0,0 +1,95 @@ +using Dlhis.Basic.WorkGrids.Request; +using Dlhis.Basic.WorkGrids.Response; +using Dlhis.Basic.WorkGrids.Services; +using Kurisu.AspNetCore.DataAccess.Dto; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Dlhis.Basic.WorkGrids.Controllers; + +/// +/// 电子围栏操作 +/// +[Authorize] +[Route("api/[controller]")] +[ApiController] +public class EFenceController : ControllerBase +{ + private readonly IEFenceService _eFenceService; + + public EFenceController(IEFenceService eFenceService) + { + _eFenceService = eFenceService; + } + + /// + /// 保存电子围栏(新增或更新) + /// + [HttpPost("save")] + public async Task SaveAsync([FromBody] EFenceSaveRequest request) + { + await _eFenceService.SaveAsync(request); + } + + /// + /// 获取电子围栏分页 + /// + /// + /// + [HttpGet("page")] + public async Task> GetEFencePageAsync([FromQuery] EFencePageRequest request) + { + return await _eFenceService.GetEFencePageAsync(request); + } + + /// + /// 获取围栏下的房间 + /// + /// + /// + [HttpGet("rooms")] + public async Task> GetRoomsAsync(Guid eFenceCode) + { + return await _eFenceService.GetRoomsAsync(eFenceCode); + } + + /// + /// 获取房间人员 + /// + /// + /// + [HttpGet("room-persons")] + public async Task> GetRoomPersonsAsync(string roomId) + { + return await _eFenceService.GetRoomPersonsAsync(roomId); + } + + /// + /// 向围栏添加设备 + /// + [HttpPost("devices/add")] + public async Task AddDevicesAsync(EFenceDevicesRequest request) + { + await _eFenceService.AddDevicesAsync(request.FenceId, request.DeviceCodes); + } + + /// + /// 从围栏移除设备 + /// + [HttpPost("devices/remove")] + public async Task RemoveDevicesAsync(EFenceDevicesRequest request) + { + await _eFenceService.RemoveDevicesAsync(request.FenceId, request.DeviceCodes); + } + + /// + /// 获取设备列表 + /// + /// + /// + [HttpGet("devices")] + public async Task> GetDevicesByFenceIdAsync(long fenceId) + { + return await _eFenceService.GetDevicesByFenceIdAsync(fenceId); + } +} \ No newline at end of file diff --git a/Src/Dlhis.Basic/WorkGrids/Request/EFenceDevicesRequest.cs b/Src/Dlhis.Basic/WorkGrids/Request/EFenceDevicesRequest.cs new file mode 100644 index 00000000..042e8138 --- /dev/null +++ b/Src/Dlhis.Basic/WorkGrids/Request/EFenceDevicesRequest.cs @@ -0,0 +1,12 @@ +using System.ComponentModel.DataAnnotations; + +namespace Dlhis.Basic.WorkGrids.Request; + +public class EFenceDevicesRequest +{ + [Range(1, long.MaxValue)] + public long FenceId { get; set; } + + [MinLength(1)] + public List DeviceCodes { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Basic/WorkGrids/Request/EFencePageRequest.cs b/Src/Dlhis.Basic/WorkGrids/Request/EFencePageRequest.cs new file mode 100644 index 00000000..33eb22e2 --- /dev/null +++ b/Src/Dlhis.Basic/WorkGrids/Request/EFencePageRequest.cs @@ -0,0 +1,8 @@ +using Kurisu.AspNetCore.DataAccess.Dto; + +namespace Dlhis.Basic.WorkGrids.Request; + +public class EFencePageRequest : PageDto +{ + +} \ No newline at end of file diff --git a/Src/Dlhis.Basic/WorkGrids/Request/EFenceSaveRequest.cs b/Src/Dlhis.Basic/WorkGrids/Request/EFenceSaveRequest.cs new file mode 100644 index 00000000..ec4edf77 --- /dev/null +++ b/Src/Dlhis.Basic/WorkGrids/Request/EFenceSaveRequest.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; + +namespace Dlhis.Basic.WorkGrids.Request; + +public class EFenceSaveRequest +{ + public long? Id { get; set; } + + [Required] + public string Name { get; set; } + + public string Description { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Basic/WorkGrids/Response/EFenceDevicePageResponse.cs b/Src/Dlhis.Basic/WorkGrids/Response/EFenceDevicePageResponse.cs new file mode 100644 index 00000000..7e200eba --- /dev/null +++ b/Src/Dlhis.Basic/WorkGrids/Response/EFenceDevicePageResponse.cs @@ -0,0 +1,43 @@ +using Dlhis.Entity.Device.Enums; + +namespace Dlhis.Basic.WorkGrids.Response; + +public class EFenceDevicePageResponse +{ + public long Id { get; set; } + + /// + /// 设备code + /// + public Guid Code { get; set; } + + /// + /// 设备唯一码,IP/MAC/SNO + /// + public string UniqueNo { get; set; } + + /// + /// 部署点 + /// + public string DeployPlace { get; set; } + + /// + /// 部署坐标 + /// + public string DeployPosition { get; set; } + + /// + /// 部署方向 + /// + public DeviceDeployDirectionEnumType? DeployDirection { get; set; } + + /// + /// 是否启用 + /// + public bool Enable { get; set; } + + /// + /// 厂区 + /// + public string Factory { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Basic/WorkGrids/Response/EFenceDormitoryRoomPersonResponse.cs b/Src/Dlhis.Basic/WorkGrids/Response/EFenceDormitoryRoomPersonResponse.cs new file mode 100644 index 00000000..2d105b35 --- /dev/null +++ b/Src/Dlhis.Basic/WorkGrids/Response/EFenceDormitoryRoomPersonResponse.cs @@ -0,0 +1,9 @@ +namespace Dlhis.Basic.WorkGrids.Response; + +public class EFenceDormitoryRoomPersonResponse +{ + public string RoomId { get; set; } + public string UserCode { get; set; } + public string UserName { get; set; } + public bool? In { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Basic/WorkGrids/Response/EFenceDormitoryRoomResponse.cs b/Src/Dlhis.Basic/WorkGrids/Response/EFenceDormitoryRoomResponse.cs new file mode 100644 index 00000000..233eecaa --- /dev/null +++ b/Src/Dlhis.Basic/WorkGrids/Response/EFenceDormitoryRoomResponse.cs @@ -0,0 +1,10 @@ +namespace Dlhis.Basic.WorkGrids.Response; + +public class EFenceDormitoryRoomResponse +{ + public Guid EFenceCode { get; set; } + public string RoomId { get; set; } + public string RoomNo { get; set; } + public string HotelId { get; set; } + public bool PowerSwitch { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Basic/WorkGrids/Response/EFencePageResponse.cs b/Src/Dlhis.Basic/WorkGrids/Response/EFencePageResponse.cs new file mode 100644 index 00000000..3630748d --- /dev/null +++ b/Src/Dlhis.Basic/WorkGrids/Response/EFencePageResponse.cs @@ -0,0 +1,23 @@ +namespace Dlhis.Basic.WorkGrids.Response; + +public class EFencePageResponse +{ + public long Id { get; set; } + + public Guid Code { get; set; } + + /// + /// 围栏名称 + /// + public string Name { get; set; } + + /// + /// 描述/备注 + /// + public string Description { get; set; } + + /// + /// 设备数量 + /// + public int DeviceCount { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Basic/WorkGrids/Services/IEFenceService.cs b/Src/Dlhis.Basic/WorkGrids/Services/IEFenceService.cs new file mode 100644 index 00000000..6f683774 --- /dev/null +++ b/Src/Dlhis.Basic/WorkGrids/Services/IEFenceService.cs @@ -0,0 +1,22 @@ +using Dlhis.Basic.WorkGrids.Request; +using Dlhis.Basic.WorkGrids.Response; +using Kurisu.AspNetCore.DataAccess.Dto; + +namespace Dlhis.Basic.WorkGrids.Services; + +public interface IEFenceService : IScopeDependency +{ + Task SaveAsync(EFenceSaveRequest request); + + Task> GetEFencePageAsync(EFencePageRequest request); + + Task> GetRoomsAsync(Guid eFenceCode); + + Task> GetRoomPersonsAsync(string roomId); + + Task AddDevicesAsync(long fenceId, List deviceCodes); + + Task RemoveDevicesAsync(long fenceId, List deviceCodes); + + Task> GetDevicesByFenceIdAsync(long fenceId); +} \ No newline at end of file diff --git a/Src/Dlhis.Basic/WorkGrids/Services/Implements/EFenceService.cs b/Src/Dlhis.Basic/WorkGrids/Services/Implements/EFenceService.cs new file mode 100644 index 00000000..a0630a04 --- /dev/null +++ b/Src/Dlhis.Basic/WorkGrids/Services/Implements/EFenceService.cs @@ -0,0 +1,143 @@ +using Dlhis.Basic.WorkGrids.Request; +using Dlhis.Basic.WorkGrids.Response; +using Dlhis.Entity.Basic.Entity; +using Dlhis.Entity.Device.Entities; +using Dlhis.Entity.Dormitory.Entity; +using Kurisu.AspNetCore.DataAccess.Dto; +using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions; +using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; +using Kurisu.AspNetCore.Utils.Extensions; +using Mapster; +using SqlSugar; + +namespace Dlhis.Basic.WorkGrids.Services.Implements; + +public class EFenceService : IEFenceService +{ + private readonly IDbContext _dbContext; + + public EFenceService(IDbContext dbContext) + { + _dbContext = dbContext; + } + + + public async Task SaveAsync(EFenceSaveRequest request) + { + if (!request.Id.HasValue) + { + var entity = request.Adapt(); + entity.Code = Guid.NewGuid(); + await _dbContext.InsertAsync(entity); + } + else + { + var entity = await _dbContext.Queryable().SingleAsync(x => x.Id == request.Id.Value); + request.Adapt(entity); + await _dbContext.UpdateAsync(entity); + } + } + + public async Task> GetEFencePageAsync(EFencePageRequest request) + { + var page = await _dbContext.Queryable() + .WhereIF(request.Search.IsPresent(), x => x.Name.Contains(request.Search)) + .OrderBy(x => x.Id, OrderByType.Desc) + .Select(x => new EFencePageResponse + { + Id = x.Id, + Code = x.Code, + Name = x.Name, + Description = x.Description, + DeviceCount = SqlFunc.Subqueryable().Where(p => p.EFenceCode == x.Code).Count(), + }) + .ToPageListAsync(request); + + return page; + } + + public async Task> GetRoomsAsync(Guid eFenceCode) + { + return await _dbContext.Queryable() + .Where(x => x.EFenceCode == eFenceCode) + .Select() + .ToListAsync(); + } + + public async Task> GetRoomPersonsAsync(string roomId) + { + return await _dbContext.Queryable() + .Where(x => x.RoomId == roomId) + .Select() + .ToListAsync(); + } + + public async Task AddDevicesAsync(long fenceId, List deviceCodes) + { + //查询电子围栏 + var fence = await _dbContext.Queryable().SingleAsync(f => f.Id == fenceId); + fence.ThrowIfNull("未找到电子围栏"); + + //查询设备 + var devices = await _dbContext.Queryable() + .Where(d => deviceCodes.Contains(d.Code)) + .Where(d => d.DeployDirection.HasValue) + .Where(d => SqlFunc.Subqueryable() + .Where(p => p.EFenceCode == fence.Code && p.DeviceCode == d.Code) + .NotAny() //不可重复分配 + ) + .ToListAsync(); + + if (devices.Any()) + { + var eFenceDeviceRelationEntities = devices.Select(x => new EFenceDeviceRelationEntity + { + DeviceCode = x.Code, + EFenceCode = fence.Code + }).ToList(); + + await _dbContext.InsertAsync(eFenceDeviceRelationEntities); + } + } + + public async Task RemoveDevicesAsync(long fenceId, List deviceCodes) + { + //查询电子围栏 + var fence = await _dbContext.Queryable().SingleAsync(f => f.Id == fenceId); + fence.ThrowIfNull("未找到电子围栏"); + + //查询EFenceDeviceRelationEntity的设备 + var relations = await _dbContext.Queryable() + .Where(r => r.EFenceCode == fence.Code && deviceCodes.Contains(r.DeviceCode)) + .ToListAsync(); + + if (relations.Any()) + { + await _dbContext.DeleteAsync(relations); + } + } + + public async Task> GetDevicesByFenceIdAsync(long fenceId) + { + //查询电子围栏 + var fence = await _dbContext.Queryable().SingleAsync(f => f.Id == fenceId); + fence.ThrowIfNull("未找到电子围栏"); + + var deviceCodes = await _dbContext.Queryable() + .Where(x => x.EFenceCode == fence.Code) + .Select(x => x.DeviceCode) + .ToListAsync(); + + + var list = await _dbContext.Queryable() + .LeftJoin((d, dt) => d.TemplateCode == dt.Code) + .Where((d, dt) => deviceCodes.Contains(d.Code)) + .Select((d, dt) => new EFenceDevicePageResponse + { + Factory = d.TenantId + }, true) + .ToListAsync(); + + return list; + } +} \ No newline at end of file diff --git a/Src/Dlhis.Entity/Device/Entities/EFenceDeviceRelationEntity.cs b/Src/Dlhis.Entity/Device/Entities/EFenceDeviceRelationEntity.cs new file mode 100644 index 00000000..a9b18c5c --- /dev/null +++ b/Src/Dlhis.Entity/Device/Entities/EFenceDeviceRelationEntity.cs @@ -0,0 +1,27 @@ +using Kurisu.AspNetCore.DataAccess.Entity; +using Kurisu.AspNetCore.DataAccess.SqlSugar; +using SqlSugar; + +namespace Dlhis.Entity.Device.Entities; + +/// +/// 设备与电子围栏关系表 +/// +[SugarTable("ElectronicFenceDeviceRelationEntity")] +[SugarIndex("idx_ElectronicFenceDeviceRelation_DeviceCode_EFenceCode", new[] { nameof(DeviceCode), nameof(EFenceCode) }, new[] { OrderByType.Asc, OrderByType.Asc }, false)] +public class EFenceDeviceRelationEntity : SugarBaseEntity, ISoftDeleted +{ + /// + /// 设备ID + /// + [SugarColumn(IsNullable = false)] + public Guid DeviceCode { get; set; } + + /// + /// 电子围栏ID + /// + [SugarColumn(IsNullable = false)] + public Guid EFenceCode { get; set; } + + public bool IsDeleted { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Entity/Device/Entities/EFenceEntity.cs b/Src/Dlhis.Entity/Device/Entities/EFenceEntity.cs new file mode 100644 index 00000000..36266fc0 --- /dev/null +++ b/Src/Dlhis.Entity/Device/Entities/EFenceEntity.cs @@ -0,0 +1,28 @@ +using Kurisu.AspNetCore.DataAccess.SqlSugar; +using Mapster; +using SqlSugar; + +namespace Dlhis.Entity.Device.Entities; + +/// +/// 电子围栏 +/// +[SugarTable("ElectronicFence")] +public class EFenceEntity : SugarBaseEntity +{ + [AdaptIgnore(MemberSide.Source)] + [SugarColumn(IsNullable = false)] + public Guid Code { get; set; } + + /// + /// 围栏名称 + /// + [SugarColumn(IsNullable = false)] + public string Name { get; set; } + + /// + /// 描述/备注 + /// + [SugarColumn(IsNullable = true, Length = 1000)] + public string Description { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Entity/Dormitory/Entity/DormitoryRoomEntity.cs b/Src/Dlhis.Entity/Dormitory/Entity/DormitoryRoomEntity.cs new file mode 100644 index 00000000..dad05f9e --- /dev/null +++ b/Src/Dlhis.Entity/Dormitory/Entity/DormitoryRoomEntity.cs @@ -0,0 +1,14 @@ +using Kurisu.AspNetCore.DataAccess.SqlSugar; +using SqlSugar; + +namespace Dlhis.Entity.Dormitory.Entity; + +[SugarTable(TableName = "DormitoryRoom")] +public class DormitoryRoomEntity : SugarBaseEntity +{ + public Guid EFenceCode { get; set; } + public string RoomId { get; set; } + public string RoomNo { get; set; } + public string HotelId { get; set; } + public bool PowerSwitch { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Entity/Dormitory/Entity/DormitoryRoomPersonEntity.cs b/Src/Dlhis.Entity/Dormitory/Entity/DormitoryRoomPersonEntity.cs new file mode 100644 index 00000000..611fafb8 --- /dev/null +++ b/Src/Dlhis.Entity/Dormitory/Entity/DormitoryRoomPersonEntity.cs @@ -0,0 +1,15 @@ +using Kurisu.AspNetCore.DataAccess.Entity; +using Kurisu.AspNetCore.DataAccess.SqlSugar; +using SqlSugar; + +namespace Dlhis.Entity.Dormitory.Entity; + +[SugarTable(TableName = "DormitoryRoomPerson")] +public class DormitoryRoomPersonEntity : SugarBaseEntity, ISoftDeleted +{ + public string RoomId { get; set; } + public string UserCode { get; set; } + public string UserName { get; set; } + public bool? In { get; set; } + public bool IsDeleted { get; set; } +} \ No newline at end of file