修复文件模版占位符错误问题
This commit is contained in:
@@ -35,6 +35,7 @@ public static class DocxTemplateProcessor
|
||||
foreach (var paragraph in document.Descendants(WordNamespace + "p"))
|
||||
{
|
||||
var text = string.Concat(paragraph.Descendants(WordNamespace + "t").Select(node => node.Value));
|
||||
ValidatePlaceholderSyntax(text);
|
||||
foreach (global::System.Text.RegularExpressions.Match match in PlaceholderRegex.Matches(text))
|
||||
codes.Add(match.Groups["code"].Value.Trim());
|
||||
}
|
||||
@@ -52,6 +53,72 @@ public static class DocxTemplateProcessor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 占位符提取正则只会匹配正确格式,因此必须先主动检查错误格式,
|
||||
/// 避免缺少花括号或变量编码写错时被静默忽略并继续创建版本。
|
||||
/// </summary>
|
||||
private static void ValidatePlaceholderSyntax(string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
return;
|
||||
|
||||
if (text.Contains("{{", StringComparison.Ordinal)
|
||||
|| text.Contains("}}", StringComparison.Ordinal))
|
||||
{
|
||||
throw Oops.Bah(
|
||||
"DOCX 占位符格式错误:检测到中文全角花括号。请使用英文半角双花括号,例如 {{employee.EmployeeName}}。");
|
||||
}
|
||||
|
||||
if (text.Contains("{{{", StringComparison.Ordinal)
|
||||
|| text.Contains("}}}", StringComparison.Ordinal))
|
||||
{
|
||||
throw Oops.Bah(
|
||||
"DOCX 占位符格式错误:检测到多余的花括号。占位符必须使用成对的英文半角双花括号,例如 {{employee.EmployeeName}}。");
|
||||
}
|
||||
|
||||
var searchStart = 0;
|
||||
while (searchStart < text.Length)
|
||||
{
|
||||
var openIndex = text.IndexOf("{{", searchStart, StringComparison.Ordinal);
|
||||
var closeIndex = text.IndexOf("}}", searchStart, StringComparison.Ordinal);
|
||||
|
||||
if (closeIndex >= 0 && (openIndex < 0 || closeIndex < openIndex))
|
||||
{
|
||||
throw Oops.Bah(
|
||||
$"DOCX 占位符格式错误:{BuildPlaceholderPreview(text, closeIndex)} 缺少对应的起始符“{{{{”。正确格式示例:{{{{employee.EmployeeName}}}}。");
|
||||
}
|
||||
|
||||
if (openIndex < 0)
|
||||
return;
|
||||
|
||||
closeIndex = text.IndexOf("}}", openIndex + 2, StringComparison.Ordinal);
|
||||
if (closeIndex < 0)
|
||||
{
|
||||
throw Oops.Bah(
|
||||
$"DOCX 占位符格式错误:{BuildPlaceholderPreview(text, openIndex)} 缺少结束符“}}}}”。正确格式示例:{{{{employee.EmployeeName}}}}。");
|
||||
}
|
||||
|
||||
var placeholder = text.Substring(openIndex, closeIndex + 2 - openIndex);
|
||||
var match = PlaceholderRegex.Match(placeholder);
|
||||
if (!match.Success || match.Length != placeholder.Length)
|
||||
{
|
||||
throw Oops.Bah(
|
||||
$"DOCX 占位符格式错误:“{placeholder}”。变量编码只能包含英文字母、数字、下划线、点和短横线,并且必须使用成对的英文半角双花括号。");
|
||||
}
|
||||
|
||||
searchStart = closeIndex + 2;
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildPlaceholderPreview(string text, int markerIndex)
|
||||
{
|
||||
const int maxLength = 60;
|
||||
var preview = text[markerIndex..].Trim();
|
||||
if (preview.Length > maxLength)
|
||||
preview = preview[..maxLength] + "…";
|
||||
return $"“{preview}”";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用任务变量快照替换 DOCX 中的占位符,支持占位符跨多个 Word 文本节点。
|
||||
/// </summary>
|
||||
|
||||
+5
@@ -37,6 +37,11 @@ public class OnboardingContractTemplateController
|
||||
if (!string.Equals(suffix, ".docx", StringComparison.OrdinalIgnoreCase))
|
||||
throw Oops.Bah("合同模板仅支持 DOCX 文件");
|
||||
|
||||
await using var input = file.OpenReadStream();
|
||||
using var bytes = new MemoryStream();
|
||||
await input.CopyToAsync(bytes);
|
||||
DocxTemplateProcessor.ExtractVariableCodes(bytes.ToArray());
|
||||
|
||||
return await _fileService.UploadFile(SysDictConst.FILE_ENGINE_ALIYUN_OSS, file);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user