feat 人脸检测
This commit is contained in:
@@ -51,6 +51,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dlhis.Middle", "Src\Dlhis.M
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dlhis.DataPermission.Model", "Src\Dlhis.DataPermission.Model\Dlhis.DataPermission.Model.csproj", "{CA1427E2-CC70-4489-8653-1C05630C8392}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dlhis.InfoCheck.Api", "Src\Dlhis.InfoCheck.Api\Dlhis.InfoCheck.Api.csproj", "{A501D16E-638F-4156-989C-2BACCC2FAC2B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -129,6 +131,10 @@ Global
|
||||
{CA1427E2-CC70-4489-8653-1C05630C8392}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA1427E2-CC70-4489-8653-1C05630C8392}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA1427E2-CC70-4489-8653-1C05630C8392}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A501D16E-638F-4156-989C-2BACCC2FAC2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A501D16E-638F-4156-989C-2BACCC2FAC2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A501D16E-638F-4156-989C-2BACCC2FAC2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A501D16E-638F-4156-989C-2BACCC2FAC2B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -148,6 +154,7 @@ Global
|
||||
{69E8A91A-5D05-4327-BC24-038523C7628C} = {489252FB-A44B-46EE-B065-21CDCB724441}
|
||||
{053BF7B2-B1A0-435F-9C77-2EF5622CC5C5} = {65E76F97-E78A-4C95-B788-4091236B1A79}
|
||||
{4D656761-8CE7-4316-A3DF-8C1722D69CCE} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A}
|
||||
{A501D16E-638F-4156-989C-2BACCC2FAC2B} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7439494A-E2FD-4FEA-8ABF-74AE57A4A5A0}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
|
||||
<ProjectReference Include="..\Dlhis.InfoCheck.Api\Dlhis.InfoCheck.Api.csproj" />
|
||||
<ProjectReference Include="..\Dlhis.Scheduled.Api\Dlhis.Scheduled.Api.csproj" />
|
||||
<ProjectReference Include="..\Dlhis.Sys.Api\Dlhis.Sys.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Dlhis.Basic.Organization.Request;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Dlhis.Basic.Organization.Request;
|
||||
using Dlhis.Basic.Organization.Response;
|
||||
using Dlhis.Basic.Organization.Services;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop;
|
||||
@@ -43,4 +44,15 @@ public class FactorySettingController : ControllerBase
|
||||
{
|
||||
await _factorySettingService.SaveAsync(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据factory获取配置
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("single")]
|
||||
public async Task<FactorySettingResponse> GetFactorySettingAsync([Required(ErrorMessage = "厂区不可为空")] string factory)
|
||||
{
|
||||
return await _factorySettingService.GetFactorySettingAsync(factory);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using Dlhis.Basic.Device.Filters;
|
||||
using Dlhis.Basic.Organization.Request;
|
||||
using Dlhis.Basic.Organization.Services;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Dlhis.Basic.Organization.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 外包人员配置
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class GainfoOutsourceSettingController : ControllerBase
|
||||
{
|
||||
private readonly IGainfoOutsourceSettingService _gainfoOutSourceService;
|
||||
|
||||
public GainfoOutsourceSettingController(IGainfoOutsourceSettingService gainfoOutSourceService)
|
||||
{
|
||||
_gainfoOutSourceService = gainfoOutSourceService;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 保存配置
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
[HttpPost("save")]
|
||||
[AssignPermissionLimit]
|
||||
[Transactional]
|
||||
[CrossTenant]
|
||||
public async Task SaveAsync(GainfoOutsourceSettingSaveRequest request)
|
||||
{
|
||||
await _gainfoOutSourceService.SaveAsync(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前厂区配置
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("current")]
|
||||
public async Task<object> GetSettingAsync()
|
||||
{
|
||||
return await _gainfoOutSourceService.GetSettingAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Dlhis.Entity.Basic.Dto;
|
||||
|
||||
namespace Dlhis.Basic.Organization.Request;
|
||||
|
||||
@@ -16,4 +17,9 @@ public class FactorySettingSaveRequest
|
||||
/// 档案二维码过期时间
|
||||
/// </summary>
|
||||
public int? UserQrCodeExpiration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人脸检测配置
|
||||
/// </summary>
|
||||
public FaceImageDetectionDto FaceImageDetection { get; set; }
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using Dlhis.Entity.Basic.Dto;
|
||||
|
||||
namespace Dlhis.Basic.Organization.Response;
|
||||
|
||||
public class FactorySettingResponse
|
||||
@@ -15,4 +17,9 @@ public class FactorySettingResponse
|
||||
/// 档案二维码过期时间
|
||||
/// </summary>
|
||||
public int? UserQrCodeExpiration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人脸检测
|
||||
/// </summary>
|
||||
public FaceImageDetectionDto FaceImageDetection { get; set; }
|
||||
}
|
||||
@@ -8,4 +8,6 @@ public interface IFactorySettingService : IScopeDependency
|
||||
Task<List<FactorySettingResponse>> GetListAsync();
|
||||
|
||||
Task SaveAsync(FactorySettingSaveRequest request);
|
||||
|
||||
Task<FactorySettingResponse> GetFactorySettingAsync(string factory);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using Dlhis.Basic.Organization.Request;
|
||||
|
||||
namespace Dlhis.Basic.Organization.Services;
|
||||
|
||||
public interface IGainfoOutsourceSettingService : IScopeDependency
|
||||
{
|
||||
Task SaveAsync(GainfoOutsourceSettingSaveRequest request);
|
||||
|
||||
Task<object> GetSettingAsync();
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
using System.Reflection;
|
||||
using Dlhis.Basic.Organization.Request;
|
||||
using Dlhis.Basic.Organization.Response;
|
||||
using Dlhis.Entity.Basic.Dto;
|
||||
using Dlhis.Entity.Basic.Enums;
|
||||
using Dlhis.Entity.Sys.Entities;
|
||||
using Dlhis.Sys.Api;
|
||||
using Dlhis.Sys.Api.Response;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
using Mapster;
|
||||
|
||||
namespace Dlhis.Basic.Organization.Services.Implements;
|
||||
@@ -20,24 +25,7 @@ public class FactorySettingService : IFactorySettingService
|
||||
|
||||
public async Task<List<FactorySettingResponse>> GetListAsync()
|
||||
{
|
||||
var apiResult = await _tenantApi.GetMyTenantsAsync();
|
||||
var factories = apiResult.Data;
|
||||
|
||||
var factoryCodes = factories.Select(x => x.Code).ToList();
|
||||
var settings = await _dbContext.Queryable<FactorySettingEntity>().Where(x => factoryCodes.Contains(x.TenantId))
|
||||
.ToListAsync();
|
||||
|
||||
return factories.Select(item =>
|
||||
{
|
||||
var factory = factories.FirstOrDefault(x => x.Code == item.Code);
|
||||
return new FactorySettingResponse
|
||||
{
|
||||
Factory = factory?.Code,
|
||||
FactoryName = factory?.Name,
|
||||
EnableOutsourceDown = settings.FirstOrDefault(x => x.TenantId == item.Code)?.EnableOutsourceDown ?? false,
|
||||
UserQrCodeExpiration = settings.FirstOrDefault(x => x.TenantId == item.Code)?.UserQrCodeExpiration
|
||||
};
|
||||
}).ToList();
|
||||
return await GetFactorySettingsAsync();
|
||||
}
|
||||
|
||||
public async Task SaveAsync(FactorySettingSaveRequest request)
|
||||
@@ -58,4 +46,60 @@ public class FactorySettingService : IFactorySettingService
|
||||
await _dbContext.UpdateAsync(setting);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<FactorySettingResponse> GetFactorySettingAsync(string factory)
|
||||
{
|
||||
var settings = await GetFactorySettingsAsync(factory);
|
||||
var setting = settings.FirstOrDefault() ?? new FactorySettingResponse();
|
||||
|
||||
setting.UserQrCodeExpiration ??= 60 * 1000 * 60;
|
||||
setting.FaceImageDetection ??= new FaceImageDetectionDto
|
||||
{
|
||||
Enable = true,
|
||||
Detections = typeof(FaceQualityTypeEnumType).GetFields(BindingFlags.Public | BindingFlags.Static).Select(x => new FaceImageDetection
|
||||
{
|
||||
Type = Enum.Parse<FaceQualityTypeEnumType>(x!.GetValue(null)!.ToString()!),
|
||||
Level = FaceQualityLevelEnumType.Medium
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
return setting;
|
||||
}
|
||||
|
||||
//************************************************************************************************************************************************************
|
||||
|
||||
private async Task<List<FactorySettingResponse>> GetFactorySettingsAsync(string factory = null)
|
||||
{
|
||||
List<TenantResponse> factories;
|
||||
|
||||
|
||||
if (factory.IsPresent())
|
||||
{
|
||||
factories = new List<TenantResponse> { new() { Code = factory } };
|
||||
}
|
||||
else
|
||||
{
|
||||
var apiResult = await _tenantApi.GetMyTenantsAsync();
|
||||
factories = apiResult.Data;
|
||||
}
|
||||
|
||||
var factoryCodes = factories.Select(x => x.Code).ToList();
|
||||
var settings = await _dbContext.Queryable<FactorySettingEntity>()
|
||||
.Where(x => factoryCodes.Contains(x.TenantId))
|
||||
.ToListAsync();
|
||||
|
||||
return factories.Select(item =>
|
||||
{
|
||||
var currentFactory = factories.FirstOrDefault(x => x.Code == item.Code);
|
||||
var currentSetting = settings.FirstOrDefault(x => x.TenantId == item.Code);
|
||||
return new FactorySettingResponse
|
||||
{
|
||||
Factory = currentFactory?.Code,
|
||||
FactoryName = currentFactory?.Name,
|
||||
EnableOutsourceDown = currentSetting?.EnableOutsourceDown ?? false,
|
||||
UserQrCodeExpiration = currentSetting?.UserQrCodeExpiration,
|
||||
FaceImageDetection = currentSetting?.FaceImageDetection
|
||||
};
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
using Dlhis.Basic.Device.Services;
|
||||
using Dlhis.Basic.Organization.Request;
|
||||
using Dlhis.Basic.Organization.Response;
|
||||
using Dlhis.Entity.Basic.Dto;
|
||||
using Dlhis.Entity.Basic.Entity;
|
||||
using Dlhis.Entity.Basic.Enums;
|
||||
using Dlhis.Entity.Device.Enums;
|
||||
using Dlhis.InfoCheck.Api;
|
||||
using Dlhis.InfoCheck.Api.Requests;
|
||||
using Dlhis.Scheduled.Api;
|
||||
using Dlhis.Scheduled.Api.Request;
|
||||
using Kurisu.AspNetCore.Authentication.Abstractions;
|
||||
@@ -26,6 +29,8 @@ public class GainfoFaceService : IGainfoFaceService
|
||||
private readonly ICurrentUser _currentUser;
|
||||
private readonly IHangfireApi _hangfireApi;
|
||||
private readonly IDevicePermissionService _devicePermissionService;
|
||||
private readonly IFactorySettingService _factorySettingService;
|
||||
private readonly IInfoCheckApi _infoCheckApi;
|
||||
private readonly IDataProtectionProvider _dataProtectionProvider;
|
||||
|
||||
public GainfoFaceService(IGainfoStore gainfoStore,
|
||||
@@ -35,6 +40,8 @@ public class GainfoFaceService : IGainfoFaceService
|
||||
ICurrentUser currentUser,
|
||||
IHangfireApi hangfireApi,
|
||||
IDevicePermissionService devicePermissionService,
|
||||
IFactorySettingService factorySettingService,
|
||||
IInfoCheckApi infoCheckApi,
|
||||
IDataProtectionProvider dataProtectionProvider)
|
||||
{
|
||||
_gainfoStore = gainfoStore;
|
||||
@@ -45,10 +52,11 @@ public class GainfoFaceService : IGainfoFaceService
|
||||
_currentUser = currentUser;
|
||||
_hangfireApi = hangfireApi;
|
||||
_devicePermissionService = devicePermissionService;
|
||||
_factorySettingService = factorySettingService;
|
||||
_infoCheckApi = infoCheckApi;
|
||||
_dataProtectionProvider = dataProtectionProvider;
|
||||
}
|
||||
|
||||
|
||||
public async Task<GainfoFacePageSummaryResponse> GetPageAsync(GainfoFacePageRequest request)
|
||||
{
|
||||
var factories = request.Factories;
|
||||
@@ -96,11 +104,12 @@ public class GainfoFaceService : IGainfoFaceService
|
||||
|
||||
var gainfo = await _gainfoStore.Queryable(GainfoStatusEnumType.External)
|
||||
.Where(x => x.IdNo == request.UserNo)
|
||||
.FirstAsync();
|
||||
.SingleAsync();
|
||||
|
||||
gainfo ??= await _gainfoStore.Queryable(GainfoStatusEnumType.Working)
|
||||
.Where(x => x.IdNo == request.UserNo)
|
||||
.FirstAsync();
|
||||
.SingleAsync();
|
||||
|
||||
gainfo.ThrowIfNull("人员信息不存在");
|
||||
|
||||
var face = await _faceDbContext.Queryable<GainfoFaceEntity>().Where(x => x.UserCode == gainfo.Code).SingleAsync();
|
||||
@@ -186,25 +195,20 @@ public class GainfoFaceService : IGainfoFaceService
|
||||
|
||||
public async Task UploadFaceAsync(GainfoUploadFaceRequest request)
|
||||
{
|
||||
var gainfo = await _gainfoStore.Queryable().Where(x => x.No == request.UserNo).FirstAsync();
|
||||
var gainfo = await _gainfoStore.Queryable().Where(x => x.No == request.UserNo || x.Code == request.UserNo).SingleAsync();
|
||||
gainfo.ThrowIfNull("人员档案信息不存在");
|
||||
|
||||
var userId = _currentUser.GetIntSubjectId();
|
||||
await DetectFaceImageQualityAsync(request.Face);
|
||||
|
||||
var face = await _faceDbContext.Queryable<GainfoFaceEntity>().Where(x => x.UserCode == gainfo.Code).SingleAsync();
|
||||
|
||||
var taskType = face == null ? DeviceTaskEnumType.Add : DeviceTaskEnumType.Update;
|
||||
|
||||
if (face == null)
|
||||
{
|
||||
face = new GainfoFaceEntity
|
||||
{
|
||||
UserCode = gainfo.Code,
|
||||
Face = request.Face,
|
||||
CreateTime = DateTime.Now,
|
||||
ModifiedTime = DateTime.Now,
|
||||
CreatedBy = userId,
|
||||
ModifiedBy = userId
|
||||
Face = request.Face
|
||||
};
|
||||
|
||||
await _faceDbContext.InsertAsync(face);
|
||||
@@ -218,8 +222,6 @@ public class GainfoFaceService : IGainfoFaceService
|
||||
}
|
||||
|
||||
face.Face = request.Face;
|
||||
face.ModifiedBy = userId;
|
||||
face.ModifiedTime = DateTime.Now;
|
||||
await _faceDbContext.UpdateAsync(face);
|
||||
}
|
||||
|
||||
@@ -236,9 +238,6 @@ public class GainfoFaceService : IGainfoFaceService
|
||||
_logger.LogError(e, "上传face数据到sap失败:{message}", e.Message);
|
||||
}
|
||||
|
||||
// var prefix = gainfo.Factory == "501" ? "jschuneng" : "jingke";
|
||||
// var url = $"https://pay.aizhuhotel.com/{prefix}/api/face";
|
||||
|
||||
//生成任务
|
||||
await _devicePermissionService.GenerateDeviceTasksAsync(gainfo.No, taskType, DeviceTaskSourceEnumType.Photo);
|
||||
}
|
||||
@@ -328,4 +327,42 @@ public class GainfoFaceService : IGainfoFaceService
|
||||
|
||||
return faceDictionary;
|
||||
}
|
||||
|
||||
//*********************************************************************************************************************************************
|
||||
|
||||
/// <summary>
|
||||
/// 人脸质量检测
|
||||
/// </summary>
|
||||
/// <param name="base64Image"></param>
|
||||
/// <param name="factory"></param>
|
||||
/// <exception cref="UserFriendlyException"></exception>
|
||||
private async Task DetectFaceImageQualityAsync(string base64Image, string factory = null)
|
||||
{
|
||||
var currentFactory = factory ?? _currentUser.GetStringTenantId();
|
||||
var factorySetting = await _factorySettingService.GetFactorySettingAsync(currentFactory);
|
||||
if (factorySetting.FaceImageDetection.Enable)
|
||||
{
|
||||
List<string> r;
|
||||
|
||||
try
|
||||
{
|
||||
var result = await _infoCheckApi.FaceDetectAsync(new FaceDetectRequest
|
||||
{
|
||||
Base64 = base64Image,
|
||||
CheckList = factorySetting.FaceImageDetection.Detections.Select(x => new FaceDetectCheckRequest
|
||||
{
|
||||
Type = (int)x.Type,
|
||||
Level = (int)x.Level
|
||||
}).ToList()
|
||||
});
|
||||
r = result.Data;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
r.IsPresent().ThrowIfTrue($"{r.Join("\r\n")}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
using Dlhis.Basic.Device.Services;
|
||||
using Dlhis.Basic.Organization.Request;
|
||||
using Dlhis.Entity.Basic.Entity;
|
||||
using Dlhis.Entity.Sys.Entities;
|
||||
using Kurisu.AspNetCore.Authentication.Abstractions;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
using SqlSugar;
|
||||
|
||||
namespace Dlhis.Basic.Organization.Services.Implements;
|
||||
|
||||
public class GainfoOutsourceSettingService : IGainfoOutsourceSettingService
|
||||
{
|
||||
private readonly IDbContext _dbContext;
|
||||
private readonly ICurrentUser _currentUser;
|
||||
private readonly IDevicePermissionService _devicePermissionService;
|
||||
|
||||
public GainfoOutsourceSettingService(IDbContext dbContext, ICurrentUser currentUser, IDevicePermissionService devicePermissionService)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_currentUser = currentUser;
|
||||
_devicePermissionService = devicePermissionService;
|
||||
}
|
||||
|
||||
public async Task SaveAsync(GainfoOutsourceSettingSaveRequest request)
|
||||
{
|
||||
var userNos = await _dbContext.Queryable<GainfoEntity>()
|
||||
.Where(x => SqlFunc.Subqueryable<OutsourceEntity>().Where(p => p.Code == x.Code).Any())
|
||||
.Select(x => x.No)
|
||||
.ToListAsync();
|
||||
|
||||
await _devicePermissionService.GenerateDeviceTasksAsync(async () =>
|
||||
{
|
||||
var currentTenantId = _currentUser.GetStringTenantId();
|
||||
|
||||
(!request.Id.HasValue && await _dbContext.Queryable<FactorySettingEntity>()
|
||||
.Where(x => x.TenantId == currentTenantId)
|
||||
.AnyAsync()).ThrowIfTrue("保存失败,请检查参数");
|
||||
|
||||
if (!request.Id.HasValue)
|
||||
{
|
||||
var entity = new FactorySettingEntity
|
||||
{
|
||||
EnableOutsourceDown = request.EnableFactory,
|
||||
TenantId = currentTenantId
|
||||
};
|
||||
|
||||
await _dbContext.InsertAsync(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
var entity = await _dbContext.Queryable<FactorySettingEntity>().Where(x => x.Id == request.Id).SingleAsync();
|
||||
entity.ThrowIfNull("数据不存在,保存失败");
|
||||
|
||||
entity.EnableOutsourceDown = request.EnableFactory;
|
||||
|
||||
await _dbContext.UpdateAsync(entity);
|
||||
}
|
||||
}, userNos);
|
||||
}
|
||||
|
||||
|
||||
public async Task<object> GetSettingAsync()
|
||||
{
|
||||
var currentTenantId = _currentUser.GetStringTenantId();
|
||||
return await _dbContext.Queryable<FactorySettingEntity>().Where(x => x.TenantId == currentTenantId).Select(x => new
|
||||
{
|
||||
x.Id, EnableFactory = x.EnableOutsourceDown
|
||||
}).SingleAsync();
|
||||
}
|
||||
}
|
||||
@@ -10,21 +10,26 @@ public class GainfoQrCodeService : IGainfoQrCodeService
|
||||
{
|
||||
private readonly IDbContext _dbContext;
|
||||
private readonly ICurrentUser _currentUser;
|
||||
private readonly IFactorySettingService _factorySettingService;
|
||||
|
||||
public GainfoQrCodeService(IDbContext dbContext, ICurrentUser currentUser)
|
||||
public GainfoQrCodeService(IDbContext dbContext, ICurrentUser currentUser, IFactorySettingService factorySettingService)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_currentUser = currentUser;
|
||||
_factorySettingService = factorySettingService;
|
||||
}
|
||||
|
||||
public async Task<string> GetMyQrCodeAsync(bool isNeedRefresh = false)
|
||||
{
|
||||
var jinkoCode = _currentUser.GetUserClaim("jinko-code");
|
||||
jinkoCode = "0123456";
|
||||
if (jinkoCode.IsEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var factory = _currentUser.GetStringTenantId();
|
||||
|
||||
var now = DateTime.Now;
|
||||
var gainfoQrCode = await _dbContext.Queryable<GainfoQrCodeEntity>().SingleAsync(x => x.UserCode == jinkoCode);
|
||||
|
||||
@@ -39,7 +44,8 @@ public class GainfoQrCodeService : IGainfoQrCodeService
|
||||
await _dbContext.InsertAsync(gainfoQrCode);
|
||||
}
|
||||
|
||||
if (gainfoQrCode.ModifiedTime.AddMinutes(60) >= now && !isNeedRefresh)
|
||||
var setting = await _factorySettingService.GetFactorySettingAsync(factory);
|
||||
if (gainfoQrCode.ModifiedTime.AddMinutes(setting.UserQrCodeExpiration!.Value) >= now && !isNeedRefresh)
|
||||
{
|
||||
return gainfoQrCode.QrCode;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ public class Startup : DefaultStartup
|
||||
public override void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
base.ConfigureServices(services);
|
||||
services.AddHttpContextAccessor();
|
||||
services.AddRedis();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,8 @@
|
||||
"InternalRequest": {
|
||||
"CommonRequestUrl": "http://localhost:5001",
|
||||
"SysRequestUrl": "http://localhost:5003",
|
||||
"ScheduledRequestUrl": "http://localhost:5010"
|
||||
"ScheduledRequestUrl": "http://localhost:5010",
|
||||
"InfoCheckRequestUrl":"http://localhost:5048"
|
||||
},
|
||||
"FaceUrlOptions": {
|
||||
"Url": "http://localhost:5002/api/gainfos/face?token=",
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
"InternalRequest": {
|
||||
"CommonRequestUrl": "http://common",
|
||||
"SysRequestUrl": "http://sys",
|
||||
"ScheduledRequestUrl": "http://Scheduled"
|
||||
"ScheduledRequestUrl": "http://Scheduled",
|
||||
"InfoCheckRequestUrl": "http://192.168.199.115:5048"
|
||||
},
|
||||
"FaceUrlOptions": {
|
||||
"Url": "https://yikatong.isawesome.cn/api/basic/gainfos/face?token=",
|
||||
|
||||
29
Src/Dlhis.Entity/Basic/Dto/FaceImageDetectionDto.cs
Normal file
29
Src/Dlhis.Entity/Basic/Dto/FaceImageDetectionDto.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Dlhis.Entity.Basic.Enums;
|
||||
|
||||
namespace Dlhis.Entity.Basic.Dto;
|
||||
|
||||
public class FaceImageDetectionDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 开关
|
||||
/// </summary>
|
||||
public bool Enable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 检查项
|
||||
/// </summary>
|
||||
public List<FaceImageDetection> Detections { get; set; }
|
||||
}
|
||||
|
||||
public class FaceImageDetection
|
||||
{
|
||||
/// <summary>
|
||||
/// 检查类型
|
||||
/// </summary>
|
||||
public FaceQualityTypeEnumType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 要求登记
|
||||
/// </summary>
|
||||
public FaceQualityLevelEnumType Level { get; set; }
|
||||
}
|
||||
23
Src/Dlhis.Entity/Basic/Enums/FaceQualityLevelEnumType.cs
Normal file
23
Src/Dlhis.Entity/Basic/Enums/FaceQualityLevelEnumType.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Dlhis.Entity.Basic.Enums;
|
||||
|
||||
[Description("质量评估等级")]
|
||||
public enum FaceQualityLevelEnumType
|
||||
{
|
||||
/// <summary>错误</summary>
|
||||
[Description("错误")]
|
||||
Error = -1,
|
||||
|
||||
/// <summary>质量差</summary>
|
||||
[Description("质量差")]
|
||||
Low = 0,
|
||||
|
||||
/// <summary>质量一般</summary>
|
||||
[Description("质量一般")]
|
||||
Medium = 1,
|
||||
|
||||
/// <summary>质量高</summary>
|
||||
[Description("质量高")]
|
||||
High = 2
|
||||
}
|
||||
46
Src/Dlhis.Entity/Basic/Enums/FaceQualityTypeEnumType.cs
Normal file
46
Src/Dlhis.Entity/Basic/Enums/FaceQualityTypeEnumType.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Dlhis.Entity.Basic.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 人脸照片检测类型
|
||||
/// </summary>
|
||||
[Description("人脸照片质量类型类型")]
|
||||
public enum FaceQualityTypeEnumType
|
||||
{
|
||||
/// <summary>
|
||||
/// 亮度评估
|
||||
/// </summary>
|
||||
[Description("亮度")]
|
||||
Brightness = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 完整度评估
|
||||
/// </summary>
|
||||
[Description("完整度")]
|
||||
Integrity = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 姿态评估(深度)
|
||||
/// </summary>
|
||||
[Description("姿态")]
|
||||
PoseEx = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 分辨率评估
|
||||
/// </summary>
|
||||
[Description("分辨率")]
|
||||
Resolution = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 清晰度评估(深度
|
||||
/// </summary>
|
||||
[Description("清晰度")]
|
||||
ClarityEx = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 遮挡评估
|
||||
/// </summary>
|
||||
[Description("遮挡")]
|
||||
Structure = 7
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using Dlhis.Entity.Basic.Dto;
|
||||
using Kurisu.AspNetCore.DataAccess.Entity;
|
||||
using Kurisu.AspNetCore.DataAccess.SqlSugar;
|
||||
using SqlSugar;
|
||||
@@ -28,5 +29,11 @@ public class FactorySettingEntity : SugarBaseEntity, ITenantId
|
||||
[SugarColumn(ColumnDescription = "电子餐券二维码过期时间", IsNullable = true)]
|
||||
public int? EMealVoucherQrCodeExpiration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 人脸检测配置
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDescription = "人脸检测配置", IsNullable = true, IsJson = true)]
|
||||
public FaceImageDetectionDto FaceImageDetection { get; set; }
|
||||
|
||||
public string TenantId { get; set; }
|
||||
}
|
||||
13
Src/Dlhis.InfoCheck.Api/Dlhis.InfoCheck.Api.csproj
Normal file
13
Src/Dlhis.InfoCheck.Api/Dlhis.InfoCheck.Api.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
20
Src/Dlhis.InfoCheck.Api/IInfoCheckApi.cs
Normal file
20
Src/Dlhis.InfoCheck.Api/IInfoCheckApi.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Dlhis.InfoCheck.Api.Requests;
|
||||
using Kurisu.RemoteCall.Attributes;
|
||||
using Kurisu.RemoteCall.Default;
|
||||
|
||||
namespace Dlhis.InfoCheck.Api;
|
||||
|
||||
/// <summary>
|
||||
/// 信息检查
|
||||
/// </summary>
|
||||
[EnableRemoteClient(Name = "infocheck-service", BaseUrl = "${InternalRequest:InfoCheckRequestUrl}")]
|
||||
public interface IInfoCheckApi
|
||||
{
|
||||
/// <summary>
|
||||
/// 检测人脸质量
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[Post("/api/face/detection")]
|
||||
Task<DefaultApiResult<List<string>>> FaceDetectAsync(FaceDetectRequest request);
|
||||
}
|
||||
17
Src/Dlhis.InfoCheck.Api/Requests/FaceDetectRequest.cs
Normal file
17
Src/Dlhis.InfoCheck.Api/Requests/FaceDetectRequest.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Dlhis.InfoCheck.Api.Requests;
|
||||
|
||||
public class FaceDetectRequest
|
||||
{
|
||||
[Required]
|
||||
public string Base64 { get; set; }
|
||||
|
||||
public List<FaceDetectCheckRequest> CheckList { get; set; }
|
||||
}
|
||||
|
||||
public class FaceDetectCheckRequest
|
||||
{
|
||||
public int Type { get; set; }
|
||||
public int Level { get; set; }
|
||||
}
|
||||
@@ -2,30 +2,25 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using SkiaSharp;
|
||||
using ViewFaceCore.Core;
|
||||
using ViewFaceCore.Model;
|
||||
using ViewFaceCore.Exceptions;
|
||||
using ViewFaceCore;
|
||||
using ViewFaceCore.Configs;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Dlhis.InfoCheck.Request;
|
||||
using Dlhis.InfoCheck.Response;
|
||||
using Kurisu.AspNetCore.Utils.Extensions;
|
||||
|
||||
namespace Dlhis.InfoCheck.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class FaceController : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 人脸质量检测
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("detection")]
|
||||
public object FacialDetection(FaceDetectRequest request)
|
||||
public IEnumerable<string> FacialDetection(FaceDetectRequest request)
|
||||
{
|
||||
var base64Bytes = Convert.FromBase64String(request.Base64);
|
||||
using var stream = new MemoryStream(base64Bytes);
|
||||
@@ -37,34 +32,30 @@ public class FaceController : ControllerBase
|
||||
MarkType = MarkType.Light
|
||||
});
|
||||
|
||||
//todo <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
var info = faceDetector.Detect(bitmap).First();
|
||||
var markPoints = faceMark.Mark(bitmap, info);
|
||||
|
||||
using var faceQuality = new FaceQuality();
|
||||
var brightnessResult = faceQuality.Detect(bitmap, info, markPoints, QualityType.Brightness);
|
||||
var resolutionResult = faceQuality.Detect(bitmap, info, markPoints, QualityType.Resolution);
|
||||
//var clarityResult = faceQuality.Detect(bitmap, info, markPoints, QualityType.Clarity);
|
||||
var clarityExResult = faceQuality.Detect(bitmap, info, markPoints, QualityType.ClarityEx);
|
||||
var integrityExResult = faceQuality.Detect(bitmap, info, markPoints, QualityType.Integrity);
|
||||
var structureeResult = faceQuality.Detect(bitmap, info, markPoints, QualityType.Structure);
|
||||
//var poseResult = faceQuality.Detect(bitmap, info, markPoints, QualityType.Pose);
|
||||
var poseExeResult = faceQuality.Detect(bitmap, info, markPoints, QualityType.PoseEx);
|
||||
var qualityResult = new List<QualityResultEx>(6);
|
||||
qualityResult.Add(faceQuality.DetectEx(bitmap, info, markPoints, QualityType.Brightness));
|
||||
|
||||
return new
|
||||
qualityResult.Add(faceQuality.DetectEx(bitmap, info, markPoints, QualityType.Resolution));
|
||||
//var clarityResult = faceQuality.Detect(bitmap, info, markPoints, QualityType.Clarity);
|
||||
qualityResult.Add(faceQuality.DetectEx(bitmap, info, markPoints, QualityType.ClarityEx));
|
||||
qualityResult.Add(faceQuality.DetectEx(bitmap, info, markPoints, QualityType.Integrity));
|
||||
qualityResult.Add(faceQuality.DetectEx(bitmap, info, markPoints, QualityType.Structure));
|
||||
//var poseResult = faceQuality.Detect(bitmap, info, markPoints, QualityType.Pose);
|
||||
qualityResult.Add(faceQuality.DetectEx(bitmap, info, markPoints, QualityType.PoseEx));
|
||||
|
||||
return request.CheckList.Where(x =>
|
||||
{
|
||||
Brightness = brightnessResult,
|
||||
Resolution = resolutionResult,
|
||||
Clarity = clarityExResult,
|
||||
Integrity = integrityExResult,
|
||||
Structure = structureeResult,
|
||||
Pose = poseExeResult
|
||||
};
|
||||
var r = qualityResult.First(item => item.Type == x.Type);
|
||||
return r.Level < x.Level;
|
||||
}).Select(x => x.Type.GetDescription().Replace("评估", string.Empty) + "不符合");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD>
|
||||
/// 图片识别对比
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
@@ -79,9 +70,7 @@ public class FaceController : ControllerBase
|
||||
using var secondStream = new MemoryStream(secondBase64Bytes);
|
||||
using var secondBitmap = SKBitmap.Decode(secondStream);
|
||||
|
||||
//<2F><>Ӧ<EFBFBD><D3A6>ֵ FaceType.Normal<61><6C>0.62<EFBFBD><EFBFBD>FaceType.Mask<73><6B>0.4<EFBFBD><EFBFBD>FaceType.Light<68><74>0.55
|
||||
//FaceType = FaceType.Normal,
|
||||
using var recognizer = new FaceRecognizer();
|
||||
using var recognizer = new FaceRecognizer(new FaceRecognizeConfig());
|
||||
|
||||
using var faceDetector = new FaceDetector();
|
||||
using var faceMark = new FaceLandmarker();
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Kurisu.AspNetCore" Version="0.9.11" />
|
||||
<PackageReference Include="Kurisu.AspNetCore" Version="0.9.25" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.0" />
|
||||
<PackageReference Include="ViewFaceCore" Version="0.3.8" />
|
||||
<PackageReference Include="ViewFaceCore.all_models" Version="6.0.7" />
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
namespace Dlhis.InfoCheck.Request;
|
||||
using ViewFaceCore.Model;
|
||||
|
||||
namespace Dlhis.InfoCheck.Request;
|
||||
|
||||
public class FaceDetectRequest
|
||||
{
|
||||
public string Base64 { get; set; }
|
||||
public List<FaceDetectCheckRequest> CheckList { get; set; }
|
||||
}
|
||||
|
||||
public class FaceDetectCheckRequest
|
||||
{
|
||||
public QualityType Type { get; set; }
|
||||
public QualityLevel Level { get; set; }
|
||||
}
|
||||
@@ -2,7 +2,13 @@
|
||||
|
||||
public class FaceRecognizeRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 第一张图片
|
||||
/// </summary>
|
||||
public string FirstBase64 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第二张图片
|
||||
/// </summary>
|
||||
public string SecondBase64 { get; set; }
|
||||
}
|
||||
|
||||
36
Src/Dlhis.InfoCheck/Response/FacialDetectionResponse.cs
Normal file
36
Src/Dlhis.InfoCheck/Response/FacialDetectionResponse.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using ViewFaceCore.Model;
|
||||
|
||||
namespace Dlhis.InfoCheck.Response;
|
||||
|
||||
public class FacialDetectionResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// 亮度
|
||||
/// </summary>
|
||||
public QualityResult Brightness { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分辨率
|
||||
/// </summary>
|
||||
public QualityResult Resolution { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 清晰度
|
||||
/// </summary>
|
||||
public QualityResult Clarity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 完整度
|
||||
/// </summary>
|
||||
public QualityResult Integrity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 遮挡
|
||||
/// </summary>
|
||||
public QualityResult Structure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 姿态
|
||||
/// </summary>
|
||||
public QualityResult Pose { get; set; }
|
||||
}
|
||||
27
Src/Dlhis.InfoCheck/faceQualityExtensions.cs
Normal file
27
Src/Dlhis.InfoCheck/faceQualityExtensions.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using ViewFaceCore;
|
||||
using ViewFaceCore.Core;
|
||||
using ViewFaceCore.Model;
|
||||
|
||||
namespace Dlhis.InfoCheck;
|
||||
|
||||
public class QualityResultEx : QualityResult
|
||||
{
|
||||
public QualityType Type { get; set; }
|
||||
}
|
||||
|
||||
public static class FaceQualityExtensions
|
||||
{
|
||||
public static QualityResultEx DetectEx<T>(this FaceQuality faceQuality, T image,
|
||||
FaceInfo info,
|
||||
FaceMarkPoint[] points,
|
||||
QualityType type) where T : class
|
||||
{
|
||||
var result = faceQuality.Detect(image, info, points, type);
|
||||
return new QualityResultEx
|
||||
{
|
||||
Level = result.Level,
|
||||
Score = result.Score,
|
||||
Type = type
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -64,9 +64,6 @@ public class BalanceRecordCheckBackgroundService : BackgroundService
|
||||
await db.Client.Ado.BeginTranAsync();
|
||||
try
|
||||
{
|
||||
//设置为已同步
|
||||
balanceRecord.IsSync = true;
|
||||
await db.UpdateAsync(balanceRecord);
|
||||
var r = await UploadAsync(balanceRecord);
|
||||
if (r.Code != ApiStateCode.Success)
|
||||
{
|
||||
@@ -80,6 +77,10 @@ public class BalanceRecordCheckBackgroundService : BackgroundService
|
||||
.Where(x => x.UserCode == d.UserCode)
|
||||
.ExecuteCommandAsync(stoppingToken);
|
||||
|
||||
//eg:一定要在此处更新为已同步
|
||||
balanceRecord.IsSync = true;
|
||||
await db.UpdateAsync(balanceRecord);
|
||||
|
||||
await db.Client.Ado.CommitTranAsync();
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
Reference in New Issue
Block a user