<template>
  <div class="data-list">
    <el-table
      :data="dataList"
      style="width: 100%"
      header-row-class-name="headerBg"
      empty-text="没有项目信息"
    >
      <el-table-column prop="id" label="项目编号" align="center" width="80" />
      <el-table-column prop="customer_id" label="客户名称" align="left">
        <template #default="scope">
          <span>{{ getCusomName(scope.row.customer_id) }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="name" label="项目名称" align="left" />

      <el-table-column prop="categoryId" label="产品类别" align="left">
        <template #default="scope">
          <span>{{ getCategoryTypeName(scope.row.product_id) }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="productName" label="产品名称" align="left">
        <template #default="scope">
          <span>{{ getCategoryName(scope.row.product_id) }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="service_content" label="服务内容" align="left" />

      <el-table-column prop="start_date" label="项目开始日期" align="center" />
      <el-table-column prop="updateTime" label="最后更新日期" align="center" />
      <el-table-column prop="calculate" label="完成度" align="center">
        <template #default="scope">
          <span :class="getCompletionClass(scope.row.calculate)">
            {{ formatCompletion(scope.row.calculate) }}
          </span>
        </template>
      </el-table-column>
      <el-table-column prop="current_phase" label="当前阶段" align="left">
        <template #default="scope">
          <el-tag :type="getPhaseType(scope.row.current_phase)" effect="plain">
            {{ getPhaseName(scope.row.current_phase) }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="project_status" label="目前状态" align="center">
        <template #default="scope">
          <el-tag
            :type="getStatusType(scope.row.project_status)"
            effect="plain"
          >
            {{ getStatusName(scope.row.project_status) }}
          </el-tag>
        </template>
      </el-table-column>

      <el-table-column label="操作" align="center" fixed="right">
        <template #default="scope">
          <el-dropdown :data="scope.row" @command="handleCommand">
            <span class="el-dropdown-link">
              <el-button
                type="text"
                size="small"
                circle
                class="operation-button"
                style="font-size: 15px; margin-left: 10px"
                icon="el-icon-more"
              />
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item
                  :command="{ type: 'template', row: scope.row }"
                >选择模版</el-dropdown-item>
                <el-dropdown-item
                  :command="{ type: 'enter', row: scope.row }"
                >输入项目</el-dropdown-item>
                <el-dropdown-item
                  v-if="
                    scope.row.documentIds && scope.row.documentIds.length > 0
                  "
                  :command="{ type: 'viewTemplates', row: scope.row }"
                >
                  已绑定模版
                </el-dropdown-item>
                <el-dropdown-item :command="{ type: 'edit', row: scope.row }">
                  <svg-icon icon-class="edit" />编辑
                </el-dropdown-item>
                <el-dropdown-item :command="{ type: 'delete', row: scope.row }">
                  <svg-icon icon-class="delete" />删除
                </el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </template>
        <!-- <template #default="scope">
          <div class="btns">
            <el-button type="primary" size="small" @click="selTemplate(scope.row)"
              >选择模版</el-button
            >
            <el-button type="primary" size="small" @click="enterPro(scope.row)"
              >输入项目</el-button
            >
            <el-button type="primary" size="small" @click="btnEdit(scope.row)"
              ><svg-icon icon-class="edit" />编辑</el-button
            >
            <el-button
              type="danger"
              size="small"
              @click="btnDelete(scope.row.id)"
              ><svg-icon icon-class="delete" />删除</el-button
            >
          </div>
        </template> -->
      </el-table-column>
    </el-table>

    <div class="page-info">
      <el-pagination
        :current-page="queryForm.page"
        :page-size="queryForm.pageSize"
        :total="recordCount"
        :page-count="pageTotal"
        background
        layout="prev, pager, next"
        @current-change="ChangePage"
      />
    </div>

    <el-dialog
      
      :visible.sync="dialogVisible"
      append-to-body
      custom-class="prod-verify"
      title="创建项目信息"
    >
      <dataInfo :id="currentDataId" @onClose="onClose" />
    </el-dialog>
    <!-- 选择模版 v-el-drag-dialog-->
    <el-dialog
      title="选择模版"
      :visible.sync="templateDialogVisible"
      width="50%"
      append-to-body
      :close-on-click-modal="false"
      top="5%"
    >
      <div class="dialog-header" style="margin-bottom: 20px">
        <!-- 左侧按钮 -->
        <div class="header-left">
          <el-button
            type="primary"
            @click="confirmTemplateSelection"
          >确 定</el-button>
          <el-button @click="closeTemplateDialog">取 消</el-button>
        </div>

        <!-- 右侧选择框 -->
        <div class="header-right">
          <el-select
            v-model="templateQueryForm.document_type"
            placeholder="请选择模板类型"
            style="width: 200px"
            @change="handleDocTypeChange"
          >
            <el-option
              v-for="item in documentTypes"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </div>
      </div>
      <!-- 添加文档类型筛选 -->
      <!-- <div class="filter-section" style="margin-bottom: 20px;">
        <el-select
          v-model="templateQueryForm.document_type"
          placeholder="请选择文档类型"
          @change="handleDocTypeChange"
          style="width: 200px;"
        >
          <el-option
            v-for="item in documentTypes"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </div> -->

      <el-table
        ref="templateTable"
        v-loading="templateLoading"
        :data="templateList"
        :max-height="600"
        :row-key="getRowKey"
        element-loading-text="加载中..."
        element-loading-spinner="el-icon-loading"
        element-loading-background="rgba(255, 255, 255, 0.8)"
        @selection-change="handleSelectionChange"
        @select="handleSelect"
        @select-all="handleSelectAll"
        @current-change="handleCurrentRowChange"
      >
        <el-table-column 
          type="selection" 
          width="55"
          :selectable="isSelectable"
          :reserve-selection="true"
        />
        <el-table-column prop="id" label="ID" width="80" align="center" />
        <el-table-column prop="title" label="模版名称" align="left" />
        <el-table-column prop="create_time" label="创建时间" align="center" />
      </el-table>
      <div class="pagination-container">
        <el-pagination
          :current-page="templateQueryForm.page"
          :page-sizes="pageSizes"
          :page-size="templateQueryForm.pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="templateTotal"
          @size-change="handleSizeChange"
          @current-change="handleTemplatePageChange"
        />
      </div>
      <div slot="footer" class="dialog-footer">
        <!-- <span style="float: left; line-height: 32px;">
          已选择 {{ getSelectedCount() }} 项
        </span>    v-el-drag-dialog-->
      </div>
    </el-dialog>
    <el-dialog
   
      title="已绑定模版"
      :visible.sync="boundTemplatesDialogVisible"
      width="50%"
      append-to-body
      :close-on-click-modal="false"
    >
      <el-table
        ref="boundTemplateTable"
        :data="boundTemplateList"
        style="width: 100%"
        @selection-change="handleBoundTemplateSelect"
      >
        <el-table-column type="selection" width="55" />
        <el-table-column prop="id" label="ID" width="80" align="center" />
        <el-table-column prop="title" label="模版名称" align="left" />
        <el-table-column prop="createTime" label="绑定时间" align="center" />
        <el-table-column label="操作" align="center" width="320">
          <template #default="scope">
            <el-button
              type="primary"
              @click="previewTemplate(scope.row)"
            >预览</el-button>
           <!--  <el-button
              type="primary"
              @click="replaceTemplate(scope.row)"
            >替换</el-button> -->
            <el-dropdown
              style="margin-left: 10px"
              trigger="click"
              @command="(command) => handleExport(command, scope.row)"
            >
              <el-button type="success">
                导出文档<i class="el-icon-arrow-down el-icon--right" />
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item command="word">Word格式</el-dropdown-item>
                  <el-dropdown-item command="pdf">PDF格式</el-dropdown-item>
                </el-dropdown-menu> </template><!-- word -->
              <!-- <el-dropdown-item command="pdf-to-word"
                    >Word</el-dropdown-item
                  > -->
            </el-dropdown>
          </template>
        </el-table-column>
      </el-table>
      <div class="dialog-footer" style="margin-top: 20px; text-align: right; margin-bottom: 10px;">
        <el-button
          type="primary"
          :loading="batchReplaceLoading"
          :disabled="selectedBoundTemplates.length === 0"
          @click="batchReplace"
        >
          批量替换
        </el-button>
      </div>
    </el-dialog>
    <el-dialog
      title=""
      :visible.sync="replaceVisible"
      width="50%"
      append-to-body
    >
      <!-- 显示匹配 -->
      <div v-if="matchResults.length" class="match-results">
        <div
          v-for="(item, index) in matchResults"
          :key="index"
          class="match-item"
        >
          <div class="match-content">
            <span>原始值: {{ item }}</span>
            <!-- <span>替换后: {{ item  }}</span> -->
          </div>
          <div class="actions">
            <el-button size="small" @click="replaceItem(item)">替换</el-button>
          </div>
        </div>
        <div style="display: flex; justify-content: flex-end; margin-top: 20px">
          <el-button type="primary" @click="replaceAll">批量替换</el-button>
        </div>
      </div>
    </el-dialog>
    <!-- 添加选择文档弹窗 -->
    <el-dialog
      title="选择文档版本"
      :visible.sync="documentSelectVisible"
      width="50%"
      append-to-body
      :close-on-click-modal="false"
    >
      <el-table
        v-loading="documentVersionsLoading"
        :data="documentVersions"
        style="width: 100%"
      >
        <el-table-column prop="id" label="ID" width="80" align="center" />
        <el-table-column prop="title" label="文档标题" align="left" />
        <el-table-column prop="createTime" label="创建时间" align="center" />
        <el-table-column label="操作" align="center" width="250">
          <template #default="scope">
            <el-button
              type="primary"
              size="small"
              style="margin-right: 10px"
              @click="handleDocPreview(scope.row)"
            >
              预览
            </el-button>
            <el-dropdown
              trigger="click"
              @command="(command) => handleDocExport(command, scope.row)"
            >
              <el-button type="success" size="small">
                导出<i class="el-icon-arrow-down el-icon--right" />
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item command="word">Word格式</el-dropdown-item>
                  <el-dropdown-item command="pdf">PDF格式</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>

<script>
import {
  searchProject,
  deleteProject,
  searchCategory,
  relate,
  searchTemplateList,
  searchTemplateListNoData,
  getstatus,
  calculate,
  getphases
} from '@/api/project'
import {
  searchList,
  exportToPDF,
  htmlWordNew,
  createDocument,
  searchlistDoc,
  getDocumentInfo,
  updateDocument,
  searchlistDocTemplate
} from '@/api/document'
import { searchCustomer } from '@/api/customer'
import { searchProduct } from '@/api/product'
/* import {searchTemplate} from "@/api/template" */
import dataInfo from './dataInfo.vue'
import elDragDialog from '@/directive/el-drag-dialog'
import axios from 'axios'
import htmlDocx from 'html-docx-js/dist/html-docx' // 需要先安装: npm install html-docx-js
import { saveAs } from 'file-saver' // 需要先安装: npm install file-saver

export default {
  components: {
    dataInfo
  },
  directives: { elDragDialog },
  props: {
    queryForm: {
      type: Object,
      default: () => {
        return {
          page: 1,
          pageSize: 10,
          name: '',
          category_id: '',
          status: ''
        }
      }
    }
  },
  data() {
    return {
      templateQueryForm: {
        page: 1,
        pageSize: 10, // 默认每页显示10条
        document_type: '' // 添加文档类型字段
      },
      pageSizes: [10, 20, 50, 100], // 每页显示条数选项
      templateTotal: 0, // 模版总数
      dialogVisible: false, // 控制产品审核
      currentDataId: 0,
      recordCount: 0,
      pageTotal: 1,
      dataList: [],
      currentData: {},
      categoryList: [],
      templateDialogVisible: false,
      templateList: [],
      selectedTemplates: [], // 改为数组以支持多选
      boundTemplatesDialogVisible: false,
      previewDialogVisible: false,
      boundTemplateList: [],
      templatePreviewContent: '',
      currentTemplateId: null,
      replaceVisible: false,
      loading: false, // 增加 loading 状态
      searchResult: {},
      matchResults: [], // 存储匹配到的结果
      TemList: [],
      docAttr: {},
      templateLoading: false, // 添加模版加载状态
      boundTemplateLoading: false, // 添加已绑定模版加载状态
      selectedBoundTemplates: [], // 新增：已选择的绑定模版
      batchReplaceLoading: false, // 新增：批量替换loading状态
      getstatusList: [], // 状态列表
      customList: [], // 客户列表
      productList: [], // 产品列表
      currentPhaseList: [], // 阶段列表
      selectedTemplateIds: new Set(), // 存储所有选中项的ID
      selectedPageIds: new Map(), // 存储每页的选择状态
      isAllSelected: false, // 是否全选
      selectionCache: new Map(), // 添加选择缓存

      // 添加文档类型选项
      documentTypes: [
        { label: '全部', value: '' },
        { label: '临床', value: 'Clinical' },
        { label: '非临床', value: 'NonClinical' }
      ],
      documentSelectVisible: false, // 文档选择弹窗显示状态
      documentVersions: [], // 文档版本列表
      documentVersionsLoading: false, // 加载状态
      currentTemplate: null, // 当前选中的模板
      confirmLoading: false, // 添加确认加载状态
    }
  },
  computed: {
    tableColumns() {
      return [
        // ... 其他列配置 ...
        {
          prop: 'calculate',
          label: '完成度',
          width: '100',
          render: (h, { row }) => {
            // 使用过渡效果显示完成度
            return h(
              'el-tooltip',
              {
                props: {
                  content: '加载中...',
                  disabled: row.calculate !== 0
                }
              },
              [
                h(
                  'span',
                  {
                    class: [
                      this.getCompletionClass(row.calculate),
                      'completion-text'
                    ]
                  },
                  [
                    row.calculate === 0
                      ? h('i', { class: 'el-icon-loading' })
                      : this.formatCompletion(row.calculate)
                  ]
                )
              ]
            )
          }
        }
      ]
    }
  },
  watch: {
    queryForm: {
      handler: function(val) {
        this.search()
      },
      // immediate: true,//立即执行
      deep: true
    }
  },
  mounted() {
    this.search()
    this.init()
  },
  methods: {
    /* 使用html-docx-js方法替换 */
    // 预处理内容，处理分页和表格
    preprocessContent(content) {
      if (!content) return ''

      const tempDiv = document.createElement('div')
      tempDiv.innerHTML = content

      // 处理分页符
      tempDiv
        .querySelectorAll('div[style*="page-break-after"]')
        .forEach((pageBreak) => {
          const newPageBreak = document.createElement('br')
          newPageBreak.style.pageBreakBefore = 'always'
          newPageBreak.style.clear = 'both'
          newPageBreak.className = 'WordSection'
          pageBreak.parentNode.replaceChild(newPageBreak, pageBreak)
        })

      // 处理图片
      tempDiv.querySelectorAll('img').forEach((img) => {
        // 保持原有尺寸或设置默认尺寸
        const width = img.getAttribute('width') || img.style.width || '595px'
        const height = img.getAttribute('height') || img.style.height || 'auto'
        img.style.width = width
        img.style.height = height
      })

      // 处理表格
      tempDiv.querySelectorAll('table').forEach((table) => {
        // 添加固定布局属性，防止列宽自适应
        table.style.tableLayout = 'fixed'
        
        // 保存原始列宽
        const firstRow = table.querySelector('tr')
        if (firstRow) {
          const cells = firstRow.querySelectorAll('td, th')
          cells.forEach((cell, index) => {
            // 获取原始宽度
            const width = cell.getAttribute('width') || cell.style.width
            if (width) {
              // 为所有行的相同位置单元格设置相同宽度
              table.querySelectorAll(`tr td:nth-child(${index + 1}), tr th:nth-child(${index + 1})`).forEach(td => {
                td.style.width = width
                // 确保宽度不会被覆盖
                td.setAttribute('width', width)
              })
            }
          })
        }
        
        if (this.isTableWithBorder(table)) {
          table.setAttribute('data-code', 'active')
        } else {
          table.setAttribute('data-code', 'noactive')
        }
      })

      return tempDiv.innerHTML
    },

    // 保证替换内容为内联且不换行：将 div/p 等块级标签转换为 span，并强制 white-space: nowrap
    ensureInlineNoWrap(html) {
      if (!html) return ''
      try {
        const wrapper = document.createElement('div')
        wrapper.innerHTML = html

        // 将所有 div/p 转为 span，保留原有内联样式
        wrapper.querySelectorAll('div, p').forEach(block => {
          const span = document.createElement('span')
          // 复制子内容
          while (block.firstChild) {
            span.appendChild(block.firstChild)
          }
          // 合并样式并强制不换行与内联显示
          const style = (block.getAttribute('style') || '')
          span.setAttribute('style', `${style}${style.endsWith(';') ? '' : ';'} display: inline; white-space: nowrap;`)
          // 替换节点
          block.parentNode.replaceChild(span, block)
        })

        // 确保所有顶层文本不含多余换行或制表符
        const normalizeTextNodes = (node) => {
          node.childNodes && Array.from(node.childNodes).forEach(child => {
            if (child.nodeType === Node.TEXT_NODE) {
              child.textContent = child.textContent.replace(/[\t\r\n\f\v]+/g, ' ')
            } else if (child.nodeType === Node.ELEMENT_NODE) {
              normalizeTextNodes(child)
            }
          })
        }
        normalizeTextNodes(wrapper)

        return wrapper.innerHTML
      } catch (e) {
        return typeof html === 'string' ? html : ''
      }
    },

    // 更新导出方法
    async exportDocumentWithHtmlDocx(template) {
      const res = await searchlistDocTemplate({
        project_id: this.currentData.id,
        id: template.id
      })
      if(res.status !== 200) return
      let templateData
      try {
        if(res.data.documents.length !== 0) {
          templateData = JSON.parse(res.data.documents[0].data || '[]')
        } else {
          const template_Data = await getDocumentInfo({id:template.id})
          if(template_Data.status !== 200) return
          templateData = JSON.parse(template_Data.data.data || '[]')
        }
        const contentContainer = document.createElement('div')
        contentContainer.className = 'content'

        // 处理每个模版段落
        templateData.forEach((item) => {
          const templateSection = document.createElement('div')
          templateSection.className = 'template-textarea'
          templateSection.innerHTML = this.preprocessContent(item.content)
          contentContainer.appendChild(templateSection)
        })
        
        let contentData = `
          <!DOCTYPE html>
          <html xmlns:v="urn:schemas-microsoft-com:vml" 
              xmlns:o="urn:schemas-microsoft-com:office:office" 
              xmlns:w="urn:schemas-microsoft-com:office:word">
          <head>
            <meta charset="UTF-8">
            <xml>
              <w:WordDocument>
                <w:View>Print</w:View>
                <w:Zoom>100</w:Zoom>
                <w:DoNotOptimizeForBrowser/>
              </w:WordDocument>
            </xml>
            <style>
              /* 基础样式 */
              
              /* 保持表格固定布局，防止自适应 */
              table {
                width: 100%;
                border-collapse: collapse !important;
                margin: 8px 0;
                table-layout: fixed !important;
                word-wrap: break-word;
              }
              
              /* 确保单元格宽度固定 */
              table td, table th {
                word-wrap: break-word;
                overflow-wrap: break-word;
                overflow: hidden;
              }
              
              /* 有边框表格样式 */
              table[data-code="active"] {
                border: 1px solid black !important;
                border-collapse: collapse !important;
              }
              
              table[data-code="active"] td,
              table[data-code="active"] th {
                border: 1px solid black !important;
                padding: 6px !important;
                mso-border-alt: solid black .5pt !important;
                mso-border-insideh: .5pt solid black !important;
                mso-border-insidev: .5pt solid black !important;
              }
              
              /* 无边框表格样式 */
              table[data-code="noactive"] {
                border: none !important;
                border-collapse: collapse !important;
              }
              
              table[data-code="noactive"] td,
              table[data-code="noactive"] th {
                border: none !important;
                padding: 6px !important;
              }
              
              /* Word特定的表格边框样式 */
              .MsoNormalTable {
                mso-style-name: "普通表格";
                mso-tstyle-rowband-size: 0;
                mso-tstyle-colband-size: 0;
                mso-padding-alt: 0cm 5.4pt 0cm 5.4pt;
                table-layout: fixed !important;
              }
              
              /* 确保空格正确显示 */
              .preserve-whitespace {
                white-space: pre-wrap;
              }
            </style>
          </head>
          <body>
            ${this.processContentForWord(contentContainer.innerHTML)}
          </body>
          </html>
        `

        // 添加Word特定的分页处理
        contentData = contentData.replace(
          /<br class="WordSection"[^>]*>/g,
          '<br clear="all" style="page-break-before:always; mso-break-type:section-break">'
        )

        const converted = htmlDocx.asBlob(contentData, {
          orientation: 'portrait',
          margins: {
            top: '2.54cm',
            right: '2.54cm',
            bottom: '2.54cm',
            left: '2.54cm'
          },
          // 添加Word特定的文档属性
          docProperties: {
            'w:sectPr': {
              'w:type': { _attr: { 'w:val': 'nextPage' }}
            }
          }
        })

        saveAs(converted, `${template.title}.docx`)
      } catch (error) {
        console.error('导出Word文档失败:', error)
        throw new Error('导出文档时发生错误，请稍后重试')
      }
    },
    /* 处理图片 */
    htmlProcessImages(content) {
      const tempDiv = document.createElement('div')
      tempDiv.innerHTML = content
      // 处理所有图片
      tempDiv.querySelectorAll('img').forEach((img) => {
        // 创建图片容器
        const container = document.createElement('div')
        container.className = 'image-container'
        // 获取所有可能的尺寸来源
        let width =
          img.getAttribute('width') || img.style.width || img.width || null
        let height =
          img.getAttribute('height') || img.style.height || img.height || null
        // 移除单位并转换为数字
        if (typeof width === 'string') {
          width = parseInt(width.replace(/[^0-9]/g, ''))
        }
        if (typeof height === 'string') {
          height = parseInt(height.replace(/[^0-9]/g, ''))
        }
        // 如果没有尺寸，创建一个临时图片来获取实际尺寸
        if (!width || !height) {
          const tempImg = new Image()
          tempImg.src = img.src
          width = tempImg.width || 595 // 默认宽度
          height = tempImg.height || Math.round(width * 0.75) // 默认高度比例
        }
        // 确保数值有效
        width = Math.max(1, parseInt(width))
        height = Math.max(1, parseInt(height))
        // 处理尺寸
        const maxWidth = 595 // A4纸宽度（像素，减去边距）
        if (width > maxWidth) {
          // 等比例缩放
          const aspectRatio = width / height
          const newHeight = Math.round(maxWidth / aspectRatio)
          width = maxWidth
          height = newHeight
        }
        // 同时设置style和属性
        img.style.width = `${width}px`
        img.style.height = `${height}px`
        img.setAttribute('width', width)
        img.setAttribute('height', height)
        // 将图片包装在容器中
        img.parentNode.insertBefore(container, img)
        container.appendChild(img)
      })
      return tempDiv.innerHTML
    },

    // 预处理表格
    preprocessTables(content) {
      const tempDiv = document.createElement('div')
      tempDiv.innerHTML = content

      // 处理所有表格
      tempDiv.querySelectorAll('table').forEach((table, index) => {
        if (this.isTableWithBorder(table)) {
          // 处理有边框表格
          this.processTableWithBorder(table, index)
        } else {
          // 处理无边框表格
          this.processTableNoBorder(table, index)
        }
      })

      return tempDiv.innerHTML
    },

    // 处理有边框表格
    processTableWithBorder(table, index) {
      // 创建表格容器
      const container = document.createElement('div')
      container.className = 'table-container'

      // 获取表头行
      const headerRow = table.querySelector('tr')
      const hasHeader = headerRow && headerRow.querySelector('th')

      // 复制原始表格并添加必要的类和属性
      const clonedTable = table.cloneNode(true)
      clonedTable.className = 'table-with-border continuous-table'
      clonedTable.setAttribute('data-table-id', `table-${index}`)

      if (hasHeader) {
        // 保存表头信息
        const headerHTML = headerRow.outerHTML
        clonedTable.setAttribute('data-header', headerHTML)
        clonedTable.setAttribute('data-repeat-header', 'true')
      }

      // 处理表格的每一行
      clonedTable.querySelectorAll('tr').forEach((row, rowIndex) => {
        row.setAttribute('data-row-index', rowIndex)
        row.style.pageBreakInside = 'avoid'
      })

      // 将处理后的表格放入容器
      container.appendChild(clonedTable)
      table.parentNode.replaceChild(container, table)
    },

    // 处理无边框表格
    processTableNoBorder(table, index) {
      // 创建表格容器
      const container = document.createElement('div')
      container.className = 'table-container-no-border'

      // 复制原始表格并添加必要的类和属性
      const clonedTable = table.cloneNode(true)
      clonedTable.className = 'table-no-border'
      clonedTable.setAttribute('data-table-id', `table-no-border-${index}`)

      // 处理表格的每一行，保持原有样式
      clonedTable.querySelectorAll('tr').forEach((row) => {
        const originalRowStyles = row.getAttribute('style') || ''
        row.style.cssText = `
          page-break-inside: avoid;
          ${originalRowStyles}
        `

        // 处理单元格，保持原有样式
        row.querySelectorAll('td, th').forEach((cell) => {
          const originalStyles = cell.getAttribute('style') || ''
          cell.style.cssText = `
            border: none !important;
            padding: 6px;
            word-wrap: break-word;
            overflow: hidden;
            ${originalStyles}
          `
        })
      })

      // 将处理后的表格放入容器
      container.appendChild(clonedTable)
      table.parentNode.replaceChild(container, table)
    },

    // 处理表格内容
    processContentForWord(content) {
      const tempDiv = document.createElement('div')
      tempDiv.innerHTML = content

      // 处理所有表格
      tempDiv.querySelectorAll('table').forEach((table) => {
        // 确保表格使用固定布局
        table.style.tableLayout = 'fixed'
        
        // 检查表格是否有边框
        const hasBorder = this.detectTableBorder(table)

        if (hasBorder) {
          // 为有边框的表格添加必要的属性和类
          table.setAttribute('data-code', 'active')
          table.setAttribute('class', 'MsoNormalTable')
          table.setAttribute('border', '1')
          table.style.borderCollapse = 'collapse'

          // 处理所有单元格
          table.querySelectorAll('td, th').forEach((cell) => {
            // 保存原有样式
            const originalStyles = cell.getAttribute('style') || ''

            // 添加Word特定的边框样式
            cell.style.cssText = `
              border: 1px solid black !important;
              mso-border-alt: solid black .5pt !important;
              padding: 6px !important;
              ${originalStyles}
            `
          })
        } else {
          // 处理无边框表格
          table.setAttribute('data-code', 'noactive')
          table.removeAttribute('border')
          table.style.border = 'none'

          // 移除所有单元格边框
          table.querySelectorAll('td, th').forEach((cell) => {
            cell.style.border = 'none'
            cell.style.padding = '6px'
          })
        }
        
        // 保存第一行的列宽并应用到所有行
        const firstRow = table.querySelector('tr')
        if (firstRow) {
          const cells = firstRow.querySelectorAll('td, th')
          cells.forEach((cell, index) => {
            // 获取原始宽度
            const width = cell.getAttribute('width') || cell.style.width
            if (width) {
              // 为所有行的相同位置单元格设置相同宽度
              table.querySelectorAll(`tr td:nth-child(${index + 1}), tr th:nth-child(${index + 1})`).forEach(td => {
                td.style.width = width
                // 确保宽度不会被覆盖
                td.setAttribute('width', width)
                // 添加Word特定的宽度属性
                td.setAttribute('w:w', width.replace(/[^\d]/g, ''))
              })
            }
          })
        }
      })

      return tempDiv.innerHTML
    },

    // 添加检测表格边框的方法
    detectTableBorder(table) {
      // 1. 检查表格本身的边框属性
      if (
        table.getAttribute('border') ||
        /border(?!-collapse)/.test(table.style.cssText) ||
        table.classList.contains('bordered') ||
        table.hasAttribute('rules')
      ) {
        return true
      }

      // 2. 检查计算样式
      const computedStyle = window.getComputedStyle(table)
      if (
        computedStyle.border !== 'none' ||
        computedStyle.borderCollapse === 'collapse'
      ) {
        return true
      }

      // 3. 检查第一个单元格的边框
      const firstCell = table.querySelector('td, th')
      if (firstCell) {
        const cellStyle = window.getComputedStyle(firstCell)
        return (
          cellStyle.border !== 'none' ||
          cellStyle.borderTop !== 'none' ||
          cellStyle.borderBottom !== 'none' ||
          cellStyle.borderLeft !== 'none' ||
          cellStyle.borderRight !== 'none'
        )
      }

      return false
    },

    // 添加处理分的辅助方法
    addPageBreaks(content) {
      // 查找需要分页的位置（可以根据实际需求调整）
      const pageBreakMarkers = ['<h1', '<h2', '<!-- pagebreak -->']

      pageBreakMarkers.forEach((marker) => {
        content = content.replace(
          new RegExp(marker, 'g'),
          `<div class="page-break"></div>${marker}`
        )
      })

      return content
    },

    // 处理表格边框的辅助方法
    processTableBorders(table) {
      const isInfoTable = this.isInformationTable(table)

      if (isInfoTable) {
        table.classList.add('info-table')
      } else {
        // 检查表格是否需要边框
        const needsBorder = this.checkTableNeedsBorder(table)
        if (needsBorder) {
          table.style.border = '1px solid black'
          table.querySelectorAll('td, th').forEach((cell) => {
            cell.style.border = '1px solid black'
          })
        }
      }
    },

    // 检查表格是否需要边框
    checkTableNeedsBorder(table) {
      // 检查表格第一行是否包含特定标记或样式
      const firstRow = table.querySelector('tr')
      if (!firstRow) return false

      // 可以根据实际需求添加更多的判断条件
      return (
        firstRow.querySelector('td[style*="border"]') !== null ||
        table.getAttribute('border') === '1' ||
        table.classList.contains('bordered')
      )
    },

    // 添加内容处方法
    processContentForWord(content) {
      const tempDiv = document.createElement('div')
      tempDiv.innerHTML = content

      // 添加表格分页标识
      let tableCounter = 0

      // 处理表格
      tempDiv.querySelectorAll('table').forEach((table) => {
        tableCounter++
        const tableId = `table_${tableCounter}`
        table.setAttribute('data-table-id', tableId)

        // 判断表格类型
        const isInfoTable = this.isInformationTable(table)
        const isContinuousTable = this.isContinuousTable(table)

        // 基本表格样式
        table.style.width = '100%'
        table.style.borderCollapse = 'collapse'
        table.style.tableLayout = 'fixed'

        if (isInfoTable) {
          // 信息表格处理逻辑保持不变
          table.classList.add('info-table')
          this.processInfoTable(table)
        } else if (isContinuousTable) {
          // 处理跨页连续表格
          table.classList.add('continuous-table')
          this.processContinuousTable(table, tableCounter)
        } else {
          // 普通表格处理逻辑保持不变
          this.processNormalTable(table)
        }
      })

      // 添加表格连续性样式
      const styleElement = document.createElement('style')
      styleElement.textContent = this.generateTableStyles(tableCounter)
      tempDiv.insertBefore(styleElement, tempDiv.firstChild)

      return tempDiv.innerHTML
    },

    // 判断是否为连续表格
    isContinuousTable(table) {
      // 检查表格是否有分页标记
      const prevElement = table.previousElementSibling
      return prevElement && prevElement.classList.contains('page-break')
    },

    // 处理连续表格
    processContinuousTable(table, tableCounter) {
      // 设置表格基本样式
      table.style.borderCollapse = 'collapse'
      table.style.border = '1px solid black'

      // 处理所有单元格
      table.querySelectorAll('tr').forEach((row, rowIndex) => {
        row.style.borderTop = '1px solid black'
        row.style.borderBottom = '1px solid black'

        row.querySelectorAll('td, th').forEach((cell) => {
          const originalStyles = cell.getAttribute('style') || ''
          cell.style.cssText = `
            border: 1px solid black !important;
            padding: 6px;
            word-wrap: break-word;
            overflow: hidden;
            ${originalStyles}
          `
        })
      })
    },

    // 生成表格样式
    generateTableStyles() {
      return `
        /* 原有表样式保持不变 */
        .table-with-border {
          /* ... */
        }
        
        .table-no-border {
          /* ... */
        }
        
        /* 确保表格不会被分页符影响 */
        table {
          -webkit-column-break-inside: avoid;
          page-break-inside: avoid;
          break-inside: avoid;
        }
      `
    },

    // 添加判断表格类型的方法
    isInformationTable(table) {
      // 获取表格第一行第一个单元格的文本
      const firstCell = table.querySelector('td')
      if (!firstCell) return false

      // 定义信息表格的特征文本数组
      const infoTableHeaders = [
        'Drafted by',
        'Reviewed by',
        'Approved by',
        'File number',
        'Revision',
        'Effective'
      ]

      // 检查第一个单元格的文本是否匹配特征文本
      return infoTableHeaders.some(
        (header) =>
          firstCell.textContent.trim().toLowerCase() === header.toLowerCase()
      )
    },
    // 添加处理普通表格的方法
    processNormalTable(table) {
      // 处理行和单元格
      table.querySelectorAll('tr').forEach((row, rowIndex) => {
        // 保持原始行高
        const height = row.style.height || row.getAttribute('height')
        if (height) {
          row.style.height = height
        }

        // 处理单元格
        row.querySelectorAll('td, th').forEach((cell, cellIndex) => {
          // 获取原始样式
          const originalStyles = cell.getAttribute('style') || ''

          // 设置单元格样式
          cell.style.cssText = `
            padding: 6px;
            word-wrap: break-word;
            overflow: hidden;
            ${originalStyles}
          `

          // 保持原始宽度
          if (rowIndex === 0) {
            const width = cell.style.width || cell.getAttribute('width')
            if (width) {
              cell.style.width = width
              // 为该列的所有单元格设置相同的宽度
              table
                .querySelectorAll(
                  `tr td:nth-child(${cellIndex + 1}), tr th:nth-child(${
                    cellIndex + 1
                  })`
                )
                .forEach((td) => {
                  td.style.width = width
                })
            }
          }

          // 处理合并单元格
          if (cell.hasAttribute('rowspan')) {
            cell.style.verticalAlign = 'middle'
          }
        })
      })
    },

    // 添加处理信息表格的方法
    processInfoTable(table) {
      table.querySelectorAll('tr').forEach((row) => {
        row.querySelectorAll('td').forEach((cell, index) => {
          // 第一列（标签列）样式
          if (index === 0) {
            cell.style.cssText = `
              border: 1px solid black;
              padding: 6px;
              width: 150px;
              font-weight: normal;
              text-align: left;
              background-color: white;
            `
          }
          // 第二列（内容列）样式
          else {
            cell.style.cssText = `
              border: 1px solid black;
              padding: 6px;
              text-align: left;
            `
          }

          // 保持原始对齐方式
          const originalAlign = cell.getAttribute('align')
          if (originalAlign) {
            cell.style.textAlign = originalAlign
          }
        })
      })
    },

    // 判断表格类型的方法
    isTableWithBorder(table) {
      // 检查表格是否有边框属性
      if (table.getAttribute('border') === '1') return true

      // 检查表格是否有边框样式
      if (table.style.border || table.classList.contains('bordered')) { return true }

      // 检查第一个单格是否有边框
      const firstCell = table.querySelector('td, th')
      if (firstCell && firstCell.style.border) return true

      // 检查是否为信息类表格
      const firstCellText = firstCell?.textContent?.trim().toLowerCase() || ''
      const infoHeaders = [
        'drafted by',
        'reviewed by',
        'approved by',
        'file number',
        'revision',
        'effective'
      ]
      return infoHeaders.some((header) =>
        firstCellText.includes(header.toLowerCase())
      )
    },

    // 处理表格的主方法
    processContentForWord(content) {
      const tempDiv = document.createElement('div')
      tempDiv.innerHTML = content

      // 添加表格分页标识
      let tableCounter = 0

      // 处理表格
      tempDiv.querySelectorAll('table').forEach((table) => {
        tableCounter++
        const tableId = `table_${tableCounter}`
        table.setAttribute('data-table-id', tableId)

        // 判断表格类型
        const isInfoTable = this.isInformationTable(table)
        const isContinuousTable = this.isContinuousTable(table)
        const hasTableBorder = this.isTableWithBorder(table)

        // 基本表格样式
        table.style.width = '100%'
        table.style.borderCollapse = 'collapse'
        table.style.tableLayout = 'fixed'

        if (isInfoTable) {
          // 信息表格处理逻辑
          table.classList.add('info-table')
          this.processInfoTable(table)
        } else if (isContinuousTable && hasTableBorder) {
          // 处理有边框的跨页连续表格
          table.classList.add('continuous-table-with-border')
          this.processContinuousTableWithBorder(table, tableCounter)
        } else if (isContinuousTable) {
          // 处理无边框的跨页连续表格
          table.classList.add('continuous-table-no-border')
          this.processContinuousTableNoBorder(table, tableCounter)
        } else if (hasTableBorder) {
          // 处理有边框的普通表格
          table.classList.add('normal-table-with-border')
          this.processNormalTableWithBorder(table)
        } else {
          // 处理无边框的普通表格
          table.classList.add('normal-table-no-border')
          this.processNormalTableNoBorder(table)
        }
      })

      // 添加表格样式
      const styleElement = document.createElement('style')
      styleElement.textContent = this.generateTableStyles(tableCounter)
      tempDiv.insertBefore(styleElement, tempDiv.firstChild)

      return tempDiv.innerHTML
    },

    // 处理有边框的普通表格
    processNormalTableWithBorder(table) {
      table.style.border = '1px solid black'

      table.querySelectorAll('tr').forEach((row, rowIndex) => {
        // 保持原始行高
        const height = row.style.height || row.getAttribute('height')
        if (height) {
          row.style.height = height
        }

        row.querySelectorAll('td, th').forEach((cell, cellIndex) => {
          const originalStyles = cell.getAttribute('style') || ''
          cell.style.cssText = `
            border: 1px solid black;
            padding: 6px;
            word-wrap: break-word;
            overflow: hidden;
            ${originalStyles}
          `

          // 保持原始宽度
          if (rowIndex === 0) {
            const width = cell.style.width || cell.getAttribute('width')
            if (width) {
              this.setColumnWidth(table, cellIndex, width)
            }
          }
        })
      })
    },

    // 处理无边框的普通表格
    processNormalTableNoBorder(table) {
      table.querySelectorAll('tr').forEach((row, rowIndex) => {
        // 保持原始行高
        const height = row.style.height || row.getAttribute('height')
        if (height) {
          row.style.height = height
        }

        row.querySelectorAll('td, th').forEach((cell, cellIndex) => {
          const originalStyles = cell.getAttribute('style') || ''
          cell.style.cssText = `
            padding: 6px;
            word-wrap: break-word;
            overflow: hidden;
            ${originalStyles}
          `

          // 保持原始宽度
          if (rowIndex === 0) {
            const width = cell.style.width || cell.getAttribute('width')
            if (width) {
              this.setColumnWidth(table, cellIndex, width)
            }
          }
        })
      })
    },

    // 处理有边框的连续表格
    processContinuousTableWithBorder(table, tableCounter) {
      // 设置表格基本样式
      table.style.borderCollapse = 'collapse'
      table.style.border = '1px solid black'

      // 为表格添加唯一标识
      const tableId = `bordered-table-${tableCounter}`
      table.id = tableId

      // 处理所有行和单元格
      table.querySelectorAll('tr').forEach((row, rowIndex) => {
        // 设置行样式
        row.style.borderTop = '1px solid black'
        row.style.borderBottom = '1px solid black'
        row.style.pageBreakInside = 'avoid' // 防止行内分页

        // 处理单元格
        row.querySelectorAll('td, th').forEach((cell, cellIndex) => {
          const originalStyles = cell.getAttribute('style') || ''
          cell.style.cssText = `
            border: 1px solid black !important;
            padding: 6px;
            word-wrap: break-word;
            overflow: hidden;
            ${originalStyles}
          `
        })
      })

      // 添加特定样式以处理分页情况
      const styleSheet = document.createElement('style')
      styleSheet.textContent = `
        #${tableId} {
          border-collapse: collapse !important;
          border: 1px solid black !important;
        }
        
        #${tableId} tr {
          border-top: 1px solid black !important;
          border-bottom: 1px solid black !important;
        }
        
        #${tableId} td,
        #${tableId} th {
          border: 1px solid black !important;
        }
        
        /* 处理分页后的表格边框 */
        @media print {
          #${tableId} {
            border: 1px solid black !important;
          }
          
          #${tableId}[data-table-continued="true"] {
            border-top: 1px solid black !important;
          }
          
          #${tableId}[data-table-start="true"] {
            border-bottom: 1px solid black !important;
          }
        }
      `
      document.head.appendChild(styleSheet)
    },

    // 处理无边框的连续表格
    processContinuousTableNoBorder(table, tableCounter) {
      table.querySelectorAll('tr').forEach((row) => {
        row.querySelectorAll('td, th').forEach((cell) => {
          const originalStyles = cell.getAttribute('style') || ''
          cell.style.cssText = `
            padding: 6px;
            word-wrap: break-word;
            overflow: hidden;
            ${originalStyles}
          `
        })
      })
    },

    // 设置列宽的辅助方法
    setColumnWidth(table, columnIndex, width) {
      table
        .querySelectorAll(
          `tr td:nth-child(${columnIndex + 1}), tr th:nth-child(${
            columnIndex + 1
          })`
        )
        .forEach((td) => {
          td.style.width = width
        })
    },

    // 生成表格样式
    generateTableStyles(tableCount) {
      return `
        /* 基础表格样式 */
        table {
          width: 100%;
          border-collapse: collapse;
          table-layout: fixed;
          page-break-inside: auto;
        }
        
        /* 自适应行高表格样式 */
        .auto-height-table tr {
          height: auto !important;
          min-height: 30px;
        }
        
        .auto-height-table td,
        .auto-height-table th {
          white-space: normal;
          word-wrap: break-word;
          vertical-align: middle;
          padding: 8px;
        }
        
        /* 有边框表格的通用样式 */
        table[data-has-border="true"] {
          border-collapse: collapse !important;
        }
        
        /* 处理分页情况 */
        @media print {
          /* 确保分页后的表格边框显示 */
          table[data-has-border="true"] {
            border: 1px solid black !important;
          }
          
          /* 处理跨页表格的边框 */
          table[data-has-border="true"][data-table-continued="true"] {
            border-top: 1px solid black !important;
            margin-top: 0 !important;
          }
          
          table[data-has-border="true"][data-table-start="true"] {
            border-bottom: 1px solid black !important;
          }
          
          /* 确保所有单元格边框显示 */
          table[data-has-border="true"] td,
          table[data-has-border="true"] th {
            border: 1px solid black !important;
          }
        }
      `
    },

    // 判断表格是否是连续的
    isTableContinued(previousTable, currentTable) {
      // 检查两个表格是否紧邻
      const nextElement = previousTable.nextElementSibling
      if (!nextElement) return false

      // 检查是否有分页标记
      if (nextElement.classList.contains('page-break')) {
        return true
      }

      // 检查表格结构是否相似
      const prevCols = previousTable.querySelectorAll(
        'tr:first-child td, tr:first-child th'
      ).length
      const currCols = currentTable.querySelectorAll(
        'tr:first-child td, tr:first-child th'
      ).length

      return prevCols === currCols
    },

    // 处理表格表头
    processTableHeaders(content) {
      const tempDiv = document.createElement('div')
      tempDiv.innerHTML = content

      // 处理所有需要重复表头的表格
      tempDiv
        .querySelectorAll('table[data-repeat-header="true"]')
        .forEach((table) => {
          const headerHTML = table.getAttribute('data-header')
          if (!headerHTML) return

          // 创建thead元素
          const thead = document.createElement('thead')
          thead.innerHTML = headerHTML

          // 将原有的表头移动到thead中
          const firstRow = table.querySelector('tr')
          if (firstRow) {
            table.insertBefore(thead, firstRow)
          }

          // 确保tbody存在
          if (!table.querySelector('tbody')) {
            const tbody = document.createElement('tbody')
            while (table.querySelector('tr')) {
              tbody.appendChild(table.querySelector('tr'))
            }
            table.appendChild(tbody)
          }
        })

      return tempDiv.innerHTML
    },
    /*  */
    // 添加 PDF 转 Word 的方法
    async convertPDFToWord(pdfPath) {
      try {
        // 创建FormData对象
        const formData = new FormData()
        formData.append('oss_url', pdfPath)

        // 调用后端转换接口
        const res = await axios.post(
          `${process.env.VUE_APP_BASE_API}/convert/pdftoword`,
          formData,
          {
            headers: {
              'Content-Type': 'multipart/form-data' // 设置请求头为form-data
            }
          }
        )

        if (res.status === 200) {
          // 将base64转换为Blob
          const byteCharacters = atob(res.data.data.file_content)
          const byteNumbers = new Array(byteCharacters.length)
          for (let i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i)
          }
          const byteArray = new Uint8Array(byteNumbers)
          const blob = new Blob([byteArray], {
            type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
          })

          // 创建下载链接
          const link = document.createElement('a')
          link.href = URL.createObjectURL(blob)
          link.download = 'converted.docx' // 或使用服务器返回的文件名
          document.body.appendChild(link)
          link.click()
          document.body.removeChild(link)

          // 清理URL对象
          URL.revokeObjectURL(link.href)

          this.$message.success('转换成功')
        } else {
          throw new Error(res.data.message || '转换失败')
        }
      } catch (error) {
        console.error('PDF转Word失败:', error)
        this.$message.error('PDF转Word失败，请稍后重试')
      }
    },
    // 2. 替换原有的 exportDocument 方法
    async exportDocument(template) {
      try {
        const templateData = JSON.parse(template.data || '[]')
        const contentData = `
          <!DOCTYPE html>
          <html>
            <head>
              <meta charset="UTF-8">
              <style>
                @page {
                  size: A4;
                  margin: 2cm;
                }
                body {
                  font-family: Arial, sans-serif;
                  font-size: 12pt;
                  line-height: 1.5;
                }
                /* 目录样式 */
                .toc {
                  margin-bottom: 30px;
                }
                .toc-item {
                  display: flex;
                  justify-content: space-between;
                  margin: 5px 0;
                  border-bottom: 1px dotted #000;
                }
                .toc-text {
                  margin-right: 10px;
                }
                .toc-page {
                  margin-left: 10px;
                }
                /* 章节标题样式 */
                .section-title {
                  font-weight: bold;
                  margin-top: 20px;
                  margin-bottom: 10px;
                  page-break-after: avoid;
                }
                /* 页码样式 */
                .page-number {
                  position: fixed;
                  bottom: 20px;
                  right: 20px;
                  font-size: 10pt;
                }
              </style>
            </head>
            <body>
              <!-- 添加目录 -->
              <div class="toc">
                <h2>Content</h2>
                ${this.generateTableOfContents(templateData)}
              </div>
              
              <!-- 添加正文内容 -->
              ${this.processContentWithSections(templateData)}
            </body>
          </html>
        `

        // 调用导出接口
        const res = await htmlWordNew({
          content: contentData,
          title: template.title,
          options: {
            format: 'docx',
            encoding: 'utf-8',
            preserveStyles: true
          }
        })

        if (res.status !== 200) {
          this.$alert(res.errMsg)
          return
        }

        // 处理文件下载
        const link = document.createElement('a')
        link.href = res.data.file_path
        link.download = `${template.title}.docx`
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)

        this.$message.success('导出成功')
      } catch (error) {
        console.error('导出Word文档失败:', error)
        this.$alert('导出文档时发生错误，请稍后重试。')
      }
    },
    /* 客户名称 */
    getCusomName(phaseId) {
      const product = this.customList.find((item) => item.id === phaseId)
      return product ? product.name : '未知客户'
    },
    /* 当前阶段 */
    getPhaseName(phaseId) {
      const product = this.currentPhaseList.find(
        (item) => item.value === phaseId
      )
      return product ? product.label : '未知阶段'
    },

    getPhaseType(phaseId) {
      const product = this.currentPhaseList.find(
        (item) => item.value === phaseId
      )
      if (!product) return 'info'

      // 根据不同阶段返回同的类型
      // 这里的判断逻辑需要根据实际的产品阶来调整
      switch (product.status) {
        case 1:
          return 'success' // 已完成
        case 2:
          return 'warning' // 进行中
        case 3:
          return 'danger' // 待处理
        default:
          return 'info' // 其他状态
      }
    },
    /* 目前状态  */
    getStatusName(statusId) {
      const status = this.getstatusList.find((item) => item.value === statusId)
      return status ? status.label : '未状态'
    },

    getStatusType(statusId) {
      // 这里可以根据不同状态返回不同的类型
      // 可用的类型：success/warning/danger/info
      const status = this.getstatusList.find((item) => item.value === statusId)
      if (!status) return 'info'

      // 根据状值返回对应的类型
      switch (status.value) {
        case 5:
          return 'success'
        case 4:
          return 'warning'
        case 3:
          return 'danger'
        default:
          return 'info'
      }
    },
    // 格式化完成度显示
    formatCompletion(rate) {
      if (rate === undefined || rate === null) {
        return '0%'
      }
      return `${rate}%`
    },

    // 根据完成度返回对应CSS类名
    getCompletionClass(rate) {
      if (!rate) return 'completion-low'
      if (rate >= 100) return 'completion-high'
      if (rate >= 50) return 'completion-medium'
      return 'completion-low'
    },
    handleCommand(command) {
      switch (command.type) {
        case 'template':
          this.selTemplate(command.row)
          break
        case 'enter':
          this.enterPro(command.row)
          break
        case 'edit':
          this.btnEdit(command.row)
          break
        case 'delete':
          this.btnDelete(command.row.id)
          break
        case 'viewTemplates':
          this.viewBoundTemplates(command.row)
          break
      }
    },
    // Add new methods
    // 查看已绑定模版
    viewBoundTemplates(row) {
      this.currentData = row
      this.boundTemplateLoading = true
      searchTemplateListNoData({ ids: row.documentIds.join(',') || 0 })
        .then((res) => {
          if (res.status === 200) {
            this.boundTemplateList = res.data
            this.boundTemplatesDialogVisible = true
          }
        })
        .finally(() => {
          this.boundTemplateLoading = false
        })
    },

    async previewTemplate(template) {
      console.log(template);
      this.currentTemplate = template
      /* this.loadDocumentVersions(template); */
      const res = await searchlistDocTemplate({
        /* page: 1,
        pageSize: 10, */
        project_id:this.currentData.id,
        id: template.id
      })

      if (res.status === 200) {
        /* this.documentVersions = res.data.dataList[0]; */
        if (res.data.documents.length !== 0) {
          const url = `#/document/viewCreate?articleId=${res.data.documents[0].id}&type=document`
          window.open(url, '_blank')
        } else {
          const a = document.createElement('a')
          a.href = '#/document/viewCreate?articleId=' + template.id
          a.target = '_blank'
          a.click()
        }

        /*  if (this.documentVersions.length === 0) {
            this.$message.warning("未找到相关文档版本");
          } */
      }
    },

    replaceTemplate(template) {
      this.docAttr = template
      const TemList = JSON.parse(template.data)
      /* this.$confirm("确定要替换此模吗？", "提示", {
        confirmButtonText: "确",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => { */
      this.replaceVisible = true
      this.searchEx(TemList)
    },

    // 新增：处理已选定模版的选择
    async handleBoundTemplateSelect(selection) {
      this.selectedBoundTemplates = selection
      /* try {
        if (!selection || selection.length === 0) {
          this.selectedBoundTemplates = [];
          return;
        }

        // 获取选中模板的详细信息
        const templatePromises = selection.map(async (item) => {
          const templateId = JSON.parse(item.data)[0].id;
          const res = await getTemplateInfo({ id: templateId });

          if (res.status === 200 && res.data) {
            return {
              ...res.data,
              data: res.data.data || '[]' // 确保 data 字段存在
            };
          }
          return null;
        });

        // 等待所有模板信息加载完成
        const templates = await Promise.all(templatePromises);

        // 过滤掉无效的模板并保存
        this.selectedBoundTemplates = templates.filter(template => template !== null);
        console.log(this.selectedBoundTemplates);
      } catch (error) {
        console.error('获取模板信息失败:', error);
        this.$message.error('获取模板信息失败');
        this.selectedBoundTemplates = [];
      } */
    },

    // 新增：批量替换方法
    async batchReplace() {
      if (this.selectedBoundTemplates.length === 0) {
        this.$message.warning('请选择需要替换的模版')
        return
      }

      this.batchReplaceLoading = true
      try {
        // 依次处理每个选中的模版
        for (const template of this.selectedBoundTemplates) {
          this.docAttr = template
          const res = await searchlistDocTemplate({
            /* page: 1,
            pageSize: 10, */
            project_id:this.currentData.id,
            id: template.id,
            is_template:1
          })
          if(res.status!== 200) return
          // 检查模板数据格式
          let templateData
          try {
            // 优先尝试使用 data 字段
            if(res.data.documents.length!==0){
                templateData = JSON.parse(res.data.documents[0].data || '[]')
            }else{
              const template_Data = await getDocumentInfo({id:template.id})
                if(template_Data.status!==200) return
                templateData = JSON.parse(template_Data.data.data || '[]')
            }
          
          } catch (e) {
            // 如果解析失败，尝试使用 content 字段
            templateData = template.content
              ? [{ content: template.content }]
              : []
          }

          if (templateData && templateData.length > 0) {
            await this.searchEx(templateData)

            if (this.matchResults.length > 0) {
              await this.replaceAll()
            }
          } else {
            console.warn(`模板 ${template.id} 没有有效的内容数据`)
          }
        }

        this.$message.success('批量替换完成')
      } catch (error) {
        console.error('批量替换失败:', error)
        this.$message.error('批量替换过程中发生错误: ' + error.message)
      } finally {
        this.batchReplaceLoading = false
      }
    },

    searchEx(val) {
      return new Promise((resolve) => {
        const allMatches = []
        this.TemList = val
        this.TemList.forEach((el) => {
          // 创建临时 div 来解析 HTML 内容
          const tempDiv = document.createElement('div')
          tempDiv.innerHTML = el.content
          const plainText = tempDiv.textContent || tempDiv.innerText

          // 分别匹配中文括号和英文括号
          const patterns = [
            /【([A-Z]{1,4}[0-9]{0,2})-([A-Z]{1,4}[0-9]{0,2})-([0-9]{2})-([0-9]{2,3})】/g,
            /\[([A-Z]{1,4}[0-9]{0,2})-([A-Z]{1,4}[0-9]{0,2})-([0-9]{2})-([0-9]{2,3})\]/g
          ]

          patterns.forEach((pattern) => {
            let match
            while ((match = pattern.exec(plainText)) !== null) {
              const fullMatch = match[0]
              const segments = [match[1], match[2], match[3], match[4]]

              // 验证个段落的格式
              const isValid = segments.every((segment) => segment.length > 0)

              if (isValid) {
                allMatches.push(fullMatch)
              }
            }
          })
        })

        this.matchResults = [...new Set(allMatches)]

        // 调试用：打印每个匹配的详细信息
        this.matchResults.forEach((match) => {
          // 据括号类型选不同的切片方式
          const content = match.startsWith('【')
            ? match.slice(1, -1)
            : match.slice(1, -1)
          const parts = content.split('-')
        })
        resolve()
      })
    },

    // 添加的辅助方法来判断文档类型
    getDocumentType(code) {
      if (code.includes('-RP-')) return 'template_location'
      if (code.includes('-IR-')) return 'middle_layer_location'
      if (code.includes('-WE-')) return 'tech_report_location'
      return 'other_location'
    },

    // 修改式化请求参数的方法
    formatRequestParams(locations) {
      const locationArray = Array.isArray(locations) ? locations : [locations]

      // 初始化求参数对象
      const params = {
        /* project_id:'', */
        template_location: [],
        middle_layer_location: [],
        tech_report_location: [],
        other_location: []
      }

      // 根据不同类型分类存储
      locationArray.forEach((location) => {
        const cleanLocation = location.replace(/[\[\]【】]/g, '')
        const type = this.getDocumentType(cleanLocation)
        console.log('params', type)
        // 为每种类型创建对应长度的空数组
        Object.keys(params).forEach((key) => {
          if (type === key) {
            params[key].push(cleanLocation)
          } else {
            params[key].push('')
          }
        })
      })

      return params
    },

    // 解析内容，处理特殊标记
    parseContent(content) {
      if (!content) return ''

      let parsed = content

      // 处理图片标记
      parsed = parsed.replace(
        /\[图片:(.*?)\|style=(.*?)\|class=(.*?)\]/g,
        (match, src, style, className) => {
          return `<img src="${src}" alt="图片" style="${style}" class="${className}">`
        }
      )

      // 处理表格标记
      parsed = parsed.replace(
        /\[表格\|style=(.*?)\|class=(.*?)\]\n([\s\S]*?)(?=\[|$)/g,
        (match, tableStyle, tableClass, tableContent) => {
          const rows = tableContent.trim().split('\n')
          let tableHtml = `<table style="${tableStyle};background-color:#ffff00;"  class="${tableClass}">`

          rows.forEach((row) => {
            tableHtml += '<tr>'
            const cells = row.split(' | ').map((cell) => {
              const [content, ...styleInfo] = cell.split('[style=')
              if (styleInfo.length) {
                const [style, className] = styleInfo[0]
                  .slice(0, -1)
                  .split('|class=')
                return `<td style="${style}" class="${className}">${content}</td>`
              }
              return `<td>${content}</td>`
            })
            tableHtml += cells.join('') + '</tr>'
          })

          tableHtml += '</table>'
          return tableHtml
        }
      )

      // 处理文本样式
      parsed = parsed.replace(
        /\[文本:(.*?)\|style=(.*?)\|class=(.*?)\]/g,
        (match, content, style, className) => {
          return `<span style="${style}" class="${className}">${content}</span>`
        }
      )

      return parsed
    },

    // 查内容是否包含表格或图片
    containsTableOrImage(content) {
      return content.includes('<table') || content.includes('<img')
    },

    // 获取所有文本节点
    getTextNodes(node) {
      const textNodes = []
      const walk = document.createTreeWalker(
        node,
        NodeFilter.SHOW_TEXT,
        null,
        false
      )
      let currentNode
      while ((currentNode = walk.nextNode())) {
        textNodes.push(currentNode)
      }
      return textNodes
    },

    /* 更新  */
   async onUpload() {
      const _this = this
      if (_this.TemList.length <= 0) {
        _this.$message.error('增加组件')
        return
      }
      if (_this.docAttr.title == '') {
        _this.$message.error('请填写模版标题')
        return
      }
      const res = await searchlistDocTemplate({
        /* page: 1,
        pageSize: 10, */
        project_id:this.currentData.id,
        id: _this.docAttr.id
      })
      if(res.status!==200) return
    if(res.data.documents.length==0){
      _this.docAttr.title = _this.docAttr.title + new Date().getTime()
      _this.docAttr.links = JSON.stringify(_this.docAttr.linkProduct)
      _this.docAttr.projects = JSON.stringify(_this.docAttr.linkProject)
      _this.docAttr.data = JSON.stringify(_this.TemList)
      _this.docAttr.is_template = 0
      /*  _this.docAttr.id = _this.docAttr.id; */
      _this.docAttr.user_name = _this.docAttr.name
      _this.docAttr.user_id = _this.$store.state.user.id // _this.docAttr.id;
      _this.docAttr.template_id = _this.docAttr.id
      createDocument(_this.docAttr).then((res) => {
        if (res.status != 200) return // 更新文档
        /*  _this.docAttr.id = res.data; */
        _this.$message.success('文档创建成功')
        searchlistDoc({
          page: 1,
          pageSize: 999
        })
      })
    }else{
      updateDocument({
        id:res.data.documents[0].id,
         data :JSON.stringify(_this.TemList),
         title:res.data.documents[0].title,
         status:5,
         document_type:res.data.documents[0].document_type,
         is_template:0,
         template_id:res.data.documents[0].template_id,
         user_id:res.data.documents[0].user_id
        }).then(res=>{
        if (res.status != 200) return 
        _this.$message.success('文档更新成功')
      })
    }

     
    },

    // 添加统一的内容处理方法
    async processAndReplaceContent(content, originalMatch) {
      try {
        const params = this.formatRequestParams(originalMatch)
        params.project_id = this.currentData.id
        const response = await axios.post(
          `${process.env.VUE_APP_BASE_API}/project-raw-data/batch-content`,
          params,
          {
            headers: {
              'Content-Type': 'application/json'
            }
          }
        )

        if (response.status === 200 && response.data) {
          const replacementContent =
            response.data.data.matched_data[0]?.content
          if (replacementContent) {
            // 处富文本内容
            this.TemList.forEach((el, index) => {
              console.log(el, originalMatch, replacementContent)
              const processedContent = this.processTableContent(
                el.content,
                originalMatch,
                replacementContent
              )
              this.$set(this.TemList[index], 'content', processedContent)
            })
            return true
          }
        }
        return false
      } catch (error) {
        console.error('处理内容失败:', error)
        return false
      }
    },

    // 修改单个替换方法
    async replaceItem(item) {
      try {
        const success = await this.processAndReplaceContent(this.TemList, item)
        if (success) {
          this.matchResults = this.matchResults.filter(
            (match) => match !== item
          )
          this.onUpload()
          this.$message.success('替换成功')
        } else {
          this.$message.warning('未获取到替换内容')
        }
      } catch (error) {
        console.error('替换失败:', error)
        this.$message.error(error.response?.data?.message || '替换失败')
      }
    },

    // 修改批量替换方法
    async replaceAll() {
      this.batchReplaceLoading = true
      try {
        // 收所有配
        const allLocations = this.matchResults.map((item) => {
          return item.replace(/[\[\]【】]/g, '')
        })

        // 格式化请求参数
        const params = {
          template_location: [],
          middle_layer_location: [],
          tech_report_location: [],
          other_location: []
        }

        // 遍历所有位置并分类
        allLocations.forEach((location) => {
          const type = this.getDocumentType(location)
          Object.keys(params).forEach((key) => {
            if (type === key) {
              params[key].push(location)
            } else {
              params[key].push('')
            }
          })
        })
        params.project_id = this.currentData.id

        // 发送批量请求
        const response = await axios.post(
          `${process.env.VUE_APP_BASE_API}/project-raw-data/batch-content`,
          params,
          {
            headers: {
              'Content-Type': 'application/json'
            }
          }
        )

        if (response.status === 200 && response.data) {
          const replacementContents = response.data.data.matched_data

          if (replacementContents && replacementContents.length > 0) {
            // 更新所有内容
            this.TemList.forEach((el, index) => {
              let updatedContent = el.content

              // 遍历所有替换内容和对应匹配项
              this.matchResults.forEach((item) => {
                // 提取编号的函数只需定义一
                const getCodeFromItem = (searchItem) => {
                  const cleanItem = searchItem.replace(/[\[\]【】]/g, '')
                  const match = cleanItem.match(/([A-Z0-9]+-[A-Z]+-\d+-\d+)/)
                  return match ? match[1] : null
                }

                // 获取当前项的编号
                const currentCode = getCodeFromItem(item)
                if (!currentCode) return // 如果没有有效编号，跳过此项

                // 查找匹配的替换内容
                const matchedContent = replacementContents.find(
                  (content) => content.template_location === currentCode
                )

                if (matchedContent?.content) {
                  // 构建替换内容
                  const cleanContent = matchedContent.content.trim() // 清理前后空格
                  // 检测是否包含表格或长段文本（超过50个字符或包含表格标签）
                  const containsTable = cleanContent.includes('<table') || cleanContent.includes('<TABLE')
                  const isLongContent = cleanContent.length > 50 || cleanContent.split(/\s+/).length > 10
                  
                  let processedContent
                  let wrapperStyle
                  
                  if (containsTable || isLongContent) {
                    // 对于表格或长段内容，保持原有结构，允许换行
                    processedContent = cleanContent
                    wrapperStyle = "background-color: #ffff00 !important; padding: 4px 6px; border-radius: 2px; display: inline-block; white-space: normal; max-width: 100%;"
                  } else {
                    // 对于短文本，使用内联且不换行
                    processedContent = this.ensureInlineNoWrap(cleanContent)
                    wrapperStyle = "background-color: #ffff00 !important; padding: 2px 4px; border-radius: 2px; display: inline; white-space: nowrap;"
                  }
                  
                  const chineseDescription = matchedContent.chinese_description || '' // 获取中文释义，如果有的话 !important
                  const formattedReplacement = `
                    <span 
                      class="replacement-content" 
                      data-code="${currentCode}" 
                      title="${chineseDescription}"
                      style="${wrapperStyle}"
                    >${processedContent}${chineseDescription ? `<span class="chinese-desc" style="color: #67c23a; margin-left: 4px; font-size: 0.9em;">(${chineseDescription})</span>` : ''}</span>`.trim()

                  // 处理表格和其他内容
                  updatedContent = this.processTableContent(
                    updatedContent,
                    item,
                    formattedReplacement
                  )

                  // 记录日志
                  if (process.env.NODE_ENV !== 'production') {
                    console.log('替换信息:', {
                      原始编号: currentCode,
                      原始内容: item,
                      替换内容: formattedReplacement
                    })
                  }
                }
              })

              // 更新内容
              this.$set(this.TemList[index], 'content', updatedContent)
            })

            /*   // 更新文档*/
            await this.onUpload()
            this.matchResults = []
            this.$message.success('批量替换成功')
            this.replaceVisible = false
          } else {
            this.$message.warning('未获取到替换内容')
          }
        }
      } catch (error) {
        console.error('批量替换失败:', error)
        this.$message.error(error.response?.data?.message || '批量替换失败')
      } finally {
        this.batchReplaceLoading = false
      }
    },

    // 辅助方法：获取文档类型
    getDocumentType(code) {
      if (code.includes('-RP-')) return 'template_location'
      if (code.includes('-IR-')) return 'middle_layer_location'
      if (code.includes('-WE-')) return 'tech_report_location'
      return 'other_location'
    },

    // 修改处理表格内容的方法，添加对多个替换的支持
    processTableContent(content, searchItem, replacement) {
      if (!content || !searchItem) return content

      try {
        // 确保传入 replacement 内部不包含导致换行的块级元素
        replacement = this.ensureInlineNoWrap(replacement)
        // 提取搜索项中的编号
        const getCodeFromItem = (item) => {
          const cleanItem = item.replace(/[\[\]【】]/g, '')
          const match = cleanItem.match(/([A-Z0-9]+-[A-Z]+-\d+-\d+)/)
          return match ? match[1] : null
        }

        const searchCode = getCodeFromItem(searchItem)
        if (!searchCode) {
          console.warn('无法从搜索项中提取编号:', searchItem)
          return content
        }

        // 处理替换内容：若为包裹表格的span，则保留span内部的所有内容（文本+表格）
        let processedReplacement = replacement
        if (replacement.includes('<table') && replacement.startsWith('<span')) {
          const wrapperDiv = document.createElement('div')
          wrapperDiv.innerHTML = replacement
          const spanWrapper = wrapperDiv.querySelector('span')
          if (spanWrapper) {
            // 增强包裹内所有表格的可读性样式，但不丢弃表格外文本
            spanWrapper.querySelectorAll('table').forEach(tableElement => {
              tableElement.style.borderCollapse = 'collapse'
              tableElement.style.backgroundColor = '#ffff00'
              // 确保表格本身有底色
              if (!tableElement.style.backgroundColor) {
                tableElement.style.backgroundColor = '#ffff00'
              }
              tableElement.querySelectorAll('tr').forEach(row => {
                if (row.style.height) {
                  row.style.minHeight = row.style.height
                  row.style.height = 'auto'
                }
                // 确保行有底色
                if (!row.style.backgroundColor) {
                  row.style.backgroundColor = '#ffff00'
                }
                row.querySelectorAll('td, th').forEach(cell => {
                  if (!cell.style.whiteSpace) cell.style.whiteSpace = 'normal'
                  if (!cell.style.wordWrap) cell.style.wordWrap = 'break-word'
                  if (!cell.style.verticalAlign) cell.style.verticalAlign = 'middle'
                  if (!cell.style.padding) cell.style.padding = '8px'
                  // 确保单元格有底色
                  if (!cell.style.backgroundColor) {
                    cell.style.backgroundColor = '#ffff00'
                  }
                })
              })
            })
            // 使用span内部所有HTML，保留表格上方/下方文本
            processedReplacement = spanWrapper.innerHTML
          }
        }

        // 创建临时DOM元素来处理HTML内容
        const tempDiv = document.createElement('div')
        tempDiv.innerHTML = content

        // 查找并替换匹配的内容 - 使用更全面的正则表达式
        const pattern = new RegExp(`(\\[|【)([^\\]】]*?)(${searchCode})([^\\[【]*?)(\\]|】)`, 'g')
        
        // 首先在整个HTML内容中进行替换，确保不遗漏任何内容
        const originalHTML = tempDiv.innerHTML
        const updatedHTML = originalHTML.replace(pattern, processedReplacement)
        
        // 如果HTML内容发生了变化，更新tempDiv
        if (updatedHTML !== originalHTML) {
          tempDiv.innerHTML = updatedHTML
          console.log('✅ 在HTML级别成功替换了内容:', {
            搜索代码: searchCode,
            原始HTML长度: originalHTML.length,
            更新后HTML长度: updatedHTML.length,
            是否包含表格: updatedHTML.includes('<table')
          })
        }
        
        // 额外处理：确保表格单元格中的内容也被正确替换
        tempDiv.querySelectorAll('td, th').forEach(cell => {
          const cellHTML = cell.innerHTML
          const updatedCellHTML = cellHTML.replace(pattern, processedReplacement)
          if (updatedCellHTML !== cellHTML) {
            cell.innerHTML = updatedCellHTML
          }
        })
        
        // 处理可能被分割的文本节点（针对表格外的内容）
        const walker = document.createTreeWalker(
          tempDiv,
          NodeFilter.SHOW_TEXT,
          null,
          false
        )
        
        let textNode
        while ((textNode = walker.nextNode())) {
          const text = textNode.textContent
          if (pattern.test(text)) {
            // 创建一个包装元素来处理替换
            const wrapper = document.createElement('div')
            wrapper.innerHTML = text.replace(pattern, processedReplacement)
            
            // 替换原始文本节点
            const fragment = document.createDocumentFragment()
            while (wrapper.firstChild) {
              fragment.appendChild(wrapper.firstChild)
            }
            
            textNode.parentNode.replaceChild(fragment, textNode)
          }
        }
        
        // 在替换点前后去除多余空白并避免自动换行
        tempDiv.querySelectorAll('span.replacement-content').forEach(span => {
          // 去除包裹点两侧的多余空白文本节点
          const trimSideWhitespace = (node, direction) => {
            let sibling = direction === 'prev' ? node.previousSibling : node.nextSibling
            while (sibling && sibling.nodeType === Node.TEXT_NODE) {
              const trimmed = sibling.textContent.replace(/[\t\f\v\u00A0\u200B]+/g, ' ').replace(/\s+/g, ' ')
              // 如果纯空白或只有一个空格，进一步根据上下文裁剪
              if (!trimmed.trim()) {
                const toRemove = sibling
                sibling = direction === 'prev' ? sibling.previousSibling : sibling.nextSibling
                toRemove.parentNode.removeChild(toRemove)
              } else {
                sibling.textContent = trimmed
                // 剔除与替换点相邻的首尾空格，避免出现额外空格
                if (direction === 'prev') sibling.textContent = sibling.textContent.replace(/[\s\u00A0]+$/, '')
                else sibling.textContent = sibling.textContent.replace(/^[\s\u00A0]+/, '')
                break
              }
            }
          }
          trimSideWhitespace(span, 'prev')
          trimSideWhitespace(span, 'next')

          // 强制不自动换行（若父元素限制导致换行，此设置可最大程度避免）
          // 但对于包含表格或长段内容的span，保持 white-space: normal
          const currentStyle = span.getAttribute('style') || ''
          const hasTable = span.querySelector('table')
          const textContent = span.textContent || ''
          const isLongText = !hasTable && (textContent.length > 50 || textContent.split(/\s+/).length > 10)
          
          // 如果包含表格或长段文本，不强制 nowrap
          if (!hasTable && !isLongText && !/white-space\s*:\s*nowrap/i.test(currentStyle)) {
            span.setAttribute('style', `${currentStyle}${currentStyle.endsWith(';') ? '' : ';'} white-space: nowrap; display: inline;`)
          }
        })

        // 处理最终结果中的表格，确保自适应行高
        // 只处理替换内容中的表格，为其添加底色；其他表格不添加底色
        tempDiv.querySelectorAll('span.replacement-content table').forEach(table => {
          // 添加自适应样式类
          table.classList.add('auto-height-table')
          
          // 确保替换内容中的表格有底色
          if (!table.style.backgroundColor) {
            table.style.backgroundColor = '#ffff00'
          }
          
          // 处理所有行
          table.querySelectorAll('tr').forEach(row => {
            if (row.style.height && !row.style.minHeight) {
              row.style.minHeight = row.style.height
              row.style.height = 'auto'
            }
            // 确保替换内容中的行有底色
            if (!row.style.backgroundColor) {
              row.style.backgroundColor = '#ffff00'
            }
            // 确保替换内容中的单元格有底色
            row.querySelectorAll('td, th').forEach(cell => {
              if (!cell.style.backgroundColor) {
                cell.style.backgroundColor = '#ffff00'
              }
            })
          })
        })
        
        // 处理不在替换内容中的表格，只设置自适应行高，不添加底色
        tempDiv.querySelectorAll('table').forEach(table => {
          const parentSpan = table.closest('span.replacement-content')
          // 如果表格不在替换内容中，只设置自适应样式，不添加底色
          if (!parentSpan) {
            table.classList.add('auto-height-table')
            table.querySelectorAll('tr').forEach(row => {
              if (row.style.height && !row.style.minHeight) {
                row.style.minHeight = row.style.height
                row.style.height = 'auto'
              }
            })
          }
        })
        
        // 处理替换内容中的长段文本，确保有底色
        tempDiv.querySelectorAll('span.replacement-content').forEach(span => {
          // 检查是否包含长段文本（非表格）
          const hasTable = span.querySelector('table')
          const textContent = span.textContent || ''
          const isLongText = !hasTable && (textContent.length > 50 || textContent.split(/\s+/).length > 10)
          
          // 确保所有替换内容的span都有底色（包括长段文本）
          const currentStyle = span.getAttribute('style') || ''
          if (!currentStyle.includes('background-color')) {
            span.setAttribute('style', `${currentStyle}${currentStyle.endsWith(';') ? '' : ';'} background-color: #ffff00 !important;`)
          }
          
          // 对于长段文本，允许换行
          if (isLongText && !currentStyle.includes('white-space')) {
            span.setAttribute('style', `${span.getAttribute('style')} white-space: normal; display: inline-block;`)
          }
        })
        
        return tempDiv.innerHTML
      } catch (error) {
        console.error('替换内容时出错:', error)
        console.error('错误详情:', {
          原始内容: content.substring(0, 100) + '...',
          搜索项: searchItem,
          替换内容: replacement,
          错误信息: error.message
        })
        return content
      }
    },

    // 添加一个辅助方法来获取所有文本节点
    getAllTextNodes(node) {
      const textNodes = []
      const walk = document.createTreeWalker(
        node,
        NodeFilter.SHOW_TEXT,
        null,
        false
      )
      
      let currentNode
      while ((currentNode = walk.nextNode())) {
        if (currentNode.textContent.trim()) {
          textNodes.push(currentNode)
        }
      }
      
      return textNodes
    },

    // 添加样式到 convertTextToHtml 方法
    convertTextToHtml(text) {
      if (!text) return ''

      let html = text

      // 处理特定格式的表格
      html = html.replace(
        /\[表格\|style=(.*?)\|class=(.*?)\]([\s\S]*?)(?=\[|$)/g,
        (match, tableStyle, tableClass, tableContent) => {
          const rows = tableContent.trim().split('\n')
          let tableHtml = `<table style="${tableStyle}; border-collapse: collapse;" class="${tableClass}">`

          rows.forEach((row, index) => {
            const [label, value] = row.split('|').map((item) => item.trim())
            if (label) {
              tableHtml += '<tr>'
              if (value) {
                // 如果有值，创建两列的行
                tableHtml += `
              <td style="border: 1px solid #000; padding: 8px;">${label}</td>
              <td style="border: 1px solid #000; padding: 8px;">${value}</td>
            `
              } else {
                // 如果只有标签，创建单列的行（可能是表头）
                tableHtml += `
              <td style="border: 1px solid #000; padding: 8px; font-weight: ${
  index === 0 ? 'bold' : 'normal'
}">${label}</td>
            `
              }
              tableHtml += '</tr>'
            }
          })

          tableHtml += '</table>'
          return tableHtml
        }
      )

      // 保持原有的图片和文本处理逻辑不变
      html = html.replace(
        /\[图片:(.*?)\|style=(.*?)\|class=(.*?)\]/g,
        (match, src, style, className) => {
          return `<img src="${src}" alt="图片" style="${style}" class="${className}">`
        }
      )

      html = html.replace(
        /\[文本:(.*?)\|style=(.*?)\|class=(.*?)\]/g,
        (match, content, style, className) => {
          return `<span style="${style}" class="${className}">${content}</span>`
        }
      )

      return html
    },

    /* 选择模版 */
    selTemplate(row) {
      this.currentData = row

      // 重置所有状态
      this.selectedTemplateIds = new Set(row.documentIds || [])
      this.selectedPageIds = new Map()
      this.selectionCache = new Map()
      this.isAllSelected = false
      this.templateQueryForm.page = 1

      // 加载模板列表
      this.loadTemplateList()
    },
    /* 全选 */
    handleSelectAll(selection) {
      // selection 为当前选中的所有行数据
    const currentPage = this.templateQueryForm.page
      if (selection.length > 0) {
      // 全选操作
      this.selectedPageIds.set(currentPage, new Set(selection.map(row => row.id)))
      // 更新所有选中项的ID集合
      selection.forEach(row => {
        this.selectedTemplateIds.add(row.id)
      })
    } else {
      // 取消全选操作
      const previousSelection = this.selectedPageIds.get(currentPage) || new Set()
      previousSelection.forEach(id => {
        this.selectedTemplateIds.delete(id)
      })
      this.selectedPageIds.delete(currentPage)
    }
    },
    // 处理模版分页变化
    async handleTemplatePageChange(page) {
      this.templateQueryForm.page = page
      this.loadTemplateList()
    },
    // 加载模版表
    async loadTemplateList() {
      this.templateLoading = true
      try {
        const res = await searchTemplateList(this.templateQueryForm)
        if (res.status === 200) {
          this.templateList = res.data.list
          this.templateTotal = res.data.total
          
          // 在数据加载完成后恢复选择状态
          this.$nextTick(() => {
            this.templateList.forEach(row => {
              if (this.selectedTemplateIds.has(row.id)) {
                this.$refs.templateTable.toggleRowSelection(row, true)
              }
            })
          })
        }
      } catch (error) {
        console.error('加载模板列表失败:', error)
        this.$message.error('加载模板列表失败')
      } finally {
        this.templateLoading = false
      }
    },

    // 添加新方法：恢复选择状态
    restoreSelectionState() {
      const currentPage = this.templateQueryForm.page

      // 遍历当前页数据
      this.templateList.forEach((row) => {
        // 检查是否在全局选中集合中
        if (this.selectedTemplateIds.has(row.id)) {
          this.$refs.templateTable.toggleRowSelection(row, true, false)
        }
      })

      // 更新当前页的选择记录
      const selectedRows = this.templateList.filter((row) =>
        this.selectedTemplateIds.has(row.id)
      )

      // 更新选择缓存
      this.selectionCache.set(
        currentPage,
        new Set(selectedRows.map((row) => row.id))
      )

      // 检查当前页是否全选
      const isCurrentPageAllSelected = this.templateList.every((row) =>
        this.selectedTemplateIds.has(row.id)
      )

      // 更新表头的全选框状态
      if (this.$refs.templateTable.store) {
        this.$refs.templateTable.store.states.isAllSelected =
          isCurrentPageAllSelected
      }

      // 触发选择变化事件
      this.handleSelectionChange(selectedRows)
    },

    // 修改 handleSelectionChange 方法
    handleSelectionChange(selection) {
      console.log(selection)
      // 更新选中项ID集合
      selection.forEach(item => {
        this.selectedTemplateIds.add(item.id)
      })
      
      // 更新已选择的模板数组
      this.selectedTemplates = selection
    },

    handleSelect(selection, row) {
      if (selection.includes(row)) {
        // 选中时添加ID
        this.selectedTemplateIds.add(row.id)
      } else {
        // 取消选中时移除ID
        this.selectedTemplateIds.delete(row.id)
      }
      
      // 更新选中状态
      this.selectedTemplates = selection
    },

    // 修改加载方法
    loadTemplateList() {
      this.templateLoading = true
      searchList(this.templateQueryForm)
        .then((res) => {
          if (res.status === 200) {
            this.templateList = res.data.dataList
            this.templateTotal = res.data.totalRecord
            this.templateDialogVisible = true

            // 在数据加载完成后设置选中状态
            this.$nextTick(() => {
              if (this.$refs.templateTable) {
                // 清除当前选择
                this.$refs.templateTable.clearSelection()

                // 遍历当前页数据，根据 selectedTemplateIds 设置选中状态
                this.templateList.forEach((row) => {
                  if (this.selectedTemplateIds.has(row.id)) {
                    this.$refs.templateTable.toggleRowSelection(row, true)
                  }
                })

                // 更新当前页的选择记录
                const currentPage = this.templateQueryForm.page
                const currentPageSelected = new Set(
                  this.templateList
                    .filter((row) => this.selectedTemplateIds.has(row.id))
                    .map((row) => row.id)
                )
                this.selectedPageIds.set(currentPage, currentPageSelected)

                // 检查当前页是否全选
                const isCurrentPageAllSelected = this.templateList.every(
                  (row) => this.selectedTemplateIds.has(row.id)
                )

                // 更新表头的全选框状态
                if (this.$refs.templateTable.store) {
                  this.$refs.templateTable.store.states.isAllSelected =
                    isCurrentPageAllSelected
                }

                // 触发选择变化事件以更新UI
                this.handleSelectionChange(
                  this.templateList.filter((row) =>
                    this.selectedTemplateIds.has(row.id)
                  )
                )
              }
            })
          }
        })
        .catch((error) => {
          console.error('加载模板列表失败:', error)
          this.$message.error('加载模板列表失败')
        })
        .finally(() => {
          this.templateLoading = false
        })
    },

    // 修改选择所有页方法
    async selectAllPages() {
      try {
        this.isAllSelected = true
        const allTemplates = await this.getAllTemplates()

        // 清除之前的选择
        this.selectedTemplateIds.clear()
        this.selectedPageIds.clear()

        // 添加所有模板ID到选择集合
        allTemplates.forEach((template) => {
          this.selectedTemplateIds.add(template.id)
        })

        // 更新当前页显示
        if (this.$refs.templateTable) {
          this.$refs.templateTable.clearSelection()
          this.templateList.forEach((row) => {
            this.$refs.templateTable.toggleRowSelection(row, true)
          })
        }

        // 更新当前页的选择记录
        const currentPage = this.templateQueryForm.page
        this.selectedPageIds.set(
          currentPage,
          new Set(this.templateList.map((row) => row.id))
        )

        this.$message.success(`已选择全部 ${this.templateTotal} 条数据`)
      } catch (error) {
        console.error('选择所有页失败:', error)
        this.$message.error('选择所有页失败')
        this.isAllSelected = false
      }
    },

    // 获取有模版数据
    async getAllTemplates() {
      const pageSize = 999 // 使用较大的页码一次性获取
      const params = {
        ...this.templateQueryForm,
        page: 1,
        pageSize
      }

      try {
        const res = await searchList(params)
        if (res.status === 200) {
          return res.data.dataList
        }
        return []
      } catch (error) {
        console.error('获取所有模版失败:', error)
        return []
      }
    },

    // 确认选择
    async confirmTemplateSelection() {
      try {
        // 检查是否有选中的模板
        if (this.selectedTemplateIds.size === 0) {
          this.$message.warning('请至少选择一个模版')
          return
        }

        // 显示加载状态
        this.confirmLoading = true

        // 转换Set为数组
        const selectedIds = Array.from(this.selectedTemplateIds)

        // 调用关联接口
        const res = await relate({
          project_id: this.currentData.id,
          doc_ids: JSON.stringify(selectedIds)
        })

        if (res.status === 200) {
          // 更新成功
          this.$message.success('模版关联成功')
          
          // 更新当前数据的documentIds
          this.$set(this.currentData, 'documentIds', selectedIds)
          
          // 关闭对话框并清理选择状态
          this.closeTemplateDialog()
          
          // 刷新列表
          await this.search()
          
          // 触发自定义事件通知父组件
          this.$emit('template-updated', {
            projectId: this.currentData.id,
            documentIds: selectedIds
          })
        } else {
          this.$message.error(res.message || '模版关联失败')
        }
      } catch (error) {
        console.error('模版关联失败:', error)
        this.$message.error(error.response?.data?.message || '模版关联失败')
      } finally {
        this.confirmLoading = false
      }
    },

    // 修改关闭对话框方法
    closeTemplateDialog() {
      // 清理选择状态
      this.selectedTemplateIds.clear()
      this.selectedTemplates = []
      this.currentPageSelected = false
      this.isAllSelected = false
      
      // 重置加载状态
      this.confirmLoading = false
      
      // 关闭对话框
      this.templateDialogVisible = false
      
      // 重置分页
      this.templateQueryForm.page = 1
      
      // 清理表格选择状态
      if (this.$refs.templateTable) {
        this.$refs.templateTable.clearSelection()
      }
    },

    // 输入项目
    enterPro(row) {
      if (row.documentIds.length == 0) {
        this.$message.warning('请先绑定模版!')
        return
      }

      // 使用去重后的数据
      this.$router.push({
            path: '/project/ProjectInput',
            query: {
              id: row.id
            }
          })
      // 获取绑定模版替换位置信息
    /*   searchTemplateList({ ids: row.documentIds.join(',') || 0 })
        .then(async(res) => {
          if (res.status === 200) {
            const templates = res.data
            const locations = []

            // 遍历所有模版，提取替换位置
            templates.forEach((template) => {
              if (template.data) {
                const templateData = JSON.parse(template.data)
                templateData.forEach((item) => {
                  const tempDiv = document.createElement('div')
                  tempDiv.innerHTML = item.content
                  const plainText = tempDiv.textContent || tempDiv.innerText

                  const patterns = [
                    /【([A-Z]{1,4}[0-9]{0,2})-([A-Z]{1,4}[0-9]{0,2})-([0-9]{2})-([0-9]{2,3})】/g,
                    /\[([A-Z]{1,4}[0-9]{0,2})-([A-Z]{1,4}[0-9]{0,2})-([0-9]{2})-([0-9]{2,3})\]/g
                  ]

                  patterns.forEach((pattern) => {
                    let match
                    while ((match = pattern.exec(plainText)) !== null) {
                      locations.push({
                        template_id: template.id,
                        template_title: template.title,
                        location: match[0],
                        type: this.getDocumentType(match[0])
                      })
                    }
                  })
                })
              }
            })

            try {
              // 按类型分组位置信息
              const params = {
                template_location: [],
                middle_layer_location: [],
                tech_report_location: [],
                other_location: []
              }

              // 遍历所有位置并分类
              locations.forEach((loc) => {
                Object.keys(params).forEach((key) => {
                  if (loc.type === key) {
                    params[key].push(loc.location.replace(/[\[\]【】]/g, '')) // 清除括号
                  } else {
                    params[key].push('')
                  }
                })
              })
              params.project_id = row.id
              // 获取替换内容
              const response = await axios.post(
                `${process.env.VUE_APP_BASE_API}/project-raw-data/batch-content`,
                params,
                {
                  headers: {
                    'Content-Type': 'application/json'
                  }
                }
              )

              if (response.status === 200 && response.data) {
                const replacementContents = response.data.data.matched_data

                // 将位置信息和对应的替换内容组合
                const enrichedLocations = locations.map((loc, index) => ({
                  ...loc,
                  content: replacementContents[index]?.content || null,
                  template_location:
                    replacementContents[index]?.template_location || null,
                  tech_report_location:
                    replacementContents[index]?.tech_report_location || []
                }))

                // 对整个 enrichedLocations 进行去重
                const uniqueEnrichedLocations = enrichedLocations.reduce(
                  (acc, current) => {
                    const isDuplicate = acc.find(
                      (item) =>
                        item.template_id === current.template_id &&
                        item.location === current.location
                    )

                    if (!isDuplicate) {
                      // 如果不是重复项，添加到结果数组中
                      return [...acc, current]
                    }
                    return acc
                  },
                  []
                )
                // 使用去重后的数据
                this.$router.push({
                  path: '/project/ProjectInput',
                  query: {
                    id: row.id,
                    projectData: encodeURIComponent(
                      JSON.stringify({
                        locations: uniqueEnrichedLocations, // 使用去重后的数据
                        templates: templates.map((t) => ({
                          id: t.id,
                          title: t.title
                        }))
                      })
                    )
                  }
                })
              }
            } catch (error) {
              console.error('获取替换内容失败:', error)
              this.$message.error('获取替换内容失败')
            }
          }
        })
        .catch((error) => {
          console.error('获取模版位置信息失败:', error)
          this.$message.error('获取模版位置信失败')
        }) */
    },
    /* 产品类别名称 */
    getCategoryTypeName(categoryId) {
      if (!categoryId) return '未分类'
      const product = this.productList.find((item) => item.id === categoryId)
      return product && product.category ? product.category.name : '未知类'
    },

    getCategoryName(categoryId) {
      if (!categoryId) return '未知产品'
      const product = this.productList.find((item) => item.id === categoryId)
      return product ? product.name : '未知产品'
    },

    searchData() {
      const _this = this
      _this.dialogVisible = false
      _this.search()
    },

    btnDelete(e) {
      const _this = this
      const par = {
        id: e
      }
      _this
        .$confirm('您是否确认删除该记录？', '提示', {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then((res) => {
          // console.log("AAA")
          deleteProject(par).then((res) => {
            _this.search()
          })
        })
        .catch(() => {})
    },

    // 编辑
    btnEdit(e) {
      const _this = this
      _this.currentDataId = e.id
      _this.dialogVisible = true
    },

    onClose(needRefresh) {
      console.log('onClose triggered with needRefresh:', needRefresh) // 添加调试日志
      this.currentDataId = 0
      this.dialogVisible = false
      if (needRefresh) {
        this.search()
      }
    },

    handleUpdate() {
      this.search() // 添加额外的更新处理方法
    },

    // 搜索
    async search() {
      try {
        // 1. 先加载并显示项目列表
        const res = await searchProject(this.queryForm)
        if (!res) return

        // 2. 先用0初始化完成度，让列表可以立即渲染
        const projectListFromTemplate = res.data.dataList.map((item) => ({
          ...item,
          calculate: 0
        }))

        // 3. 立即更新列表数据
        this.dataList = projectListFromTemplate
        this.recordCount = res.data.totalRecord
        this.pageTotal = res.data.totalPage

        // 4. 异步加载完成度
        this.loadProjectCompletions(projectListFromTemplate)
      } catch (err) {
        console.error('搜索失败:', err)
        this.$message.error('获取项目列表失败')
      }
    },
    // 修改分页
    ChangePage(e) {
      const _this = this
      _this.queryForm.page = e
      _this.search()
    },
    init() {
      searchCategory().then((res) => {
        if (res.status !== 200) return
        this.categoryList = res.data.dataList
      })
      /* 获取阶段 */
      getphases().then((res) => {
        this.currentPhaseList = res.data.options
      })
      /* 获取目前态 */
      getstatus().then((res) => {
        this.getstatusList = res.data.options
      })
      /* 获取客户列表 */
      searchCustomer({ page: 1, pageSize: 999 }).then((res) => {
        this.customList = res.data.dataList
      })
      /* 获取产品列表 */
      searchProduct({ page: 1, pageSize: 999 }).then((res) => {
        this.productList = res.data.dataList
      })
    },
    // 新增：处理导出命令
    async handleExport(command, row) {
      switch (command) {
        case 'word':
          await this.exportDocumentWithHtmlDocx(row) // this.exportDocument(row);
          break
        case 'pdf':
          await this.exportToPDF(row)
          break
        case 'pdf-to-word': // 添加新的命令类型
          const pdfResult = await this.exportToPDF_url(row)
          /* if (pdfResult && pdfResult.file_path) {
            await this.convertPDFToWord(pdfResult.file_path);
          } */
          break
      }
    },
    /* 过去pdf链接 */
    async exportToPDF_url(template) {
      try {
        // 解析模版内容
        const templateData = JSON.parse(template.data || '[]')

        // 创建一个临时的容器来存放内容
        const contentContainer = document.createElement('div')
        contentContainer.className = 'content'

        // 处理每个模版段落
        templateData.forEach((item) => {
          const templateSection = document.createElement('div')
          templateSection.className = 'template-textarea'
          templateSection.innerHTML = item.content
          contentContainer.appendChild(templateSection)
        })

        // 处理所有输入框
        contentContainer
          .querySelectorAll('input[type="text"]')
          .forEach((input) => {
            const span = document.createElement('span')
            span.textContent = input.value
            input.parentNode.replaceChild(span, input)
          })

        // 构建HTML内容
        const contentData = `<!DOCTYPE html>
        <html>
          <head>
            <meta charset="UTF-8">
            <style>
              @page {
                size: A4;
                margin: 2cm;
              }
              body {
                font-family: Arial, sans-serif;
                font-size: 12pt;
                line-height: 1.5;
              }
              /* 添加图片控制样式 */
              img {
                max-width: 100%;
                max-height: 100vh;
                object-fit: contain;
                page-break-inside: avoid;
              }
              /* 图片容器样式 */
              .image-container {
                width: 100%;
                text-align: center;
                margin: 10px 0;
                page-break-inside: avoid;
              }
              table {
                width: 100%;
                border-collapse: collapse;
              }
              td, th {
                border: 1px solid black;
                padding: 5px;
              }
              .template-textarea {
                page-break-after: always;
              }
              .TOC {
                display: none !important;
              }
            </style>
          </head>
          <body>
            ${this.processImages(contentContainer.innerHTML)}
          </body>
        </html>`

        /*    // 处理表格样式
        contentData = contentData
          .replaceAll("<table ", `<table style="border-collapse: collapse;" `)
          .replaceAll("<td>", `<td style="border: 1px solid black;">`); */
        const formData = new FormData()
        formData.append('content', contentData)
        formData.append('title', template.title)
        // 调用导出接口，指定导出类型为 PDF
        const res = await axios.post(
          `${process.env.VUE_APP_BASE_API}/document/htmlPDFWord`,
          formData,
          {
            headers: {
              'Content-Type': 'multipart/form-data' // 设置请求头为form-data
            }
          }
        ) /* await htmlPDFWord({
          content: contentData,
          title: template.title,
        }); */

        if (res.status !== 200) {
          this.$alert(res.errMsg)
          return
        }
        console.log(res)
        // 处理文件下载
        const link = document.createElement('a')
        link.href = res.data.data.file_path
        link.download = res.data.data.file_name
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)

        this.$message.success('导出成功')

        // 处理文件下载
        return res.data // 返回结果，包含 file_path
      } catch (error) {
        console.error('导出PDF失败:', error)
        this.$alert('导出PDF时发生错误，请稍后重试。')
      }
    },
    // 添加新的 exportToPDF 方法
    async exportToPDF(template) {
      /* const res = await searchlistDocTemplate({
       
        project_id:this.currentData.id,
        id: template.id
      })
      if(res.status!==200) return
      let templateData */
      try {
      // 1. 先获取文档模板数据
      const resData = await searchlistDocTemplate({
      project_id: this.currentData.id,
      id: template.id
    })

    if (resData.status !== 200) {
      this.$message.error('获取文档模板失败')
      return
    }

    // 2. 获取模板数据
    let templateData
    if (resData.data.documents.length !== 0) {
      templateData = JSON.parse(resData.data.documents[0].data || '[]')
    } else {
      const templateDataRes = await getDocumentInfo({id: template.id})
      if (templateDataRes.status !== 200) {
        this.$message.error('获取文档信息失败')
        return
      }
      templateData = JSON.parse(templateDataRes.data.data || '[]')
    }

    if (!templateData || !Array.isArray(templateData)) {
      this.$message.error('无效的模板数据格式')
      return
    }

        // 创建一个临时的容器来存放内容
        const contentContainer = document.createElement('div')
        contentContainer.className = 'content'

        // 处理每个模版段落
        templateData.forEach((item) => {
          const templateSection = document.createElement('div')
          templateSection.className = 'template-textarea'
          templateSection.innerHTML = item.content
          contentContainer.appendChild(templateSection)
        })

        // 处理所有输入框
        contentContainer
          .querySelectorAll('input[type="text"]')
          .forEach((input) => {
            const span = document.createElement('span')
            span.textContent = input.value
            input.parentNode.replaceChild(span, input)
          })

        // 构建HTML内容
        const contentData = `<!DOCTYPE html>
        <html>
          <head>
            <meta charset="UTF-8">
            <style>
              @page {
                size: A4;
                margin: 2cm;
              }
              body {
                font-family: Arial, sans-serif;
                font-size: 12pt;
                line-height: 1.5;
              }
              /* 添加图片控制样式 */
              img {
                max-width: 100%;
                max-height: 100vh;
                object-fit: contain;
                page-break-inside: avoid;
              }
              /* 图片容器样式 */
              .image-container {
                width: 100%;
                text-align: center;
                margin: 10px 0;
                page-break-inside: avoid;
              }
              table {
                width: 100%;
                border-collapse: collapse;
              }
              td, th {
                border: 1px solid black;
                padding: 5px;
              }
              .template-textarea {
                page-break-after: always;
              }
              .TOC {
                display: none !important;
              }
            </style>
          </head>
          <body>
            ${this.processImages(contentContainer.innerHTML)}
          </body>
        </html>`

        /*    // 处理表格样式
        contentData = contentData
          .replaceAll("<table ", `<table style="border-collapse: collapse;" `)
          .replaceAll("<td>", `<td style="border: 1px solid black;">`); */

        // 调用导出接口，指定导出类型为 PDF
        const res = await exportToPDF({
          content: contentData,
          title: template.title
        })

        if (res.status !== 200) {
          this.$alert(res.errMsg)
          return
        }

        // 处理文件下载
        const link = document.createElement('a')
        link.href = res.data.file_path
        link.download = res.data.file_name
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)

        this.$message.success('导出成功')
        return res.data // 返回结果，包含 file_path
      } catch (error) {
        console.error('导出PDF失败:', error)
        this.$alert('导出PDF时发生错误，请稍后重试。')
      }
    },
    // 添加处理图片的辅助方法
    processImages(content) {
      const tempDiv = document.createElement('div')
      tempDiv.innerHTML = content
      // 处理所有图片
      tempDiv.querySelectorAll('img').forEach((img) => {
        // 创建图片容器
        const container = document.createElement('div')
        container.className = 'image-container'
        // 获取所有可能的尺寸来源
        let width =
          img.getAttribute('width') || img.style.width || img.width || null
        let height =
          img.getAttribute('height') || img.style.height || img.height || null
        // 移除单位并转换为数字
        if (typeof width === 'string') {
          width = parseInt(width.replace(/[^0-9]/g, ''))
        }
        if (typeof height === 'string') {
          height = parseInt(height.replace(/[^0-9]/g, ''))
        }
        // 如果没有尺寸，创建一个临时图片来获取实际尺寸
        if (!width || !height) {
          const tempImg = new Image()
          tempImg.src = img.src
          width = tempImg.width || 595 // 默认宽度
          height = tempImg.height || Math.round(width * 0.75) // 默认高度比例
        }
        // 确保数值有效
        width = Math.max(1, parseInt(width))
        height = Math.max(1, parseInt(height))
        // 处理尺寸
        const maxWidth = 595 // A4纸宽度（像素，减去边距）
        if (width > maxWidth) {
          // 等比例缩放
          const aspectRatio = width / height
          const newHeight = Math.round(maxWidth / aspectRatio)
          width = maxWidth
          height = newHeight
        }
        // 同时设置style和属性
        img.style.width = `${width}px`
        img.style.height = `${height}px`
        img.setAttribute('width', width)
        img.setAttribute('height', height)
        // 将图片包装在容器中
        img.parentNode.insertBefore(container, img)
        container.appendChild(img)
      })
      return tempDiv.innerHTML
    },

    // 添加一个方法来显示选中数量
    getSelectedCount() {
      return this.selectedTemplateIds.size
    },

    // 添加处理每页条数变化的方法
    handleSizeChange(val) {
      // 保存当前的选择状态
      const currentSelection = this.$refs.templateTable?.selection || []
      currentSelection.forEach((row) => {
        this.selectedTemplateIds.add(row.id)
      })

      // 更新每页显示条数
      this.templateQueryForm.pageSize = val
      // 重置为第一页
      this.templateQueryForm.page = 1

      // 重新加载数据
      this.loadTemplateList()
    },

    // 处理文档类型变化
    handleDocTypeChange(value) {
      this.templateQueryForm.document_type = value
      this.templateQueryForm.page = 1 // 重置页码
      this.loadTemplateList() // 重新加载列表
    },

    // 新增方法：异步加载完成度
    async loadProjectCompletions(projects) {
      // 使用 Promise.all 和 chunk 分批处理
      const chunkSize = 5 // 每批处理5个项目
      const chunks = this.chunkArray(projects, chunkSize)

      for (const chunk of chunks) {
        const promises = chunk.map(async(project) => {
          try {
            const calcRes = await calculate({ id: project.id })
            if (calcRes.status === 200) {
              // 使用 Vue.set 更新单个项目的完成度
              const index = this.dataList.findIndex(
                (item) => item.id === project.id
              )
              if (index !== -1) {
                this.$set(
                  this.dataList[index],
                  'calculate',
                  calcRes.data.completionRate
                )
              }
            }
          } catch (err) {
            console.error(`获取项目${project.id}完成度失败:`, err)
          }
        })

        await Promise.all(promises)
      }
    },

    // 辅助方法：将数组分成小块
    chunkArray(array, size) {
      const chunks = []
      for (let i = 0; i < array.length; i += size) {
        chunks.push(array.slice(i, i + size))
      }
      return chunks
    },

    // 生成目录的方法
    generateTableOfContents(templateData) {
      let toc = ''
      let currentPage = 1

      // 定义章节标题数组
      const sections = [
        '1 PURPOSE OF THE RISK MANAGEMENT REVIEW',
        '2 SCOPE OF APPLICATION',
        '3 RISK MANAGEMENT PROCESS',
        '4 REFERENCES',
        '5 RISK MANAGEMENT REVIEW PERSONNEL',
        '6 RISK ACCEPTABILITY CRITERIA',
        '7 RISK MANAGEMENT REVIEW',
        '8 PRODUCTION AND POST-PRODUCTION ACTIVITIES',
        '9 CONCLUSIONS OF RISK MANAGEMENT REVIEW',
        '10 THE FILE REVIEW COMPLETED',
        'ANNEX A: QUESTION LIST USED TO IDENTIFY MEDICAL DEVICE SAFETY CHARACTERISTICS',
        'ANNEX B: IDENTIFICATION OF KNOWN OR FORESEEABLE HAZARDS',
        'ANNEX C: DETERMINATION OF SOFTWARE SAFETY CLASS',
        'ANNEX D: RISK ANALYSIS AND CONTROL MEASURES',
        'ANNEX E: TRACEABILITY'
      ]

      sections.forEach((section) => {
        toc += `
          <div class="toc-item">
            <span class="toc-text">${section}</span>
            <span class="toc-page">${currentPage}</span>
          </div>
        `
        currentPage++ // 简单估算每个章节占一页
      })

      return toc
    },

    // 处理正文内容的方法
    processContentWithSections(templateData) {
      let processedContent = ''
      let currentPage = 1

      templateData.forEach((item, index) => {
        // 添加章节标题
        processedContent += `
          <div class="section-title">
            ${this.getSectionTitle(index + 1)}
          </div>
          <div class="section-content">
            ${item.content}
          </div>
          <div class="page-number">${currentPage}</div>
        `
        currentPage++
      })

      return processedContent
    },

    // 获取章节标题的辅助方法
    getSectionTitle(index) {
      const titles = {
        1: '1 PURPOSE OF THE RISK MANAGEMENT REVIEW',
        2: '2 SCOPE OF APPLICATION',
        3: '3 RISK MANAGEMENT PROCESS',
        4: '4 REFERENCES',
        5: '5 RISK MANAGEMENT REVIEW PERSONNEL',
        6: '6 RISK ACCEPTABILITY CRITERIA',
        7: '7 RISK MANAGEMENT REVIEW',
        8: '8 PRODUCTION AND POST-PRODUCTION ACTIVITIES',
        9: '9 CONCLUSIONS OF RISK MANAGEMENT REVIEW',
        10: '10 THE FILE REVIEW COMPLETED',
        11: 'ANNEX A: QUESTION LIST USED TO IDENTIFY MEDICAL DEVICE SAFETY CHARACTERISTICS',
        12: 'ANNEX B: IDENTIFICATION OF KNOWN OR FORESEEABLE HAZARDS',
        13: 'ANNEX C: DETERMINATION OF SOFTWARE SAFETY CLASS',
        14: 'ANNEX D: RISK ANALYSIS AND CONTROL MEASURES',
        15: 'ANNEX E: TRACEABILITY'
      }
      return titles[index] || `${index} SECTION`
    },

    // 估算页数的方法
    estimatePageCount(content) {
      const tempDiv = document.createElement('div')
      tempDiv.style.cssText = `
        width: 595px; /* A4 宽度 */
        font-size: 12pt;
        line-height: 1.5;
        visibility: hidden;
        position: absolute;
      `
      tempDiv.innerHTML = content
      document.body.appendChild(tempDiv)

      const contentHeight = tempDiv.offsetHeight
      const pageHeight = 842 // A4 高度
      document.body.removeChild(tempDiv)

      return Math.ceil(contentHeight / pageHeight)
    },

    // 加载文档版本列表
    async loadDocumentVersions(template) {
      this.documentVersionsLoading = true
      this.documentSelectVisible = true

      try {
        const res = await searchlistDoc({
          page: 1,
          pageSize: 999,
          template_id: template.id
        })

        if (res.status === 200) {
          this.documentVersions = res.data.dataList
          if (this.documentVersions.length === 0) {
            this.$message.warning('未找到相关文档版本')
          }
        }
      } catch (error) {
        console.error('加载文档版本失败:', error)
        this.$message.error('加载文档版本失败')
      } finally {
        this.documentVersionsLoading = false
      }
    },

    // 处理文档预览
    handleDocPreview(doc) {
      const url = `#/document/viewCreate?articleId=${doc.id}&type=document`
      window.open(url, '_blank')
      this.documentSelectVisible = false
    },

    // 处理文档导出
    async handleDocExport(command, doc) {
      try {
        switch (command) {
          case 'word':
            // 获取完整的文档信息
            const docInfo = await getDocumentInfo({ id: doc.id })
            if (docInfo.status === 200 && docInfo.data) {
              // 使用 exportDocumentWithHtmlDocx 方法导出
              await this.exportDocumentWithHtmlDocx(docInfo.data)
            } else {
              throw new Error('获取文档信息失败')
            }
            break

          case 'pdf':
            // 保持原有的 PDF 导出功能不变
            const res = await exportToPDF({
              content: doc.content,
              title: doc.title
            })
            if (res.status === 200) {
              const link = document.createElement('a')
              link.href = res.data.file_path
              link.download = `${doc.title}.pdf`
              document.body.appendChild(link)
              link.click()
              document.body.removeChild(link)
            } else {
              throw new Error(res.message || '导出失败')
            }
            break
        }

        this.$message.success('导出成功')
      } catch (error) {
        console.error('导出失败:', error)
        this.$message.error(error.message || '导出失败')
      }
      this.documentSelectVisible = false
    },

    // 新增方法:处理选择变化
    handleCurrentRowChange(selection) {
      // 更新当前页的选择状态
      const currentPage = this.templateQueryForm.page
      this.selectedPageIds.set(currentPage, selection.map(item => item.id))
      
      // 更新所有选中项的集合
      this.selectedTemplates = selection
      
      // 更新全局选中状态集合
      this.selectedTemplateIds = new Set([
        ...Array.from(this.selectedPageIds.values()).flat()
      ])
    },

    // 新增方法:处理单行选择
    isSelectable(row) {
      // 这里可以添加行选择的条件判断
      return true
    },

    // 新增方法:获取行的唯一标识
    getRowKey(row) {
      return row.id
    },

    // 新增：清除选择缓存方法
    clearSelection() {
      this.selectedTemplateIds.clear()
      this.selectedTemplates = []
      if (this.$refs.templateTable) {
        this.$refs.templateTable.clearSelection()
      }
    }
  }
}
</script>

<style lang="scss" scoped>
@import "./dataList.scss";
.match-results {
  margin-top: 20px;

  .match-item {
    padding: 10px;
    border-bottom: 1px solid #eee;
    display: flex;
    justify-content: space-between;
    align-items: center;

    .match-content {
      flex: 1;
      display: flex;
      gap: 20px;
    }

    .actions {
      margin-left: 10px;
    }
  }
}
// 完成度文字样式
.completion-high {
  color: #67c23a;
  font-weight: bold;
}

.completion-medium {
  color: #e6a23c;
  font-weight: bold;
}

.completion-low {
  color: #f56c6c;
  font-weight: bold;
}

// 添加PDF相关样式
.content {
  background: white;

  .template-textarea {
    page-break-after: always;

    table {
      width: 100%;
      border-collapse: collapse;

      td,
      th {
        border: 1px solid black;
        padding: 5px;
      }
    }
  }
}
.header_t {
  margin: 10px 0;
}
/* 添加分页样式 */
.pagination-container {
  margin-top: 15px;
  padding: 10px 0;
  text-align: right;
}

.filter-section {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 20px;
}

/* 添加到已有的 style 标签中 */
.dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 20px;
}

.header-left {
  display: flex;
  gap: 10px;
}

.header-right {
  display: flex;
  align-items: center;
}
</style>
