package com.njcn.gather.tools.report.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.docx4j.XmlUtils;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.DocumentSettingsPart;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.*;
import org.docx4j.wml.TcPrInner.GridSpan;
import org.docx4j.wml.TcPrInner.VMerge;
import org.docx4j.wml.CTVerticalJc;
import org.docx4j.wml.STVerticalJc;
import org.docx4j.wml.STHeightRule;

import javax.xml.bind.JAXBElement;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author hongawen
 * @version 1.0
 * @data 2025/3/26 13:47
 */
@Slf4j
public class Docx4jUtil {

    /**
     * 让 Word 打开文档时自动刷新 PAGE / NUMPAGES 等域，避免动态插表后页码显示旧值。
     */
    public static void enableUpdateFieldsOnOpen(WordprocessingMLPackage wordPackage) throws Exception {
        if (wordPackage == null || wordPackage.getMainDocumentPart() == null) {
            return;
        }
        DocumentSettingsPart settingsPart = wordPackage.getMainDocumentPart().getDocumentSettingsPart(true);
        CTSettings settings = settingsPart.getContents();
        if (settings == null) {
            settings = new CTSettings();
            settingsPart.setJaxbElement(settings);
        }
        BooleanDefaultTrue updateFields = settings.getUpdateFields();
        if (updateFields == null) {
            updateFields = new BooleanDefaultTrue();
            settings.setUpdateFields(updateFields);
        }
        updateFields.setVal(Boolean.TRUE);
    }

    /**
     * 创建标题
     *
     * @param factory   工厂
     * @param paragraph 段落容器
     * @param content   标题内容
     * @param fontSize  字体大小
     * @param isBold    是否加粗
     */
    public static void createTitle(ObjectFactory factory, P paragraph, String content, int fontSize, boolean isBold) {
        R run = factory.createR();
        Text text = factory.createText();
        text.setValue(content);
        // 创建运行属性
        RPr rPr = factory.createRPr();
        // 设置字体
        RFonts fonts = factory.createRFonts();
        fonts.setAscii("Arial");
        // 宋体
        fonts.setEastAsia("SimSun");
        rPr.setRFonts(fonts);
        // 设置字号
        HpsMeasure size = new HpsMeasure();
        // 12号字=24
        size.setVal(new BigInteger("" + fontSize));
        rPr.setSz(size);
        rPr.setSzCs(size);
        // 设置粗体
        if (isBold) {
            BooleanDefaultTrue b = new BooleanDefaultTrue();
            rPr.setB(b);
        }
        run.setRPr(rPr);
        run.getContent().add(text);
        paragraph.getContent().add(run);
    }


    /**
     * 创建标题，与上面的方法区别是本方法指定了大纲级别
     *
     * @param factory      工厂类
     * @param level        大纲级别
     * @param titleContent 标题内容
     * @param fontStyle    字体样式
     * @param size         字体大小
     * @return 段落
     */
    public static P createTitle(ObjectFactory factory, int level, String titleContent, String fontStyle, int size, boolean isBold) {
        P titleParagraph = factory.createP();
        // 设置段落属性 - 大纲级别2（标题3）
        PPr pPr = factory.createPPr();
        PPrBase.OutlineLvl outlineLvl = factory.createPPrBaseOutlineLvl();
        outlineLvl.setVal(BigInteger.valueOf(level));
        pPr.setOutlineLvl(outlineLvl);
        // 设置段落间距：段前1磅，段后1磅，行距1.5倍
        PPrBase.Spacing spacing = factory.createPPrBaseSpacing();
        // 段前间距：1磅 = 20缇（1磅=20缇）
        spacing.setBefore(BigInteger.valueOf(20));
        // 段后间距：1磅 = 20缇
        spacing.setAfter(BigInteger.valueOf(20));
        // 行间距：1.5倍 = 360（240为单倍行距，360为1.5倍）
        spacing.setLine(BigInteger.valueOf(360));
        // 行距类型设置为倍数
        spacing.setLineRule(STLineSpacingRule.AUTO);
        pPr.setSpacing(spacing);
        titleParagraph.setPPr(pPr);
        // 创建文本运行，格式为：lineNo.测量回路
        R run = factory.createR();
        // 设置字体样式：宋体、小三（16号）
        RPr rPr = factory.createRPr();
        // 设置字体为宋体
        RFonts fonts = factory.createRFonts();
        fonts.setAscii("Arial");
        fonts.setEastAsia(fontStyle);
        fonts.setHAnsi(fontStyle);
        rPr.setRFonts(fonts);
        // 设置字号为小三（15号 = 30半角）
        HpsMeasure fontSize = factory.createHpsMeasure();
        fontSize.setVal(BigInteger.valueOf(size));
        rPr.setSz(fontSize);
        rPr.setSzCs(fontSize);
        // 设置粗体
        if (isBold) {
            BooleanDefaultTrue bold = factory.createBooleanDefaultTrue();
            rPr.setB(bold);
            // 复杂脚本也设置加粗
            rPr.setBCs(bold);
        }
        run.setRPr(rPr);
        Text text = factory.createText();
        text.setValue(titleContent);
        run.getContent().add(text);
        titleParagraph.getContent().add(run);
        return titleParagraph;
    }


    /**
     * 提取文档中所有Heading 5标题及其子内容
     * <p>
     * 该方法按文档顺序遍历内容，识别Heading 5级别的标题，并收集每个标题下的所有子内容，
     * 直到遇到下一个Heading 5标题为止。
     * <p>
     * 处理逻辑：
     * 1. 遇到Heading 5时，保存前一个标题组并开始新的收集
     * 2. 在标题组内时，收集所有段落和表格等子内容（包括1-4级标题）
     * 3. 只有遇到下一个Heading 5标题时才结束当前标题组的收集
     * 4. 文档末尾时，保存最后一个标题组
     *
     * @param allContent       文档内所有内容对象的列表（包含段落、表格等）
     * @param mainDocumentPart 主文档部分，用于获取样式定义
     * @return Heading 5标题及其子内容的列表，按文档中出现的顺序排列
     */
    public static List<HeadingContent> extractHeading5Contents(List<Object> allContent, MainDocumentPart mainDocumentPart) {
        // 参数验证
        if (allContent == null || allContent.isEmpty()) {
            return new ArrayList<>();
        }
        List<HeadingContent> result = new ArrayList<>();
        // 是否正在Heading 5标题组内
        boolean inHeading5Section = false;
        // 当前正在处理的标题组
        HeadingContent currentHeading = null;
        for (Object obj : allContent) {
            if (obj instanceof P) {
                P paragraph = (P) obj;
                if (isHeading5(paragraph, mainDocumentPart)) {
                    // 发现新的Heading 5标题，保存前一个标题组并创建新的
                    if (currentHeading != null) {
                        result.add(currentHeading);
                    }
                    currentHeading = new HeadingContent();
                    currentHeading.setHeadingText(getTextFromP(paragraph));
                    inHeading5Section = true;
                } else if (inHeading5Section) {
                    // 在标题组内时，收集所有段落作为子内容（包括1-4级标题）
                    currentHeading.addSubContent(paragraph);
                }
            } else if (inHeading5Section) {
                // 在标题组内时，收集所有其他内容（表格、图片、书签等）
                currentHeading.addSubContent(obj);
            }
            // 注意：删除了isHigherLevelHeading的处理，因为需要收集5级标题间的所有内容
        }

        // 处理文档末尾：添加最后一个Heading 5标题组
        if (currentHeading != null) {
            result.add(currentHeading);
        }

        return result;
    }


    /**
     * 判断段落是否为Heading 5 - 通过样式名称判断
     *
     * @param paragraph        段落
     * @param mainDocumentPart 主文档部分
     * @return 是否为Heading 5标题
     */
    private static boolean isHeading5(P paragraph, MainDocumentPart mainDocumentPart) {
        PPr ppr = paragraph.getPPr();
        if (ppr != null) {
            PPrBase.PStyle pStyle = ppr.getPStyle();
            if (pStyle != null) {
                String styleVal = pStyle.getVal();

                try {
                    org.docx4j.openpackaging.parts.WordprocessingML.StyleDefinitionsPart stylesPart =
                            mainDocumentPart.getStyleDefinitionsPart();
                    if (stylesPart != null) {
                        org.docx4j.wml.Style style = stylesPart.getStyleById(styleVal);
                        if (style != null && style.getName() != null) {
                            String styleName = style.getName().getVal();

                            return styleName != null && (
                                    styleName.toLowerCase().contains("heading 5") ||
                                            styleName.toLowerCase().contains("标题 5") ||
                                            styleName.toLowerCase().equals("heading5") ||
                                            (styleName.toLowerCase().contains("heading") && styleName.contains("5"))
                            );
                        }
                    }
                } catch (Exception e) {
                    return false;
                }
            }
        }
        return false;
    }


    /**
     * 判断表格是否横向
     *
     * @param obj row
     */
    public static boolean judgeTableCross(Object obj) {
        Tr row = (Tr) obj;
        List<Object> content = row.getContent();
        // 取最后一个单元格，判断是否包含汉字，有汉字就是横向的
        Object cellObject = content.get(content.size() - 1);
        JAXBElement<Tc> cellElement = (JAXBElement<Tc>) cellObject;
        Tc cell = cellElement.getValue();
        String text = getTextFromCell(cell);
        if (StrUtil.isBlank(text)) {
            return true;
        }
        // 遍历字符串中的每个字符，存在中文就认为是横向的，理论上设置的key全是英文
        for (char c : text.toCharArray()) {
            // 检查字符是否在中文Unicode范围内
            if (c >= '\u4E00' && c <= '\u9FFF') {
                // 发现中文字符，返回 false
                return true;
            }
        }
        return false;
    }

    /**
     * 读取cell内的文本内容
     */
    public static String getTextFromCell(Tc cell) {
        List<Object> cellContent = cell.getContent();
        StringBuilder cellText = new StringBuilder();
        for (Object content : cellContent) {
            if (content instanceof P) {
                P paragraph = (P) content;
                cellText.append(getTextFromP(paragraph));
            }
        }
        return cellText.toString();
    }


