diff --git a/Dlhis.Jinko.Face.slnx b/Dlhis.Jinko.Face.slnx
index 6115dc44..feeb2dfc 100644
--- a/Dlhis.Jinko.Face.slnx
+++ b/Dlhis.Jinko.Face.slnx
@@ -18,6 +18,7 @@
+
diff --git a/Src/Dlhis.Dormitory.Api/Dlhis.Dormitory.Api.csproj b/Src/Dlhis.Dormitory.Api/Dlhis.Dormitory.Api.csproj
new file mode 100644
index 00000000..3c1b5c9d
--- /dev/null
+++ b/Src/Dlhis.Dormitory.Api/Dlhis.Dormitory.Api.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net6.0
+ enable
+ disable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Src/Dlhis.Dormitory.Api/DormitoryRemoteCallResultHandler.cs b/Src/Dlhis.Dormitory.Api/DormitoryRemoteCallResultHandler.cs
new file mode 100644
index 00000000..133a33ff
--- /dev/null
+++ b/Src/Dlhis.Dormitory.Api/DormitoryRemoteCallResultHandler.cs
@@ -0,0 +1,27 @@
+using System.Net;
+using Kurisu.RemoteCall.Abstractions;
+using Newtonsoft.Json;
+
+namespace Dlhis.Dormitory.Api;
+
+public class DormitoryRemoteCallResultHandler : IRemoteCallResultHandler
+{
+ public TResult Handle(HttpStatusCode statusCode, string responseBody)
+ {
+ ApiResult apiResult = JsonConvert.DeserializeObject>(responseBody);
+ if ((statusCode < HttpStatusCode.OK ? 0 : (statusCode <= (HttpStatusCode)299 ? 1 : 0)) != 0 && apiResult.Code == 200)
+ return apiResult.Data;
+ if (!string.IsNullOrEmpty(apiResult?.Message))
+ throw new Exception(apiResult.Message);
+ throw new HttpRequestException($"{statusCode.ToString()} {((int)statusCode).ToString()}");
+ }
+
+ internal class ApiResult
+ {
+ public string Message { get; set; }
+
+ public T Data { get; set; }
+
+ public int Code { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Dormitory.Api/IDormitoryRoomPowerSwitchApi.cs b/Src/Dlhis.Dormitory.Api/IDormitoryRoomPowerSwitchApi.cs
new file mode 100644
index 00000000..e31b9bca
--- /dev/null
+++ b/Src/Dlhis.Dormitory.Api/IDormitoryRoomPowerSwitchApi.cs
@@ -0,0 +1,16 @@
+using Dlhis.Dormitory.Api.Request;
+using Kurisu.RemoteCall.Attributes;
+
+namespace Dlhis.Dormitory.Api;
+
+[RequestLog]
+[RequestResultHandler(typeof(DormitoryRemoteCallResultHandler))]
+[EnableRemoteClient(Name = "dormitory-service", BaseUrl = "https://apartment.jinkosolar.com/pcapi")]
+public interface IDormitoryRoomPowerSwitchApi
+{
+ [Post("/api/Energy/DhIccElectricityControl")]
+ Task SwitchAsync(PowerSwitchRequest request);
+
+ [Get("/api/Users/GetDormitoryInfoByUserCode")]
+ Task GetUserRoomInfoAsync(string userCode);
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Dormitory.Api/Request/PowerSwitchRequest.cs b/Src/Dlhis.Dormitory.Api/Request/PowerSwitchRequest.cs
new file mode 100644
index 00000000..09f46e05
--- /dev/null
+++ b/Src/Dlhis.Dormitory.Api/Request/PowerSwitchRequest.cs
@@ -0,0 +1,21 @@
+using Newtonsoft.Json;
+
+namespace Dlhis.Dormitory.Api.Request;
+
+public class PowerSwitchRequest
+{
+ public PowerSwitchRequest(string roomid, int power)
+ {
+ this.RoomId = roomid;
+ this.Power = power;
+ }
+
+ [JsonProperty("roomid")]
+ public string RoomId { get; set; }
+
+ ///
+ /// 0 断电 1 上电
+ ///
+ [JsonProperty("power")]
+ public int Power { 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
index 611fafb8..f6a88f21 100644
--- a/Src/Dlhis.Entity/Dormitory/Entity/DormitoryRoomPersonEntity.cs
+++ b/Src/Dlhis.Entity/Dormitory/Entity/DormitoryRoomPersonEntity.cs
@@ -10,6 +10,6 @@ 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 In { get; set; }
public bool IsDeleted { get; set; }
}
\ No newline at end of file
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/EventBus/Handler/DormitoryPowerSwitchHandler.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/EventBus/Handler/DormitoryPowerSwitchHandler.cs
new file mode 100644
index 00000000..99df1d99
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/EventBus/Handler/DormitoryPowerSwitchHandler.cs
@@ -0,0 +1,12 @@
+using Dlhis.ScheduledTask.DeviceUploadLog.EventBus.Message;
+using Kurisu.AspNetCore.EventBus.Abstractions.Handler;
+
+namespace Dlhis.ScheduledTask.DeviceUploadLog.EventBus.Handler;
+
+public class DormitoryPowerSwitchHandler : IAsyncChannelHandler
+{
+ public async Task InvokeAsync(IServiceProvider serviceProvider, DormitoryPowerSwitchMessage message)
+ {
+ await Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/EventBus/Message/DormitoryPowerSwitchMessage.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/EventBus/Message/DormitoryPowerSwitchMessage.cs
new file mode 100644
index 00000000..0acd6cff
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/EventBus/Message/DormitoryPowerSwitchMessage.cs
@@ -0,0 +1,8 @@
+using Kurisu.AspNetCore.EventBus.Abstractions;
+
+namespace Dlhis.ScheduledTask.DeviceUploadLog.EventBus.Message;
+
+public class DormitoryPowerSwitchMessage : IAsyncChannelMessage
+{
+
+}
\ No newline at end of file
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Response/DormitoryResponse.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Response/DormitoryResponse.cs
new file mode 100644
index 00000000..9a44609e
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Response/DormitoryResponse.cs
@@ -0,0 +1,18 @@
+namespace Dlhis.ScheduledTask.DeviceUploadLog.Response;
+
+public class DormitoryResponse
+{
+ public string RoomId { get; set; }
+ public string RoomNo { get; set; }
+ public string HotelId { get; set; }
+
+ public bool MCB { get; set; }
+
+ public List Persons { get; set; }
+}
+
+public class DormitoryPerson
+{
+ public string UserCode { get; set; }
+ public string UserName { get; set; }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs
index 0ae6ed35..3e1fa1e6 100644
--- a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs
@@ -1,11 +1,14 @@
using Dlhis.Basic.Api;
using Dlhis.Basic.Api.Requests;
using Dlhis.Constants;
+using Dlhis.Dormitory.Api;
+using Dlhis.Dormitory.Api.Request;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Basic.Enums;
using Dlhis.Entity.Device.Entities;
using Dlhis.Entity.Device.Enums;
using Dlhis.Entity.Device.Models;
+using Dlhis.Entity.Dormitory.Entity;
using Dlhis.Jip.Api;
using Dlhis.Jip.Api.Requests;
using Dlhis.ScheduledTask.DeviceUploadLog.Request;
@@ -22,18 +25,21 @@ namespace Dlhis.ScheduledTask.DeviceUploadLog.Services.Implements;
public class DeviceUploadLogService : IDeviceUploadLogService
{
private readonly IDbContext _dbContext;
+ private readonly IDormitoryRoomPowerSwitchApi _dormitoryRoomPowerSwitchApi;
private readonly ICurrentUser _currentUser;
private readonly IJinkoJipApi _jinkoJipApi;
private readonly ILogger _logger;
private readonly IDingTalkApi _dingTalkApi;
public DeviceUploadLogService(IDbContext dbContext,
+ IDormitoryRoomPowerSwitchApi dormitoryRoomPowerSwitchApi,
ICurrentUser currentUser,
IJinkoJipApi jinkoJipApi,
ILogger logger,
IDingTalkApi dingTalkApi)
{
_dbContext = dbContext;
+ _dormitoryRoomPowerSwitchApi = dormitoryRoomPowerSwitchApi;
_currentUser = currentUser;
_jinkoJipApi = jinkoJipApi;
_logger = logger;
@@ -44,7 +50,11 @@ public class DeviceUploadLogService : IDeviceUploadLogService
{
var deviceUniqueNos = requests.Select(x => x.DeviceUniqueNo).Distinct().ToList();
var devices = await _dbContext.Queryable().Where(x => deviceUniqueNos.Contains(x.UniqueNo)).ToListAsync();
- var existsDeviceUniqueNos = devices.Select(x => x.UniqueNo).ToList();
+ var existsDeviceUniqueNos = devices.Select(x => x.UniqueNo).ToList();
+
+ var deviceCodes = devices.Where(x => x.DeployDirection.HasValue).Select(x => x.Code).Distinct().ToList();
+ var eFenceDeviceRelations = await _dbContext.Queryable().Where(x => deviceCodes.Contains(x.DeviceCode)).ToListAsync();
+ var eFenceDeviceMap = eFenceDeviceRelations.ToDictionary(x => x.DeviceCode, x => x.EFenceCode);
var userCodes = requests.Where(x => x.UserUniqueNo.IsPresent()).Select(x => x.UserUniqueNo).Distinct().ToList();
var gainfo1 = await _dbContext.Queryable().Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Name, x.Type }).ToListAsync();
@@ -111,6 +121,11 @@ public class DeviceUploadLogService : IDeviceUploadLogService
? DeviceUploadLogTypeEnumType.Attendance
: DeviceUploadLogTypeEnumType.Door;
+ if (eFenceDeviceMap.TryGetValue(device.Code, out var eFenceCore))
+ {
+ await HandlerPowerSwitchAsync(eFenceCore, request.UserUniqueNo, device.DeployDirection.Value);
+ }
+
var workGridInfo = new WorkGridInfo();
var currentWorkGridTimePeriods = workGridTimePeriods.Where(x => x.TenantId == device.TenantId).ToList();
var currentWorkGridSchedules = workGridSchedules.Where(x => x.UserCode == request.UserUniqueNo).ToList();
@@ -262,6 +277,134 @@ public class DeviceUploadLogService : IDeviceUploadLogService
await _dbContext.InsertAsync(inserts);
}
+
+ ///
+ /// 宿舍只能空开触发
+ ///
+ ///
+ ///
+ ///
+ private async Task HandlerPowerSwitchAsync(Guid eFenceCode, string userCode, DeviceDeployDirectionEnumType directionType)
+ {
+ try
+ {
+ //调用获取人员信息接口
+ var roomInfo = await _dormitoryRoomPowerSwitchApi.GetUserRoomInfoAsync(userCode);
+ if (!roomInfo.MCB)
+ {
+ return;
+ }
+
+ var room = await _dbContext.Queryable().Where(x => x.RoomId == roomInfo.RoomId).SingleAsync();
+ if (room == null)
+ {
+ room = new DormitoryRoomEntity
+ {
+ EFenceCode = eFenceCode,
+ RoomId = roomInfo.RoomId,
+ RoomNo = roomInfo.RoomNo,
+ HotelId = roomInfo.HotelId,
+ PowerSwitch = true
+ };
+
+ await _dbContext.InsertAsync(room);
+
+ var personEntities = roomInfo.Persons.Select(x => new DormitoryRoomPersonEntity
+ {
+ RoomId = roomInfo.RoomId,
+ UserCode = x.UserCode,
+ UserName = x.UserName,
+ In = true,
+ IsDeleted = false
+ })
+ .ToList();
+
+ await _dbContext.InsertAsync(personEntities);
+
+ var person = await _dbContext.Queryable()
+ .Where(x => x.RoomId != roomInfo.RoomId && x.UserCode == userCode)
+ .FirstAsync();
+ if (person != null)
+ {
+ await _dbContext.DeleteAsync(person);
+ }
+ }
+ else
+ {
+ var existsPersons = await _dbContext.Queryable()
+ .Where(x => x.RoomId == roomInfo.RoomId)
+ .ToListAsync();
+
+ //根据roomInfo.Persons和existsPersons不在当前房间的人
+ var toDeletePersons = existsPersons.Where(x => roomInfo.Persons.All(p => p.UserCode != x.UserCode)).ToList();
+ if (toDeletePersons.Any())
+ {
+ await _dbContext.DeleteAsync(toDeletePersons);
+ }
+
+ //需要新增的
+ var toAddPersons = roomInfo.Persons.Where(x => existsPersons.All(p => p.UserCode != x.UserCode)).ToList();
+ if (toAddPersons.Any())
+ {
+ var personEntities = toAddPersons.Select(x => new DormitoryRoomPersonEntity()
+ {
+ RoomId = roomInfo.RoomId,
+ UserCode = x.UserCode,
+ UserName = x.UserName,
+ In = true,
+ IsDeleted = false
+ }).ToList();
+
+ await _dbContext.InsertAsync(personEntities);
+ }
+
+ room.EFenceCode = eFenceCode;
+ await _dbContext.UpdateAsync(room);
+ }
+
+
+ //如果DormitoryRoomPersonEntity.in都为false,断电, 否则上电(前提是DormitoryRoomEntity.PowerSwitch==false)
+ // 查询房间所有人员
+ var persons = await _dbContext.Queryable()
+ .Where(x => x.RoomId == roomInfo.RoomId)
+ .ToListAsync();
+
+ persons.ForEach(x =>
+ {
+ if (x.UserCode == userCode)
+ {
+ x.In = directionType == DeviceDeployDirectionEnumType.Entry;
+ }
+ });
+ await _dbContext.UpdateAsync(persons);
+
+ // 如果所有人都不在房间,且当前房间是通电状态,则断电
+ if (persons.All(x => !x.In))
+ {
+ if (room.PowerSwitch)
+ {
+ room.PowerSwitch = false; // 断电
+ await _dbContext.UpdateAsync(room);
+ await _dormitoryRoomPowerSwitchApi.SwitchAsync(new PowerSwitchRequest(room.RoomId, 0));
+ }
+ }
+ else
+ {
+ // 只在房间断电状态时才上电
+ if (!room.PowerSwitch)
+ {
+ room.PowerSwitch = true; // 上电
+ await _dbContext.UpdateAsync(room);
+ await _dormitoryRoomPowerSwitchApi.SwitchAsync(new PowerSwitchRequest(room.RoomId, 1));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "宿舍空开触发失败, userCode:{userCode} directionType:{directionType} error:{error}", userCode, directionType, e.Message);
+ }
+ }
+
public async Task> GetMyRecordsAsync(DeviceUploadLogMyRecordRequest request)
{
var jinkoCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode) ?? string.Empty;
diff --git a/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj b/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj
index 01b99815..15f3bc42 100644
--- a/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj
+++ b/Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj
@@ -16,6 +16,9 @@
+
+ .dockerignore
+
@@ -34,6 +37,7 @@
+
diff --git a/Src/Dlhis.ScheduledTask/Dockerfile b/Src/Dlhis.ScheduledTask/Dockerfile
index dadbd4fe..dc0b574f 100644
--- a/Src/Dlhis.ScheduledTask/Dockerfile
+++ b/Src/Dlhis.ScheduledTask/Dockerfile
@@ -1,12 +1,8 @@
-# 请参阅 https://aka.ms/customizecontainer 以了解如何自定义调试容器,以及 Visual Studio 如何使用此 Dockerfile 生成映像以更快地进行调试。
-
-# 此阶段用于在快速模式(默认为调试配置)下从 VS 运行时
-FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
+FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
+EXPOSE 443
-
-# 此阶段用于生成服务项目
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
@@ -18,18 +14,17 @@ COPY ["Src/Dlhis.Entity/Dlhis.Entity.csproj", "Src/Dlhis.Entity/"]
COPY ["Src/Dlhis.DataPermission.Model/Dlhis.DataPermission.Model.csproj", "Src/Dlhis.DataPermission.Model/"]
COPY ["Src/Dlhis.Jip.Api/Dlhis.Jip.Api.csproj", "Src/Dlhis.Jip.Api/"]
COPY ["Src/Dlhis.Sys.Api/Dlhis.Sys.Api.csproj", "Src/Dlhis.Sys.Api/"]
-RUN dotnet restore "./Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj"
+COPY ["Src/Dlhis.Dormitory.Api/Dlhis.Dormitory.Api.csproj", "Src/Dlhis.Dormitory.Api/"]
+RUN dotnet restore "Src/Dlhis.ScheduledTask/Dlhis.ScheduledTask.csproj"
COPY . .
WORKDIR "/src/Src/Dlhis.ScheduledTask"
RUN dotnet build "./Dlhis.ScheduledTask.csproj" -c $BUILD_CONFIGURATION -o /app/build
-# 此阶段用于发布要复制到最终阶段的服务项目
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./Dlhis.ScheduledTask.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
-# 此阶段在生产中使用,或在常规模式下从 VS 运行时使用(在不使用调试配置时为默认值)
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
-ENTRYPOINT ["dotnet", "Dlhis.ScheduledTask.dll"]
\ No newline at end of file
+ENTRYPOINT ["dotnet", "Dlhis.ScheduledTask.dll"]