电子签基础功能

This commit is contained in:
fuenmao
2026-09-07 16:17:49 +08:00
parent 384eaff444
commit da777327f5
31 changed files with 3992 additions and 61 deletions
@@ -0,0 +1,64 @@
namespace SimpleAdmin.Application;
/// <summary>
/// 电子签流程中的合同文件映射,一条任务合同对应一个契约锁文档。
/// </summary>
[SugarTable("ob_electronic_sign_document", TableDescription = "入职电子签文档")]
[Tenant(SqlSugarConst.DB_DEFAULT)]
public class ObElectronicSignDocument : BaseEntity
{
/// <summary>
/// 所属电子签流程 Id。
/// </summary>
public long SignProcessId { get; set; }
/// <summary>
/// 对应的入职任务合同 Id。
/// </summary>
public long TaskContractId { get; set; }
/// <summary>
/// 契约锁文档 Id。
/// </summary>
public string ProviderDocumentId { get; set; }
/// <summary>
/// 发起签署时冻结的文档名称。
/// </summary>
public string DocumentName { get; set; }
/// <summary>
/// 文档在同一签署流程中的顺序。
/// </summary>
public int DocumentSort { get; set; }
/// <summary>
/// 上传契约锁的原始 DOCX 系统文件 Id。
/// </summary>
public long OriginalDocxFileId { get; set; }
/// <summary>
/// 签署完成后归档的 PDF 系统文件 Id。
/// </summary>
public long? SignedPdfFileId { get; set; }
/// <summary>
/// 员工签名关键字快照。
/// </summary>
public string EmployeeSignKeyword { get; set; }
/// <summary>
/// 企业盖章关键字快照。
/// </summary>
public string CompanySealKeyword { get; set; }
/// <summary>
/// 契约锁员工签署动作 Id。
/// </summary>
public string EmployeeActionId { get; set; }
/// <summary>
/// 契约锁企业盖章动作 Id。
/// </summary>
public string CompanyActionId { get; set; }
}
@@ -0,0 +1,55 @@
namespace SimpleAdmin.Application;
/// <summary>
/// 契约锁回调与主动同步事件,用于幂等处理和完整审计。
/// </summary>
[SugarTable("ob_electronic_sign_event", TableDescription = "入职电子签事件")]
[Tenant(SqlSugarConst.DB_DEFAULT)]
public class ObElectronicSignEvent : BaseEntity
{
/// <summary>
/// 所属电子签流程 Id;无法识别流程的异常回调可为空。
/// </summary>
public long? SignProcessId { get; set; }
/// <summary>
/// 回调内容 SHA-256,用于识别完全重复的通知。
/// </summary>
public string PayloadHash { get; set; }
/// <summary>
/// 事件来源,例如 callback 或 manual_sync。
/// </summary>
public string EventSource { get; set; }
/// <summary>
/// 契约锁回调事件类型。
/// </summary>
public string EventType { get; set; }
/// <summary>
/// 回调携带或主动查询得到的契约锁状态。
/// </summary>
public string ProviderStatus { get; set; }
/// <summary>
/// 契约锁原始请求内容,保留用于审计排查。
/// </summary>
[SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString, IsNullable = true)]
public string PayloadJson { get; set; }
/// <summary>
/// 本次事件处理结果。
/// </summary>
public string ProcessResult { get; set; }
/// <summary>
/// 接收到事件的时间。
/// </summary>
public DateTime ReceivedAt { get; set; }
/// <summary>
/// 事件处理完成时间。
/// </summary>
public DateTime? ProcessedAt { get; set; }
}
@@ -0,0 +1,162 @@
namespace SimpleAdmin.Application;
/// <summary>
/// 入职任务的一次电子签流程,一次流程可以包含多份合同文件。
/// </summary>
[SugarTable("ob_electronic_sign_process", TableDescription = "入职电子签流程")]
[Tenant(SqlSugarConst.DB_DEFAULT)]
public class ObElectronicSignProcess : BaseEntity
{
/// <summary>
/// 所属入职任务 Id。
/// </summary>
public long TaskId { get; set; }
/// <summary>
/// 审核通过后生成的正式员工 Id。
/// </summary>
public long EmployeeId { get; set; }
/// <summary>
/// 电子签服务商编码。
/// </summary>
public string Provider { get; set; } = ElectronicSignProvider.Qiyuesuo;
/// <summary>
/// 本系统生成的幂等业务编号。
/// </summary>
public string BizId { get; set; }
/// <summary>
/// 是否为该入职任务当前使用的电子签流程。
/// 历史流程保存为空,当前流程保存为 true,并通过数据库唯一索引防止重复发起。
/// </summary>
public bool? IsCurrent { get; set; } = true;
/// <summary>
/// 契约锁合同流程 Id。
/// </summary>
public string ProviderContractId { get; set; }
/// <summary>
/// 契约锁业务分类 Id 快照。
/// </summary>
public string CategoryId { get; set; }
/// <summary>
/// 契约锁企业印章 Id 快照。
/// </summary>
public string SealId { get; set; }
/// <summary>
/// 电子签流程标题。
/// </summary>
public string Subject { get; set; }
/// <summary>
/// 员工姓名快照。
/// </summary>
public string EmployeeName { get; set; }
/// <summary>
/// 员工手机号码快照。
/// </summary>
public string EmployeeMobile { get; set; }
/// <summary>
/// 员工身份证号码快照,仅用于锁定本次电子签署人的实名信息。
/// </summary>
public string EmployeeIdCardNumber { get; set; }
/// <summary>
/// 契约锁合同创建人姓名快照。
/// </summary>
public string CreatorName { get; set; }
/// <summary>
/// 契约锁合同创建人手机号快照。
/// </summary>
public string CreatorMobile { get; set; }
/// <summary>
/// 本系统电子签状态。
/// </summary>
public string SignStatus { get; set; } = ElectronicSignStatus.Creating;
/// <summary>
/// 契约锁返回的原始合同状态。
/// </summary>
public string ProviderStatus { get; set; }
/// <summary>
/// 员工签署页面地址。
/// </summary>
[SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString, IsNullable = true)]
public string SignUrl { get; set; }
/// <summary>
/// 员工签署页面地址到期时间。
/// </summary>
public DateTime? SignUrlExpireAt { get; set; }
/// <summary>
/// 管理员点击发起电子签的时间。
/// </summary>
public DateTime StartedAt { get; set; }
/// <summary>
/// 合同流程正式发送的时间。
/// </summary>
public DateTime? SentAt { get; set; }
/// <summary>
/// 所有签署方完成签署的时间。
/// </summary>
public DateTime? CompletedAt { get; set; }
/// <summary>
/// 签署文件与签署日志保存到 OSS 的时间。
/// </summary>
public DateTime? ArchivedAt { get; set; }
/// <summary>
/// 契约锁完整归档 ZIP 在系统文件表中的 Id。
/// </summary>
public long? ArchiveFileId { get; set; }
/// <summary>
/// 最后一次主动查询契约锁状态的时间。
/// </summary>
public DateTime? LastSyncedAt { get; set; }
/// <summary>
/// 最后一次收到契约锁回调的时间。
/// </summary>
public DateTime? LastCallbackAt { get; set; }
/// <summary>
/// 最近一次失败原因,供管理员排查和重试。
/// </summary>
[SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString, IsNullable = true)]
public string LastError { get; set; }
/// <summary>
/// 创建或同步失败后的重试次数。
/// </summary>
public int RetryCount { get; set; }
/// <summary>
/// 管理员重新发起本任务电子签时填写的原因。
/// </summary>
public string ReissueReason { get; set; }
/// <summary>
/// 当前流程被新流程替代的时间。
/// </summary>
public DateTime? ReissuedAt { get; set; }
/// <summary>
/// 替代当前流程的新电子签流程 Id。
/// </summary>
public long? ReissuedByProcessId { get; set; }
}
@@ -128,12 +128,89 @@ public static class TaskContractStatus
/// </summary>
public const string OfflinePendingSign = "offline_pending_sign";
/// <summary>
/// 已发起第三方电子签,等待员工签署或企业盖章。
/// </summary>
public const string ElectronicSigning = "electronic_signing";
/// <summary>
/// 第三方电子签已完成,签署文件正在或已经归档。
/// </summary>
public const string ElectronicSigned = "electronic_signed";
/// <summary>
/// 已归档,任务流程结束且历史数据只读。
/// </summary>
public const string Archived = "archived";
}
/// <summary>
/// 电子签服务商。
/// </summary>
public static class ElectronicSignProvider
{
/// <summary>
/// 契约锁开放平台。
/// </summary>
public const string Qiyuesuo = "qiyuesuo";
}
/// <summary>
/// 入职电子签流程状态。
/// </summary>
public static class ElectronicSignStatus
{
/// <summary>
/// 正在调用第三方创建流程。
/// </summary>
public const string Creating = "creating";
/// <summary>
/// 已创建草稿,尚未成功发送。
/// </summary>
public const string Draft = "draft";
/// <summary>
/// 已发送,等待员工签署。
/// </summary>
public const string PendingEmployeeSign = "pending_employee_sign";
/// <summary>
/// 员工已签,等待企业自动盖章或平台完成流程。
/// </summary>
public const string PendingCompanySeal = "pending_company_seal";
/// <summary>
/// 所有签署已完成,等待文件归档。
/// </summary>
public const string Completed = "completed";
/// <summary>
/// 签署文件和签署日志已经归档。
/// </summary>
public const string Archived = "archived";
/// <summary>
/// 流程被拒签。
/// </summary>
public const string Rejected = "rejected";
/// <summary>
/// 流程已作废。
/// </summary>
public const string Invalid = "invalid";
/// <summary>
/// 流程已过期。
/// </summary>
public const string Expired = "expired";
/// <summary>
/// 创建、发送、同步或归档失败,可由管理员重试。
/// </summary>
public const string Failed = "failed";
}
/// <summary>
/// 合同变量类型。
/// </summary>