    /**
     * 从段落中提取纯文本
     *
     * @param paragraph 段落
     * @return 段落内容
     */
    public static String getTextFromP(P paragraph) {
        StringBuilder textContent = new StringBuilder();
        for (Object runObj : paragraph.getContent()) {
            if (runObj instanceof R) {
                R run = (R) runObj;
                for (Object textObj : run.getContent()) {
                    if (textObj instanceof Text) {
                        textContent.append(((Text) textObj).getValue());
                    } else if (textObj instanceof JAXBElement) {
                        JAXBElement<?> jaxbElement = (JAXBElement<?>) textObj;
                        if (jaxbElement.getValue() instanceof Text) {
                            Text temp = (Text) jaxbElement.getValue();
                            textContent.append(temp.getValue());
                        }
                    }
                }
            }
        }
        return textContent.toString().trim();
    }

    /**
     * 获取段落的样式
     *
     * @param paragraph 段落
     */
    public static RPr getTcPrFromParagraph(P paragraph) {
        // 1. 获取段落中的所有内容
        List<Object> content = paragraph.getContent();
        // 2. 清空原有内容但保留第一个Run的样式
        RPr preservedRPr = null;
        if (!content.isEmpty()) {
            Object firstObj = content.get(0);
            if (firstObj instanceof R) {
                // 保存第一个Run的样式
                preservedRPr = ((R) firstObj).getRPr();
            }
        }
        return preservedRPr;
    }

    /**
     * 段落中添加内容
     */
    public static void addPContent(ObjectFactory factory, P paragraph, String content, RPr rPr, PPr ppr) {
        R run = factory.createR();
        Text text = factory.createText();
        text.setValue(content);
        run.setRPr(rPr);
        run.getContent().add(text);
        paragraph.getContent().add(run);
        paragraph.setPPr(ppr);
    }

    /**
     * 创建N个换行符
     */
    public static void addBr(ObjectFactory factory, P paragraph, int n) {
        R run = factory.createR();
        for (int i = 0; i < n; i++) {
            // 换行
            Br br = factory.createBr();
            run.getContent().add(br);
        }
        paragraph.getContent().add(run);
    }

    /**
     * 根据表格行获取需要填的值的key
     */
    public static List<String> getTableKey(Tr row) {
        List<String> keys = new ArrayList<>();
        // 横向的，最后一行为需要填充的数据后，前面的均是表头
        // 遍历获取出该row的所有key
        List<Object> content = row.getContent();
        for (Object cellObject : content) {
            if (cellObject instanceof JAXBElement) {
                JAXBElement<Tc> cellElement = (JAXBElement<Tc>) cellObject;
                Tc cell = cellElement.getValue();
                keys.add(Docx4jUtil.getTextFromCell(cell));
            }
        }
        return keys;
    }

    /**
     * 获取内容中需要填充的keys
     *
     * @param tempContent 标题下配置的内容
     */
    public static List<List<String>> getFillKeys(List<HeadingContent> tempContent) {
        List<List<String>> keys = new ArrayList<>();
        List<String> pKeys = new ArrayList<>();
        List<String> tableKeys = new ArrayList<>();
        if (CollUtil.isNotEmpty(tempContent)) {
            // 读取该标题下所有的内容，并准备读取出所有需替换的占位符
            Docx4jUtil.HeadingContent headingContent = tempContent.get(0);
            for (Object object : headingContent.getSubContent()) {
                if (object instanceof P) {
                    // 如果是段落，渲染段落内容
                    P paragraph = (P) object;
                    String textFromP = getTextFromP(paragraph);
                    String[] splitKeys = textFromP.split(StrPool.DASHED);
                    pKeys.addAll(Arrays.asList(splitKeys));
                } else if (object instanceof JAXBElement) {
                    // 复制表格元素
                    JAXBElement<Tbl> copiedTableElement = (JAXBElement<Tbl>) object;
                    // 解析表格并插入对应数据，最关键的是得知道表格是横向还是纵向以及表头占了几行
                    Tbl tbl = copiedTableElement.getValue();
                    // 获取表格的行
                    List<Object> rows = tbl.getContent();
                    boolean isRow = Docx4jUtil.judgeTableCross(rows.get(0));
                    if (isRow) {
                        // 获取需要填的值的key
                        List<String> cellKeys = Docx4jUtil.getTableKey((Tr) rows.get(rows.size() - 1));
                        tableKeys.addAll(cellKeys);
                    } else {
                        // 纵向表格暂不考虑
                    }
                }
            }
        }
        keys.add(pKeys);
        keys.add(tableKeys);
        return keys;

    }

    /**
     * 获取内容中表格需要填充的keys
     *
     * @param tempContent 标题下配置的内容
     */
    public static List<String> getTableFillKeys(List<HeadingContent> tempContent) {
        List<String> tableKeys = new ArrayList<>();
        if (CollUtil.isNotEmpty(tempContent)) {
            // 读取该标题下所有的内容，并准备读取出所有需替换的占位符
            Docx4jUtil.HeadingContent headingContent = tempContent.get(0);
            for (Object object : headingContent.getSubContent()) {
                if (object instanceof JAXBElement) {
                    // 复制表格元素
                    JAXBElement<Tbl> copiedTableElement = (JAXBElement<Tbl>) object;
                    // 解析表格并插入对应数据，最关键的是得知道表格是横向还是纵向以及表头占了几行
                    Tbl tbl = copiedTableElement.getValue();
                    // 获取表格的行
                    List<Object> rows = tbl.getContent();
                    boolean isRow = Docx4jUtil.judgeTableCross(rows.get(0));
                    if (isRow) {
                        // 获取需要填的值的key
                        List<String> cellKeys = Docx4jUtil.getTableKey((Tr) rows.get(rows.size() - 1));
                        tableKeys.addAll(cellKeys);
                    } else {
                        // 纵向表格暂不考虑 todo...
                    }
                }
            }
        }
        return tableKeys;

    }

    /**
     * 根据已知信息创建新行
     *
     * @param factory      工厂
     * @param valueMap     数据
     * @param tableKeys    keys
     * @param trPr         行样式
     * @param tcPrList     每个单元格的样式列表（用于保留各单元格独立的边框设置）
     * @param templateRPr  模板中的字体样式（可为null，为null时使用默认宋体10号）
     * @param centerFlag   是否居中
     */
    public static Tr createCustomRow(ObjectFactory factory, Map<String, String> valueMap, List<String> tableKeys, TrPr trPr, List<TcPr> tcPrList, RPr templateRPr, boolean centerFlag) {
        Tr row = factory.createTr();
        for (int i = 0; i < tableKeys.size(); i++) {
            String tableKey = tableKeys.get(i);
            Tc cell = factory.createTc();
            P paragraph = factory.createP();
            R run = factory.createR();
            String value = valueMap.get(tableKey);
            Text text = factory.createText();
            text.setValue(value);
            run.getContent().add(text);
            paragraph.getContent().add(run);

            // 从模板复制字体样式
            RPr rPr = factory.createRPr();
            if (templateRPr != null) {
                // 复制字体
                if (templateRPr.getRFonts() != null) {
                    RFonts rFonts = factory.createRFonts();
                    rFonts.setEastAsia(templateRPr.getRFonts().getEastAsia());
                    rFonts.setAscii(templateRPr.getRFonts().getAscii());
                    rFonts.setHAnsi(templateRPr.getRFonts().getHAnsi());
                    rPr.setRFonts(rFonts);
                }
                // 复制字号
                if (templateRPr.getSz() != null) {
                    HpsMeasure sz = factory.createHpsMeasure();
                    sz.setVal(templateRPr.getSz().getVal());
                    rPr.setSz(sz);
                }
                if (templateRPr.getSzCs() != null) {
                    HpsMeasure szCs = factory.createHpsMeasure();
                    szCs.setVal(templateRPr.getSzCs().getVal());
                    rPr.setSzCs(szCs);
                }
            } else {
                // 默认使用宋体10号
                RFonts rFonts = factory.createRFonts();
                rFonts.setEastAsia("宋体");
                rFonts.setAscii("宋体");
                rFonts.setHAnsi("宋体");
                rPr.setRFonts(rFonts);
                HpsMeasure sz = factory.createHpsMeasure();
                sz.setVal(new BigInteger("20"));
                rPr.setSz(sz);
            }

            // 设置段落居中
            if (centerFlag) {
                PPr pPr = factory.createPPr();
                Jc jc = factory.createJc();
                jc.setVal(JcEnumeration.CENTER);
                pPr.setJc(jc);
                paragraph.setPPr(pPr);
            }
            // 不合格标红
            if (value != null && value.equals("不合格")) {
                Color color = factory.createColor();
                color.setVal("FF0000");
                rPr.setColor(color);
            }
            run.setRPr(rPr);

            cell.getContent().add(paragraph);
            // 使用对应位置的单元格样式（保留边框设置）
            if (tcPrList != null && i < tcPrList.size()) {
                cell.setTcPr(tcPrList.get(i));
            }
            row.getContent().add(cell);
            row.setTrPr(trPr);
        }
        return row;
    }


    /**
     * 根据已知信息创建新行
     *
     * @param factory   工厂
     * @param valueMap  数据
     * @param tableKeys keys
     * @param trPr      行样式
     * @param tcPr      单元格样式
     */
    public static Tr createCustomRow(ObjectFactory factory, Map<String, String> valueMap, List<String> tableKeys, TrPr trPr, TcPr tcPr, boolean centerFlag) {
        Tr row = factory.createTr();
        for (String tableKey : tableKeys) {
            Tc cell = factory.createTc();
            P paragraph = factory.createP();
            R run = factory.createR();
            String value = valueMap.get(tableKey);
            Text text = factory.createText();
            text.setValue(value);
            run.getContent().add(text);
            paragraph.getContent().add(run);
            // 字体
            // 设置字体
            RPr rPr = factory.createRPr();
            RFonts rFonts = factory.createRFonts();
            if (containsChinese(value)) {
                rFonts.setEastAsia("宋体");
                rFonts.setAscii("宋体");
                rFonts.setHAnsi("宋体");
            } else {
                rFonts.setEastAsia("Arial");
                rFonts.setAscii("Arial");
                rFonts.setHAnsi("Arial");
            }
            rPr.setRFonts(rFonts);
            // 设置段落居中
            if (centerFlag) {
                PPr pPr = factory.createPPr();
                Jc jc = factory.createJc();
                jc.setVal(JcEnumeration.CENTER);
                pPr.setJc(jc);
                paragraph.setPPr(pPr);
            }
            // 根据检测结果设置颜色
            if (value != null) {
                if (value.equals("不合格") || value.equals("不符合")) {
                    Color color = factory.createColor();
                    color.setVal("FF0000"); // 红色
                    rPr.setColor(color);
                } else if (value.equals("无法比较")) {
                    Color color = factory.createColor();
                    color.setVal("E36C09"); // 橙色
                    rPr.setColor(color);
                }
            }
            run.setRPr(rPr);
            HpsMeasure sz = factory.createHpsMeasure();
            // 10号字体 = 20 half-points
            sz.setVal(new BigInteger("20"));
            rPr.setSz(sz);

            cell.getContent().add(paragraph);
            cell.setTcPr(tcPr);
            // 添加垂直居中
            addVerticalCenter(factory, cell);
            row.getContent().add(cell);
            row.setTrPr(trPr);
        }
        return row;
    }

