feixian_weifajianguan/OpenAuth.App/Common/MiWordHelper.cs

200 lines
8.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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}";
}
/// <summary>
/// 替换物品列表部分
/// </summary>
private void ReplaceItemsList(Body body, string itemsStr)
{
var paragraphs = body.Elements<Paragraph>().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<Run>().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<Paragraph>().ToList();
if (startIdx <= currentParas.Count)
body.InsertAt(newPara, startIdx + i);
else
body.AppendChild(newPara);
}
}
/// <summary>
/// 替换文档中的占位符
/// </summary>
private void ReplacePlaceholders(Body body, MiSeizureDocument mr)
{
string dateStr = mr.SeizureDate?.ToString("yyyy年MM月dd日") ?? " 年 月 日";
foreach (var para in body.Elements<Paragraph>())
{
// 处理日期占位符(单独的“年 月 日”段落)
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<Run>())
{
Text text = run.Elements<Text>().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;
}
}
}
}
}