using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; using DocumentFormat.OpenXml.Drawing.Wordprocessing; using Furion.DependencyInjection; namespace YD_Event.Core.Certificate { /// /// DOCX模板处理器 /// public class DocxTemplateProcessor : ITransient { private const string PlaceholderPattern = @"\{\{([^}]+)\}\}"; /// /// 处理DOCX模板,替换占位符 /// /// 模板文件流 /// 数据字典 /// 二维码数据字典 /// 处理后的文件流 public Stream ProcessTemplate(Stream templateStream, Dictionary data, Dictionary qrCodeData = null) { var outputStream = new MemoryStream(); // 复制模板到输出流 templateStream.Position = 0; templateStream.CopyTo(outputStream); outputStream.Position = 0; using (var document = WordprocessingDocument.Open(outputStream, true)) { var body = document.MainDocumentPart?.Document?.Body; if (body == null) return outputStream; // 处理段落中的占位符 ProcessParagraphs(body, data, qrCodeData); // 处理表格中的占位符 ProcessTables(body, data, qrCodeData); // 处理页眉页脚中的占位符 ProcessHeaderFooter(document, data, qrCodeData); document.Save(); } outputStream.Position = 0; return outputStream; } /// /// 处理段落中的占位符 /// private void ProcessParagraphs(Body body, Dictionary data, Dictionary qrCodeData) { foreach (var paragraph in body.Elements()) { ProcessParagraph(paragraph, data, qrCodeData); } } /// /// 处理单个段落 /// private void ProcessParagraph(Paragraph paragraph, Dictionary data, Dictionary qrCodeData) { var runs = paragraph.Elements().ToList(); foreach (var run in runs) { var texts = run.Elements().ToList(); foreach (var text in texts) { var processedText = ReplacePlaceholders(text.Text, data, qrCodeData); // 检查是否是二维码占位符 if (IsQRCodePlaceholder(text.Text)) { var placeholder = ExtractPlaceholderKey(text.Text); if (qrCodeData != null && qrCodeData.ContainsKey(placeholder)) { // 替换为二维码图片 ReplaceTextWithQRCode(run, qrCodeData[placeholder]); } else { text.Text = processedText; } } else { text.Text = processedText; } } } } /// /// 处理表格中的占位符 /// private void ProcessTables(Body body, Dictionary data, Dictionary qrCodeData) { foreach (var table in body.Elements()) { foreach (var row in table.Elements()) { foreach (var cell in row.Elements()) { foreach (var paragraph in cell.Elements()) { ProcessParagraph(paragraph, data, qrCodeData); } } } } } /// /// 处理页眉页脚中的占位符 /// private void ProcessHeaderFooter(WordprocessingDocument document, Dictionary data, Dictionary qrCodeData) { // 暂时跳过页眉页脚处理,因为API兼容性问题 // 实际项目中需要根据具体的DocumentFormat.OpenXml版本调整 } /// /// 替换文本中的占位符 /// private string ReplacePlaceholders(string text, Dictionary data, Dictionary qrCodeData) { if (string.IsNullOrWhiteSpace(text)) return text; return Regex.Replace(text, PlaceholderPattern, match => { var key = match.Groups[1].Value.Trim(); // 优先使用二维码数据 if (qrCodeData != null && qrCodeData.ContainsKey(key)) { return qrCodeData[key]; } // 使用普通数据 if (data != null && data.ContainsKey(key)) { return data[key] ?? string.Empty; } // 返回原始占位符(未找到数据) return match.Value; }); } /// /// 检查是否是二维码占位符 /// private bool IsQRCodePlaceholder(string text) { if (string.IsNullOrWhiteSpace(text)) return false; var match = Regex.Match(text, PlaceholderPattern); if (!match.Success) return false; var key = match.Groups[1].Value.Trim().ToLowerInvariant(); return key.Contains("qr") || key.Contains("qrcode"); } /// /// 提取占位符键名 /// private string ExtractPlaceholderKey(string text) { var match = Regex.Match(text, PlaceholderPattern); return match.Success ? match.Groups[1].Value.Trim() : string.Empty; } /// /// 将文本替换为二维码图片 /// private void ReplaceTextWithQRCode(Run run, string qrCodeContent) { // 注意:这里需要实现二维码图片生成和插入逻辑 // 由于DocumentFormat.OpenXml处理图片比较复杂,这里先简化处理 // 实际实现需要使用QRCodeService生成图片,然后插入到文档中 // 临时实现:用文本替代 var texts = run.Elements().ToList(); foreach (var text in texts) { text.Text = $"[QR: {qrCodeContent}]"; } } /// /// 验证数据完整性 /// /// 必填占位符列表 /// 数据字典 /// 验证结果 public TemplateValidationResult ValidateTemplateData(List requiredPlaceholders, Dictionary data) { var result = new TemplateValidationResult { IsValid = true }; foreach (var placeholder in requiredPlaceholders) { if (!data.ContainsKey(placeholder) || string.IsNullOrWhiteSpace(data[placeholder])) { result.IsValid = false; result.MissingPlaceholders.Add(placeholder); } } return result; } } /// /// 模板验证结果 /// public class TemplateValidationResult { public bool IsValid { get; set; } public List MissingPlaceholders { get; set; } = new List(); public List Warnings { get; set; } = new List(); } }