Merge branch 'feature/feat-efence'

This commit is contained in:
2025-10-09 14:32:24 +08:00
12 changed files with 274 additions and 12 deletions

View File

@@ -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<DormitoryPowerSwitchMessage>
{
public async Task InvokeAsync(IServiceProvider serviceProvider, DormitoryPowerSwitchMessage message)
{
await Task.CompletedTask;
}
}

View File

@@ -0,0 +1,8 @@
using Kurisu.AspNetCore.EventBus.Abstractions;
namespace Dlhis.ScheduledTask.DeviceUploadLog.EventBus.Message;
public class DormitoryPowerSwitchMessage : IAsyncChannelMessage
{
}

View File

@@ -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<DormitoryPerson> Persons { get; set; }
}
public class DormitoryPerson
{
public string UserCode { get; set; }
public string UserName { get; set; }
}

View File

@@ -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<DeviceUploadLogService> _logger;
private readonly IDingTalkApi _dingTalkApi;
public DeviceUploadLogService(IDbContext dbContext,
IDormitoryRoomPowerSwitchApi dormitoryRoomPowerSwitchApi,
ICurrentUser currentUser,
IJinkoJipApi jinkoJipApi,
ILogger<DeviceUploadLogService> 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<DeviceEntity>().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<EFenceDeviceRelationEntity>().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<GainfoEntity>().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);
}
/// <summary>
/// 宿舍只能空开触发
/// </summary>
/// <param name="eFenceCode"></param>
/// <param name="userCode"></param>
/// <param name="directionType"></param>
private async Task HandlerPowerSwitchAsync(Guid eFenceCode, string userCode, DeviceDeployDirectionEnumType directionType)
{
try
{
//调用获取人员信息接口
var roomInfo = await _dormitoryRoomPowerSwitchApi.GetUserRoomInfoAsync<DormitoryResponse>(userCode);
if (!roomInfo.MCB)
{
return;
}
var room = await _dbContext.Queryable<DormitoryRoomEntity>().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<DormitoryRoomPersonEntity>()
.Where(x => x.RoomId != roomInfo.RoomId && x.UserCode == userCode)
.FirstAsync();
if (person != null)
{
await _dbContext.DeleteAsync(person);
}
}
else
{
var existsPersons = await _dbContext.Queryable<DormitoryRoomPersonEntity>()
.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<DormitoryRoomPersonEntity>()
.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<List<DeviceUploadLogResponse>> GetMyRecordsAsync(DeviceUploadLogMyRecordRequest request)
{
var jinkoCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode) ?? string.Empty;

View File

@@ -16,6 +16,9 @@
<ItemGroup>
<Compile Remove="log\**" />
<Content Remove="log\**" />
<Content Include="..\..\.dockerignore">
<Link>.dockerignore</Link>
</Content>
<EmbeddedResource Remove="log\**" />
<None Remove="log\**" />
<Content Update="appsettings.Development.json">
@@ -34,6 +37,7 @@
<ProjectReference Include="..\Dlhis.Basic.Api\Dlhis.Basic.Api.csproj" />
<ProjectReference Include="..\Dlhis.Canteen.Api\Dlhis.Canteen.Api.csproj" />
<ProjectReference Include="..\Dlhis.Constants\Dlhis.Constants.csproj" />
<ProjectReference Include="..\Dlhis.Dormitory.Api\Dlhis.Dormitory.Api.csproj" />
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
<ProjectReference Include="..\Dlhis.Jip.Api\Dlhis.Jip.Api.csproj" />
<ProjectReference Include="..\Dlhis.Sys.Api\Dlhis.Sys.Api.csproj" />

View File

@@ -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"]
ENTRYPOINT ["dotnet", "Dlhis.ScheduledTask.dll"]