master
parent
f3ed210832
commit
7987906db7
|
|
@ -12,188 +12,123 @@ 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. 替换其他占位符
|
||||
Body body = wordDoc.MainDocumentPart.Document.Body;
|
||||
ReplacePlaceholders(body, mr);
|
||||
|
||||
mainPart.Document.Save();
|
||||
wordDoc.MainDocumentPart.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日") ?? " 年 月 日";
|
||||
// 准备替换值
|
||||
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() : "";
|
||||
|
||||
foreach (var para in body.Elements<Paragraph>())
|
||||
var paragraphs = body.Elements<Paragraph>().ToList();
|
||||
|
||||
for (int i = 0; i < paragraphs.Count; i++)
|
||||
{
|
||||
// 处理日期占位符(单独的“年 月 日”段落)
|
||||
string paraText = para.InnerText.Trim();
|
||||
if (paraText == "年 月 日")
|
||||
Paragraph para = paragraphs[i];
|
||||
string paraText = para.InnerText;
|
||||
|
||||
// 处理物品列表占位符 {{Items}}
|
||||
if (paraText.Contains("{{Items}}"))
|
||||
{
|
||||
// 清除原有内容
|
||||
para.RemoveAllChildren();
|
||||
// 添加新的Run
|
||||
Run run = new Run();
|
||||
run.AppendChild(new Text(dateStr));
|
||||
para.AppendChild(run);
|
||||
continue; // 已处理,跳过后续替换
|
||||
// 获取原段落属性(用于复制样式)
|
||||
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)
|
||||
{
|
||||
runProps = (RunProperties)firstRun.RunProperties.CloneNode(true);
|
||||
}
|
||||
|
||||
// 移除原段落
|
||||
para.Remove();
|
||||
|
||||
// 生成新列表项段落,插入到当前位置
|
||||
InsertItemsParagraphs(body, i, mr.Items, paraProps, runProps);
|
||||
|
||||
// 重新开始循环(因为段落集合已变)
|
||||
ReplacePlaceholders(body, mr);
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理其他占位符(遍历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;
|
||||
string replaced = original
|
||||
.Replace("{{Party}}", party)
|
||||
.Replace("{{ClueLocation}}", clueLocation)
|
||||
.Replace("{{Year}}", year)
|
||||
.Replace("{{Month}}", monthStr)
|
||||
.Replace("{{Day}}", dayStr)
|
||||
.Replace("{{SerialNumber}}", serialNumber)
|
||||
.Replace("[ViolationType]", violationType); // 方括号形式
|
||||
|
||||
// 替换 [当事人]
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,17 +92,15 @@ namespace OpenAuth.App
|
|||
.LeftJoin<MiViolationReport>((p, r) => p.ViolationReportId == r.Id)
|
||||
.LeftJoin<MiMinePoint>((p, r, m) => r.MinePointId == m.Id)
|
||||
.LeftJoin<SysUser>((p, r, m, u) => p.Initiator == u.Id.ToString())
|
||||
.LeftJoin<SysUser>((p, r, m, u, u1) => p.Reviewer == u1.Id.ToString())
|
||||
|
||||
.WhereIF(!string.IsNullOrEmpty(req.pointname), (p, r, m, u, u1) => m.Name.Contains(req.pointname))
|
||||
.WhereIF(!string.IsNullOrEmpty(req.key), (p, r, m, u, u1) => u.Name.Contains(req.key))
|
||||
.OrderByDescending((p, r, m, u, u1) => p.InitiateTime)
|
||||
.Select<dynamic>((p, r, m, u, u1) => new
|
||||
.WhereIF(!string.IsNullOrEmpty(req.pointname), (p, r, m, u) => m.Name.Contains(req.pointname))
|
||||
.WhereIF(!string.IsNullOrEmpty(req.key), (p, r, m, u) => u.Name.Contains(req.key))
|
||||
.OrderByDescending((p, r, m, u) => p.InitiateTime)
|
||||
.Select<dynamic>((p, r, m, u) => new
|
||||
{
|
||||
Id = p.Id.SelectAll(),
|
||||
InitiatorName = u.Name,
|
||||
PointName = m.Name,
|
||||
ReviewerName = u1.Name
|
||||
PointName = m.Name
|
||||
})
|
||||
.ToPageListAsync(req.page, req.limit, totalCount);
|
||||
return new Response<PageInfo<List<dynamic>>>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
费县综合行政执法局
|
||||
扣押财物决定书
|
||||
费综执扣字 [2026] 第 8 号
|
||||
张三 :
|
||||
经查,你(单位) 于兰山区柳青街道柳青街道直属测试巡检点的[ViolationType]行为
|
||||
|
||||
违反了《中华人民共和国矿产资源法》第四条的规定。本机关根据《中华人民共和国矿产资源法》第五十七条之规定,决定于 2026 年 3 月 6 日对下列物品予以扣押:
|
||||
1、 装载机*1
|
||||
2、 挖掘机*1
|
||||
|
||||
2026年 3 月 6 日
|
||||
|
||||
Loading…
Reference in New Issue