1
This commit is contained in:
+97
@@ -0,0 +1,97 @@
|
||||
namespace SimpleAdmin.Application;
|
||||
|
||||
public class OnboardingContractDocumentService : IOnboardingContractDocumentService
|
||||
{
|
||||
private readonly ISqlSugarClient _db;
|
||||
private readonly IFileService _fileService;
|
||||
|
||||
public OnboardingContractDocumentService(ISqlSugarClient db, IFileService fileService)
|
||||
{
|
||||
_db = db;
|
||||
_fileService = fileService;
|
||||
}
|
||||
|
||||
public async Task<long> Generate(OnboardingGenerateContractInput input)
|
||||
{
|
||||
var contract = await _db.Queryable<ObTaskContract>().InSingleAsync(input.TaskContractId)
|
||||
?? throw Oops.Bah("任务合同不存在");
|
||||
var task = await _db.Queryable<ObOnboardingTask>().InSingleAsync(contract.TaskId)
|
||||
?? throw Oops.Bah("入职任务不存在");
|
||||
|
||||
if (task.TaskStatus != OnboardingTaskStatus.Approved)
|
||||
throw Oops.Bah("仅审核通过的任务可生成归档合同");
|
||||
|
||||
if (contract.GeneratedDocxFileId.HasValue)
|
||||
return contract.GeneratedDocxFileId.Value;
|
||||
|
||||
var version = await _db.Queryable<ObContractTemplateVersion>().InSingleAsync(contract.TemplateVersionId)
|
||||
?? throw Oops.Bah("合同版本不存在");
|
||||
var source = await _db.Queryable<SysFile>().InSingleAsync(version.SourceDocxFileId)
|
||||
?? throw Oops.Bah("合同源文件不存在");
|
||||
var variables = await _db.Queryable<ObTaskContractVariable>()
|
||||
.Where(x => x.TaskContractId == contract.Id)
|
||||
.ToListAsync();
|
||||
var sourceResult = await _fileService.Download(new BaseIdInput { Id = source.Id })
|
||||
?? throw Oops.Bah("无法读取合同源文件");
|
||||
|
||||
await using var sourceStream = sourceResult.FileStream;
|
||||
using var sourceBytes = new MemoryStream();
|
||||
await sourceStream.CopyToAsync(sourceBytes);
|
||||
|
||||
var rendered = ReplaceDocxText(
|
||||
sourceBytes.ToArray(),
|
||||
variables.ToDictionary(x => x.VariableCode, x => x.VariableValue ?? string.Empty));
|
||||
var name = $"{task.TaskNo}_{contract.ContractName}.docx";
|
||||
var fileId = await _fileService.StoreGeneratedFile(source.Engine, name, rendered);
|
||||
|
||||
contract.GeneratedDocxFileId = fileId;
|
||||
contract.GeneratedAt = DateTime.Now;
|
||||
await _db.Updateable(contract).ExecuteCommandAsync();
|
||||
|
||||
return fileId;
|
||||
}
|
||||
|
||||
private static byte[] ReplaceDocxText(byte[] docx, Dictionary<string, string> values)
|
||||
{
|
||||
using var input = new MemoryStream(docx);
|
||||
using var archive = new global::System.IO.Compression.ZipArchive(
|
||||
input,
|
||||
global::System.IO.Compression.ZipArchiveMode.Read);
|
||||
using var output = new MemoryStream();
|
||||
using var target = new global::System.IO.Compression.ZipArchive(
|
||||
output,
|
||||
global::System.IO.Compression.ZipArchiveMode.Create,
|
||||
true);
|
||||
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
var next = target.CreateEntry(entry.FullName, global::System.IO.Compression.CompressionLevel.Optimal);
|
||||
using var reader = entry.Open();
|
||||
using var writer = next.Open();
|
||||
|
||||
var isWordTextXml = entry.FullName == "word/document.xml"
|
||||
|| ((entry.FullName.StartsWith("word/header") || entry.FullName.StartsWith("word/footer"))
|
||||
&& entry.FullName.EndsWith(".xml"));
|
||||
if (!isWordTextXml)
|
||||
{
|
||||
reader.CopyTo(writer);
|
||||
continue;
|
||||
}
|
||||
|
||||
using var textReader = new StreamReader(reader);
|
||||
var document = global::System.Xml.Linq.XDocument.Parse(textReader.ReadToEnd());
|
||||
var word = global::System.Xml.Linq.XNamespace.Get("http://schemas.openxmlformats.org/wordprocessingml/2006/main");
|
||||
|
||||
foreach (var node in document.Descendants(word + "t"))
|
||||
{
|
||||
foreach (var item in values)
|
||||
node.Value = node.Value.Replace("{{" + item.Key + "}}", item.Value ?? string.Empty);
|
||||
}
|
||||
|
||||
using var textWriter = new StreamWriter(writer);
|
||||
textWriter.Write(document.ToString(global::System.Xml.Linq.SaveOptions.DisableFormatting));
|
||||
}
|
||||
|
||||
return output.ToArray();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user