ow
This commit is contained in:
1 parent
282d8ce583
commit
28dd3ffebd
229 files changed
+5765
-4786
No files matched your search
@@ -19,6 +19,7 @@ using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
using Image = SixLabors.ImageSharp.Image;
|
||||
@@ -1129,6 +1130,103 @@ namespace CloudBuilder.Master.Service
|
||||
repositoryFolderMap.InsertNow(map);
|
||||
}
|
||||
|
||||
[PermissionOperate(name: MasterPermissionPolicy.DmsFile, operate: Operate.Insert)]
|
||||
[UnitOfWork]
|
||||
public FamilyPersonDisplayData UploadIdCardFile()
|
||||
{
|
||||
FamilyPersonDisplayData data = new FamilyPersonDisplayData();
|
||||
|
||||
//1) 先走原有分片上传落盘(FilePath 头指定 idcard 目录)
|
||||
UploadFile();
|
||||
|
||||
//2) 取本次上传文件,server-to-server 调 OCR 识别服务(无浏览器跨域)
|
||||
var file = httpContextAccessor.HttpContext?.Request?.Form?.Files?.FirstOrDefault();
|
||||
if (file == null || file.Length <= 0) return data;
|
||||
|
||||
//文件名(xxxx-1-1.ext 分片名)与识别面:side 以普通表单字段传入,缺省取配置
|
||||
data.IdCardFilename = file.FileName;
|
||||
string side = ServiceSettingsPolicy.GetIdCardOcrSide(service);
|
||||
if (httpContextAccessor.HttpContext.Request.Form.ContainsKey("side"))
|
||||
{
|
||||
var formSide = httpContextAccessor.HttpContext.Request.Form["side"].ToString();
|
||||
if (!string.IsNullOrWhiteSpace(formSide)) side = formSide;
|
||||
}
|
||||
|
||||
string apiUrl = ServiceSettingsPolicy.GetIdCardOcrApiUrl(service);
|
||||
if (string.IsNullOrWhiteSpace(apiUrl)) return data;
|
||||
|
||||
try
|
||||
{
|
||||
using var recognizeStream = file.OpenReadStream();
|
||||
using var form = new System.Net.Http.MultipartFormDataContent();
|
||||
var fileContent = new System.Net.Http.StreamContent(recognizeStream);
|
||||
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(
|
||||
string.IsNullOrWhiteSpace(file.ContentType) ? "image/jpeg" : file.ContentType);
|
||||
form.Add(fileContent, "file", file.FileName);
|
||||
form.Add(new System.Net.Http.StringContent(side), "side");
|
||||
|
||||
using var client = new System.Net.Http.HttpClient();
|
||||
client.Timeout = TimeSpan.FromSeconds(ServiceSettingsPolicy.GetIdCardOcrTimeoutSeconds(service));
|
||||
using var response = client.PostAsync(apiUrl, form).GetAwaiter().GetResult();
|
||||
string json = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
|
||||
if (string.IsNullOrWhiteSpace(json)) return data;
|
||||
|
||||
using var doc = System.Text.Json.JsonDocument.Parse(json);
|
||||
var root = doc.RootElement;
|
||||
|
||||
//识别服务返回 { code:0, data:{... } },code!=0 视为未识别到,仅返回文件名
|
||||
int code = -1;
|
||||
if (root.TryGetProperty("code", out var codeEl) && codeEl.ValueKind == System.Text.Json.JsonValueKind.Number)
|
||||
code = codeEl.GetInt32();
|
||||
if (code != 0) return data;
|
||||
if (!root.TryGetProperty("data", out var info) || info.ValueKind != System.Text.Json.JsonValueKind.Object)
|
||||
return data;
|
||||
|
||||
string GetStr(string key)
|
||||
{
|
||||
if (info.TryGetProperty(key, out var el))
|
||||
{
|
||||
if (el.ValueKind == System.Text.Json.JsonValueKind.String) return el.GetString();
|
||||
if (el.ValueKind != System.Text.Json.JsonValueKind.Null && el.ValueKind != System.Text.Json.JsonValueKind.Undefined)
|
||||
return el.ToString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//常用名/民族/住址/身份证号/签发机关/有效期限(姓名映射到 CommonName 已在需求确认)
|
||||
data.CommonName = GetStr("name");
|
||||
data.Nation = GetStr("nation");
|
||||
data.Address = GetStr("address");
|
||||
data.IdNumber = GetStr("id_number");
|
||||
data.Issuer = GetStr("issuer");
|
||||
data.Validity = GetStr("validity");
|
||||
|
||||
//性别回传原始文本(如“男”),由前端按 GenderPolicy 匹配为策略编码,避免后端依赖运行时语言包
|
||||
data.Gender = GetStr("gender");
|
||||
|
||||
//出生日期:OCR 返回多为 yyyyMMdd,解析为 DateTime(Kind=Unspecified,避免时区偏移)
|
||||
var birth = GetStr("birth");
|
||||
if (!string.IsNullOrWhiteSpace(birth))
|
||||
{
|
||||
var digits = new string(birth.Where(char.IsDigit).ToArray());
|
||||
if (digits.Length >= 8
|
||||
&& DateTime.TryParseExact(digits.Substring(0, 8), "yyyyMMdd",
|
||||
System.Globalization.CultureInfo.InvariantCulture,
|
||||
DateTimeStyles.None, out var birthDate))
|
||||
{
|
||||
data.BirthDate = birthDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//OCR 调用失败不影响图片已上传:记录日志,返回仅含文件名的 data,前端据此提示“未识别到信息”
|
||||
Console.WriteLine($"[UploadIdCardFile] OCR recognize failed: {ex.Message}");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[PermissionOperate(name: MasterPermissionPolicy.DmsFile, operate: Operate.Insert)]
|
||||
[UnitOfWork]
|
||||
public void UploadFile()
|
||||
@@ -1386,7 +1484,7 @@ namespace CloudBuilder.Master.Service
|
||||
{
|
||||
DmsFileEntity entity = repository.DetachedEntities.Where(x => x.FileId == fileId && x.CreatedBy == service.UserId).FirstOrDefault()!;
|
||||
|
||||
return FileTypePolicy.PackSourceVideoUrl(service, entity.CreatedBy, entity.OrderKey,entity.TranscodeIndc);
|
||||
return FileTypePolicy.PackSourceVideoUrl(service, entity.CreatedBy, entity.OrderKey, entity.TranscodeIndc);
|
||||
}
|
||||
|
||||
[PermissionOperate(name: MasterPermissionPolicy.DmsFile, operate: Operate.Find)]
|
||||
@@ -1395,7 +1493,7 @@ namespace CloudBuilder.Master.Service
|
||||
IRepository<DmsFileDeleteLogEntity> repositoryDmsFileDeleteLog = repository.GetRepository<IRepository<DmsFileDeleteLogEntity>>();
|
||||
DmsFileDeleteLogEntity entity = repositoryDmsFileDeleteLog.DetachedEntities.Where(x => x.FileId == fileId && x.CreatedBy == service.UserId).FirstOrDefault()!;
|
||||
|
||||
return FileTypePolicy.PackSourceVideoUrl(service, entity.CreatedBy, entity.OrderKey,entity.TranscodeIndc);
|
||||
return FileTypePolicy.PackSourceVideoUrl(service, entity.CreatedBy, entity.OrderKey, entity.TranscodeIndc);
|
||||
}
|
||||
|
||||
private string PackParameters(DmsFileEntity dmsFile)
|
||||
@@ -1436,14 +1534,14 @@ namespace CloudBuilder.Master.Service
|
||||
}
|
||||
|
||||
para = string.Format(service.Configuration[ServiceSettingsPolicy.FfmpegArguments], mp4Url, "", fullName);
|
||||
|
||||
|
||||
IRepository<SecurityScheduleTaskQueueEntity> logRepository = repository.GetRepository<IRepository<SecurityScheduleTaskQueueEntity>>();
|
||||
SecurityScheduleTaskQueueEntity task = new SecurityScheduleTaskQueueEntity();
|
||||
|
||||
task.DocumentId = documentId;
|
||||
task.TaskId = service.Configuration[ServiceSettingsPolicy.FfmpegPath];
|
||||
task.TaskParam = para;
|
||||
|
||||
|
||||
logRepository.InsertNow(task);
|
||||
|
||||
para = string.Format(service.Configuration[ServiceSettingsPolicy.FfmpegArguments], mp4Url, " -t 10", fullName);
|
||||
|
||||
@@ -26,6 +26,28 @@ namespace CloudBuilder.Master.Data
|
||||
|
||||
public string? AvatarUrl { get; set; }
|
||||
|
||||
public bool? IsCanAmend { get; set; } = false;
|
||||
public bool? IsCanAmend { get; set; } = false;
|
||||
|
||||
// ===== 身份证 OCR 识别信息(transient 显示字段:识别后回填表单,随保存提交但不落 family_person 表) =====
|
||||
/// <summary>民族(OCR nation)</summary>
|
||||
public string? Nation { get; set; }
|
||||
|
||||
/// <summary>住址(OCR address)</summary>
|
||||
public string? Address { get; set; }
|
||||
|
||||
/// <summary>公民身份号码(OCR id_number)</summary>
|
||||
public string? IdNumber { get; set; }
|
||||
|
||||
/// <summary>签发机关(OCR issuer,仅背面)</summary>
|
||||
public string? Issuer { get; set; }
|
||||
|
||||
/// <summary>有效期限(OCR validity,仅背面)</summary>
|
||||
public string? Validity { get; set; }
|
||||
|
||||
/// <summary>身份证照片物理文件名(上传到 idcard 目录后回写,与头像 AvatarFilename 同口径)</summary>
|
||||
public string? IdCardFilename { get; set; }
|
||||
|
||||
/// <summary>身份证照片预览 URL(本地临时预览,不入库)</summary>
|
||||
public string? IdCardUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace CloudBuilder.Master.Service
|
||||
DmsFolderData FindDmsFolderData();
|
||||
void UploadFile();
|
||||
void UploadDmsFile();
|
||||
|
||||
FamilyPersonDisplayData UploadIdCardFile();
|
||||
string FindM3u8Path(long fileId);
|
||||
|
||||
string FindSourceVideoPath(long fileId);
|
||||
|
||||
@@ -103,6 +103,10 @@ return Task.Run(() => serviceRequest.PostAsJsonAsync<DmsFolderData> ("/DmsFile
|
||||
{
|
||||
Task.Run(() => serviceRequest.PostAsJsonAsync<DmsFileEntity,dynamic>("/DmsFile/MoveDmsFolder" , dmsFile)).GetAwaiter().GetResult(); }
|
||||
|
||||
public FamilyPersonDisplayData UploadIdCardFile()
|
||||
{
|
||||
return Task.Run(() => serviceRequest.PostAsJsonAsync<FamilyPersonDisplayData> ("/DmsFile/UploadIdCardFile")).GetAwaiter().GetResult(); }
|
||||
|
||||
public void UploadFile()
|
||||
{
|
||||
Task.Run(() => serviceRequest.PostAsync("/DmsFile/UploadFile")).GetAwaiter().GetResult(); }
|
||||
|
||||
@@ -24,6 +24,28 @@ namespace CloudBuilder.Security.Policy
|
||||
public const string FfmpegPictrue = "Ffmpeg:Pictrue";
|
||||
public const string FfmpegArguments = "Ffmpeg:Arguments";
|
||||
|
||||
// 身份证 OCR 识别服务(server-to-server 调用,地址来自 appsettings.json,避免写死)
|
||||
public const string IdCardOcrApiUrl = "IdCardOcr:ApiUrl";
|
||||
public const string IdCardOcrSide = "IdCardOcr:Side";
|
||||
public const string IdCardOcrTimeoutSeconds = "IdCardOcr:TimeoutSeconds";
|
||||
|
||||
public static string GetIdCardOcrApiUrl(IApplicationService service)
|
||||
{
|
||||
return service.Configuration[IdCardOcrApiUrl];
|
||||
}
|
||||
|
||||
public static string GetIdCardOcrSide(IApplicationService service)
|
||||
{
|
||||
var side = service.Configuration[IdCardOcrSide];
|
||||
return string.IsNullOrWhiteSpace(side) ? "auto" : side;
|
||||
}
|
||||
|
||||
public static int GetIdCardOcrTimeoutSeconds(IApplicationService service)
|
||||
{
|
||||
var raw = service.Configuration[IdCardOcrTimeoutSeconds];
|
||||
return int.TryParse(raw, out var seconds) && seconds > 0 ? seconds : 30;
|
||||
}
|
||||
|
||||
public static string GetPhysicalFileDirectory(IApplicationService service)
|
||||
{
|
||||
return service.Configuration[PhysicalFileDirectory];
|
||||
|
||||
@@ -430,6 +430,27 @@ this.dmsFileService= dmsFileService;
|
||||
{
|
||||
return new ServiceErrorException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
[PermissionOperate(name: "DmsFile", operate: "Insert")]
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
public dynamic UploadIdCardFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
var result = dmsFileService.UploadIdCardFile();
|
||||
return result;
|
||||
}
|
||||
catch (ValidatedException vex)
|
||||
{
|
||||
return vex;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ServiceErrorException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
[PermissionOperate(name: "DmsFile", operate: "Insert")]
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<_PublishTargetUrl>C:\inetpub\wwwroot\dockwebapi2</_PublishTargetUrl>
|
||||
<History>True|2026-09-23T05:19:13.0148919Z||;True|2026-09-23T13:16:07.8584304+08:00||;True|2026-09-22T23:03:13.6509491+08:00||;True|2026-09-22T16:07:15.9177123+08:00||;True|2026-09-22T11:19:19.6087109+08:00||;True|2026-09-22T11:09:24.9165065+08:00||;True|2026-09-21T22:40:07.1232044+08:00||;True|2026-09-21T22:35:06.9446571+08:00||;True|2026-09-21T22:27:42.1146825+08:00||;False|2026-09-21T22:27:17.6066573+08:00||;True|2026-09-21T21:01:22.8888913+08:00||;True|2026-09-21T19:15:03.4753747+08:00||;True|2026-09-21T18:08:30.0866986+08:00||;True|2026-09-21T16:51:19.8137872+08:00||;True|2026-09-21T16:30:01.0950896+08:00||;True|2026-09-21T15:09:00.2326737+08:00||;True|2026-09-21T14:47:09.6120256+08:00||;True|2026-09-21T14:16:35.3194409+08:00||;True|2026-09-21T13:54:58.2829712+08:00||;True|2026-09-21T13:36:45.3134499+08:00||;True|2026-09-19T09:48:52.0085130+08:00||;False|2026-09-19T09:47:56.1658214+08:00||;True|2026-09-17T18:50:15.9493380+08:00||;True|2026-09-17T18:11:11.5364547+08:00||;True|2026-09-17T18:07:27.7830758+08:00||;True|2026-09-17T17:58:16.5798560+08:00||;True|2026-09-17T15:37:30.9025614+08:00||;True|2026-09-17T15:25:46.9116292+08:00||;True|2026-09-17T15:05:18.6592403+08:00||;True|2026-09-17T14:57:28.7997437+08:00||;True|2026-09-17T14:36:00.6339386+08:00||;True|2026-09-17T13:56:43.2376873+08:00||;True|2026-09-16T13:56:51.8724546+08:00||;True|2026-09-15T20:44:46.6559899+08:00||;True|2026-09-13T19:02:59.5654245+08:00||;True|2026-09-10T09:14:56.2914193+08:00||;True|2026-09-09T16:40:16.6461154+08:00||;True|2026-09-08T13:55:23.1502435+08:00||;True|2026-09-08T08:04:53.4279263+08:00||;True|2026-09-07T08:48:17.4682304+08:00||;True|2026-09-04T14:39:08.7878670+08:00||;True|2026-09-04T14:35:48.2937877+08:00||;True|2026-09-04T11:45:16.1372876+08:00||;True|2026-09-04T11:42:59.9356436+08:00||;True|2026-09-03T16:05:52.5270232+08:00||;True|2026-09-03T14:52:56.8559144+08:00||;True|2026-09-02T11:08:23.8720038+08:00||;True|2026-09-02T10:58:16.8081797+08:00||;True|2026-08-26T13:34:12.3805892+08:00||;True|2026-08-25T08:31:30.7787234+08:00||;True|2026-08-20T13:10:46.4725468+08:00||;True|2026-08-20T13:10:28.3142576+08:00||;True|2026-08-19T16:10:27.3362887+08:00||;True|2026-08-19T16:01:12.6234971+08:00||;True|2026-08-19T15:42:46.6576265+08:00||;True|2026-08-19T13:39:59.9363522+08:00||;True|2026-08-19T13:36:53.0379313+08:00||;True|2026-08-19T13:31:36.0841398+08:00||;True|2026-08-19T11:44:37.5319626+08:00||;True|2026-08-19T09:36:45.6000047+08:00||;True|2026-08-19T09:34:36.8468631+08:00||;True|2026-08-19T08:35:41.2202300+08:00||;True|2026-08-18T16:20:59.0170916+08:00||;</History>
|
||||
<History>True|2026-10-17T12:49:21.0401213Z||;True|2026-09-23T13:19:13.0148919+08:00||;True|2026-09-23T13:16:07.8584304+08:00||;True|2026-09-22T23:03:13.6509491+08:00||;True|2026-09-22T16:07:15.9177123+08:00||;True|2026-09-22T11:19:19.6087109+08:00||;True|2026-09-22T11:09:24.9165065+08:00||;True|2026-09-21T22:40:07.1232044+08:00||;True|2026-09-21T22:35:06.9446571+08:00||;True|2026-09-21T22:27:42.1146825+08:00||;False|2026-09-21T22:27:17.6066573+08:00||;True|2026-09-21T21:01:22.8888913+08:00||;True|2026-09-21T19:15:03.4753747+08:00||;True|2026-09-21T18:08:30.0866986+08:00||;True|2026-09-21T16:51:19.8137872+08:00||;True|2026-09-21T16:30:01.0950896+08:00||;True|2026-09-21T15:09:00.2326737+08:00||;True|2026-09-21T14:47:09.6120256+08:00||;True|2026-09-21T14:16:35.3194409+08:00||;True|2026-09-21T13:54:58.2829712+08:00||;True|2026-09-21T13:36:45.3134499+08:00||;True|2026-09-19T09:48:52.0085130+08:00||;False|2026-09-19T09:47:56.1658214+08:00||;True|2026-09-17T18:50:15.9493380+08:00||;True|2026-09-17T18:11:11.5364547+08:00||;True|2026-09-17T18:07:27.7830758+08:00||;True|2026-09-17T17:58:16.5798560+08:00||;True|2026-09-17T15:37:30.9025614+08:00||;True|2026-09-17T15:25:46.9116292+08:00||;True|2026-09-17T15:05:18.6592403+08:00||;True|2026-09-17T14:57:28.7997437+08:00||;True|2026-09-17T14:36:00.6339386+08:00||;True|2026-09-17T13:56:43.2376873+08:00||;True|2026-09-16T13:56:51.8724546+08:00||;True|2026-09-15T20:44:46.6559899+08:00||;True|2026-09-13T19:02:59.5654245+08:00||;True|2026-09-10T09:14:56.2914193+08:00||;True|2026-09-09T16:40:16.6461154+08:00||;True|2026-09-08T13:55:23.1502435+08:00||;True|2026-09-08T08:04:53.4279263+08:00||;True|2026-09-07T08:48:17.4682304+08:00||;True|2026-09-04T14:39:08.7878670+08:00||;True|2026-09-04T14:35:48.2937877+08:00||;True|2026-09-04T11:45:16.1372876+08:00||;True|2026-09-04T11:42:59.9356436+08:00||;True|2026-09-03T16:05:52.5270232+08:00||;True|2026-09-03T14:52:56.8559144+08:00||;True|2026-09-02T11:08:23.8720038+08:00||;True|2026-09-02T10:58:16.8081797+08:00||;True|2026-08-26T13:34:12.3805892+08:00||;True|2026-08-25T08:31:30.7787234+08:00||;True|2026-08-20T13:10:46.4725468+08:00||;True|2026-08-20T13:10:28.3142576+08:00||;True|2026-08-19T16:10:27.3362887+08:00||;True|2026-08-19T16:01:12.6234971+08:00||;True|2026-08-19T15:42:46.6576265+08:00||;True|2026-08-19T13:39:59.9363522+08:00||;True|2026-08-19T13:36:53.0379313+08:00||;True|2026-08-19T13:31:36.0841398+08:00||;True|2026-08-19T11:44:37.5319626+08:00||;True|2026-08-19T09:36:45.6000047+08:00||;True|2026-08-19T09:34:36.8468631+08:00||;True|2026-08-19T08:35:41.2202300+08:00||;True|2026-08-18T16:20:59.0170916+08:00||;</History>
|
||||
<LastFailureDetails />
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -73,6 +73,11 @@
|
||||
"Pictrue": " -i {0} -ss 00:00:2.000 -frames:v 1 -vf \"scale=1280:-2\" -q:v 4 {1}", //" -i {0} -ss 00:00:2.000 -frames:v 1 {1}",
|
||||
"Arguments": "-i {0}{1} -c:v libx264 -preset veryfast -crf 26 -profile:v main -level 3.1 -vf \"scale='min(1280,iw)':-2\" -maxrate 1500k -bufsize 2400k -c:a aac -b:a 96k -ac 2 -ar 44100 -start_number 0 -hls_time 3 -hls_list_size 0 -hls_flags independent_segments -f hls {2}" //0-源路径,1-切片秒数,2-目标路径
|
||||
},
|
||||
"IdCardOcr": {
|
||||
"ApiUrl": "https://web.youjiala.com/api/v1/idcard/recognize", //身份证 OCR 识别服务(同 docker 内网,server-to-server 调用,无浏览器跨域)
|
||||
"Side": "auto", //识别面:auto/front/back
|
||||
"TimeoutSeconds": 30
|
||||
},
|
||||
"CloudBuilder.Topshelf": {
|
||||
"Path": "D:\\MAFAI\\CloudBuilder.Topshelf\\bin\\Debug\\net8.0\\CloudBuilder.Topshelf.exe" //图片压缩
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user