169 lines
5.9 KiB
C#
169 lines
5.9 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text.RegularExpressions;
|
||
using DocumentFormat.OpenXml.Packaging;
|
||
using DocumentFormat.OpenXml.Wordprocessing;
|
||
using Furion.DependencyInjection;
|
||
|
||
namespace YD_Event.Core.Certificate
|
||
{
|
||
/// <summary>
|
||
/// DOCX模板解析器
|
||
/// </summary>
|
||
public class DocxTemplateParser : ITransient
|
||
{
|
||
private const string PlaceholderPattern = @"\{\{([^}]+)\}\}";
|
||
|
||
/// <summary>
|
||
/// 从DOCX文件中提取占位符
|
||
/// </summary>
|
||
/// <param name="docxStream">DOCX文件流</param>
|
||
/// <returns>占位符列表</returns>
|
||
public List<string> ExtractPlaceholders(Stream docxStream)
|
||
{
|
||
var placeholders = new HashSet<string>();
|
||
|
||
using (var document = WordprocessingDocument.Open(docxStream, false))
|
||
{
|
||
var body = document.MainDocumentPart?.Document?.Body;
|
||
if (body == null) return new List<string>();
|
||
|
||
// 解析段落中的占位符
|
||
foreach (var paragraph in body.Elements<Paragraph>())
|
||
{
|
||
var text = ExtractTextFromParagraph(paragraph);
|
||
var foundPlaceholders = ExtractPlaceholdersFromText(text);
|
||
foreach (var placeholder in foundPlaceholders)
|
||
{
|
||
placeholders.Add(placeholder);
|
||
}
|
||
}
|
||
|
||
// 解析表格中的占位符
|
||
foreach (var table in body.Elements<Table>())
|
||
{
|
||
var tablePlaceholders = ExtractPlaceholdersFromTable(table);
|
||
foreach (var placeholder in tablePlaceholders)
|
||
{
|
||
placeholders.Add(placeholder);
|
||
}
|
||
}
|
||
|
||
// 解析页眉页脚中的占位符
|
||
ExtractPlaceholdersFromHeaderFooter(document, placeholders);
|
||
}
|
||
|
||
return placeholders.OrderBy(x => x).ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从文本中提取占位符
|
||
/// </summary>
|
||
/// <param name="text">文本内容</param>
|
||
/// <returns>占位符列表</returns>
|
||
private List<string> ExtractPlaceholdersFromText(string text)
|
||
{
|
||
var placeholders = new List<string>();
|
||
var matches = Regex.Matches(text, PlaceholderPattern);
|
||
|
||
foreach (Match match in matches)
|
||
{
|
||
var placeholder = match.Groups[1].Value.Trim();
|
||
if (!string.IsNullOrWhiteSpace(placeholder))
|
||
{
|
||
placeholders.Add(placeholder);
|
||
}
|
||
}
|
||
|
||
return placeholders;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从段落中提取文本
|
||
/// </summary>
|
||
/// <param name="paragraph">段落元素</param>
|
||
/// <returns>文本内容</returns>
|
||
private string ExtractTextFromParagraph(Paragraph paragraph)
|
||
{
|
||
return string.Join("", paragraph.Elements<Run>().Select(run =>
|
||
string.Join("", run.Elements<Text>().Select(text => text.Text))));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从表格中提取占位符
|
||
/// </summary>
|
||
/// <param name="table">表格元素</param>
|
||
/// <returns>占位符列表</returns>
|
||
private List<string> ExtractPlaceholdersFromTable(Table table)
|
||
{
|
||
var placeholders = new HashSet<string>();
|
||
|
||
foreach (var row in table.Elements<TableRow>())
|
||
{
|
||
foreach (var cell in row.Elements<TableCell>())
|
||
{
|
||
foreach (var paragraph in cell.Elements<Paragraph>())
|
||
{
|
||
var text = ExtractTextFromParagraph(paragraph);
|
||
var cellPlaceholders = ExtractPlaceholdersFromText(text);
|
||
foreach (var placeholder in cellPlaceholders)
|
||
{
|
||
placeholders.Add(placeholder);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return placeholders.ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从页眉页脚中提取占位符
|
||
/// </summary>
|
||
/// <param name="document">Word文档对象</param>
|
||
/// <param name="placeholders">占位符集合</param>
|
||
private void ExtractPlaceholdersFromHeaderFooter(WordprocessingDocument document, HashSet<string> placeholders)
|
||
{
|
||
// 暂时跳过页眉页脚处理,因为API兼容性问题
|
||
// 实际项目中需要根据具体的DocumentFormat.OpenXml版本调整
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证占位符格式
|
||
/// </summary>
|
||
/// <param name="placeholder">占位符</param>
|
||
/// <returns>是否有效</returns>
|
||
public bool IsValidPlaceholder(string placeholder)
|
||
{
|
||
return !string.IsNullOrWhiteSpace(placeholder) &&
|
||
Regex.IsMatch(placeholder, @"^[a-zA-Z_][a-zA-Z0-9_]*$");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取占位符类型
|
||
/// </summary>
|
||
/// <param name="placeholder">占位符</param>
|
||
/// <returns>占位符类型</returns>
|
||
public string GetPlaceholderType(string placeholder)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(placeholder))
|
||
return "Text";
|
||
|
||
var lowerPlaceholder = placeholder.ToLowerInvariant();
|
||
|
||
if (lowerPlaceholder.Contains("date") || lowerPlaceholder.Contains("time"))
|
||
return "Date";
|
||
|
||
if (lowerPlaceholder.Contains("qr") || lowerPlaceholder.Contains("qrcode"))
|
||
return "QRCode";
|
||
|
||
if (lowerPlaceholder.Contains("image") || lowerPlaceholder.Contains("img") || lowerPlaceholder.Contains("photo"))
|
||
return "Image";
|
||
|
||
return "Text";
|
||
}
|
||
}
|
||
}
|