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)
{
// 模板文件路径(假设放在项目根目录的 Templates 文件夹下)
string templatePath = Path.Combine(env.ContentRootPath, "Templates", "扣押财物决定书.docx");
if (!File.Exists(templatePath))
throw new FileNotFoundException("模板文件不存在", templatePath);
// 生成文件名(使用ID保证唯一)
string fileName = $"扣押财物决定书_{mr.Id}.docx";
// 上传目录(发布文件夹下的 upload)
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);
// 使用 OpenXml 修改文档
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(outputPath, true))
{
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
Body body = mainPart.Document.Body;
// 1. 替换物品列表(先处理,避免后续替换影响索引)
ReplaceItemsList(body, mr.Items);
// 2. 替换其他占位符
ReplacePlaceholders(body, mr);
mainPart.Document.Save();
}
// 返回相对路径(用于存入数据库)
return $"/upload/{fileName}";
}
///
/// 替换物品列表部分
///
private void ReplaceItemsList(Body body, string itemsStr)
{
var paragraphs = body.Elements().ToList();
// 解析物品列表(按分号分隔)
string[] items = itemsStr.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
// 查找列表起始段落(包含 "1、" 和 "[设备及车辆类型]")
int startIdx = -1;
for (int i = 0; i < paragraphs.Count; i++)
{
string text = paragraphs[i].InnerText;
if (text.Contains("1、") && text.Contains("[设备及车辆类型]"))
{
startIdx = i;
break;
}
}
if (startIdx == -1) return; // 未找到列表区域,不处理
// 查找列表结束段落(包含 "3、" 和 "[其它设备的录入内容]")
int endIdx = startIdx;
for (int i = startIdx; i < paragraphs.Count; i++)
{
string text = paragraphs[i].InnerText;
if (text.Contains("3、") && text.Contains("[其它设备的录入内容]"))
{
endIdx = i;
break;
}
}
// 如果没找到结束,默认往后找2个段落(假设模板固定三行)
if (endIdx == startIdx)
endIdx = Math.Min(startIdx + 2, paragraphs.Count - 1);
// 移除原列表段落
for (int i = endIdx; i >= startIdx; i--)
{
paragraphs[i].Remove();
}
// 获取参考段落样式(取前一段落或后一段落的样式属性)
Paragraph refPara = null;
if (startIdx > 0)
refPara = paragraphs[startIdx - 1];
else if (startIdx < paragraphs.Count - 1)
refPara = paragraphs[startIdx + 1];
// 在起始位置插入新的列表项
for (int i = 0; i < items.Length; i++)
{
string itemText = $"{i + 1}、 {items[i].Trim()}";
Paragraph newPara = new Paragraph();
// 复制参考段落的样式(如果有)
if (refPara != null)
{
// 复制段落属性
if (refPara.ParagraphProperties != null)
newPara.ParagraphProperties = (ParagraphProperties)refPara.ParagraphProperties.CloneNode(true);
// 复制第一个Run的样式(如果有)
Run refRun = refPara.Elements().FirstOrDefault();
if (refRun != null && refRun.RunProperties != null)
{
Run newRun = new Run();
newRun.RunProperties = (RunProperties)refRun.RunProperties.CloneNode(true);
newRun.AppendChild(new Text(itemText));
newPara.AppendChild(newRun);
}
else
{
newPara.AppendChild(new Run(new Text(itemText)));
}
}
else
{
newPara.AppendChild(new Run(new Text(itemText)));
}
// 在起始索引位置插入(body.InsertAt 需要索引,但由于已经移除了原段落,现在的段落集合已变化,需要使用 body 的插入方法)
// 更简单的方法:重新获取 body 的段落列表,找到合适的插入点
var currentParas = body.Elements().ToList();
if (startIdx <= currentParas.Count)
body.InsertAt(newPara, startIdx + i);
else
body.AppendChild(newPara);
}
}
///
/// 替换文档中的占位符
///
private void ReplacePlaceholders(Body body, MiSeizureDocument mr)
{
string dateStr = mr.SeizureDate?.ToString("yyyy年MM月dd日") ?? " 年 月 日";
foreach (var para in body.Elements())
{
// 处理日期占位符(单独的“年 月 日”段落)
string paraText = para.InnerText.Trim();
if (paraText == "年 月 日")
{
// 清除原有内容
para.RemoveAllChildren();
// 添加新的Run
Run run = new Run();
run.AppendChild(new Text(dateStr));
para.AppendChild(run);
continue; // 已处理,跳过后续替换
}
// 处理其他占位符(遍历Run)
foreach (var run in para.Elements())
{
Text text = run.Elements().FirstOrDefault();
if (text == null) continue;
string original = text.Text;
string replaced = original;
// 替换 [当事人]
replaced = replaced.Replace("[当事人]", mr.Party ?? "");
// 替换 [线索位置]
replaced = replaced.Replace("[线索位置]", mr.ClueLocation ?? "");
// 替换 [违法类型]
replaced = replaced.Replace("[违法类型]", mr.ViolationType ?? "");
// 替换组合占位符 [于[线索位置]的[违法类型]行为]
string combined = $"于{mr.ClueLocation}的{mr.ViolationType}行为";
replaced = replaced.Replace("[于[线索位置]的[违法类型]行为]", combined);
// 如果文本有变化,更新
if (original != replaced)
text.Text = replaced;
}
}
}
}
}