2026-03-06 11:38:05 +08:00
|
|
|
|
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))
|
|
|
|
|
|
{
|
2026-03-06 16:57:19 +08:00
|
|
|
|
Body body = wordDoc.MainDocumentPart.Document.Body;
|
2026-03-06 11:38:05 +08:00
|
|
|
|
ReplacePlaceholders(body, mr);
|
2026-03-06 16:57:19 +08:00
|
|
|
|
wordDoc.MainDocumentPart.Document.Save();
|
2026-03-06 11:38:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
return $"/upload/{fileName}";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
private void ReplacePlaceholders(Body body, MiSeizureDocument mr)
|
2026-03-06 11:38:05 +08:00
|
|
|
|
{
|
2026-03-06 16:57:19 +08:00
|
|
|
|
// 准备替换值
|
|
|
|
|
|
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() : "";
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
var paragraphs = body.Elements<Paragraph>().ToList();
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < paragraphs.Count; i++)
|
|
|
|
|
|
{
|
2026-03-06 16:57:19 +08:00
|
|
|
|
Paragraph para = paragraphs[i];
|
|
|
|
|
|
string paraText = para.InnerText;
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
// 处理物品列表占位符 {{Items}}
|
|
|
|
|
|
if (paraText.Contains("{{Items}}"))
|
2026-03-06 11:38:05 +08:00
|
|
|
|
{
|
2026-03-06 16:57:19 +08:00
|
|
|
|
// 获取原段落属性(用于复制样式)
|
|
|
|
|
|
ParagraphProperties paraProps = para.ParagraphProperties != null
|
|
|
|
|
|
? (ParagraphProperties)para.ParagraphProperties.CloneNode(true)
|
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
|
|
// 获取原Run属性(如下划线)
|
|
|
|
|
|
RunProperties runProps = null;
|
|
|
|
|
|
Run firstRun = para.Elements<Run>().FirstOrDefault();
|
|
|
|
|
|
if (firstRun?.RunProperties != null)
|
2026-03-06 11:38:05 +08:00
|
|
|
|
{
|
2026-03-06 16:57:19 +08:00
|
|
|
|
runProps = (RunProperties)firstRun.RunProperties.CloneNode(true);
|
2026-03-06 11:38:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
// 移除原段落
|
|
|
|
|
|
para.Remove();
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
// 生成新列表项段落,插入到当前位置
|
|
|
|
|
|
InsertItemsParagraphs(body, i, mr.Items, paraProps, runProps);
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
// 重新开始循环(因为段落集合已变)
|
|
|
|
|
|
ReplacePlaceholders(body, mr);
|
|
|
|
|
|
return;
|
2026-03-06 11:38:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
// 处理普通占位符替换
|
2026-03-06 11:38:05 +08:00
|
|
|
|
foreach (var run in para.Elements<Run>())
|
|
|
|
|
|
{
|
|
|
|
|
|
Text text = run.Elements<Text>().FirstOrDefault();
|
|
|
|
|
|
if (text == null) continue;
|
|
|
|
|
|
|
|
|
|
|
|
string original = text.Text;
|
2026-03-06 16:57:19 +08:00
|
|
|
|
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()}";
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
Paragraph newPara = new Paragraph();
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
// 应用模板段落属性
|
|
|
|
|
|
if (templateParaProps != null)
|
|
|
|
|
|
newPara.ParagraphProperties = (ParagraphProperties)templateParaProps.CloneNode(true);
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
Run newRun = new Run();
|
|
|
|
|
|
// 应用模板Run属性(如下划线)
|
|
|
|
|
|
if (templateRunProps != null)
|
|
|
|
|
|
newRun.RunProperties = (RunProperties)templateRunProps.CloneNode(true);
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
newRun.AppendChild(new Text(itemText));
|
|
|
|
|
|
newPara.AppendChild(newRun);
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
// 在指定索引插入
|
|
|
|
|
|
body.InsertAt(newPara, insertIndex + i);
|
2026-03-06 11:38:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|