2026-03-07 15:16:34 +08:00
|
|
|
|
using DocumentFormat.OpenXml;
|
|
|
|
|
|
using DocumentFormat.OpenXml.Packaging;
|
2026-03-06 11:38:05 +08:00
|
|
|
|
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
|
|
|
|
|
|
{
|
2026-03-07 15:16:34 +08:00
|
|
|
|
#region
|
2026-03-06 11:38:05 +08:00
|
|
|
|
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();
|
2026-03-07 15:16:34 +08:00
|
|
|
|
string serialNumber = mr.SerialNumber.ToString("D3");
|
2026-03-06 16:57:19 +08:00
|
|
|
|
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-07 15:16:34 +08:00
|
|
|
|
ParagraphProperties paraProps = para.ParagraphProperties?.CloneNode(true) as ParagraphProperties;
|
|
|
|
|
|
|
|
|
|
|
|
var runs = para.Elements<Run>().ToList();
|
|
|
|
|
|
RunProperties indexRunProps = null; // 序号部分的样式
|
|
|
|
|
|
RunProperties contentRunProps = null; // 内容部分的样式
|
|
|
|
|
|
|
|
|
|
|
|
// 找到包含 "{{Items}}" 的 Run 作为内容 Run
|
|
|
|
|
|
Run contentRun = runs.FirstOrDefault(r => r.InnerText.Contains("{{Items}}"));
|
|
|
|
|
|
if (contentRun?.RunProperties != null)
|
|
|
|
|
|
contentRunProps = contentRun.RunProperties.CloneNode(true) as RunProperties;
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-07 15:16:34 +08:00
|
|
|
|
// 取第一个 Run 作为序号 Run(假设序号在最前面)
|
|
|
|
|
|
Run indexRun = runs.FirstOrDefault();
|
|
|
|
|
|
if (indexRun != null && indexRun != contentRun && indexRun.RunProperties != null)
|
|
|
|
|
|
indexRunProps = indexRun.RunProperties.CloneNode(true) as RunProperties;
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-07 15:16:34 +08:00
|
|
|
|
para.Remove();
|
|
|
|
|
|
InsertItemsParagraphs(body, i, mr.Items, paraProps, indexRunProps, contentRunProps);
|
|
|
|
|
|
ReplacePlaceholders(body, mr); // 重新开始循环
|
2026-03-06 16:57:19 +08:00
|
|
|
|
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)
|
2026-03-07 15:16:34 +08:00
|
|
|
|
.Replace("{{ViolationType}}", violationType); // 方括号形式
|
2026-03-06 16:57:19 +08:00
|
|
|
|
|
|
|
|
|
|
if (original != replaced)
|
|
|
|
|
|
text.Text = replaced;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void InsertItemsParagraphs(Body body, int insertIndex, string itemsStr,
|
2026-03-07 15:16:34 +08:00
|
|
|
|
ParagraphProperties templateParaProps,
|
|
|
|
|
|
RunProperties indexRunProps,
|
|
|
|
|
|
RunProperties contentRunProps)
|
2026-03-06 16:57:19 +08:00
|
|
|
|
{
|
|
|
|
|
|
string[] items = itemsStr.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < items.Length; i++)
|
|
|
|
|
|
{
|
2026-03-07 15:16:34 +08:00
|
|
|
|
string indexText = $"{i + 1}、 ";
|
|
|
|
|
|
string rawContent = items[i].Trim();
|
|
|
|
|
|
int leadingSpaces = 6;
|
|
|
|
|
|
int trailingSpaces = 30 - leadingSpaces - rawContent.Length;
|
|
|
|
|
|
if (trailingSpaces < 0) trailingSpaces = 0;
|
|
|
|
|
|
string contentText = new string(' ', leadingSpaces) + rawContent + new string(' ', trailingSpaces);
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-06 16:57:19 +08:00
|
|
|
|
Paragraph newPara = new Paragraph();
|
|
|
|
|
|
if (templateParaProps != null)
|
|
|
|
|
|
newPara.ParagraphProperties = (ParagraphProperties)templateParaProps.CloneNode(true);
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-07 15:16:34 +08:00
|
|
|
|
// 序号 Run(移除可能的下划线)
|
|
|
|
|
|
Run indexRun = new Run();
|
|
|
|
|
|
if (indexRunProps != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
indexRun.RunProperties = (RunProperties)indexRunProps.CloneNode(true);
|
|
|
|
|
|
if (indexRun.RunProperties.Underline != null)
|
|
|
|
|
|
indexRun.RunProperties.Underline.Remove();
|
|
|
|
|
|
}
|
|
|
|
|
|
// 关键:设置 Space 为 Preserve 以保留空格
|
|
|
|
|
|
indexRun.AppendChild(new Text(indexText) { Space = SpaceProcessingModeValues.Preserve });
|
|
|
|
|
|
newPara.AppendChild(indexRun);
|
2026-03-06 11:38:05 +08:00
|
|
|
|
|
2026-03-07 15:16:34 +08:00
|
|
|
|
// 内容 Run(强制黑色下划线)
|
|
|
|
|
|
Run contentRun = new Run();
|
|
|
|
|
|
if (contentRunProps != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
contentRun.RunProperties = (RunProperties)contentRunProps.CloneNode(true);
|
|
|
|
|
|
if (contentRun.RunProperties.Color == null)
|
|
|
|
|
|
contentRun.RunProperties.Color = new Color() { Val = "000000" };
|
|
|
|
|
|
else
|
|
|
|
|
|
contentRun.RunProperties.Color.Val = "000000";
|
|
|
|
|
|
if (contentRun.RunProperties.Underline == null)
|
|
|
|
|
|
contentRun.RunProperties.Underline = new Underline() { Val = UnderlineValues.Single };
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
contentRun.RunProperties = new RunProperties();
|
|
|
|
|
|
contentRun.RunProperties.Underline = new Underline() { Val = UnderlineValues.Single };
|
|
|
|
|
|
contentRun.RunProperties.Color = new Color() { Val = "000000" };
|
|
|
|
|
|
}
|
|
|
|
|
|
// 关键:设置 Space 为 Preserve 以保留前后空格
|
|
|
|
|
|
contentRun.AppendChild(new Text(contentText) { Space = SpaceProcessingModeValues.Preserve });
|
|
|
|
|
|
newPara.AppendChild(contentRun);
|
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
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-07 15:16:34 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
#region 解除扣押
|
|
|
|
|
|
public string GenerateReleaseDocumentWord(MiReleaseDocument rd, IWebHostEnvironment env)
|
|
|
|
|
|
{
|
|
|
|
|
|
string templatePath = Path.Combine(env.ContentRootPath, "Templates", "解除扣押决定书.docx");
|
|
|
|
|
|
if (!File.Exists(templatePath))
|
|
|
|
|
|
throw new FileNotFoundException("模板文件不存在", templatePath);
|
|
|
|
|
|
|
|
|
|
|
|
string fileName = $"解除扣押决定书_{rd.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;
|
|
|
|
|
|
ReplacePlaceholdersForRelease(body, rd);
|
|
|
|
|
|
wordDoc.MainDocumentPart.Document.Save();
|
|
|
|
|
|
}
|
|
|
|
|
|
return $"/upload/{fileName}";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ReplacePlaceholdersForRelease(Body body, MiReleaseDocument rd)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 准备替换值
|
|
|
|
|
|
string party = rd.Party ?? "";
|
|
|
|
|
|
string clueLocation = rd.ClueLocation ?? "";
|
|
|
|
|
|
string violationType = rd.ViolationType ?? "";
|
|
|
|
|
|
string year = rd.Year ?? DateTime.Now.Year.ToString();
|
|
|
|
|
|
string serialNumber = rd.SerialNumber.ToString("D3");
|
|
|
|
|
|
|
|
|
|
|
|
// 解除扣押决定日期(落款)
|
|
|
|
|
|
int rYear = rd.ReleaseDate?.Year ?? 0;
|
|
|
|
|
|
int rMonth = rd.ReleaseDate?.Month ?? 0;
|
|
|
|
|
|
int rDay = rd.ReleaseDate?.Day ?? 0;
|
|
|
|
|
|
string rYearStr = rYear > 0 ? rYear.ToString() : "";
|
|
|
|
|
|
string rMonthStr = rMonth > 0 ? rMonth.ToString() : "";
|
|
|
|
|
|
string rDayStr = rDay > 0 ? rDay.ToString() : "";
|
|
|
|
|
|
|
|
|
|
|
|
// 领取截止日期
|
|
|
|
|
|
int pYear = rd.PickupDeadline?.Year ?? 0;
|
|
|
|
|
|
int pMonth = rd.PickupDeadline?.Month ?? 0;
|
|
|
|
|
|
int pDay = rd.PickupDeadline?.Day ?? 0;
|
|
|
|
|
|
string pYearStr = pYear > 0 ? pYear.ToString() : "";
|
|
|
|
|
|
string pMonthStr = pMonth > 0 ? pMonth.ToString() : "";
|
|
|
|
|
|
string pDayStr = pDay > 0 ? pDay.ToString() : "";
|
|
|
|
|
|
|
|
|
|
|
|
// 扣押财物日期(来自实体类 SeizureData)
|
|
|
|
|
|
int fYear = rd.SeizureData?.Year ?? 0;
|
|
|
|
|
|
int fMonth = rd.SeizureData?.Month ?? 0;
|
|
|
|
|
|
int fDay = rd.SeizureData?.Day ?? 0;
|
|
|
|
|
|
string fYearStr = fYear > 0 ? fYear.ToString() : "";
|
|
|
|
|
|
string fMonthStr = fMonth > 0 ? fMonth.ToString() : "";
|
|
|
|
|
|
string fDayStr = fDay > 0 ? fDay.ToString() : "";
|
|
|
|
|
|
|
|
|
|
|
|
string parkingLot = rd.ParkingLot ?? "";
|
|
|
|
|
|
|
|
|
|
|
|
var paragraphs = body.Elements<Paragraph>().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?.CloneNode(true) as ParagraphProperties;
|
|
|
|
|
|
|
|
|
|
|
|
var runs = para.Elements<Run>().ToList();
|
|
|
|
|
|
RunProperties indexRunProps = null;
|
|
|
|
|
|
RunProperties contentRunProps = null;
|
|
|
|
|
|
|
|
|
|
|
|
// 找到包含 "{{Items}}" 的 Run 作为内容 Run
|
|
|
|
|
|
Run contentRun = runs.FirstOrDefault(r => r.InnerText.Contains("{{Items}}"));
|
|
|
|
|
|
if (contentRun?.RunProperties != null)
|
|
|
|
|
|
contentRunProps = contentRun.RunProperties.CloneNode(true) as RunProperties;
|
|
|
|
|
|
|
|
|
|
|
|
// 取第一个 Run 作为序号 Run(假设序号在最前面)
|
|
|
|
|
|
Run indexRun = runs.FirstOrDefault();
|
|
|
|
|
|
if (indexRun != null && indexRun != contentRun && indexRun.RunProperties != null)
|
|
|
|
|
|
indexRunProps = indexRun.RunProperties.CloneNode(true) as RunProperties;
|
|
|
|
|
|
|
|
|
|
|
|
para.Remove();
|
|
|
|
|
|
InsertItemsParagraphs(body, i, rd.Items, paraProps, indexRunProps, contentRunProps);
|
|
|
|
|
|
ReplacePlaceholdersForRelease(body, rd); // 重新开始循环
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理普通占位符替换
|
|
|
|
|
|
foreach (var run in para.Elements<Run>())
|
|
|
|
|
|
{
|
|
|
|
|
|
Text text = run.Elements<Text>().FirstOrDefault();
|
|
|
|
|
|
if (text == null) continue;
|
|
|
|
|
|
|
|
|
|
|
|
string original = text.Text;
|
|
|
|
|
|
string replaced = original
|
|
|
|
|
|
.Replace("{{Year}}", year) // 文书编号年份
|
|
|
|
|
|
.Replace("{{SerialNumber}}", serialNumber)
|
|
|
|
|
|
.Replace("{{Paty}}", party) // 注意模板拼写为 Paty
|
|
|
|
|
|
.Replace("{{ClueLocation}}", clueLocation)
|
|
|
|
|
|
.Replace("{{ViolationType}}", violationType)
|
|
|
|
|
|
.Replace("{{FYear}}", fYearStr)
|
|
|
|
|
|
.Replace("{{FMonth}}", fMonthStr)
|
|
|
|
|
|
.Replace("{{FDay}}", fDayStr)
|
|
|
|
|
|
.Replace("{{PYear}}", pYearStr)
|
|
|
|
|
|
.Replace("{{Pmonth}}", pMonthStr) // 注意大小写
|
|
|
|
|
|
.Replace("{{Pday}}", pDayStr)
|
|
|
|
|
|
.Replace("{{ParkingLot}}", parkingLot)
|
|
|
|
|
|
.Replace("{{Month}}", rMonthStr) // 落款月份
|
|
|
|
|
|
.Replace("{{Day}}", rDayStr); // 落款日
|
|
|
|
|
|
|
|
|
|
|
|
if (original != replaced)
|
|
|
|
|
|
text.Text = replaced;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//private void InsertItemsParagraphs(Body body, int insertIndex, string itemsStr,
|
|
|
|
|
|
// ParagraphProperties templateParaProps,
|
|
|
|
|
|
// RunProperties indexRunProps,
|
|
|
|
|
|
// RunProperties contentRunProps)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// string[] items = itemsStr.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
|
|
|
|
|
|
|
// for (int i = 0; i < items.Length; i++)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// string indexText = $"{i + 1}、 ";
|
|
|
|
|
|
// string rawContent = items[i].Trim();
|
|
|
|
|
|
// int leadingSpaces = 6;
|
|
|
|
|
|
// int trailingSpaces = 30 - leadingSpaces - rawContent.Length;
|
|
|
|
|
|
// if (trailingSpaces < 0) trailingSpaces = 0;
|
|
|
|
|
|
// string contentText = new string(' ', leadingSpaces) + rawContent + new string(' ', trailingSpaces);
|
|
|
|
|
|
|
|
|
|
|
|
// Paragraph newPara = new Paragraph();
|
|
|
|
|
|
// if (templateParaProps != null)
|
|
|
|
|
|
// newPara.ParagraphProperties = (ParagraphProperties)templateParaProps.CloneNode(true);
|
|
|
|
|
|
|
|
|
|
|
|
// // 序号 Run(移除可能的下划线)
|
|
|
|
|
|
// Run indexRun = new Run();
|
|
|
|
|
|
// if (indexRunProps != null)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// indexRun.RunProperties = (RunProperties)indexRunProps.CloneNode(true);
|
|
|
|
|
|
// if (indexRun.RunProperties.Underline != null)
|
|
|
|
|
|
// indexRun.RunProperties.Underline.Remove();
|
|
|
|
|
|
// }
|
|
|
|
|
|
// // 关键:设置 Space 为 Preserve 以保留空格
|
|
|
|
|
|
// indexRun.AppendChild(new Text(indexText) { Space = SpaceProcessingModeValues.Preserve });
|
|
|
|
|
|
// newPara.AppendChild(indexRun);
|
|
|
|
|
|
|
|
|
|
|
|
// // 内容 Run(强制黑色下划线)
|
|
|
|
|
|
// Run contentRun = new Run();
|
|
|
|
|
|
// if (contentRunProps != null)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// contentRun.RunProperties = (RunProperties)contentRunProps.CloneNode(true);
|
|
|
|
|
|
// if (contentRun.RunProperties.Color == null)
|
|
|
|
|
|
// contentRun.RunProperties.Color = new Color() { Val = "000000" };
|
|
|
|
|
|
// else
|
|
|
|
|
|
// contentRun.RunProperties.Color.Val = "000000";
|
|
|
|
|
|
// if (contentRun.RunProperties.Underline == null)
|
|
|
|
|
|
// contentRun.RunProperties.Underline = new Underline() { Val = UnderlineValues.Single };
|
|
|
|
|
|
// }
|
|
|
|
|
|
// else
|
|
|
|
|
|
// {
|
|
|
|
|
|
// contentRun.RunProperties = new RunProperties();
|
|
|
|
|
|
// contentRun.RunProperties.Underline = new Underline() { Val = UnderlineValues.Single };
|
|
|
|
|
|
// contentRun.RunProperties.Color = new Color() { Val = "000000" };
|
|
|
|
|
|
// }
|
|
|
|
|
|
// // 关键:设置 Space 为 Preserve 以保留前后空格
|
|
|
|
|
|
// contentRun.AppendChild(new Text(contentText) { Space = SpaceProcessingModeValues.Preserve });
|
|
|
|
|
|
// newPara.AppendChild(contentRun);
|
|
|
|
|
|
|
|
|
|
|
|
// body.InsertAt(newPara, insertIndex + i);
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
#endregion
|
2026-03-06 11:38:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|