    /**
     * 根据已知信息创建新行（支持自定义字号）
     *
     * @param factory    工厂
     * @param valueMap   数据
     * @param tableKeys  keys
     * @param trPr       行样式
     * @param tcPr       单元格样式
     * @param centerFlag 是否居中
     * @param fontSize   字号大小（half-points，五号=21）
     */
    public static Tr createCustomRow(ObjectFactory factory, Map<String, String> valueMap, List<String> tableKeys, TrPr trPr, TcPr tcPr, boolean centerFlag, int fontSize) {
        Tr row = factory.createTr();
        for (String tableKey : tableKeys) {
            Tc cell = factory.createTc();
            P paragraph = factory.createP();
            R run = factory.createR();
            String value = valueMap.get(tableKey);
            Text text = factory.createText();
            text.setValue(value);
            run.getContent().add(text);
            paragraph.getContent().add(run);
            // 字体
            // 设置字体
            RPr rPr = factory.createRPr();
            RFonts rFonts = factory.createRFonts();
            if (containsChinese(value)) {
                rFonts.setEastAsia("宋体");
                rFonts.setAscii("宋体");
                rFonts.setHAnsi("宋体");
            } else {
                rFonts.setEastAsia("Arial");
                rFonts.setAscii("Arial");
                rFonts.setHAnsi("Arial");
            }
            rPr.setRFonts(rFonts);
            // 设置段落居中和1.5倍行距
            if (centerFlag) {
                PPr pPr = factory.createPPr();
                Jc jc = factory.createJc();
                jc.setVal(JcEnumeration.CENTER);
                pPr.setJc(jc);

                // 设置1.5倍行距
                PPrBase.Spacing spacing = factory.createPPrBaseSpacing();
                spacing.setLine(BigInteger.valueOf(360)); // 360缇 = 1.5倍行距（240缇是单倍行距）
                spacing.setLineRule(STLineSpacingRule.AUTO);
                pPr.setSpacing(spacing);

                paragraph.setPPr(pPr);
            } else {
                // 即使不居中，也要设置1.5倍行距
                PPr pPr = factory.createPPr();

                // 设置1.5倍行距
                PPrBase.Spacing spacing = factory.createPPrBaseSpacing();
                spacing.setLine(BigInteger.valueOf(360)); // 360缇 = 1.5倍行距（240缇是单倍行距）
                spacing.setLineRule(STLineSpacingRule.AUTO);
                pPr.setSpacing(spacing);

                paragraph.setPPr(pPr);
            }
            // 根据检测结果设置颜色
            if (value != null) {
                if (value.equals("不合格") || value.equals("不符合")) {
                    Color color = factory.createColor();
                    color.setVal("FF0000"); // 红色
                    rPr.setColor(color);
                } else if (value.equals("无法比较")) {
                    Color color = factory.createColor();
                    color.setVal("E36C09"); // 橙色
                    rPr.setColor(color);
                }
            }
            run.setRPr(rPr);
            HpsMeasure sz = factory.createHpsMeasure();
            // 使用传入的字号参数
            sz.setVal(new BigInteger(String.valueOf(fontSize)));
            rPr.setSz(sz);

            cell.getContent().add(paragraph);
            cell.setTcPr(tcPr);
            // 添加垂直居中
            addVerticalCenter(factory, cell);
            row.getContent().add(cell);
            row.setTrPr(trPr);
        }
        return row;
    }

    /**
     * 创建谐波表格行，支持次数列的垂直合并
     *
     * @param factory      ObjectFactory实例
     * @param dataMap      数据Map
     * @param tableKeys    表格键列表
     * @param trPr         行属性
     * @param tcPr         单元格属性
     * @param isFirstPhase 是否是该次谐波的第一个相
     * @param isLastPhase  是否是该次谐波的最后一个相
     * @return 创建的表格行
     */
    public static Tr createHarmonicTableRow(ObjectFactory factory, Map<String, String> dataMap,
                                            List<String> tableKeys, TrPr trPr, TcPr tcPr,
                                            boolean isFirstPhase, boolean isLastPhase) {
        Tr row = factory.createTr();
        row.setTrPr(trPr);

        for (String tableKey : tableKeys) {
            Tc cell = factory.createTc();
            P paragraph = factory.createP();
            R run = factory.createR();
            String value = dataMap.get(tableKey);
            Text text = factory.createText();
            text.setValue(value != null ? value : "");
            run.getContent().add(text);
            paragraph.getContent().add(run);

            // 设置单元格属性
            TcPr cellPr = factory.createTcPr();
            if (tcPr != null && tcPr.getTcW() != null) {
                cellPr.setTcW(tcPr.getTcW());
            }

            // 如果是"次数"列（通常是第一列），处理垂直合并
            if (tableKey.equals("次数") || tableKey.equals("TIME") || tableKey.equals("time")) {
                if (isFirstPhase) {
                    // 第一个相：设置为合并起始单元格
                    VMerge vMerge = factory.createTcPrInnerVMerge();
                    vMerge.setVal("restart");
                    cellPr.setVMerge(vMerge);

                    // 设置垂直居中对齐
                    CTVerticalJc vAlign = factory.createCTVerticalJc();
                    vAlign.setVal(STVerticalJc.CENTER);
                    cellPr.setVAlign(vAlign);
                } else {
                    // 其他相：设置为继续合并，并清空单元格内容
                    VMerge vMerge = factory.createTcPrInnerVMerge();
                    // 不设置val属性，或设置为null，表示继续合并
                    cellPr.setVMerge(vMerge);
                    // 清空单元格内容
                    text.setValue("");
                }
            }

            // 设置居中对齐
            PPr pPr = factory.createPPr();
            Jc jc = factory.createJc();
            jc.setVal(JcEnumeration.CENTER);
            pPr.setJc(jc);
            paragraph.setPPr(pPr);

            // 设置字体
            RPr rPr = factory.createRPr();
            RFonts rFonts = factory.createRFonts();
            if (value != null && containsChinese(value)) {
                rFonts.setEastAsia("宋体");
                rFonts.setAscii("宋体");
                rFonts.setHAnsi("宋体");
            } else {
                rFonts.setEastAsia("Arial");
                rFonts.setAscii("Arial");
                rFonts.setHAnsi("Arial");
            }
            rPr.setRFonts(rFonts);

            // 设置字体大小
            HpsMeasure size = factory.createHpsMeasure();
            size.setVal(BigInteger.valueOf(20)); // 10pt = 20 half-points
            rPr.setSz(size);
            rPr.setSzCs(size);

            // 根据检测结果设置颜色
            if (value != null) {
                Color color = factory.createColor();
                if (value.equals("不合格") || value.equals("不符合")) {
                    color.setVal("FF0000"); // 红色
                    rPr.setColor(color);
                } else if (value.equals("无法比较")) {
                    color.setVal("E36C09"); // 橙色
                    rPr.setColor(color);
                }
            }

            run.setRPr(rPr);

            cell.setTcPr(cellPr);
            cell.getContent().add(paragraph);
            row.getContent().add(cell);
        }

        return row;
    }

    /**
     * 创建谐波表格行，支持次数列的垂直合并（支持自定义字号）
     *
     * @param factory      ObjectFactory实例
     * @param dataMap      数据Map
     * @param tableKeys    表格键列表
     * @param trPr         行属性
     * @param tcPr         单元格属性
     * @param isFirstPhase 是否是该次谐波的第一个相
     * @param isLastPhase  是否是该次谐波的最后一个相
     * @param fontSize     字号大小（half-points，五号=21）
     * @return 创建的表格行
     */
    public static Tr createHarmonicTableRow(ObjectFactory factory, Map<String, String> dataMap,
                                            List<String> tableKeys, TrPr trPr, TcPr tcPr,
                                            boolean isFirstPhase, boolean isLastPhase, int fontSize) {
        Tr row = factory.createTr();
        row.setTrPr(trPr);

        for (String tableKey : tableKeys) {
            Tc cell = factory.createTc();
            P paragraph = factory.createP();
            R run = factory.createR();
            String value = dataMap.get(tableKey);
            Text text = factory.createText();
            text.setValue(value != null ? value : "");
            run.getContent().add(text);
            paragraph.getContent().add(run);

            // 设置单元格属性
            TcPr cellPr = factory.createTcPr();
            if (tcPr != null && tcPr.getTcW() != null) {
                cellPr.setTcW(tcPr.getTcW());
            }

            // 如果是"次数"列（通常是第一列），处理垂直合并
            if (tableKey.equals("次数") || tableKey.equals("TIME") || tableKey.equals("time")) {
                if (isFirstPhase) {
                    // 第一个相：设置为合并起始单元格
                    VMerge vMerge = factory.createTcPrInnerVMerge();
                    vMerge.setVal("restart");
                    cellPr.setVMerge(vMerge);

                    // 设置垂直居中对齐
                    CTVerticalJc vAlign = factory.createCTVerticalJc();
                    vAlign.setVal(STVerticalJc.CENTER);
                    cellPr.setVAlign(vAlign);
                } else {
                    // 其他相：设置为继续合并，并清空单元格内容
                    VMerge vMerge = factory.createTcPrInnerVMerge();
                    // 不设置val属性，或设置为null，表示继续合并
                    cellPr.setVMerge(vMerge);
                    // 清空单元格内容
                    text.setValue("");
                }
            }

            // 设置居中对齐和1.5倍行距
            PPr pPr = factory.createPPr();
            Jc jc = factory.createJc();
            jc.setVal(JcEnumeration.CENTER);
            pPr.setJc(jc);

            // 设置1.5倍行距
            PPrBase.Spacing spacing = factory.createPPrBaseSpacing();
            spacing.setLine(BigInteger.valueOf(360)); // 360缇 = 1.5倍行距（240缇是单倍行距）
            spacing.setLineRule(STLineSpacingRule.AUTO);
            pPr.setSpacing(spacing);

            paragraph.setPPr(pPr);

            // 设置字体
            RPr rPr = factory.createRPr();
            RFonts rFonts = factory.createRFonts();
            if (value != null && containsChinese(value)) {
                rFonts.setEastAsia("宋体");
                rFonts.setAscii("宋体");
                rFonts.setHAnsi("宋体");
            } else {
                rFonts.setEastAsia("Arial");
                rFonts.setAscii("Arial");
                rFonts.setHAnsi("Arial");
            }
            rPr.setRFonts(rFonts);

            // 设置字体大小（使用传入的字号参数）
            HpsMeasure size = factory.createHpsMeasure();
            size.setVal(BigInteger.valueOf(fontSize));
            rPr.setSz(size);
            rPr.setSzCs(size);

            // 根据检测结果设置颜色
            if (value != null) {
                Color color = factory.createColor();
                if (value.equals("不合格") || value.equals("不符合")) {
                    color.setVal("FF0000"); // 红色
                    rPr.setColor(color);
                } else if (value.equals("无法比较")) {
                    color.setVal("E36C09"); // 橙色
                    rPr.setColor(color);
                }
            }

            run.setRPr(rPr);

            cell.setTcPr(cellPr);
            cell.getContent().add(paragraph);
            row.getContent().add(cell);
        }

        return row;
    }

