From 7721dc22a40c356c536389fd9f77e8477715c265 Mon Sep 17 00:00:00 2001 From: liguoyang Date: Wed, 17 Apr 2024 18:14:34 +0800 Subject: [PATCH] =?UTF-8?q?fix=20=E4=BA=BA=E8=84=B8=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/GainfosController.cs | 22 +- .../Services/IGainfoFaceService.cs | 13 + .../Organization/Services/IGainfoService.cs | 12 - .../Services/Implements/GainfoFaceService.cs | 222 +++++++++++++++++- .../Services/Implements/GainfoService.cs | 178 +------------- 5 files changed, 251 insertions(+), 196 deletions(-) diff --git a/Src/Dlhis.Basic/Organization/Controllers/GainfosController.cs b/Src/Dlhis.Basic/Organization/Controllers/GainfosController.cs index ed23f0ae..c94a192d 100644 --- a/Src/Dlhis.Basic/Organization/Controllers/GainfosController.cs +++ b/Src/Dlhis.Basic/Organization/Controllers/GainfosController.cs @@ -68,7 +68,7 @@ public class GainfosController : ControllerBase [Transactional] public async Task UploadFaceAsync(GainfoUploadFaceRequest request) { - await _gainfoService.UploadFaceAsync(request); + await _gainfoFaceService.UploadFaceAsync(request); } /// @@ -82,6 +82,18 @@ public class GainfosController : ControllerBase await _gainfoFaceService.UploadExternalFaceAsync(request); } + /// + /// 外部人员人脸照片 + /// + /// + /// + [AllowAnonymous] + [HttpGet("external/face")] + public async Task GetExternalFaceAsync(string idno) + { + return await _gainfoFaceService.GetExternalFaceAsync(idno); + } + /// /// 批量上传人脸照片 /// @@ -91,7 +103,7 @@ public class GainfosController : ControllerBase [IgnoreTenant] public async Task UploadFaceAsync(List request) { - await _gainfoService.UploadFacesAsync(request); + await _gainfoFaceService.UploadFacesAsync(request); } /// @@ -104,7 +116,7 @@ public class GainfosController : ControllerBase [HttpGet("face")] public async Task GetFaceAsync(string token) { - return await _gainfoService.GetFaceAsync(token); + return await _gainfoFaceService.GetFaceAsync(token); } /// @@ -115,7 +127,7 @@ public class GainfosController : ControllerBase [HttpGet("face/{userCode}")] public async Task GetFaceByUserCodeAsync(string userCode) { - return await _gainfoService.GetFaceByUserCodeAsync(userCode); + return await _gainfoFaceService.GetFaceByUserCodeAsync(userCode); } /// @@ -127,7 +139,7 @@ public class GainfosController : ControllerBase [HttpPost("faces")] public async Task> GetFaceByUserCodesAsync(GetFaceByUserCodesRequest request) { - return await _gainfoService.GetFaceByUserCodesAsync(request); + return await _gainfoFaceService.GetFaceByUserCodesAsync(request); } /// diff --git a/Src/Dlhis.Basic/Organization/Services/IGainfoFaceService.cs b/Src/Dlhis.Basic/Organization/Services/IGainfoFaceService.cs index e2f00e2f..e4653c21 100644 --- a/Src/Dlhis.Basic/Organization/Services/IGainfoFaceService.cs +++ b/Src/Dlhis.Basic/Organization/Services/IGainfoFaceService.cs @@ -1,8 +1,21 @@ using Dlhis.Basic.Organization.Request; +using Microsoft.AspNetCore.Mvc; namespace Dlhis.Basic.Organization.Services; public interface IGainfoFaceService : IScopeDependency { Task UploadExternalFaceAsync(GainfoUploadFaceRequest request); + + Task GetExternalFaceAsync(string idno); + + Task GetFaceAsync(string token); + + Task UploadFaceAsync(GainfoUploadFaceRequest request); + + Task UploadFacesAsync(List request); + + Task GetFaceByUserCodeAsync(string userCode); + + Task> GetFaceByUserCodesAsync(GetFaceByUserCodesRequest request); } diff --git a/Src/Dlhis.Basic/Organization/Services/IGainfoService.cs b/Src/Dlhis.Basic/Organization/Services/IGainfoService.cs index 7624acfc..43347e5c 100644 --- a/Src/Dlhis.Basic/Organization/Services/IGainfoService.cs +++ b/Src/Dlhis.Basic/Organization/Services/IGainfoService.cs @@ -1,7 +1,6 @@ using Dlhis.Basic.Organization.Request; using Dlhis.Basic.Organization.Response; using Kurisu.Core.DataAccess.Dto; -using Microsoft.AspNetCore.Mvc; namespace Dlhis.Basic.Organization.Services; @@ -13,21 +12,10 @@ public interface IGainfoService : IScopeDependency Task CurrentUserInfoAsync(); - Task UploadFaceAsync(GainfoUploadFaceRequest request); - - Task UploadFacesAsync(List request); - - Task GetFaceAsync(string token); - - Task GetFaceByUserCodeAsync(string userCode); - - Task> GetFaceByUserCodesAsync(GetFaceByUserCodesRequest request); - Task> GetGainfoListAsync(GainfoListRequest request); Task GetGainfoDetailAsync(GainfoDetailRequest request); - Task MigrationAsync(MigrationRequest request); Task CheckIdNoAndNameMatchAsync(GainfoCheckIdNoAndNameRequest request); diff --git a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoFaceService.cs b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoFaceService.cs index 2b91d5d8..b7754a96 100644 --- a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoFaceService.cs +++ b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoFaceService.cs @@ -1,8 +1,15 @@ -using Dlhis.Basic.Organization.Request; +using Dlhis.Basic.Device.Services; +using Dlhis.Basic.Organization.Request; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Enums; +using Dlhis.Entity.Device.Enums; +using Kurisu.AspNetCore.Utils; using Kurisu.AspNetCore.Utils.Extensions; +using Kurisu.Core.CustomClass; +using Kurisu.Core.User.Abstractions; using Kurisu.SqlSugar.Services; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Mvc; namespace Dlhis.Basic.Organization.Services.Implements; @@ -10,11 +17,30 @@ public class GainfoFaceService : IGainfoFaceService { private readonly IGainfoStore _gainfoStore; private readonly IDbContext _dbContext; + private readonly ILogger _logger; + private readonly IConfiguration _configuration; + private readonly RedisCache _redisCache; + private readonly ICurrentUser _currentUser; + private readonly IDevicePermissionService _devicePermissionService; + private readonly IDataProtectionProvider _dataProtectionProvider; - public GainfoFaceService(IGainfoStore gainfoStore, IDbContext dbContext) + public GainfoFaceService(IGainfoStore gainfoStore, + IDbContext dbContext, + ILogger logger, + IConfiguration configuration, + RedisCache redisCache, + ICurrentUser currentUser, + IDevicePermissionService devicePermissionService, + IDataProtectionProvider dataProtectionProvider) { _gainfoStore = gainfoStore; _dbContext = dbContext; + _logger = logger; + _configuration = configuration; + _redisCache = redisCache; + _currentUser = currentUser; + _devicePermissionService = devicePermissionService; + _dataProtectionProvider = dataProtectionProvider; } public async Task UploadExternalFaceAsync(GainfoUploadFaceRequest request) @@ -48,4 +74,196 @@ public class GainfoFaceService : IGainfoFaceService await faceContext.UpdateAsync(face); } } + + public async Task GetExternalFaceAsync(string idno) + { + var protector = _dataProtectionProvider.CreateProtector("gainfo:external:idno"); + try + { + idno = protector.Unprotect(idno); + } + catch (Exception) + { + throw new UserFriendlyException("凭证有误,无法获取人脸数"); + } + + var dbContext = _dbContext.ChangeDb("face"); + var face = await dbContext.Queryable() + .Where(x => x.UserCode == idno) + .SingleAsync(); + + face.ThrowIfNull("人脸照片尚未录入"); + + var timeLimitedDataProtector = _dataProtectionProvider.CreateProtector("down:face").ToTimeLimitedDataProtector(); + + var faceUrl = _configuration.GetSection("FaceUrlOptions:Url").Value; + var limit = _configuration.GetSection("FaceUrlOptions:Limit").Get(); + + var key = $"face:{idno}"; + var token = timeLimitedDataProtector.Protect(key, TimeSpan.FromSeconds(limit)); + + return faceUrl + token; + } + + public async Task GetFaceAsync(string token) + { + var timeLimitedDataProtector = _dataProtectionProvider.CreateProtector("down:face").ToTimeLimitedDataProtector(); + + try + { + var password = timeLimitedDataProtector.Unprotect(token); + var userCode = password.Split(':')[1]; + + var faceCache = await _redisCache.HashGetAsync("faces", userCode); + if (faceCache.HasValue) + { + return new FileContentResult(Convert.FromBase64String(faceCache), "image/png"); + } + + var dbContext = _dbContext.ChangeDb("face"); + var face = await dbContext.Queryable().Where(x => x.UserCode == userCode).SingleAsync(); + + if (face == null) + { + _logger.LogWarning("学工号:{userCode}不存在人脸照片", userCode); + return new NotFoundResult(); + } + + return new FileContentResult(Convert.FromBase64String(face.Face), "image/png"); + } + catch (Exception ex) + { + _logger.LogError(ex, "获取人脸失败:{message}", ex.Message); + return new NotFoundResult(); + } + } + + public async Task UploadFaceAsync(GainfoUploadFaceRequest request) + { + var gainfo = await _gainfoStore.Queryable().Where(x => x.No == request.UserNo).FirstAsync(); + gainfo.ThrowIfNull("人员档案信息不存在"); + + var userId = _currentUser.GetIntSubjectId(); + + var faceContext = _dbContext.ChangeDb("face"); + var face = await faceContext.Queryable().Where(x => x.UserCode == gainfo.Code).SingleAsync(); + + var taskType = face == null ? DeviceTaskEnumType.Add : DeviceTaskEnumType.Update; + + await _redisCache.HashSetAsync("faces", gainfo.Code, request.Face); + if (face == null) + { + face = new GainfoFaceEntity + { + UserCode = gainfo.Code, + Face = request.Face, + CreateTime = DateTime.Now, + ModifiedTime = DateTime.Now, + CreatedBy = userId, + ModifiedBy = userId + }; + + await faceContext.InsertAsync(face); + } + else + { + if (face.Face == request.Face) + { + _logger.LogWarning("相同的人脸照片更新忽略"); + return; + } + + face.Face = request.Face; + face.ModifiedBy = userId; + face.ModifiedTime = DateTime.Now; + await faceContext.UpdateAsync(face); + } + + //生成任务 + await _devicePermissionService.GenerateDeviceTasksAsync(gainfo.No, taskType); + } + + public async Task UploadFacesAsync(List requests) + { + foreach (var request in requests) + { + var gainfo = await _gainfoStore.Queryable(GainfoStatusEnumType.Working).Where(x => x.No == request.UserNo).FirstAsync(); + gainfo ??= await _gainfoStore.Queryable(GainfoStatusEnumType.External).Where(x => x.No == request.UserNo).FirstAsync(); + + gainfo.ThrowIfNull("人员档案信息不存在"); + + var dbContext = _dbContext.ChangeDb("face"); + var face = await dbContext.Queryable().Where(x => x.UserCode == gainfo.Code).SingleAsync(); + + var taskType = face == null ? DeviceTaskEnumType.Add : DeviceTaskEnumType.Update; + + await _redisCache.HashSetAsync("faces", gainfo.Code, request.Face); + if (face == null) + { + face = new GainfoFaceEntity + { + UserCode = gainfo.Code, + Face = request.Face + }; + + await dbContext.InsertAsync(face); + } + else + { + if (face.Face == request.Face) + { + _logger.LogWarning("相同的人脸照片更新忽略"); + return; + } + + face.Face = request.Face; + await dbContext.UpdateAsync(face); + } + + //生成任务 + await _devicePermissionService.GenerateDeviceTasksAsync(gainfo.No, taskType); + } + } + + + public async Task GetFaceByUserCodeAsync(string userCode) + { + var gainfo = await _dbContext.Queryable().Where(x => x.Code == userCode).SingleAsync(); + gainfo.ThrowIfNull($"{userCode}人员信息不存在"); + + var dbContext = _dbContext.ChangeDb("face"); + var face = await dbContext.Queryable() + .Where(x => x.UserCode == userCode) + .SingleAsync(); + + face.ThrowIfNull("人脸照片尚未录入"); + + var timeLimitedDataProtector = _dataProtectionProvider.CreateProtector("down:face").ToTimeLimitedDataProtector(); + + var faceUrl = _configuration.GetSection("FaceUrlOptions:Url").Value; + var limit = _configuration.GetSection("FaceUrlOptions:Limit").Get(); + + var key = $"face:{userCode}"; + var token = timeLimitedDataProtector.Protect(key, TimeSpan.FromSeconds(limit)); + + return faceUrl + token; + } + + public async Task> GetFaceByUserCodesAsync(GetFaceByUserCodesRequest request) + { + var faceDictionary = new Dictionary(); + + foreach (var userCode in request.UserCodes) + { + try + { + var faceUrl = await GetFaceByUserCodeAsync(userCode); + faceDictionary.Add(userCode, faceUrl); + } + catch (Exception) + { + } + } + return faceDictionary; + } } diff --git a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs index ee5a9bba..33c1ea94 100644 --- a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs +++ b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoService.cs @@ -1,20 +1,16 @@ -using Dlhis.Basic.Device.Services; -using Dlhis.Basic.Organization.Request; +using Dlhis.Basic.Organization.Request; using Dlhis.Basic.Organization.Response; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Enums; -using Dlhis.Entity.Device.Enums; using Dlhis.Scheduled.Api; using Dlhis.Scheduled.Api.Request; using Dlhis.Sys.Api; -using Kurisu.AspNetCore.Utils; using Kurisu.AspNetCore.Utils.Extensions; using Kurisu.Core.DataAccess.Dto; using Kurisu.Core.User.Abstractions; using Kurisu.SqlSugar.Extensions; using Kurisu.SqlSugar.Services; using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Mvc; namespace Dlhis.Basic.Organization.Services.Implements; @@ -24,9 +20,6 @@ public class GainfoService : IGainfoService private readonly IDbContext _dbContext; private readonly IDataProtectionProvider _dataProtectionProvider; private readonly ICurrentUser _currentUser; - private readonly IDevicePermissionService _devicePermissionService; - private readonly RedisCache _redisCache; - private readonly IConfiguration _configuration; private readonly ITenantApi _tenantApi; private readonly IHangfireApi _hangfireApi; private readonly ILogger _logger; @@ -35,9 +28,6 @@ public class GainfoService : IGainfoService IDbContext dbContext, IDataProtectionProvider dataProtectionProvider, ICurrentUser currentUser, - IDevicePermissionService devicePermissionService, - RedisCache redisCache, - IConfiguration configuration, ITenantApi tenantApi, IHangfireApi hangfireApi, ILogger logger) @@ -46,9 +36,6 @@ public class GainfoService : IGainfoService _dbContext = dbContext; _dataProtectionProvider = dataProtectionProvider; _currentUser = currentUser; - _devicePermissionService = devicePermissionService; - _redisCache = redisCache; - _configuration = configuration; _tenantApi = tenantApi; _hangfireApi = hangfireApi; _logger = logger; @@ -162,169 +149,6 @@ public class GainfoService : IGainfoService return info; } - public async Task GetFaceAsync(string token) - { - var timeLimitedDataProtector = _dataProtectionProvider.CreateProtector("down:face").ToTimeLimitedDataProtector(); - - try - { - var password = timeLimitedDataProtector.Unprotect(token); - var userCode = password.Split(':')[1]; - - var faceCache = await _redisCache.HashGetAsync("faces", userCode); - if (faceCache.HasValue) - { - return new FileContentResult(Convert.FromBase64String(faceCache), "image/png"); - } - - var dbContext = _dbContext.ChangeDb("face"); - var face = await dbContext.Queryable().Where(x => x.UserCode == userCode).SingleAsync(); - - if (face == null) - { - _logger.LogWarning("学工号:{userCode}不存在人脸照片", userCode); - return new NotFoundResult(); - } - - return new FileContentResult(Convert.FromBase64String(face.Face), "image/png"); - } - catch (Exception ex) - { - _logger.LogError(ex, "获取人脸失败:{message}", ex.Message); - return new NotFoundResult(); - } - } - - public async Task UploadFaceAsync(GainfoUploadFaceRequest request) - { - var gainfo = await _gainfoStore.Queryable().Where(x => x.No == request.UserNo).FirstAsync(); - gainfo.ThrowIfNull("人员档案信息不存在"); - - var userId = _currentUser.GetIntSubjectId(); - - var faceContext = _dbContext.ChangeDb("face"); - var face = await faceContext.Queryable().Where(x => x.UserCode == gainfo.Code).SingleAsync(); - - var taskType = face == null ? DeviceTaskEnumType.Add : DeviceTaskEnumType.Update; - - await _redisCache.HashSetAsync("faces", gainfo.Code, request.Face); - if (face == null) - { - face = new GainfoFaceEntity - { - UserCode = gainfo.Code, - Face = request.Face, - CreateTime = DateTime.Now, - ModifiedTime = DateTime.Now, - CreatedBy = userId, - ModifiedBy = userId - }; - - await faceContext.InsertAsync(face); - } - else - { - if (face.Face == request.Face) - { - _logger.LogWarning("相同的人脸照片更新忽略"); - return; - } - - face.Face = request.Face; - face.ModifiedBy = userId; - face.ModifiedTime = DateTime.Now; - await faceContext.UpdateAsync(face); - } - - //生成任务 - await _devicePermissionService.GenerateDeviceTasksAsync(gainfo.No, taskType); - } - - public async Task UploadFacesAsync(List requests) - { - foreach (var request in requests) - { - var gainfo = await _gainfoStore.Queryable(GainfoStatusEnumType.Working).Where(x => x.No == request.UserNo).FirstAsync(); - gainfo ??= await _gainfoStore.Queryable(GainfoStatusEnumType.External).Where(x => x.No == request.UserNo).FirstAsync(); - - gainfo.ThrowIfNull("人员档案信息不存在"); - - var dbContext = _dbContext.ChangeDb("face"); - var face = await dbContext.Queryable().Where(x => x.UserCode == gainfo.Code).SingleAsync(); - - var taskType = face == null ? DeviceTaskEnumType.Add : DeviceTaskEnumType.Update; - - await _redisCache.HashSetAsync("faces", gainfo.Code, request.Face); - if (face == null) - { - face = new GainfoFaceEntity - { - UserCode = gainfo.Code, - Face = request.Face - }; - - await dbContext.InsertAsync(face); - } - else - { - if (face.Face == request.Face) - { - _logger.LogWarning("相同的人脸照片更新忽略"); - return; - } - - face.Face = request.Face; - await dbContext.UpdateAsync(face); - } - - //生成任务 - await _devicePermissionService.GenerateDeviceTasksAsync(gainfo.No, taskType); - } - } - - public async Task GetFaceByUserCodeAsync(string userCode) - { - var gainfo = await _dbContext.Queryable().Where(x => x.Code == userCode).SingleAsync(); - gainfo.ThrowIfNull($"{userCode}人员信息不存在"); - - var dbContext = _dbContext.ChangeDb("face"); - - var face = await dbContext.Queryable() - .Where(x => x.UserCode == userCode) - .SingleAsync(); - - face.ThrowIfNull("人脸照片尚未录入"); - - var timeLimitedDataProtector = _dataProtectionProvider.CreateProtector("down:face").ToTimeLimitedDataProtector(); - - var faceUrl = _configuration.GetSection("FaceUrlOptions:Url").Value; - var limit = _configuration.GetSection("FaceUrlOptions:Limit").Get(); - - var key = $"face:{userCode}"; - var token = timeLimitedDataProtector.Protect(key, TimeSpan.FromSeconds(limit)); - - return faceUrl + token; - } - - public async Task> GetFaceByUserCodesAsync(GetFaceByUserCodesRequest request) - { - var faceDictionary = new Dictionary(); - - foreach (var userCode in request.UserCodes) - { - try - { - var faceUrl = await GetFaceByUserCodeAsync(userCode); - faceDictionary.Add(userCode, faceUrl); - } - catch (Exception) - { - } - } - return faceDictionary; - } - - public async Task CheckIdNoAndNameMatchAsync(GainfoCheckIdNoAndNameRequest request) { var match = await _gainfoStore.Queryable(GainfoStatusEnumType.External).AnyAsync(x => x.IdNo == request.IdNo && x.Name == request.Name);