using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; using Microsoft.AspNetCore.Hosting; using OpenAuth.Repository.Domain; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace OpenAuth.App.Common { public class MiWordHelper { public string GenerateSeizureDocumentWord(MiSeizureDocument mr, IWebHostEnvironment env) { string templatePath = Path.Combine(env.ContentRootPath, "Templates", "扣押财物决定书.docx"); if (!File.Exists(templatePath)) throw new FileNotFoundException("模板文件不存在", templatePath); string fileName = $"扣押财物决定书_{mr.Id}.docx"; string uploadDir = Path.Combine(env.ContentRootPath, "upload"); if (!Directory.Exists(uploadDir)) Directory.CreateDirectory(uploadDir); string outputPath = Path.Combine(uploadDir, fileName); File.Copy(templatePath, outputPath, true); using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(outputPath, true)) { Body body = wordDoc.MainDocumentPart.Document.Body; ReplacePlaceholders(body, mr); wordDoc.MainDocumentPart.Document.Save(); } return $"/upload/{fileName}"; } private void ReplacePlaceholders(Body body, MiSeizureDocument mr) { // 准备替换值 string party = mr.Party ?? ""; string clueLocation = mr.ClueLocation ?? ""; string violationType = mr.ViolationType ?? ""; string year = mr.Year ?? DateTime.Now.Year.ToString(); string serialNumber = mr.SerialNumber.ToString(); int month = mr.SeizureDate?.Month ?? 0; int day = mr.SeizureDate?.Day ?? 0; string monthStr = month > 0 ? month.ToString() : ""; string dayStr = day > 0 ? day.ToString() : ""; var paragraphs = body.Elements().ToList(); for (int i = 0; i < paragraphs.Count; i++) { Paragraph para = paragraphs[i]; string paraText = para.InnerText; // 处理物品列表占位符 {{Items}} if (paraText.Contains("{{Items}}")) { // 获取原段落属性(用于复制样式) ParagraphProperties paraProps = para.ParagraphProperties != null ? (ParagraphProperties)para.ParagraphProperties.CloneNode(true) : null; // 获取原Run属性(如下划线) RunProperties runProps = null; Run firstRun = para.Elements().FirstOrDefault(); if (firstRun?.RunProperties != null) { runProps = (RunProperties)firstRun.RunProperties.CloneNode(true); } // 移除原段落 para.Remove(); // 生成新列表项段落,插入到当前位置 InsertItemsParagraphs(body, i, mr.Items, paraProps, runProps); // 重新开始循环(因为段落集合已变) ReplacePlaceholders(body, mr); return; } // 处理普通占位符替换 foreach (var run in para.Elements()) { Text text = run.Elements().FirstOrDefault(); if (text == null) continue; string original = text.Text; string replaced = original .Replace("{{Party}}", party) .Replace("{{ClueLocation}}", clueLocation) .Replace("{{Year}}", year) .Replace("{{Month}}", monthStr) .Replace("{{Day}}", dayStr) .Replace("{{SerialNumber}}", serialNumber) .Replace("[ViolationType]", violationType); // 方括号形式 if (original != replaced) text.Text = replaced; } } } private void InsertItemsParagraphs(Body body, int insertIndex, string itemsStr, ParagraphProperties templateParaProps, RunProperties templateRunProps) { string[] items = itemsStr.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < items.Length; i++) { string itemText = $"{i + 1}、 {items[i].Trim()}"; Paragraph newPara = new Paragraph(); // 应用模板段落属性 if (templateParaProps != null) newPara.ParagraphProperties = (ParagraphProperties)templateParaProps.CloneNode(true); Run newRun = new Run(); // 应用模板Run属性(如下划线) if (templateRunProps != null) newRun.RunProperties = (RunProperties)templateRunProps.CloneNode(true); newRun.AppendChild(new Text(itemText)); newPara.AppendChild(newRun); // 在指定索引插入 body.InsertAt(newPara, insertIndex + i); } } } }