    /**
     * 判断字符串是否包含中文
     *
     * @param str 需要判断的字符串
     * @return 是否包含中文
     */
    private static boolean containsChinese(String str) {
        if (str == null) {
            return false;
        }
        for (char c : str.toCharArray()) {
            if (Character.UnicodeScript.of(c) == Character.UnicodeScript.HAN) {
                return true;
            }
        }
        return false;
    }


    /**
     * 根据已知信息创建新行
     *
     * @param factory       工厂
     * @param cellValues    数据
     * @param ascFontStyle  西文字体
     * @param eastFontStyle 中文字体
     * @param size          字体大小
     * @param boldFlag      是否加粗
     * @param centerFlag    是否居中
     */
    public static Tr createCustomRow(ObjectFactory factory, List<String> cellValues, String ascFontStyle, String eastFontStyle, Integer size, boolean boldFlag, List<Integer> centerFlag) {
        Tr row = factory.createTr();
        for (int i = 0; i < cellValues.size(); i++) {
            String value = cellValues.get(i);
            Tc cell = factory.createTc();
            P paragraph = factory.createP();
            R run = factory.createR();
            Text text = factory.createText();
            text.setValue(value);
            run.getContent().add(text);
            paragraph.getContent().add(run);
            // 设置段落居中
            if (!centerFlag.contains(i)) {
                PPr pPr = factory.createPPr();
                Jc jc = factory.createJc();
                jc.setVal(JcEnumeration.CENTER);
                pPr.setJc(jc);
                paragraph.setPPr(pPr);
            }
            RPr rPr = factory.createRPr();
            // 根据检测结果设置颜色
            if (value != null) {
                if (value.equals("不合格") || value.equals("不符合")) {
                    Color color = factory.createColor();
                    color.setVal("FF0000"); // 红色
                    rPr.setColor(color);
                } else if (value.equals("无法比较")) {
                    Color color = factory.createColor();
                    color.setVal("E36C09"); // 橙色
                    rPr.setColor(color);
                }
            }
            if (boldFlag) {
                BooleanDefaultTrue bold = factory.createBooleanDefaultTrue();
                rPr.setB(bold);
            }
            RFonts fonts = factory.createRFonts();
            // 西文字体
            fonts.setAscii(ascFontStyle);
            // 中文字体
            fonts.setEastAsia(eastFontStyle);
            rPr.setRFonts(fonts);

            HpsMeasure fontSize = factory.createHpsMeasure();
            fontSize.setVal(BigInteger.valueOf(size));
            // 西文字号
            rPr.setSz(fontSize);
            // 中文字号
            rPr.setSzCs(fontSize);
            run.setRPr(rPr);
            cell.getContent().add(paragraph);
            // 设置单元格边距
            TcPr cellProperties = factory.createTcPr();
            cell.setTcPr(cellProperties);
            // 设置单元格上下边距（单位：缇）
            TcMar mar = factory.createTcMar();
            TblWidth top = factory.createTblWidth();
            top.setW(BigInteger.valueOf(100));
            mar.setTop(top);
            TblWidth bottom = factory.createTblWidth();
            bottom.setW(BigInteger.valueOf(100));
            mar.setBottom(bottom);
            cellProperties.setTcMar(mar);
            // 添加垂直居中
            addVerticalCenter(factory, cell);
            row.getContent().add(cell);
        }
        return row;
    }

    /**
     * 深拷贝表格
     *
     * @param original 原表格
     */
    public static JAXBElement<Tbl> deepCopyTbl(JAXBElement<Tbl> original) throws Exception {
        // 使用 docx4j 的 XmlUtils 进行深拷贝
        Tbl clonedTbl = XmlUtils.deepCopy(original.getValue());
        // 重新包装为 JAXBElement
        return new JAXBElement<>(
                original.getName(),
                original.getDeclaredType(),
                original.getScope(),
                clonedTbl
        );
    }


    /**
     * 存储Heading 5及其子内容的辅助类
     */
    @Getter
    public static class HeadingContent {
        @Setter
        private String headingText;
        private final List<Object> subContent = new ArrayList<>();

        public void addSubContent(Object obj) {
            subContent.add(obj);
        }

    }


    /**
     * 获取表格样式
     */
    public static TblPr getTblPr(ObjectFactory factory) {
        // **关键步骤：设置黑色实线边框**
        TblPr tblPr = factory.createTblPr();
        TblBorders borders = factory.createTblBorders();

        // 定义边框样式（1磅黑色单实线）
        CTBorder border = new CTBorder();
        // 实线类型
        border.setVal(STBorder.SINGLE);
        // 1磅=4单位（1/8磅）
        border.setSz(BigInteger.valueOf(4));
        // 黑色
        border.setColor("000000");

        // 应用边框到所有边
        borders.setTop(border);
        borders.setBottom(border);
        borders.setLeft(border);
        borders.setRight(border);
        // 内部水平线
        borders.setInsideH(border);
        // 内部垂直线
        borders.setInsideV(border);

        tblPr.setTblBorders(borders);


        // 设置表格宽度为96%
        TblWidth tblWidth = factory.createTblWidth();
        // 百分比类型
        tblWidth.setType("pct");
        // 96% = 4800/5000 (ISO标准)
        tblWidth.setW(BigInteger.valueOf(5000));
        tblPr.setTblW(tblWidth);

        return tblPr;
    }


