新增员工确认信息实名认证相关信息板块

This commit is contained in:
fuenmao
2026-09-11 11:31:09 +08:00
parent 571db6fc55
commit 378bf7fe51
2 changed files with 71 additions and 4 deletions
@@ -71,4 +71,27 @@ public class OnboardingSubmitInput
/// </summary> /// </summary>
[global::System.ComponentModel.DataAnnotations.Required] [global::System.ComponentModel.DataAnnotations.Required]
public string Token { get; set; } public string Token { get; set; }
/// <summary>
/// 员工是否已在最终提交前逐项确认实名认证信息。
/// </summary>
public bool IdentityInformationConfirmed { get; set; }
/// <summary>
/// 员工最终确认的真实姓名。
/// </summary>
[global::System.ComponentModel.DataAnnotations.Required]
public string ConfirmedEmployeeName { get; set; }
/// <summary>
/// 员工最终确认的身份证号码。
/// </summary>
[global::System.ComponentModel.DataAnnotations.Required]
public string ConfirmedIdCardNumber { get; set; }
/// <summary>
/// 员工最终确认的手机号码。
/// </summary>
[global::System.ComponentModel.DataAnnotations.Required]
public string ConfirmedPhone { get; set; }
} }
@@ -127,6 +127,7 @@ public class OnboardingPublicSubmissionService : IOnboardingPublicSubmissionServ
// 最终提交必须重新执行全量校验,不能只依赖员工手机端的页面校验。 // 最终提交必须重新执行全量校验,不能只依赖员工手机端的页面校验。
OnboardingEmployeeInfoValidator.ValidateAndNormalize(info); OnboardingEmployeeInfoValidator.ValidateAndNormalize(info);
EnsureIdentityInformationConfirmed(input, info);
await _db.Updateable(info).ExecuteCommandAsync(); await _db.Updateable(info).ExecuteCommandAsync();
await _identityValidationService.EnsureNoDuplicate( await _identityValidationService.EnsureNoDuplicate(
@@ -155,9 +156,11 @@ public class OnboardingPublicSubmissionService : IOnboardingPublicSubmissionServ
if (hasUnconfirmedRequiredContract) if (hasUnconfirmedRequiredContract)
throw Oops.Bah("请查看并确认全部必签合同"); throw Oops.Bah("请查看并确认全部必签合同");
var submittedAt = DateTime.Now;
var identityConfirmationHash = BuildIdentityConfirmationHash(info);
task.TaskStatus = OnboardingTaskStatus.Reviewing; task.TaskStatus = OnboardingTaskStatus.Reviewing;
task.SubmitCount++; task.SubmitCount++;
task.LastSubmittedAt = DateTime.Now; task.LastSubmittedAt = submittedAt;
task.RejectReason = null; task.RejectReason = null;
await _db.Updateable(task).ExecuteCommandAsync(); await _db.Updateable(task).ExecuteCommandAsync();
@@ -167,9 +170,18 @@ public class OnboardingPublicSubmissionService : IOnboardingPublicSubmissionServ
TaskId = task.Id, TaskId = task.Id,
AuditRound = task.SubmitCount, AuditRound = task.SubmitCount,
AuditAction = OnboardingAuditAction.Submit, AuditAction = OnboardingAuditAction.Submit,
AuditOpinion = "员工提交入职资料", AuditOpinion = "员工提交入职资料,并确认姓名、身份证号码和手机号码用于实名认证",
SnapshotJson = global::System.Text.Json.JsonSerializer.Serialize(new { info, materials }), SnapshotJson = global::System.Text.Json.JsonSerializer.Serialize(new
AuditedAt = DateTime.Now {
info,
materials,
identityConfirmation = new
{
confirmedAt = submittedAt,
summaryHash = identityConfirmationHash
}
}),
AuditedAt = submittedAt
}).ExecuteCommandAsync(); }).ExecuteCommandAsync();
} }
@@ -214,6 +226,38 @@ public class OnboardingPublicSubmissionService : IOnboardingPublicSubmissionServ
throw Oops.Bah("该材料已达到最大上传数量"); throw Oops.Bah("该材料已达到最大上传数量");
} }
/// <summary>
/// 后端再次比较员工勾选确认时的三项实名信息,防止绕过页面或确认后数据发生变化。
/// </summary>
private static void EnsureIdentityInformationConfirmed(
OnboardingSubmitInput input,
ObTaskEmployeeInfo info)
{
if (!input.IdentityInformationConfirmed)
throw Oops.Bah("请逐项确认姓名、身份证号码和手机号码无误");
var confirmedEmployeeName = input.ConfirmedEmployeeName?.Trim();
var confirmedIdCardNumber = input.ConfirmedIdCardNumber?.Trim().ToUpperInvariant();
var confirmedPhone = input.ConfirmedPhone?.Trim();
if (!string.Equals(confirmedEmployeeName, info.EmployeeName, StringComparison.Ordinal))
throw Oops.Bah("姓名在确认后发生了变化,请返回基本信息重新核对并确认");
if (!string.Equals(confirmedIdCardNumber, info.IdCardNumber, StringComparison.Ordinal))
throw Oops.Bah("身份证号码在确认后发生了变化,请返回基本信息重新核对并确认");
if (!string.Equals(confirmedPhone, info.Phone, StringComparison.Ordinal))
throw Oops.Bah("手机号码在确认后发生了变化,请返回基本信息重新核对并确认");
}
/// <summary>
/// 审核快照只记录实名信息摘要,完整原始值仍以本轮员工信息快照为准。
/// </summary>
private static string BuildIdentityConfirmationHash(ObTaskEmployeeInfo info)
{
var value = $"{info.EmployeeName}\n{info.IdCardNumber}\n{info.Phone}";
var bytes = global::System.Text.Encoding.UTF8.GetBytes(value);
return Convert.ToHexString(global::System.Security.Cryptography.SHA256.HashData(bytes));
}
private Task<List<ObTaskMaterialRequirement>> GetMaterialRequirements(long taskId) private Task<List<ObTaskMaterialRequirement>> GetMaterialRequirements(long taskId)
{ {
return _db.Queryable<ObTaskMaterialRequirement>() return _db.Queryable<ObTaskMaterialRequirement>()