diff --git a/Src/Dlhis.Basic/Organization/Controllers/GainfoIdCardFaceCompareController.cs b/Src/Dlhis.Basic/Organization/Controllers/GainfoIdCardFaceCompareController.cs
new file mode 100644
index 00000000..94a3e27a
--- /dev/null
+++ b/Src/Dlhis.Basic/Organization/Controllers/GainfoIdCardFaceCompareController.cs
@@ -0,0 +1,46 @@
+using Dlhis.Basic.Organization.Request;
+using Dlhis.Basic.Organization.Response;
+using Dlhis.Basic.Organization.Services;
+using Kurisu.AspNetCore.DataAccess.Dto;
+using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop;
+using Kurisu.AspNetCore.UnifyResultAndValidation.Aop;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Dlhis.Basic.Organization.Controllers;
+
+///
+/// 人证人脸对比
+///
+[Authorize]
+[Route("api/[controller]")]
+[ApiController]
+public class GainfoIdCardFaceCompareController : ControllerBase
+{
+ private readonly IGainfoIdCardFaceCompareService _service;
+
+ public GainfoIdCardFaceCompareController(IGainfoIdCardFaceCompareService service)
+ {
+ _service = service;
+ }
+
+ ///
+ /// 人证人脸对比记录分页
+ ///
+ [DisableApiLog]
+ [HttpPost("page")]
+ public async Task> GetPageAsync(IdCardFaceComparePageRequest request)
+ {
+ return await _service.GetPageAsync(request);
+ }
+
+ ///
+ /// 人证人脸对比
+ ///
+ [HttpPost("compare")]
+ [Transactional]
+ public async Task CompareAsync(IdCardFaceCompareRequest request)
+ {
+ return await _service.CompareAsync(request);
+ }
+}
diff --git a/Src/Dlhis.Basic/Organization/Request/IdCardFaceComparePageRequest.cs b/Src/Dlhis.Basic/Organization/Request/IdCardFaceComparePageRequest.cs
new file mode 100644
index 00000000..f61c0b8c
--- /dev/null
+++ b/Src/Dlhis.Basic/Organization/Request/IdCardFaceComparePageRequest.cs
@@ -0,0 +1,22 @@
+using Dlhis.Entity.Basic.Enums;
+using Kurisu.AspNetCore.DataAccess.Dto;
+
+namespace Dlhis.Basic.Organization.Request;
+
+public class IdCardFaceComparePageRequest : PageDto
+{
+ ///
+ /// 厂区
+ ///
+ public List Factories { get; set; }
+
+ ///
+ /// 人员类型
+ ///
+ public GainfoUserTypeEnumType? UserType { get; set; }
+
+ ///
+ /// 对比结果
+ ///
+ public IdCardFaceCompareResultEnumType? CompareResult { get; set; }
+}
diff --git a/Src/Dlhis.Basic/Organization/Request/IdCardFaceCompareRequest.cs b/Src/Dlhis.Basic/Organization/Request/IdCardFaceCompareRequest.cs
new file mode 100644
index 00000000..81574cbd
--- /dev/null
+++ b/Src/Dlhis.Basic/Organization/Request/IdCardFaceCompareRequest.cs
@@ -0,0 +1,12 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Dlhis.Basic.Organization.Request;
+
+public class IdCardFaceCompareRequest
+{
+ ///
+ /// 用户code
+ ///
+ [Required(ErrorMessage = "用户code不可为空")]
+ public string UserCode { get; set; }
+}
diff --git a/Src/Dlhis.Basic/Organization/Response/AliyunId3MetaVerifyResponse.cs b/Src/Dlhis.Basic/Organization/Response/AliyunId3MetaVerifyResponse.cs
new file mode 100644
index 00000000..82803563
--- /dev/null
+++ b/Src/Dlhis.Basic/Organization/Response/AliyunId3MetaVerifyResponse.cs
@@ -0,0 +1,39 @@
+namespace Dlhis.Basic.Organization.Response;
+
+public class AliyunId3MetaVerifyResponse
+{
+ ///
+ /// 请求ID
+ ///
+ public string RequestId { get; set; }
+
+ ///
+ /// 接口调用返回码,200表示接口调用成功
+ ///
+ public string Code { get; set; }
+
+ ///
+ /// 接口调用返回信息,仅表示接口是否异常
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// 业务核验结果,1一致、2不一致、3查无记录
+ ///
+ public string BizCode { get; set; }
+
+ ///
+ /// 业务核验是否通过,来源于BizCode
+ ///
+ public bool? Passed { get; set; }
+
+ ///
+ /// 人像比对分值,来源于FaceDetail.verifyScore,可能为空
+ ///
+ public double? Similarity { get; set; }
+
+ ///
+ /// 阿里云原始响应
+ ///
+ public string RawResponse { get; set; }
+}
diff --git a/Src/Dlhis.Basic/Organization/Response/IdCardFaceCompareRecordResponse.cs b/Src/Dlhis.Basic/Organization/Response/IdCardFaceCompareRecordResponse.cs
new file mode 100644
index 00000000..f32e5be1
--- /dev/null
+++ b/Src/Dlhis.Basic/Organization/Response/IdCardFaceCompareRecordResponse.cs
@@ -0,0 +1,81 @@
+using Dlhis.Entity.Basic.Enums;
+
+namespace Dlhis.Basic.Organization.Response;
+
+public class IdCardFaceCompareRecordResponse
+{
+ ///
+ /// 记录ID
+ ///
+ public long Id { get; set; }
+
+ ///
+ /// 用户code
+ ///
+ public string UserCode { get; set; }
+
+ ///
+ /// 姓名
+ ///
+ public string UserName { get; set; }
+
+ ///
+ /// 人员类型
+ ///
+ public GainfoUserTypeEnumType UserType { get; set; }
+
+ ///
+ /// 证件号
+ ///
+ public string IdNo { get; set; }
+
+ ///
+ /// 部门名称
+ ///
+ public string DepartmentName { get; set; }
+
+ ///
+ /// 厂区
+ ///
+ public string Factory { get; set; }
+
+ ///
+ /// 对比结果
+ ///
+ public IdCardFaceCompareResultEnumType CompareResult { get; set; }
+
+ ///
+ /// 业务核验是否通过,来源于阿里云ResultObject.BizCode
+ ///
+ public bool? IsPassed { get; set; }
+
+ ///
+ /// 人像比对分值,来源于阿里云ResultObject.FaceDetail.verifyScore,可能为空
+ ///
+ public double? Similarity { get; set; }
+
+ ///
+ /// 当前用户累计对比次数
+ ///
+ public int CompareCount { get; set; }
+
+ ///
+ /// 最近对比时间
+ ///
+ public DateTime? LastCompareTime { get; set; }
+
+ ///
+ /// 阿里云原始响应
+ ///
+ public string ApiResponse { get; set; }
+
+ ///
+ /// 对比异常信息
+ ///
+ public string ErrorMessage { get; set; }
+
+ ///
+ /// 记录创建时间
+ ///
+ public DateTime CreateTime { get; set; }
+}
diff --git a/Src/Dlhis.Basic/Organization/Services/IAliyunClient.cs b/Src/Dlhis.Basic/Organization/Services/IAliyunClient.cs
new file mode 100644
index 00000000..3ee539f4
--- /dev/null
+++ b/Src/Dlhis.Basic/Organization/Services/IAliyunClient.cs
@@ -0,0 +1,218 @@
+using System.Security.Cryptography;
+using System.Text;
+using Dlhis.Basic.Organization.Response;
+using Kurisu.AspNetCore.CustomClass;
+using Newtonsoft.Json;
+
+namespace Dlhis.Basic.Organization.Services;
+
+public interface IAliyunClient : IScopeDependency
+{
+ Task Id3MetaVerifyAsync(
+ string identifyNum,
+ string userName,
+ string faceBase64,
+ string crop = "F");
+}
+
+public class AliyunClient : IAliyunClient
+{
+ private readonly IHttpClientFactory _httpClientFactory;
+ private readonly IConfiguration _configuration;
+ private readonly string _accessKeyId;
+ private readonly string _accessKeySecret;
+
+ private const string Endpoint = "cloudauth.aliyuncs.com";
+ private const string ApiVersion = "2019-03-07";
+
+ public AliyunClient(IHttpClientFactory httpClientFactory, IConfiguration configuration, ILogger logger)
+ {
+ _httpClientFactory = httpClientFactory;
+ _configuration = configuration;
+ }
+
+ public AliyunClient(string accessKeyId, string accessKeySecret)
+ {
+ _accessKeyId = accessKeyId ?? "LTAI5tAqyWKcBcSvzpc1ZM72";
+ _accessKeySecret = accessKeySecret ?? "YZMSqsmMGlGZuHw5WU2tqt0mmIBX6h";
+ }
+
+ ///
+ /// 使用 Base64 图片进行三要素核验
+ ///
+ public async Task Id3MetaVerifyAsync(
+ string identifyNum,
+ string userName,
+ string faceBase64,
+ string crop = "F")
+ {
+ var accessKeyId = _accessKeyId ?? GetRequiredConfig("AliyunOptions:AccessKeyId", "Aliyun:AccessKeyId");
+ var accessKeySecret = _accessKeySecret ?? GetRequiredConfig("AliyunOptions:AccessKeySecret", "Aliyun:AccessKeySecret");
+
+ if (faceBase64.Contains(","))
+ {
+ faceBase64 = faceBase64[(faceBase64.IndexOf(',') + 1)..];
+ }
+
+ var parameters = new SortedDictionary
+ {
+ { "Action", "Id3MetaVerify" },
+ { "Format", "JSON" },
+ { "Version", ApiVersion },
+ { "AccessKeyId", accessKeyId },
+ { "SignatureMethod", "HMAC-SHA1" },
+ { "SignatureVersion", "1.0" },
+ { "SignatureNonce", Guid.NewGuid().ToString("N") },
+ { "Timestamp", DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ") },
+ { "ParamType", "normal" },
+ { "IdentifyNum", identifyNum },
+ { "UserName", userName },
+ { "FacePicture", faceBase64 },
+ { "Crop", crop }
+ };
+
+ var signature = ComputeSignature(parameters, "POST", accessKeySecret);
+ var url = $"https://{Endpoint}/?Signature={PercentEncode(signature)}";
+ var bodyString = BuildBodyString(parameters);
+
+ using var fallbackClient = _httpClientFactory == null ? new HttpClient() : null;
+ var client = _httpClientFactory?.CreateClient() ?? fallbackClient;
+ client.DefaultRequestHeaders.Add("Host", Endpoint);
+ var content = new StringContent(bodyString, Encoding.UTF8, "application/x-www-form-urlencoded");
+ var response = await client.PostAsync(url, content);
+ var rawResponse = await response.Content.ReadAsStringAsync();
+
+ return ParseResponse(rawResponse);
+ }
+
+ private string GetRequiredConfig(params string[] keys)
+ {
+ foreach (var key in keys)
+ {
+ var value = _configuration.GetSection(key).Value;
+ if (!string.IsNullOrWhiteSpace(value))
+ {
+ return value;
+ }
+ }
+
+ throw new UserFriendlyException($"阿里云配置缺失:{string.Join("或", keys)}");
+ }
+
+ private static AliyunId3MetaVerifyResponse ParseResponse(string rawResponse)
+ {
+ var result = new AliyunId3MetaVerifyResponse
+ {
+ RawResponse = rawResponse
+ };
+
+ if (string.IsNullOrWhiteSpace(rawResponse))
+ {
+ return result;
+ }
+
+ try
+ {
+ var response = JsonConvert.DeserializeObject(rawResponse);
+ result.RequestId = response?.RequestId;
+ result.Code = response?.Code;
+ result.Message = response?.Message;
+ result.BizCode = response?.ResultObject?.BizCode;
+ result.Similarity = ParseVerifyScore(response?.ResultObject?.FaceDetail);
+ result.Passed = response?.ResultObject?.BizCode switch
+ {
+ "1" => true,
+ "2" or "3" => false,
+ _ => null
+ };
+ }
+ catch
+ {
+ result.Message = "阿里云响应不是合法JSON";
+ }
+
+ return result;
+ }
+
+ private static double? ParseVerifyScore(string faceDetail)
+ {
+ if (string.IsNullOrWhiteSpace(faceDetail))
+ {
+ return null;
+ }
+
+ var detail = JsonConvert.DeserializeObject(faceDetail);
+ return detail?.VerifyScore;
+ }
+
+ private static string ComputeSignature(SortedDictionary parameters, string httpMethod, string accessKeySecret)
+ {
+ var canonicalized = new StringBuilder();
+ foreach (var kv in parameters)
+ {
+ if (kv.Key == "Signature")
+ {
+ continue;
+ }
+
+ if (canonicalized.Length > 0)
+ {
+ canonicalized.Append('&');
+ }
+
+ canonicalized.Append(PercentEncode(kv.Key))
+ .Append('=')
+ .Append(PercentEncode(kv.Value));
+ }
+
+ var stringToSign = httpMethod + "&" + PercentEncode("/") + "&" + PercentEncode(canonicalized.ToString());
+ var signKey = accessKeySecret + "&";
+ using var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(signKey));
+ var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
+ return Convert.ToBase64String(hash);
+ }
+
+ private static string BuildBodyString(SortedDictionary parameters)
+ {
+ return string.Join("&", parameters
+ .Where(x => x.Key != "Signature")
+ .Select(x => PercentEncode(x.Key) + "=" + PercentEncode(x.Value)));
+ }
+
+ private static string PercentEncode(string value)
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ return string.Empty;
+ }
+
+ return Uri.EscapeDataString(value)
+ .Replace("+", "%20")
+ .Replace("*", "%2A")
+ .Replace("%7E", "~");
+ }
+
+ private class AliyunId3MetaVerifyApiResponse
+ {
+ public string RequestId { get; set; }
+
+ public string Message { get; set; }
+
+ public string Code { get; set; }
+
+ public AliyunId3MetaVerifyResultObject ResultObject { get; set; }
+ }
+
+ private class AliyunId3MetaVerifyResultObject
+ {
+ public string BizCode { get; set; }
+
+ public string FaceDetail { get; set; }
+ }
+
+ private class AliyunId3MetaVerifyFaceDetail
+ {
+ [JsonProperty("verifyScore")]
+ public double? VerifyScore { get; set; }
+ }
+}
diff --git a/Src/Dlhis.Basic/Organization/Services/IGainfoIdCardFaceCompareService.cs b/Src/Dlhis.Basic/Organization/Services/IGainfoIdCardFaceCompareService.cs
new file mode 100644
index 00000000..307860a1
--- /dev/null
+++ b/Src/Dlhis.Basic/Organization/Services/IGainfoIdCardFaceCompareService.cs
@@ -0,0 +1,22 @@
+using Dlhis.Basic.Organization.Request;
+using Dlhis.Basic.Organization.Response;
+using Kurisu.AspNetCore.DataAccess.Dto;
+
+namespace Dlhis.Basic.Organization.Services;
+
+public interface IGainfoIdCardFaceCompareService : IScopeDependency
+{
+ ///
+ /// 人证人脸对比记录分页查询
+ ///
+ /// 分页查询条件
+ /// 人证人脸对比记录分页结果
+ Task> GetPageAsync(IdCardFaceComparePageRequest request);
+
+ ///
+ /// 执行人证人脸对比
+ ///
+ /// 人证人脸对比请求
+ /// 人证人脸对比记录
+ Task CompareAsync(IdCardFaceCompareRequest request);
+}
diff --git a/Src/Dlhis.Basic/Organization/Services/Implements/GainfoIdCardFaceCompareService.cs b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoIdCardFaceCompareService.cs
new file mode 100644
index 00000000..90170693
--- /dev/null
+++ b/Src/Dlhis.Basic/Organization/Services/Implements/GainfoIdCardFaceCompareService.cs
@@ -0,0 +1,191 @@
+using Dlhis.Basic.Organization.Request;
+using Dlhis.Basic.Organization.Response;
+using Dlhis.Entity.Basic.Entity;
+using Dlhis.Entity.Basic.Enums;
+using Kurisu.AspNetCore.Authentication.Abstractions;
+using Kurisu.AspNetCore.CustomClass;
+using Kurisu.AspNetCore.DataAccess.Dto;
+using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions;
+using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
+using Kurisu.AspNetCore.Utils.Extensions;
+using SqlSugar;
+
+namespace Dlhis.Basic.Organization.Services.Implements;
+
+public class GainfoIdCardFaceCompareService : IGainfoIdCardFaceCompareService
+{
+ private readonly IDbContext _dbContext;
+ private readonly IDbContext _faceDbContext;
+ private readonly IAliyunClient _aliyunClient;
+ private readonly ICurrentUser _currentUser;
+
+ public GainfoIdCardFaceCompareService(
+ IDbContext dbContext,
+ IAliyunClient aliyunClient,
+ ICurrentUser currentUser)
+ {
+ _dbContext = dbContext;
+ _faceDbContext = dbContext.ChangeDb("face");
+ _aliyunClient = aliyunClient;
+ _currentUser = currentUser;
+ }
+
+ public async Task> GetPageAsync(IdCardFaceComparePageRequest request)
+ {
+ var factories = GetFactories(request.Factories);
+
+ return await _dbContext.Queryable()
+ .LeftJoin((record, gainfo) => record.UserCode == gainfo.Code)
+ .LeftJoin((record, gainfo, department) => gainfo.DepartmentNo == department.No)
+ .WhereIF(factories.Any(), (record, gainfo) => factories.Contains(gainfo.Factory))
+ .WhereIF(request.UserType.HasValue, record => record.UserType == request.UserType.Value)
+ .WhereIF(request.CompareResult.HasValue, record => record.CompareResult == request.CompareResult.Value)
+ .WhereIF(request.Search.IsPresent(), (record, gainfo) =>
+ record.UserCode == request.Search
+ || record.IdNo == request.Search
+ || record.UserName.Contains(request.Search)
+ || gainfo.Name.Contains(request.Search))
+ .OrderBy(record => record.CreateTime, OrderByType.Desc)
+ .Select((record, gainfo, department) => new IdCardFaceCompareRecordResponse
+ {
+ Id = record.Id,
+ UserCode = record.UserCode,
+ UserName = record.UserName,
+ UserType = record.UserType,
+ IdNo = record.IdNo,
+ DepartmentName = department.Name,
+ Factory = gainfo.Factory,
+ CompareResult = record.CompareResult,
+ IsPassed = record.IsPassed,
+ Similarity = record.Similarity,
+ CompareCount = record.CompareCount,
+ LastCompareTime = record.LastCompareTime,
+ ApiResponse = record.ApiResponse,
+ ErrorMessage = record.ErrorMessage,
+ CreateTime = record.CreateTime
+ })
+ .ToPageListAsync(request);
+ }
+
+ public async Task CompareAsync(IdCardFaceCompareRequest request)
+ {
+ var gainfo = await _dbContext.Queryable()
+ .Where(x => x.Code == request.UserCode)
+ .SingleAsync();
+ gainfo.ThrowIfNull("人员档案信息不存在");
+ gainfo.IdNo.IsPresent().ThrowIfFalse("人员证件号为空,无法对比");
+
+ var now = DateTime.Now;
+ var userId = _currentUser.GetIntSubjectId();
+ var record = await _dbContext.Queryable()
+ .Where(x => x.UserCode == gainfo.Code)
+ .SingleAsync();
+
+ if (record == null)
+ {
+ record = new IdCardFaceCompareRecordEntity
+ {
+ UserCode = gainfo.Code,
+ UserType = gainfo.Type,
+ UserName = gainfo.Name,
+ IdNo = gainfo.IdNo,
+ CompareResult = IdCardFaceCompareResultEnumType.NotCompared,
+ CompareCount = 0,
+ CreateTime = now,
+ ModifiedTime = now,
+ CreatedBy = userId,
+ ModifiedBy = userId
+ };
+
+ await _dbContext.InsertAsync(record);
+ }
+ else
+ {
+ record.UserType = gainfo.Type;
+ record.UserName = gainfo.Name;
+ record.IdNo = gainfo.IdNo;
+ record.CompareResult = IdCardFaceCompareResultEnumType.NotCompared;
+ record.ErrorMessage = null;
+ record.ModifiedTime = now;
+ record.ModifiedBy = userId;
+ await _dbContext.UpdateAsync(record);
+ }
+
+ var face = await _faceDbContext.Queryable()
+ .Where(x => x.UserCode == gainfo.Code)
+ .Select(x => x.Face)
+ .SingleAsync();
+
+ if (!face.IsPresent())
+ {
+ record.ErrorMessage = "人脸照片尚未录入";
+ record.ModifiedTime = DateTime.Now;
+ record.ModifiedBy = userId;
+ await _dbContext.UpdateAsync(record);
+ throw new UserFriendlyException(record.ErrorMessage);
+ }
+
+ try
+ {
+ var response = await _aliyunClient.Id3MetaVerifyAsync(gainfo.IdNo, gainfo.Name, face);
+ record.CompareResult = IdCardFaceCompareResultEnumType.Compared;
+ record.ApiResponse = response.RawResponse;
+ record.IsPassed = response.Passed;
+ record.Similarity = response.Similarity;
+ record.CompareCount += 1;
+ record.LastCompareTime = now;
+ record.ModifiedTime = DateTime.Now;
+ record.ModifiedBy = userId;
+ }
+ catch (Exception ex)
+ {
+ record.ErrorMessage = ex.Message;
+ record.ModifiedTime = DateTime.Now;
+ record.ModifiedBy = userId;
+ await _dbContext.UpdateAsync(record);
+ throw;
+ }
+
+ await _dbContext.UpdateAsync(record);
+
+ return await GetRecordAsync(record.Id);
+ }
+
+ private async Task GetRecordAsync(long id)
+ {
+ return await _dbContext.Queryable()
+ .LeftJoin((record, gainfo) => record.UserCode == gainfo.Code)
+ .LeftJoin((record, gainfo, department) => gainfo.DepartmentNo == department.No)
+ .Where(record => record.Id == id)
+ .Select((record, gainfo, department) => new IdCardFaceCompareRecordResponse
+ {
+ Id = record.Id,
+ UserCode = record.UserCode,
+ UserName = record.UserName,
+ UserType = record.UserType,
+ IdNo = record.IdNo,
+ DepartmentName = department.Name,
+ Factory = gainfo.Factory,
+ CompareResult = record.CompareResult,
+ IsPassed = record.IsPassed,
+ Similarity = record.Similarity,
+ CompareCount = record.CompareCount,
+ LastCompareTime = record.LastCompareTime,
+ ApiResponse = record.ApiResponse,
+ ErrorMessage = record.ErrorMessage,
+ CreateTime = record.CreateTime
+ })
+ .SingleAsync();
+ }
+
+ private List GetFactories(List requestFactories)
+ {
+ var currentFactories = _currentUser.GetUserClaim("tenants")?.Split(",").Where(x => x.IsPresent()).ToList() ?? new List();
+ if (requestFactories == null || !requestFactories.Any())
+ {
+ return currentFactories;
+ }
+
+ return requestFactories.Where(x => currentFactories.Contains(x)).ToList();
+ }
+}
diff --git a/Src/Dlhis.Entity/Basic/Entity/IdCardFaceCompareRecordEntity.cs b/Src/Dlhis.Entity/Basic/Entity/IdCardFaceCompareRecordEntity.cs
new file mode 100644
index 00000000..436021c7
--- /dev/null
+++ b/Src/Dlhis.Entity/Basic/Entity/IdCardFaceCompareRecordEntity.cs
@@ -0,0 +1,79 @@
+using Dlhis.Entity.Basic.Enums;
+using Kurisu.AspNetCore.DataAccess.SqlSugar;
+using SqlSugar;
+using SqlSugar.DbConvert;
+
+namespace Dlhis.Entity.Basic.Entity;
+
+///
+/// 人证人脸对比记录
+///
+[SugarTable(TableName = "IdCardFaceCompareRecord", TableDescription = "人证人脸对比记录表")]
+public class IdCardFaceCompareRecordEntity : SugarBaseEntity
+{
+ ///
+ /// 用户code
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "用户code", UniqueGroupNameList = new[] { "idx_IdCardFaceCompareRecord_UserCode" })]
+ public string UserCode { get; set; }
+
+ ///
+ /// 人员类型
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "人员类型", ColumnDataType = "varchar(50)", SqlParameterDbType = typeof(EnumToStringConvert))]
+ public GainfoUserTypeEnumType UserType { get; set; }
+
+ ///
+ /// 姓名
+ ///
+ [SugarColumn(IsNullable = true, ColumnDescription = "姓名")]
+ public string UserName { get; set; }
+
+ ///
+ /// 证件号
+ ///
+ [SugarColumn(IsNullable = true, ColumnDescription = "证件号", UniqueGroupNameList = new[] { "idx_IdCardFaceCompareRecord_IdNo" })]
+ public string IdNo { get; set; }
+
+ ///
+ /// 对比结果
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "对比结果", ColumnDataType = "varchar(50)", SqlParameterDbType = typeof(EnumToStringConvert))]
+ public IdCardFaceCompareResultEnumType CompareResult { get; set; }
+
+ ///
+ /// api响应结果
+ ///
+ [SugarColumn(IsNullable = true, ColumnDescription = "api响应结果", ColumnDataType = "longtext")]
+ public string ApiResponse { get; set; }
+
+ ///
+ /// 是否通过
+ ///
+ [SugarColumn(IsNullable = true, ColumnDescription = "是否通过", ColumnDataType = "bit")]
+ public bool? IsPassed { get; set; }
+
+ ///
+ /// 相似度
+ ///
+ [SugarColumn(IsNullable = true, ColumnDescription = "相似度")]
+ public double? Similarity { get; set; }
+
+ ///
+ /// 对比次数
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "对比次数")]
+ public int CompareCount { get; set; }
+
+ ///
+ /// 最近对比时间
+ ///
+ [SugarColumn(IsNullable = true, ColumnDescription = "最近对比时间")]
+ public DateTime? LastCompareTime { get; set; }
+
+ ///
+ /// 错误消息
+ ///
+ [SugarColumn(IsNullable = true, ColumnDescription = "错误消息", ColumnDataType = "text")]
+ public string ErrorMessage { get; set; }
+}
diff --git a/Src/Dlhis.Entity/Basic/Enums/IdCardFaceCompareResultEnumType.cs b/Src/Dlhis.Entity/Basic/Enums/IdCardFaceCompareResultEnumType.cs
new file mode 100644
index 00000000..9e624c91
--- /dev/null
+++ b/Src/Dlhis.Entity/Basic/Enums/IdCardFaceCompareResultEnumType.cs
@@ -0,0 +1,22 @@
+using System.ComponentModel;
+
+namespace Dlhis.Entity.Basic.Enums;
+
+///
+/// 人证人脸对比结果
+///
+[Description("人证人脸对比结果")]
+public enum IdCardFaceCompareResultEnumType
+{
+ ///
+ /// 未对比
+ ///
+ [Description("未对比")]
+ NotCompared = 0,
+
+ ///
+ /// 已对比
+ ///
+ [Description("已对比")]
+ Compared = 1
+}