diff --git a/SimpleAdmin.Application/Services/Onboarding/ContractSnapshot/OnboardingContractSnapshotService.cs b/SimpleAdmin.Application/Services/Onboarding/ContractSnapshot/OnboardingContractSnapshotService.cs index ec54839..a4611f6 100644 --- a/SimpleAdmin.Application/Services/Onboarding/ContractSnapshot/OnboardingContractSnapshotService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/ContractSnapshot/OnboardingContractSnapshotService.cs @@ -63,13 +63,29 @@ public class OnboardingContractSnapshotService : IOnboardingContractSnapshotServ }; }).ToList(); + // 仅当参与合同渲染的变量编码或变量值发生变化时,才作废已生成文件。 + // 重复保存完全相同的员工资料不应导致员工刚查看的合同突然失效。 + var snapshotChanged = oldRows.Count != rows.Count + || rows.Any(row => + { + var old = oldRows.FirstOrDefault(item => + item.VariableCode == row.VariableCode); + return old == null + || !string.Equals( + old.VariableValue, + row.VariableValue, + StringComparison.Ordinal); + }); + await _db.Deleteable() .Where(item => item.TaskContractId == contract.Id) .ExecuteCommandAsync(); if (rows.Count > 0) await _db.Insertable(rows).ExecuteCommandAsync(); - if (invalidateGeneratedPreview && task.TaskStatus is OnboardingTaskStatus.PendingFill or OnboardingTaskStatus.Rejected) + if (invalidateGeneratedPreview + && snapshotChanged + && task.TaskStatus is OnboardingTaskStatus.PendingFill or OnboardingTaskStatus.Rejected) { contract.GeneratedDocxFileId = null; contract.GeneratedPdfFileId = null; @@ -204,4 +220,4 @@ public class OnboardingContractSnapshotService : IOnboardingContractSnapshotServ _ => sourceField }; } -} \ No newline at end of file +} diff --git a/SimpleAdmin.Application/Services/Onboarding/PublicTask/OnboardingPublicTaskService.cs b/SimpleAdmin.Application/Services/Onboarding/PublicTask/OnboardingPublicTaskService.cs index 60b94ff..dc449e4 100644 --- a/SimpleAdmin.Application/Services/Onboarding/PublicTask/OnboardingPublicTaskService.cs +++ b/SimpleAdmin.Application/Services/Onboarding/PublicTask/OnboardingPublicTaskService.cs @@ -213,10 +213,16 @@ public class OnboardingPublicTaskService : IOnboardingPublicTaskService var contract = await _db.Queryable() .FirstAsync(item => item.Id == input.TaskContractId && item.TaskId == link.TaskId) ?? throw Oops.Bah("合同不存在"); - var fileId = contract.GeneratedDocxFileId - ?? throw Oops.Bah("合同尚未准备完成,请刷新页面后重试"); + var fileId = contract.GeneratedDocxFileId; + if (!fileId.HasValue) + { + // 下载入口增加服务端兜底,避免前端状态与数据库短暂不同步时打开 JSON 错误页。 + var prepared = await PrepareContract(input); + fileId = prepared.FileId; + } + var fileExists = await _db.Queryable() - .AnyAsync(item => item.Id == fileId); + .AnyAsync(item => item.Id == fileId.Value); if (!fileExists) throw Oops.Bah("合同文件不存在,请重新准备合同"); @@ -227,7 +233,7 @@ public class OnboardingPublicTaskService : IOnboardingPublicTaskService await _db.Updateable(contract) .UpdateColumns(item => new { item.ReadAt, item.ContractStatus }) .ExecuteCommandAsync(); - return fileId; + return fileId.Value; } ///