    /**
     * 获取分页符
     */
    public static P getPageBreak() {
        try {
            ObjectFactory factory = new ObjectFactory();
            // 创建分页符
            R run = factory.createR();
            Br br = factory.createBr();
            br.setType(STBrType.PAGE);
            // 直接添加 br 对象
            run.getContent().add(br);
            // 创建包含分页符的段落
            P pageBreakParagraph = factory.createP();
            pageBreakParagraph.getContent().add(run);
            return pageBreakParagraph;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 创建分页符段落 - 用于在书签位置强制换页
     *
     * @return 包含分页符的段落，可直接添加到文档内容中
     */
    public static P createPageBreakParagraph() {
        ObjectFactory factory = new ObjectFactory();

        // 创建段落
        P paragraph = factory.createP();

        // 创建运行
        R run = factory.createR();

        // 创建分页符
        Br pageBreak = factory.createBr();
        pageBreak.setType(STBrType.PAGE); // 设置为页面分页符

        // 将分页符添加到运行中
        run.getContent().add(pageBreak);

        // 将运行添加到段落中
        paragraph.getContent().add(run);

        return paragraph;
    }

    /**
     * 检查并清除文档中仅由createPageBreakParagraph创建的独占页面
     *
     * <p>使用示例：</p>
     * <pre>
     * try {
     *     // 1. 完成所有文档内容的构建
     *     // ... 您的文档构建逻辑
     *
     *     // 2. 在保存前清理孤立的分页符页面
     *     int cleanedCount = Docx4jUtil.cleanBlankPagesAndRedundantPageBreaks(wordPackage);
     *     System.out.println("已清理 " + cleanedCount + " 个孤立分页符");
     *
     *     // 3. 保存文档
     *     wordPackage.save(new java.io.File(outputPath));
     * } catch (Exception e) {
     *     e.printStackTrace();
     * }
     * </pre>
     *
     * <p>清理功能：</p>
     * <ul>
     * <li>只清理由 createPageBreakParagraph() 创建且独占一页的分页符</li>
     * <li>不影响文档的其他内容和格式</li>
     * </ul>
     *
     * @param wordPackage Word文档包
     * @return 清理的孤立分页符数量
     */
    public static int cleanBlankPagesAndRedundantPageBreaks(WordprocessingMLPackage wordPackage) {
        try {
            MainDocumentPart mainDocumentPart = wordPackage.getMainDocumentPart();
            List<Object> allContent = mainDocumentPart.getContent();

            int cleanedCount = 0;

            // 只清理独占页面的createPageBreakParagraph分页符
            cleanedCount += removeStandalonePageBreaks(allContent);

            return cleanedCount;
        } catch (Exception e) {
            System.err.println("清理孤立分页符时发生错误: " + e.getMessage());
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除独占页面的分页符（非常保守的策略，只删除明确的重复分页符）
     */
    private static int removeStandalonePageBreaks(List<Object> allContent) {
        int removedCount = 0;

        for (int i = allContent.size() - 1; i >= 0; i--) {
            Object obj = allContent.get(i);

            // 检查当前元素是否为分页符段落
            if (isPageBreakParagraph(obj)) {
                // 只删除连续的分页符（保留第一个）
                if (i > 0 && isPageBreakParagraph(allContent.get(i - 1))) {
                    allContent.remove(i);
                    removedCount++;
                }
            }
        }

        return removedCount;
    }


    /**
     * 判断段落是否为分页符段落
     */
    private static boolean isPageBreakParagraph(Object obj) {
        if (!(obj instanceof P)) {
            return false;
        }

        P paragraph = (P) obj;

        // 检查段落内容
        for (Object content : paragraph.getContent()) {
            if (content instanceof R) {
                R run = (R) content;
                for (Object runContent : run.getContent()) {
                    if (runContent instanceof Br) {
                        Br br = (Br) runContent;
                        return STBrType.PAGE.equals(br.getType());
                    }
                }
            }
        }

        return false;
    }

    /**
     * 判断段落是否为空白段落
     */
    private static boolean isBlankParagraph(P paragraph) {
        String text = getTextFromP(paragraph);
        return text == null || text.trim().isEmpty();
    }


    /**
     * 复制段落的所有样式信息并更新文本内容（原有方法）
     *
     * @param factory         对象工厂
     * @param sourceParagraph 源段落（包含要复制的样式）
     * @param newText         新的文本内容
     * @param lineNumber      行号，用于更新标题编号（从1开始）
     * @return 复制样式后的新段落
     */
    public static P copyParagraphStyleAndUpdateText(ObjectFactory factory, P sourceParagraph, String newText, int lineNumber) {
        if (sourceParagraph == null) {
            return null;
        }

        // 创建新段落
        P newParagraph = factory.createP();

        // 复制段落属性（PPr）
        if (sourceParagraph.getPPr() != null) {
            try {
                PPr copiedPPr = (PPr) XmlUtils.deepCopy(sourceParagraph.getPPr());
                newParagraph.setPPr(copiedPPr);
            } catch (Exception e) {
                // 如果深拷贝失败，创建基本的段落属性
                PPr basicPPr = factory.createPPr();
                if (sourceParagraph.getPPr().getPStyle() != null) {
                    basicPPr.setPStyle(sourceParagraph.getPPr().getPStyle());
                }
                newParagraph.setPPr(basicPPr);
            }
        }

        // 复制第一个Run的样式并设置新文本
        List<Object> sourceContent = sourceParagraph.getContent();
        if (!sourceContent.isEmpty()) {
            for (Object obj : sourceContent) {
                if (obj instanceof R) {
                    R sourceRun = (R) obj;
                    R newRun = factory.createR();

                    // 复制Run属性（RPr）
                    if (sourceRun.getRPr() != null) {
                        try {
                            RPr copiedRPr = (RPr) XmlUtils.deepCopy(sourceRun.getRPr());
                            newRun.setRPr(copiedRPr);
                        } catch (Exception e) {
                            // 如果深拷贝失败，创建基本的运行属性
                            RPr basicRPr = factory.createRPr();
                            if (sourceRun.getRPr().getRFonts() != null) {
                                basicRPr.setRFonts(sourceRun.getRPr().getRFonts());
                            }
                            if (sourceRun.getRPr().getSz() != null) {
                                basicRPr.setSz(sourceRun.getRPr().getSz());
                            }
                            if (sourceRun.getRPr().getB() != null) {
                                basicRPr.setB(sourceRun.getRPr().getB());
                            }
                            newRun.setRPr(basicRPr);
                        }
                    }

                    // 设置新文本（处理编号逻辑）
                    Text text = factory.createText();
                    String finalText = updateTitleWithLineNumber(newText, lineNumber);
                    text.setValue(finalText);
                    newRun.getContent().add(text);

                    newParagraph.getContent().add(newRun);
                    // 只复制第一个Run的样式，后续Run忽略
                    break;
                }
            }
        } else {
            // 如果源段落没有Run，创建一个基本的Run
            R newRun = factory.createR();
            Text text = factory.createText();
            String finalText = updateTitleWithLineNumber(newText, lineNumber);
            text.setValue(finalText);
            newRun.getContent().add(text);
            newParagraph.getContent().add(newRun);
        }

        return newParagraph;
    }

    /**
     * 完整复制段落的所有样式信息和内容（新增方法 - 不修改文本）
     *
     * @param factory         对象工厂
     * @param sourceParagraph 源段落（包含要复制的样式）
     * @return 完整复制的新段落
     */
    public static P copyParagraphCompletely(ObjectFactory factory, P sourceParagraph) {
        if (sourceParagraph == null) {
            return null;
        }

        try {
            // 使用XmlUtils进行完整的深拷贝，确保所有样式信息都被保留
            P copiedParagraph = (P) XmlUtils.deepCopy(sourceParagraph);
            System.out.println("深拷贝成功");
            // 验证复制后的outlineLvl
            if (copiedParagraph.getPPr() != null && copiedParagraph.getPPr().getOutlineLvl() != null) {
                System.out.println("复制后 outlineLvl: " + copiedParagraph.getPPr().getOutlineLvl().getVal());
            } else {
                System.out.println("复制后没有 outlineLvl");
            }
            return copiedParagraph;
        } catch (Exception e) {
            // 深拷贝失败时的手动复制逻辑
            System.out.println("深拷贝失败，使用手动复制: " + e.getMessage());
            P manualCopied = manualCopyParagraph(factory, sourceParagraph);
            // 验证手动复制后的outlineLvl
            if (manualCopied.getPPr() != null && manualCopied.getPPr().getOutlineLvl() != null) {
                System.out.println("手动复制后 outlineLvl: " + manualCopied.getPPr().getOutlineLvl().getVal());
            } else {
                System.out.println("手动复制后没有 outlineLvl");
            }
            return manualCopied;
        }
    }

    /**
     * 基于样式名称创建具有正确标题等级的段落
     *
     * @param factory          对象工厂
     * @param mainDocumentPart 主文档部分，用于获取样式定义
     * @param sourceParagraph  源段落（用于获取样式ID）
     * @param text             段落文本内容
     * @return 具有正确标题样式的新段落
     */
    public static P createParagraphWithCorrectHeadingStyle(ObjectFactory factory, MainDocumentPart mainDocumentPart, P sourceParagraph, String text) {
        if (sourceParagraph == null || mainDocumentPart == null) {
            return null;
        }

        // 创建新段落
        P newParagraph = factory.createP();

        // 获取源段落的样式ID
        String styleId = null;
        if (sourceParagraph.getPPr() != null && sourceParagraph.getPPr().getPStyle() != null) {
            styleId = sourceParagraph.getPPr().getPStyle().getVal();
        }

        if (styleId != null) {
            try {
                // 获取样式定义部分
                org.docx4j.openpackaging.parts.WordprocessingML.StyleDefinitionsPart stylesPart =
                        mainDocumentPart.getStyleDefinitionsPart();

                if (stylesPart != null) {
                    // 获取样式定义对象
                    org.docx4j.wml.Style style = stylesPart.getStyleById(styleId);

                    if (style != null && style.getName() != null) {
                        String styleName = style.getName().getVal();
                        System.out.println("样式名称: " + styleName);

                        // 根据样式名称判断并设置正确的outlineLvl
                        int correctOutlineLvl = getOutlineLvlByStyleName(styleName);
                        System.out.println("根据样式名称确定的 outlineLvl: " + correctOutlineLvl);

                        // 设置段落属性
                        PPr pPr = factory.createPPr();
                        PPrBase.PStyle pStyle = factory.createPPrBasePStyle();
                        pStyle.setVal(styleId);
                        pPr.setPStyle(pStyle);

                        // 设置正确的大纲等级
                        PPrBase.OutlineLvl outlineLvl = factory.createPPrBaseOutlineLvl();
                        outlineLvl.setVal(BigInteger.valueOf(correctOutlineLvl));
                        pPr.setOutlineLvl(outlineLvl);

                        // 复制其他段落属性
                        if (sourceParagraph.getPPr() != null) {
                            if (sourceParagraph.getPPr().getJc() != null) {
                                pPr.setJc(sourceParagraph.getPPr().getJc());
                            }
                            if (sourceParagraph.getPPr().getSpacing() != null) {
                                pPr.setSpacing(sourceParagraph.getPPr().getSpacing());
                            }
                            if (sourceParagraph.getPPr().getInd() != null) {
                                pPr.setInd(sourceParagraph.getPPr().getInd());
                            }
                        }

                        newParagraph.setPPr(pPr);

                        // 创建Run并设置文本
                        R run = factory.createR();

                        // 复制Run属性
                        copyRunPropertiesFromSource(factory, sourceParagraph, run);

                        // 设置文本内容
                        Text textElement = factory.createText();
                        textElement.setValue(text);
                        run.getContent().add(textElement);

                        newParagraph.getContent().add(run);

                        return newParagraph;
                    }
                }
            } catch (Exception e) {
                System.err.println("获取样式定义失败: " + e.getMessage());
            }
        }

        // 如果以上方式都失败，使用深拷贝作为最后手段
        return copyParagraphCompletely(factory, sourceParagraph);
    }

    /**
     * 根据样式名称确定正确的outlineLvl值
     */
    private static int getOutlineLvlByStyleName(String styleName) {
        if (styleName == null) {
            return 2; // 默认返回3级标题
        }

        String lowerName = styleName.toLowerCase();

        if (lowerName.contains("heading 1") || lowerName.contains("标题 1")) {
            return 0; // Heading 1
        } else if (lowerName.contains("heading 2") || lowerName.contains("标题 2")) {
            return 1; // Heading 2  
        } else if (lowerName.contains("heading 3") || lowerName.contains("标题 3")) {
            return 2; // Heading 3
        } else if (lowerName.contains("heading 4") || lowerName.contains("标题 4")) {
            return 3; // Heading 4
        } else if (lowerName.contains("heading 5") || lowerName.contains("标题 5")) {
            return 4; // Heading 5
        } else if (lowerName.contains("heading 6") || lowerName.contains("标题 6")) {
            return 5; // Heading 6
        }

        // 如果没有匹配到标准标题样式，默认返回3级标题
        return 2;
    }

    /**
     * 从源段落复制Run属性到目标Run
     */
    private static void copyRunPropertiesFromSource(ObjectFactory factory, P sourceParagraph, R targetRun) {
        // 从源段落的第一个Run获取属性
        for (Object obj : sourceParagraph.getContent()) {
            if (obj instanceof R) {
                R sourceRun = (R) obj;
                if (sourceRun.getRPr() != null) {
                    try {
                        RPr copiedRPr = (RPr) XmlUtils.deepCopy(sourceRun.getRPr());
                        targetRun.setRPr(copiedRPr);
                    } catch (Exception e) {
                        // 手动复制基本属性
                        RPr rPr = factory.createRPr();
                        if (sourceRun.getRPr().getRFonts() != null) {
                            rPr.setRFonts(sourceRun.getRPr().getRFonts());
                        }
                        if (sourceRun.getRPr().getSz() != null) {
                            rPr.setSz(sourceRun.getRPr().getSz());
                        }
                        if (sourceRun.getRPr().getB() != null) {
                            rPr.setB(sourceRun.getRPr().getB());
                        }
                        targetRun.setRPr(rPr);
                    }
                }
                break;
            }
        }
    }

    /**
     * 手动复制段落（当深拷贝失败时的备用方案）
     */
    private static P manualCopyParagraph(ObjectFactory factory, P sourceParagraph) {
        P newParagraph = factory.createP();

        // 复制段落属性（PPr）- 包括样式ID、对齐方式、间距等
        if (sourceParagraph.getPPr() != null) {
            PPr sourcePPr = sourceParagraph.getPPr();
            PPr newPPr = factory.createPPr();

            // 复制样式引用（最重要 - 保持标题等级）
            if (sourcePPr.getPStyle() != null) {
                PPrBase.PStyle newPStyle = factory.createPPrBasePStyle();
                newPStyle.setVal(sourcePPr.getPStyle().getVal());
                newPPr.setPStyle(newPStyle);
            }

            // 复制对齐方式
            if (sourcePPr.getJc() != null) {
                newPPr.setJc(sourcePPr.getJc());
            }

            // 复制段落间距
            if (sourcePPr.getSpacing() != null) {
                newPPr.setSpacing(sourcePPr.getSpacing());
            }

            // 复制大纲等级（重要 - 影响标题等级）
            if (sourcePPr.getOutlineLvl() != null) {
                newPPr.setOutlineLvl(sourcePPr.getOutlineLvl());
            }

            newParagraph.setPPr(newPPr);
        }

        // 复制所有Run内容
        for (Object obj : sourceParagraph.getContent()) {
            if (obj instanceof R) {
                R sourceRun = (R) obj;
                R newRun = factory.createR();

                // 复制Run属性（RPr）
                if (sourceRun.getRPr() != null) {
                    RPr sourceRPr = sourceRun.getRPr();
                    RPr newRPr = factory.createRPr();

                    // 复制字体
                    if (sourceRPr.getRFonts() != null) {
                        newRPr.setRFonts(sourceRPr.getRFonts());
                    }

                    // 复制字号
                    if (sourceRPr.getSz() != null) {
                        newRPr.setSz(sourceRPr.getSz());
                    }
                    if (sourceRPr.getSzCs() != null) {
                        newRPr.setSzCs(sourceRPr.getSzCs());
                    }

                    // 复制粗体
                    if (sourceRPr.getB() != null) {
                        newRPr.setB(sourceRPr.getB());
                    }
                    if (sourceRPr.getBCs() != null) {
                        newRPr.setBCs(sourceRPr.getBCs());
                    }

                    // 复制颜色
                    if (sourceRPr.getColor() != null) {
                        newRPr.setColor(sourceRPr.getColor());
                    }

                    newRun.setRPr(newRPr);
                }

                // 复制Run的所有内容
                for (Object runObj : sourceRun.getContent()) {
                    newRun.getContent().add(runObj);
                }

                newParagraph.getContent().add(newRun);
            } else {
                // 复制非Run对象（如书签等）
                newParagraph.getContent().add(obj);
            }
        }

        return newParagraph;
    }

    /**
     * 创建动态检测结果表格（正确的合并单元格版本）
     *
     * @param factory      对象工厂
     * @param testItems    检测项目列表 ["电压", "频率", "电压不平衡度"...]
     * @param circuitNames 回路名称列表 ["测量回路1", "测量回路2"...] 或 ["#1母线", "#2母线"...]
     * @param testResults  检测结果数据 testResults[项目索引][回路索引] = "合格/不合格/无法比较"
     * @param sampleResult 样品结果 "合格/不合格"
     * @param dataType     数据类型（如："任意值"、"部分值"、"平均值"等）
     * @param numOfSamples 样本数量
     * @param dataRule     处理原则（如："取第一个满足条件的数据"、"去除最大最小值"等）
     * @return 动态表格
     */
    public static JAXBElement<Tbl> createDynamicTestResultTable(ObjectFactory factory,
                                                                List<String> testItems, List<String> circuitNames, String[][] testResults, String sampleResult,
                                                                String dataType, String numOfSamples, String dataRule) {

        // 创建表格
        Tbl table = factory.createTbl();
        table.setTblPr(getTblPr(factory));

        int circuitCount = circuitNames.size();
        int totalColumns = circuitCount + 2; // 检测项目列 + 回路列 + 样品结果列

        // 创建第一行表头：检测项目（纵向合并）| 检测结果（横向合并）
        Tr titleHeaderRow = createTestResultTitleHeader(factory, circuitCount, testItems.size() + 2);
        table.getContent().add(titleHeaderRow);

        // 创建第二行表头：（空）| 回路名称列表 | 样品结果
        Tr columnHeaderRow = createTestResultColumnHeader(factory, circuitNames, sampleResult);
        table.getContent().add(columnHeaderRow);

        // 创建检测项目行
        for (int i = 0; i < testItems.size(); i++) {
            String testItem = testItems.get(i);
            String[] itemResults = testResults[i];
            Tr dataRow = createTestResultDataRow(factory, testItem, itemResults, sampleResult, i, testItems.size());
            table.getContent().add(dataRow);
        }

        // 添加说明内容行（在表格内部）
        Tr descriptionRow = createDescriptionRow(factory, totalColumns, dataType, numOfSamples, dataRule);
        table.getContent().add(descriptionRow);

        // 包装为JAXBElement
        return new JAXBElement<>(
                new javax.xml.namespace.QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "tbl"),
                Tbl.class,
                table
        );
    }

    /**
     * 创建第一行表头：检测项目（纵向合并）| 检测结果（横向合并所有列）
     */
    private static Tr createTestResultTitleHeader(ObjectFactory factory, int circuitCount, int totalRows) {
        Tr titleRow = factory.createTr();

        // 设置行高
        TrPr trPr = factory.createTrPr();
        CTHeight height = new CTHeight();
        height.setVal(BigInteger.valueOf(600)); // 设置行高（单位：缇，600缇约30磅）
        height.setHRule(STHeightRule.AT_LEAST); // 至少这个高度
        // 使用正确的方法名
        JAXBElement<CTHeight> trHeight = factory.createCTTrPrBaseTrHeight(height);
        trPr.getCnfStyleOrDivIdOrGridBefore().add(trHeight);
        titleRow.setTrPr(trPr);

        // 1. 创建"检测项目"单元格（纵向合并2行）
        Tc itemTitleCell = createCenteredTableCell(factory, "检测项目", "宋体", 21, true);
        TcPr itemCellPr = itemTitleCell.getTcPr();
        if (itemCellPr == null) {
            itemCellPr = factory.createTcPr();
            itemTitleCell.setTcPr(itemCellPr);
            // 重新添加垂直居中
            addVerticalCenter(factory, itemTitleCell);
        }
        VMerge itemVMerge = new VMerge();
        itemVMerge.setVal("restart");
        itemCellPr.setVMerge(itemVMerge);
        titleRow.getContent().add(itemTitleCell);

        // 2. 创建"检测结果"合并单元格（横向合并所有回路列+样品结果列）
        Tc resultTitleCell = createCenteredTableCell(factory, "检测结果", "宋体", 21, true);
        TcPr resultCellPr = resultTitleCell.getTcPr();
        if (resultCellPr == null) {
            resultCellPr = factory.createTcPr();
            resultTitleCell.setTcPr(resultCellPr);
        }
        GridSpan gridSpan = new GridSpan();
        gridSpan.setVal(BigInteger.valueOf(circuitCount + 1)); // +1 包括样品结果列
        resultCellPr.setGridSpan(gridSpan);
        titleRow.getContent().add(resultTitleCell);

        return titleRow;
    }

    /**
     * 创建第二行表头：（空）| 回路名称列表 | 样品结果
     */
    private static Tr createTestResultColumnHeader(ObjectFactory factory, List<String> circuitNames, String sampleResult) {
        Tr headerRow = factory.createTr();

        // 设置行高
        TrPr trPr = factory.createTrPr();
        CTHeight height = new CTHeight();
        height.setVal(BigInteger.valueOf(600)); // 设置行高
        height.setHRule(STHeightRule.AT_LEAST); // 至少这个高度
        // 使用正确的方法名
        JAXBElement<CTHeight> trHeight = factory.createCTTrPrBaseTrHeight(height);
        trPr.getCnfStyleOrDivIdOrGridBefore().add(trHeight);
        headerRow.setTrPr(trPr);

        // 1. 检测项目列（继续纵向合并）
        Tc itemEmptyCell = createCenteredTableCell(factory, "", "宋体", 21, true);
        TcPr itemCellPr = itemEmptyCell.getTcPr();
        if (itemCellPr == null) {
            itemCellPr = factory.createTcPr();
            itemEmptyCell.setTcPr(itemCellPr);
        }
        VMerge itemVMerge = new VMerge();
        itemVMerge.setVal("continue");
        itemCellPr.setVMerge(itemVMerge);
        headerRow.getContent().add(itemEmptyCell);

        // 2. 添加回路列（使用传入的回路名称）
        for (String circuitName : circuitNames) {
            Tc circuitCell = createCenteredTableCell(factory, circuitName, "宋体", 21, true);
            headerRow.getContent().add(circuitCell);
        }

        // 3. 样品结果列（显示"样品结果"标题）
        Tc sampleResultCell = createCenteredTableCell(factory, "样品结果", "宋体", 21, true);
        headerRow.getContent().add(sampleResultCell);

        return headerRow;
    }

    /**
     * 创建检测结果数据行（样品结果纵向合并）
     */
    private static Tr createTestResultDataRow(ObjectFactory factory, String testItem,
                                              String[] results, String sampleResult, int rowIndex, int totalRows) {

        Tr dataRow = factory.createTr();

        // 设置行高
        TrPr trPr = factory.createTrPr();
        CTHeight height = new CTHeight();
        height.setVal(BigInteger.valueOf(500)); // 数据行稍微矮一点（500缇约25磅）
        height.setHRule(STHeightRule.AT_LEAST);
        JAXBElement<CTHeight> trHeight = factory.createCTTrPrBaseTrHeight(height);
        trPr.getCnfStyleOrDivIdOrGridBefore().add(trHeight);
        dataRow.setTrPr(trPr);

        // 1. 检测项目列
        Tc itemCell = createTableCell(factory, testItem, "宋体", 21, false);
        dataRow.getContent().add(itemCell);

        // 2. 各回路结果列
        for (String result : results) {
            Tc resultCell = createTableCell(factory, result, "宋体", 21, false);
            // 根据结果设置颜色
            if ("不合格".equals(result) || "不符合".equals(result)) {
                setRedColor(factory, resultCell);
            } else if ("无法比较".equals(result)) {
                setOrangeColor(factory, resultCell);
            }
            dataRow.getContent().add(resultCell);
        }

        // 3. 样品结果列（根据行索引决定是否显示内容或合并）
        if (rowIndex == 0) {
            // 第一行数据行，显示样品结果并开始纵向合并
            Tc sampleDataCell = createTableCell(factory, sampleResult, "宋体", 21, false);
            TcPr sampleCellPr = sampleDataCell.getTcPr();
            if (sampleCellPr == null) {
                sampleCellPr = factory.createTcPr();
                sampleDataCell.setTcPr(sampleCellPr);
            }

            // 开始纵向合并到其他数据行
            VMerge sampleVMerge = new VMerge();
            sampleVMerge.setVal("restart");
            sampleCellPr.setVMerge(sampleVMerge);

            // 根据样品结果设置颜色
            if ("不合格".equals(sampleResult) || "不符合".equals(sampleResult)) {
                setRedColor(factory, sampleDataCell);
            } else if ("无法比较".equals(sampleResult)) {
                setOrangeColor(factory, sampleDataCell);
            }

            dataRow.getContent().add(sampleDataCell);
        } else {
            // 其他数据行，继续纵向合并
            Tc sampleDataCell = createTableCell(factory, "", "宋体", 21, false);
            TcPr sampleCellPr = sampleDataCell.getTcPr();
            if (sampleCellPr == null) {
                sampleCellPr = factory.createTcPr();
                sampleDataCell.setTcPr(sampleCellPr);
            }
            VMerge sampleVMerge = new VMerge();
            sampleVMerge.setVal("continue");
            sampleCellPr.setVMerge(sampleVMerge);
            dataRow.getContent().add(sampleDataCell);
        }

        return dataRow;
    }

    /**
     * 创建表格单元格（水平和垂直居中）
     */
    private static Tc createTableCell(ObjectFactory factory, String text, String fontFamily, int fontSize, boolean isBold) {
        Tc cell = factory.createTc();
        P paragraph = factory.createP();
        R run = factory.createR();
        Text textElement = factory.createText();
        textElement.setValue(text);

        // 设置字体样式
        RPr rPr = factory.createRPr();
        RFonts fonts = factory.createRFonts();
        fonts.setEastAsia(fontFamily);
        fonts.setAscii("Arial");
        rPr.setRFonts(fonts);

        HpsMeasure size = factory.createHpsMeasure();
        size.setVal(BigInteger.valueOf(fontSize));
        rPr.setSz(size);

        if (isBold) {
            BooleanDefaultTrue bold = factory.createBooleanDefaultTrue();
            rPr.setB(bold);
        }

        run.setRPr(rPr);
        run.getContent().add(textElement);
        paragraph.getContent().add(run);

        // 设置段落水平居中
        PPr pPr = factory.createPPr();
        Jc jc = factory.createJc();
        jc.setVal(JcEnumeration.CENTER);
        pPr.setJc(jc);

        // 设置段落间距为0，以便更好地垂直居中
        PPrBase.Spacing spacing = factory.createPPrBaseSpacing();
        spacing.setBefore(BigInteger.ZERO);
        spacing.setAfter(BigInteger.ZERO);
        spacing.setLine(BigInteger.valueOf(240)); // 单倍行距
        pPr.setSpacing(spacing);

        paragraph.setPPr(pPr);

        // 设置单元格属性并垂直居中
        TcPr cellPr = factory.createTcPr();

        // 设置垂直居中
        CTVerticalJc vAlign = new CTVerticalJc();
        vAlign.setVal(STVerticalJc.CENTER);
        cellPr.setVAlign(vAlign);

        cell.setTcPr(cellPr);

        cell.getContent().add(paragraph);
        return cell;
    }

    /**
     * 创建居中的表格单元格（专门用于表头）
     */
    private static Tc createCenteredTableCell(ObjectFactory factory, String text, String fontFamily, int fontSize, boolean isBold) {
        return createTableCell(factory, text, fontFamily, fontSize, isBold);
    }

    /**
     * 为单元格添加垂直居中属性
     */
    private static void addVerticalCenter(ObjectFactory factory, Tc cell) {
        TcPr cellPr = cell.getTcPr();
        if (cellPr == null) {
            cellPr = factory.createTcPr();
            cell.setTcPr(cellPr);
        }

        // 设置垂直居中 - 使用正确的方式创建CTVerticalJc
        CTVerticalJc vAlign = new CTVerticalJc();
        vAlign.setVal(STVerticalJc.CENTER);
        cellPr.setVAlign(vAlign);

        // 同时确保段落也设置了居中对齐（这有助于内容更好地显示）
        for (Object content : cell.getContent()) {
            if (content instanceof P) {
                P paragraph = (P) content;
                PPr pPr = paragraph.getPPr();
                if (pPr == null) {
                    pPr = factory.createPPr();
                    paragraph.setPPr(pPr);
                }
                // 设置段落水平居中（保持原有的水平居中）
                Jc jc = pPr.getJc();
                if (jc == null) {
                    jc = factory.createJc();
                    jc.setVal(JcEnumeration.CENTER);
                    pPr.setJc(jc);
                }
                // 设置段落间距为0，并使用1.5倍行距
                PPrBase.Spacing spacing = factory.createPPrBaseSpacing();
                spacing.setBefore(BigInteger.ZERO);
                spacing.setAfter(BigInteger.ZERO);
                spacing.setLine(BigInteger.valueOf(360)); // 1.5倍行距
                spacing.setLineRule(STLineSpacingRule.AUTO);
                pPr.setSpacing(spacing);
            }
        }
    }

    /**
     * 为单元格设置红色文字
     */
    private static void setRedColor(ObjectFactory factory, Tc cell) {
        if (!cell.getContent().isEmpty()) {
            Object content = cell.getContent().get(0);
            if (content instanceof P) {
                P paragraph = (P) content;
                if (!paragraph.getContent().isEmpty()) {
                    Object runContent = paragraph.getContent().get(0);
                    if (runContent instanceof R) {
                        R run = (R) runContent;
                        RPr rPr = run.getRPr();
                        if (rPr == null) {
                            rPr = factory.createRPr();
                            run.setRPr(rPr);
                        }
                        Color color = factory.createColor();
                        color.setVal("FF0000"); // 红色
                        rPr.setColor(color);
                    }
                }
            }
        }
    }

    /**
     * 为单元格设置橙色文字
     */
    private static void setOrangeColor(ObjectFactory factory, Tc cell) {
        if (!cell.getContent().isEmpty()) {
            Object content = cell.getContent().get(0);
            if (content instanceof P) {
                P paragraph = (P) content;
                if (!paragraph.getContent().isEmpty()) {
                    Object runContent = paragraph.getContent().get(0);
                    if (runContent instanceof R) {
                        R run = (R) runContent;
                        RPr rPr = run.getRPr();
                        if (rPr == null) {
                            rPr = factory.createRPr();
                            run.setRPr(rPr);
                        }
                        Color color = factory.createColor();
                        color.setVal("E36C09"); // 橙色
                        rPr.setColor(color);
                    }
                }
            }
        }
    }


    /**
     * 创建表格内的说明行（跨所有列合并）
     */
    private static Tr createDescriptionRow(ObjectFactory factory, int totalColumns,
                                           String dataType, String numOfSamples, String dataRule) {

        Tr descRow = factory.createTr();

        // 创建跨列合并的单元格
        Tc descCell = factory.createTc();

        // 设置单元格跨列合并
        TcPr tcPr = factory.createTcPr();
        GridSpan gridSpan = new GridSpan();
        gridSpan.setVal(BigInteger.valueOf(totalColumns));
        tcPr.setGridSpan(gridSpan);
        descCell.setTcPr(tcPr);

        // 创建说明内容的字体样式（宋体、五号、非粗体）
        RPr descRPr = factory.createRPr();
        RFonts fonts = factory.createRFonts();
        fonts.setEastAsia("宋体");
        fonts.setAscii("Arial");
        descRPr.setRFonts(fonts);
        HpsMeasure size = factory.createHpsMeasure();
        size.setVal(BigInteger.valueOf(21)); // 五号字体
        descRPr.setSz(size);
        // 不设置粗体（非粗体）

        // 创建段落格式（1.5倍行距，段前段后为0）
        PPr descPPr = factory.createPPr();
        // 设置行距为1.5倍
        PPrBase.Spacing spacing = factory.createPPrBaseSpacing();
        spacing.setLine(BigInteger.valueOf(360)); // 360缇 = 1.5倍行距（240缇是单倍行距）
        spacing.setLineRule(STLineSpacingRule.AUTO); // 自动行距
        spacing.setBefore(BigInteger.ZERO); // 段前间距为0
        spacing.setAfter(BigInteger.ZERO);  // 段后间距为0
        descPPr.setSpacing(spacing);

        // 创建子项段落格式（包含首行缩进2个字符）
        PPr subItemPPr = factory.createPPr();
        // 设置行距为1.5倍
        PPrBase.Spacing subSpacing = factory.createPPrBaseSpacing();
        subSpacing.setLine(BigInteger.valueOf(360));
        subSpacing.setLineRule(STLineSpacingRule.AUTO);
        subSpacing.setBefore(BigInteger.ZERO);
        subSpacing.setAfter(BigInteger.ZERO);
        subItemPPr.setSpacing(subSpacing);
        // 设置首行缩进2个字符（2个字符 = 420缇，1个字符约210缇）
        PPrBase.Ind indentation = factory.createPPrBaseInd();
        indentation.setFirstLine(BigInteger.valueOf(420)); // 首行缩进2个字符
        subItemPPr.setInd(indentation);

        // 创建说明内容的段落
        // 1. 数据源标题
        P dataSourceTitle = factory.createP();
        addPContent(factory, dataSourceTitle, "1. 数据源：", descRPr, descPPr);
        descCell.getContent().add(dataSourceTitle);

        // 数据类型（去掉手动缩进的空格，使用首行缩进）
        P dataTypeP = factory.createP();
        addPContent(factory, dataTypeP, "数据类型：" + dataType + "；", descRPr, subItemPPr);
        descCell.getContent().add(dataTypeP);

        // 采集规模
        P sampleSizeP = factory.createP();
        addPContent(factory, sampleSizeP, "采集规模：" + numOfSamples + "数据样本；", descRPr, subItemPPr);
        descCell.getContent().add(sampleSizeP);

        // 处理原则
        P dataRuleP = factory.createP();
        addPContent(factory, dataRuleP, "处理原则：" + dataRule + "。", descRPr, subItemPPr);
        descCell.getContent().add(dataRuleP);

        // 2. 检测结论判定标准
        P criteriaTitle = factory.createP();
        addPContent(factory, criteriaTitle, "2. 检测结论判定标准：", descRPr, descPPr);
        descCell.getContent().add(criteriaTitle);

        // 合格（去掉手动缩进的空格，使用首行缩进）
        P qualifiedP = factory.createP();
        addPContent(factory, qualifiedP,
                "合格：收条数据中存在符合误差计算条件的样本，经" + dataRule + "处理后，所有样本数据误差计算结果均符合误差标准要求；",
                descRPr, subItemPPr);
        descCell.getContent().add(qualifiedP);

        // 不合格
        P unqualifiedP = factory.createP();
        addPContent(factory, unqualifiedP,
                "不合格：收条数据中存在符合误差计算条件的样本，经" + dataRule + "处理后，存在样本数据误差计算结果不符合误差标准要求；",
                descRPr, subItemPPr);
        descCell.getContent().add(unqualifiedP);

        // 无法比较（去掉手动缩进的空格，使用首行缩进）
        P incomparableP = factory.createP();
        addPContent(factory, incomparableP,
                "无法比较：收集数据中，无样本数据满足误差比较的前置条件，无法执行有效性判定。",
                descRPr, subItemPPr);
        descCell.getContent().add(incomparableP);

        descRow.getContent().add(descCell);
        return descRow;
    }

    /**
     * 创建检测结果说明段落
     *
     * @param factory      对象工厂
     * @param dataType     数据类型
     * @param numOfSamples 样本数量
     * @param dataRule     处理原则
     * @return 说明段落列表
     */
    public static List<P> createTestResultDescription(ObjectFactory factory,
                                                      String dataType, int numOfSamples, String dataRule) {

        List<P> descriptions = new ArrayList<>();

        // 1. 数据源
        P dataSourceP = factory.createP();
        addPContent(factory, dataSourceP, "1. 数据源：", null, null);
        descriptions.add(dataSourceP);

        P dataTypeP = factory.createP();
        addPContent(factory, dataTypeP, "    数据类型：" + dataType + "；", null, null);
        descriptions.add(dataTypeP);

        P sampleSizeP = factory.createP();
        addPContent(factory, sampleSizeP, "    采集规模：" + numOfSamples + " 组数据样本；", null, null);
        descriptions.add(sampleSizeP);

        P dataRuleP = factory.createP();
        addPContent(factory, dataRuleP, "    处理原则：" + dataRule + "。", null, null);
        descriptions.add(dataRuleP);

        // 2. 检测结论判定标准
        P criteriaP = factory.createP();
        addPContent(factory, criteriaP, "2. 检测结论判定标准：", null, null);
        descriptions.add(criteriaP);

        P qualifiedP = factory.createP();
        addPContent(factory, qualifiedP,
                "    合格：收条数据中存在符合误差计算条件的样本，经部分值处理后，所有样本数据误差计算结果均符合误差标准要求；",
                null, null);
        descriptions.add(qualifiedP);

        P unqualifiedP = factory.createP();
        R run = factory.createR();
        Text text = factory.createText();
        text.setValue("    不合格：收条数据中存在符合误差计算条件的样本，经部分值处理后，存在样本数据误差计算结果不符合误差标准要求；");

        // 设置红色
        RPr rPr = factory.createRPr();
        Color color = factory.createColor();
        color.setVal("FF0000");
        rPr.setColor(color);
        run.setRPr(rPr);
        run.getContent().add(text);
        unqualifiedP.getContent().add(run);
        descriptions.add(unqualifiedP);

        P incomparableP = factory.createP();
        addPContent(factory, incomparableP,
                "    无法比较：收集的200组数据中，无样本数据满足误差比较的前置条件，无法执行有效性判定。",
                null, null);
        descriptions.add(incomparableP);

        return descriptions;
    }

    /**
     * 根据行号更新标题文本中的编号
     *
     * @param originalText 原始文本
     * @param lineNumber   行号（从1开始）
     * @return 更新编号后的文本
     */
    private static String updateTitleWithLineNumber(String originalText, int lineNumber) {
        if (originalText == null || originalText.trim().isEmpty()) {
            return "测量回路" + lineNumber;
        }

        // 常见的标题编号模式替换
        String text = originalText;

        // 替换"回路1"、"回路2"等模式
        text = text.replaceAll("回路\\d+", "回路" + lineNumber);

        // 替换"第1回路"、"第2回路"等模式
        text = text.replaceAll("第\\d+回路", "第" + lineNumber + "回路");

        // 替换"1#"、"2#"等模式
        text = text.replaceAll("\\d+#", lineNumber + "#");

        // 替换单独的数字（在开头或被空格包围）
        text = text.replaceAll("^\\d+\\s*", lineNumber + " ");
        text = text.replaceAll("\\s+\\d+\\s+", " " + lineNumber + " ");

        // 如果没有找到任何编号模式，在文本前添加编号
        if (text.equals(originalText)) {
            text = lineNumber + " " + originalText;
        }

        return text;
    }

    /**
     * 创建特殊情况说明段落
     * 统一格式：宋体5号字、首行缩进2字符
     *
     * @param factory     Word文档对象工厂
     * @param specialCase 特殊情况说明文本
     * @return 格式化的段落对象
     */
    public static P createSpecialCaseParagraph(ObjectFactory factory, String specialCase) {
        P specialCaseP = factory.createP();

        // 设置段落属性
        PPr pPr = factory.createPPr();

        // 设置首行缩进2字符（中文字符）
        PPrBase.Ind ind = factory.createPPrBaseInd();
        // 2字符缩进，1个中文字符约等于240twips，2字符=480twips
        ind.setFirstLine(BigInteger.valueOf(480));
        pPr.setInd(ind);

        specialCaseP.setPPr(pPr);

        // 创建运行元素
        R run = factory.createR();

        // 设置字体样式
        RPr rPr = factory.createRPr();

        // 设置字体为宋体
        RFonts rFonts = factory.createRFonts();
        rFonts.setAscii("宋体");
        rFonts.setEastAsia("宋体");
        rFonts.setHAnsi("宋体");
        rPr.setRFonts(rFonts);

        // 设置字号为5号（10.5磅，21半磅）
        HpsMeasure size = factory.createHpsMeasure();
        size.setVal(BigInteger.valueOf(21));
        rPr.setSz(size);
        rPr.setSzCs(size); // 复杂脚本字体大小

        run.setRPr(rPr);

        // 添加文本内容
        Text text = factory.createText();
        text.setValue(specialCase);
        text.setSpace("preserve");
        run.getContent().add(text);

        // 将运行元素添加到段落
        specialCaseP.getContent().add(run);

        return specialCaseP;
    }

    /**
     * 为Word文档添加水印
     * 使用页眉方式，但设置页眉高度为0，确保不影响文档结构
     *
     * @param wordPackage   Word文档包
     * @param watermarkText 水印文字（如："非正式"）
     * @throws Exception 添加水印失败时抛出异常
     */
    public static void addWatermarkToDocument(WordprocessingMLPackage wordPackage, String watermarkText) throws Exception {
        try {
            MainDocumentPart mainDocumentPart = wordPackage.getMainDocumentPart();
            ObjectFactory factory = new ObjectFactory();

            // 创建页眉部分
            org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart headerPart = 
                new org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart();
            
            // 将页眉部分添加到文档并获取关系ID
            org.docx4j.relationships.Relationship relationship = mainDocumentPart.addTargetPart(headerPart);

            // 创建页眉对象
            org.docx4j.wml.Hdr hdr = factory.createHdr();
            
            // 创建段落
            P paragraph = factory.createP();
            
            // 创建Run
            R run = factory.createR();
            
            // 使用VML textbox方式创建水印文本（绝对定位，显示在页面中部）
            String vmlString = String.format(
                "<w:pict xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" " +
                "xmlns:v=\"urn:schemas-microsoft-com:vml\">" +
                "<v:shape style=\"position:absolute;left:0;text-align:center;margin-left:0;margin-top:0;" +
                "width:500pt;height:200pt;z-index:-251658240;" +
                "mso-position-horizontal:center;mso-position-horizontal-relative:page;" +
                "mso-position-vertical:center;mso-position-vertical-relative:page\" " +
                "fillcolor=\"none\" stroked=\"f\">" +
                "<v:textbox style=\"mso-fit-shape-to-text:t\">" +
                "<w:txbxContent>" +
                "<w:p><w:pPr><w:jc w:val=\"center\"/></w:pPr>" +
                "<w:r><w:rPr>" +
                "<w:color w:val=\"D8D8D8\"/>" +
                "<w:sz w:val=\"240\"/>" +
                "<w:szCs w:val=\"240\"/>" +
                "<w:rFonts w:ascii=\"微软雅黑\" w:eastAsia=\"微软雅黑\" w:hAnsi=\"微软雅黑\"/>" +
                "</w:rPr><w:t>%s</w:t></w:r></w:p>" +
                "</w:txbxContent></v:textbox>" +
                "</v:shape></w:pict>", watermarkText);
            
            // 解析VML并添加到Run
            Object vmlObject = XmlUtils.unmarshalString(vmlString);
            run.getContent().add(vmlObject);
            
            paragraph.getContent().add(run);
            hdr.getContent().add(paragraph);
            headerPart.setJaxbElement(hdr);

            // 获取或创建节属性（SectPr）
            SectPr sectPr = mainDocumentPart.getJaxbElement().getBody().getSectPr();
            if (sectPr == null) {
                sectPr = factory.createSectPr();
                mainDocumentPart.getJaxbElement().getBody().setSectPr(sectPr);
            }

            // 创建页眉引用并关联到节属性
            org.docx4j.wml.HeaderReference headerReference = factory.createHeaderReference();
            headerReference.setId(relationship.getId());
            headerReference.setType(org.docx4j.wml.HdrFtrRef.DEFAULT);
            sectPr.getEGHdrFtrReferences().add(headerReference);

            log.info("成功添加水印：{}", watermarkText);
        } catch (Exception e) {
            log.error("添加水印失败：{}", e.getMessage(), e);
            throw new Exception("添加水印失败：" + e.getMessage(), e);
        }
    }


}
