<!-- 项目输入页面 -->
<template>
  <div class="project-input-container">
    <!-- 从原代码中移动第一个 tab-pane 的内容 -->
    <div class="project-selector">
      <el-form :inline="true">
        <el-form-item label="当前项目">
          <el-select v-model="selectedProjectId" disabled placeholder="请选择项目" style="width: 300px"
            @change="handleProjectConfirm">
            <el-option v-for="project in projectOptions" :key="project.id" :label="project.name" :value="project.id" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button v-if="!hasExistingData" type="primary" @click="handleAddGspr">创建输入项目</el-button>
          <el-button v-else type="primary" @click="handleUpdateGspr">更新输入项目</el-button>
          <el-button type="danger" @click="handleDeleteItems">删除</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 使用 v-if 控制其余内容的显示 -->
    <template v-if="selectedProjectId">
      <div class="operation-bar">
        <el-form :inline="true" :model="gsprSearchForm" class="search-form">
          <el-form-item label="内容">
            <el-input v-model="gsprSearchForm.keyword" placeholder="请输入项目名称/技术报告位置" style="width: 300px" clearable />
          </el-form-item>
          <el-form-item label="部门">
            <el-select v-model="gsprSearchForm.department" placeholder="请选择部门" clearable>
              <el-option v-for="(item, index) in departList" :key="index" :label="item.label" :value="item.label" />
            </el-select>
          </el-form-item>
          <!-- 添加时间范围选择器 -->
          <el-form-item label="创建时间">
            <el-date-picker v-model="gsprSearchForm.dateRange" type="daterange" range-separator="至"
              start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd"
              :picker-options="pickerOptions" />
          </el-form-item>
          <!-- 添加内容状态筛选 -->
          <el-form-item label="内容状态">
            <el-select v-model="gsprSearchForm.content_empty" placeholder="请选择" clearable>
              <!-- <el-option label="请选择状态" value="null" /> -->
              <el-option label="有内容" :value="false" />
              <el-option label="无内容" :value="true" />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleGsprSearch">搜索</el-button>
            <el-button @click="handleGsprReset">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
      <div>
        <el-button type="primary" @click="handleExport">导出输入项目</el-button>
        <!-- <el-button type="primary" @click="handleDocViewGspr"
          >文档预览</el-button
        > -->
      </div>
      <el-table :data="gsprTableData" style="width: 100%" :default-sort="{ prop: sort_field, order: sort_order }"
        @sort-change="handleSortChange" :row-class-name="getRowClassName">
        <el-table-column prop="sequence" label="排序" sortable width="80">
          <template slot-scope="scope">
            <div style="display: flex; align-items: center">
              <span style="margin-right: 10px">{{ scope.row.sequence }}</span>
              <i class="el-icon-edit" style="cursor: pointer; margin-left: 5px"
                @click="handleEditSequence(scope.row)" />
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="name" label="项目名称" sortable>
          <template slot-scope="scope">
            <span v-if="currentModifiedItem === scope.row.id" class="modified-indicator"></span>
            {{ scope.row.name }}
          </template>
        </el-table-column>
        <el-table-column prop="tech_report_location" label="技术报告位置" />
        <el-table-column prop="department" label="部门" sortable />
        <el-table-column prop="content" label="内容" width="450">
          <template slot-scope="scope">
            <div class="content-cell">
              <!--  <el-tooltip
                placement="top-start"
                :disabled="!scope.row.content"
                popper-class="custom-tooltip"
              >
                <template slot="content">
                  <div
                    class="tooltip-content"
                    style="color: #fff !important"
                    v-html="scope.row.content"
                  ></div>
                </template>

  </el-tooltip> -->
              <span class="content-text">{{
                getPlainText(scope.row.content)
                }}</span>
              <i class="el-icon-edit" style="cursor: pointer; margin-left: 5px" @click="handleEditContent(scope.row)" />
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="" label="难度" sortable>
          <template slot-scope="scope">
            <el-rate v-model="scope.row.score" show-score text-color="#ff9900" score-template="{value}"
              @change="(value) => rateScope(value, scope.row)" />
          </template>
        </el-table-column>
        <el-table-column label="备注" width="200">
          <template slot-scope="scope">
            <div style="display: flex; align-items: center">
              <span style="margin-right: 10px">{{ scope.row.remarks }}</span>
              <i class="el-icon-edit" style="cursor: pointer; margin-left: 5px" @click="handleEditRemark(scope.row)" />
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="modified_by" label="创建人" />
        <el-table-column label="操作">
          <template slot-scope="scope">
            <el-button type="primary" @click="handleViewGspr(scope.row)">查看</el-button>
            <!--   <el-button type="primary" @click="handleDocViewGspr(scope.row)"
              >文档预览</el-button
            > -->
            <!--   <el-button type="primary" @click="handleEditGspr(scope.row)"
              >编辑</el-button
            >
            <el-button type="danger" @click="handleDeleteGspr(scope.row)"
              >删除</el-button
            > -->
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination-container">
        <el-pagination :current-page.sync="currentPage" :page-sizes="[30, 50]" :page-size="pageSize"
          layout="total, sizes, prev, pager, next, jumper" :total="gsprTotal" @size-change="handleGsprSizeChange"
          @current-change="handleGsprCurrentChange" />
      </div>

      <!-- GSPR表单弹窗 -->
      <el-dialog :title="gsprDialogTitle" :visible.sync="gsprDialogVisible" :close-on-click-modal="false" width="700px">
        <el-form ref="gsprForm" :model="gsprForm" :rules="gsprRules" label-width="120px">
          <el-form-item label="名称" prop="name">
            <el-input v-model="gsprForm.name" />
          </el-form-item>
          <el-form-item label="技术报告位置" prop="tech_report_location">
            <el-input v-model="gsprForm.tech_report_location" />
          </el-form-item>

          <el-form-item label="部门" prop="department">
            <el-select v-model="gsprForm.department" placeholder="请选择状态">
              <el-option v-for="(item, index) in departList" :key="index" :label="item.label" :value="item.label" />
            </el-select>
          </el-form-item>
          <!--  <el-form-item label="内容" prop="content">
            <div class="editor-area sticky-editor">
              <ckeditor
                ref="editor"
                v-model="gsprForm.content"
                :config="editorConfig"
                :editorUrl="editorUrl"
              ></ckeditor>
            </div>
          </el-form-item> -->
        </el-form>
        <div slot="footer">
          <el-button @click="gsprDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleGsprSubmit">确定</el-button>
        </div>
      </el-dialog>
      <!-- 添加内容编辑弹窗 -->
      <el-dialog title="编辑内容" :visible.sync="contentDialogVisible" :close-on-click-modal="false" width="70%" top="10px">
        <!--  <el-form :model="contentForm" ref="contentForm">
          <el-form-item label="内容" prop="content"> -->
        <!-- <el-inputwidth="600px"
              type="textarea"
              v-model="contentForm.content"
              :rows="4"
              placeholder="请输入内容"
            /> -->
        <!-- <ckeditor
          ref="editor"
          v-model="contentForm.content"
          :config="editorConfig"
          :editorUrl="editorUrl"
        ></ckeditor> -->
        <CanvasEditor ref="wordEditor" :key="keys" :edit-mode="Modetype" :html-data="htmlData" :doc-json="docJson"
          :editor-options="editorOptions" @save="save" @is-save="getSave" />
        <!--   </el-form-item>
        </el-form> -->
        <div slot="footer">
          <el-button @click="contentDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleContentSubmit">确定</el-button>
        </div>
      </el-dialog>
      <!-- 查看弹窗 -->
      <el-dialog title="查看详情" :visible.sync="viewDialogVisible" :close-on-click-modal="false" width="80%">
        <div class="view-details">
          <el-descriptions :column="2" border>
            <el-descriptions-item label="项目名称">{{
              viewForm.name
              }}</el-descriptions-item>
            <el-descriptions-item label="技术报告位置">{{
              viewForm.tech_report_location
              }}</el-descriptions-item>
            <el-descriptions-item label="部门">{{
              viewForm.department
              }}</el-descriptions-item>
            <el-descriptions-item label="难度">
              <el-rate v-model="viewForm.score" disabled show-score text-color="#ff9900" score-template="{value}" />
            </el-descriptions-item>
            <el-descriptions-item label="备注" :span="2">{{
              viewForm.remarks || "-"
              }}</el-descriptions-item>
            <el-descriptions-item label="内容" :span="2">
              <div class="content-view" v-html="viewForm.content || '-'" />
            </el-descriptions-item>
          </el-descriptions>
        </div>
      </el-dialog>
      <!-- 添加文档预览对话框 -->
      <el-dialog title="文档预览" :visible.sync="docPreviewDialogVisible" :close-on-click-modal="false" width="65%"
        class="doc-preview-dialog">
        <div class="doc-preview-header">
          <span>当前文档:</span>
          <el-select v-model="docPreviewSel" placeholder="请选择文档" style="width: 300px" @change="handleDocPreviewChange">
            <el-option v-for="doc in boundTemplateList" :key="doc.id" :label="doc.title" :value="doc" />
          </el-select>
        </div>
        <div v-loading="previewLoading" class="doc-preview-content">
          <div v-if="previewContent" v-html="previewContent" />
          <el-empty v-else description="请选择要预览的文档" />
        </div>
      </el-dialog>
    </template>

    <!-- 未选择项目时显示提示 -->
    <el-empty v-else description="请先选择一个项目" :image-size="200" />

    <!-- 添加删除确认对话框 -->
    <el-dialog title="删除确认" :visible.sync="deleteDialogVisible" width="400px">
      <!-- 添加提示信息区域 -->
      <div class="delete-warning" style="margin-bottom: 20px">
        <i class="el-icon-warning" style="color: #e6a23c; margin-right: 8px" />
        <span>此操作将永久删除该项目下的所有输入项目，请输入'DELETE'确认删除</span>
      </div>

      <el-form ref="deleteForm" :model="deleteForm" :rules="deleteRules" label-width="100px">
        <el-form-item label="确认文本" prop="confirmText">
          <el-input v-model="deleteForm.confirmText" placeholder="请输入'DELETE'" />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="deleteDialogVisible = false">取消</el-button>
        <el-button type="danger" @click="confirmDelete">确认删除</el-button>
      </span>
    </el-dialog>
    <!-- 其余第一个tab的内容... -->
    <!-- 修改序号 -->
    <el-dialog v-el-drag-dialog :visible.sync="dialogVisible" title="修改序号" width="30%" :close-on-click-modal="false"
      append-to-body>
      <el-form :model="sequenceForm" label-width="80px">
        <el-form-item label="序号">
          <el-input-number v-model="sequenceForm.sequence" :min="0" controls-position="right" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitSequence">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 添加备注编辑对话框 -->
    <el-dialog title="编辑备注" :visible.sync="remarkDialogVisible" :close-on-click-modal="false" width="500px">
      <el-form :model="remarkForm">
        <el-form-item label="备注">
          <el-input v-model="remarkForm.remarks" type="textarea" :rows="4" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="remarkDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleRemarkSubmit">确定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  projectListFromTemplate,
  projectAdd,
  departments,
  projectUpdate,
  projectDelete,
  create_items,
  delete_items,
  update_items,
  rateScope,
  sequence,
  projectList,
} from "@/api/knowledge";
import {
  searchProject,
  getProjectInfo,
  searchTemplateList,
} from "@/api/project";
import axios from "axios";
import elDragDialog from "@/directive/el-drag-dialog";
import CanvasEditor from "@/components/CanvasEditor/index"; // 确保路径正确
export default {
  name: "ProjectInput",
  components: {
    CanvasEditor, // 使用驼峰式注册
    // 或者使用短横线式注册
    // 'canvas-editor': CanvasEditor,
  },
  directives: { elDragDialog },
  data() {
    // 自定义验证规则
    const validateDeleteConfirm = (rule, value, callback) => {
      if (value !== "DELETE") {
        callback(new Error("请输入正确的确认文本"));
      } else {
        callback();
      }
    };
    return {
      pickerOptions: {
        shortcuts: [
          {
            text: "最近一周",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
              picker.$emit("pick", [start, end]);
            },
          },
          {
            text: "最近一个月",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setMonth(start.getMonth() - 1);
              picker.$emit("pick", [start, end]);
            },
          },
        ],
      },
      selectedProjectId: null,
      projectOptions: [],
      gsprTableData: [],
      gsprSearchForm: {
        keyword: "",
        department: "",
        content_empty: null,
      },
      gsprTotal: 0,
      departList: [],
      sort_field: "sequence",
      sort_order: "asc",
      hasExistingData: false,
      gsprDialogVisible: false,
      gsprDialogTitle: "",
      gsprForm: {
        id: "",
        name: "",
        tech_report_locations: "",
        department: "",
        content: "",
        remarks: "",
        sequence: 0,
      },
      gsprRules: {
        name: [{ required: true, message: "请输入名称", trigger: "blur" }],
        tech_report_location: [
          { required: true, message: "请输入技术报告位置", trigger: "blur" },
        ],
        department: [
          { required: true, message: "请输入部门", trigger: "blur" },
        ],
        status: [{ required: true, message: "请选择状态", trigger: "change" }],
      },
      editorOptions: {},
      contentDialogVisible: false,
      contentForm: {
        id: "",
        content: "",
        name: "",
        department: "",
      },
      /* 删除逻辑 */
      deleteDialogVisible: false,
      deleteForm: {
        confirmText: "",
      },
      deleteRules: {
        confirmText: [
          { required: true, message: "请输入确认文本", trigger: "blur" },
          { validator: validateDeleteConfirm, trigger: "blur" },
        ],
      },
      editorUrl: "/ckeditor/ckeditor.js",
      editorConfig: {
        language: "zh-cn",
        height: "300px",
      },
      dialogVisible: false,
      sequenceForm: {
        sequence: 1,
        id: null,
      },
      remarkDialogVisible: false,
      remarkForm: {
        id: "",
        remarks: "",
      },
      /* 已绑定项目 */
      documentIds: [],
      templateLocations: [], // 存储传递过来的位置信息
      matchedContents: {}, // 存储技术报告位置匹配的内容

      Modetype: "edit",
      htmlData: "", // 编辑器html数据
      docJson: null, // 编辑器getValue数据
      keys: new Date().getTime(), // 给编辑器赋值不刷新的时候，改变key

      /* 查看 */
      viewDialogVisible: false,
      viewForm: {
        name: "",
        tech_report_location: "",
        department: "",
        score: 0,
        remarks: "",
        content: "",
      },
      /* 文档预览 */
      docPreviewDialogVisible: false,
      previewData: {
        name: "",
        tech_report_location: "",
        interpretation: "",
        content: "",
      },
      /* 文档列表 */
      boundTemplateList: [],
      docPreviewSel: "",
      previewLoading: false,
      previewContent: "",
      currentPage: 1,
      pageSize: 30,
      // 修改状态跟踪
      currentModifiedItem: null, // 当前高亮的项ID（只保持一个）
      originalData: new Map(), // 存储原始数据用于对比
      clearTimer: null, // 自动清理定时器
    };
  },
  mounted() {
    this.fetchProjects().then(() => {
      // Get project ID from URL query parameter
      const urlProjectId = this.$route.query.id;
      if (urlProjectId) {
        this.selectedProjectId = parseInt(urlProjectId);
        this.handleProjectConfirm();
      }
    });

    // 获取并处理传递过来的模板位置数据
    /*  const projectDataStr = this.$route.query.projectData;
     if (projectDataStr) {
       try {
         const projectData = JSON.parse(decodeURIComponent(projectDataStr));
         this.templateLocations = projectData.locations;
 
         // 创建位置到内容的映射
         this.matchedContents = this.templateLocations.reduce((acc, loc) => {
           if (loc.type === "template_location") {
             // 移除位置标记中的括号以便匹配
             const cleanLocation = loc.tech_report_location;
             acc[cleanLocation] = loc;
           }
 
           return acc;
         }, {});
       } catch (error) {
         console.error("解析项目数据失败:", error);
       }
     } */
    this.init();
  },

  methods: {
    /* 当前文档选择 */
    // 处理文档选择变化
    async handleDocPreviewChange(docId) {
      if (!docId) {
        this.previewContent = "";
        return;
      }

      this.previewLoading = true;
      try {
        const docData = JSON.parse(docId.data);
        // 假设这是获取文档预览内容的API
        this.previewContent = docData[0].content;
      } catch (error) {
        this.$message.error(
          "获取文档预览失败：" + (error.message || "未知错误")
        );
        this.previewContent = "";
      } finally {
        this.previewLoading = false;
      }
    },
    /* 处理文字 */
    getPlainText(html) {
      if (!html) return "";

      // 创建临时 DOM 元素来解析 HTML
      const temp = document.createElement("div");
      temp.innerHTML = html;

      // 获取纯文本内容
      const plainText = temp.textContent || temp.innerText;

      // 截断文本
      return plainText.length > 50
        ? plainText.substring(0, 50) + "..."
        : plainText;
    },
    // 添加 CanvasEditor 相关的方法
    save(data) {
      // 处理保存逻辑
      console.log("保存数据:", data);
      // 这里可以添加具体的保存实现
    },

    getSave(isSaved) {
      // 处理保存状态
      console.log("是否已保存:", isSaved);
      // 这里可以添加保存状态的处理逻辑
    },

    // 修改 handleEditContent 方法，添加编辑器数据的处理
    handleEditContent(row) {
      const selectedProject = this.projectOptions.find(
        (p) => p.id === this.selectedProjectId
      );

      // 保存原始数据用于对比
      this.saveOriginalData(row);

      // 处理 content 内容，将文本格式转换为 HTML 并清理空样式
      const processedContent = this.cleanEmptyStyles(
        this.convertTextToHtml(row.content)
      );

      this.contentForm = {
        sequence: row.sequence,
        project: selectedProject.id,
        project_name: selectedProject.name,
        id: row.id,
        tech_report_location: row.tech_report_location,
        content: row.content, // processedContent,
        name: row.name,
        department: row.department,
      };
      if (row.font_style) {
        this.editorOptions = row.font_style;
      } else {
        this.editorOptions = {
          font: "Arial",
          size: 14,
          bold: false,
          align: "left",
        };
      }
      // 设置编辑器数据
      this.htmlData = processedContent;
      this.Modetype = "edit";
      this.keys = new Date().getTime(); // 强制刷新编辑器

      this.contentDialogVisible = true;
    },

    // 处理内容中的a标签，移除a标签但保持表头样式
    processContentForSave(htmlContent) {
      try {
        if (!htmlContent) return htmlContent;

        console.log('开始处理内容，移除a标签但保持表头样式:', htmlContent);

        // 创建临时DOM元素来解析HTML
        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = htmlContent;

        // 处理所有表格
        const tables = tempDiv.querySelectorAll('table');
        tables.forEach(table => {
          // 处理表头行
          const headerRows = table.querySelectorAll('thead tr, tr:first-child');
          headerRows.forEach(headerRow => {
            // 确保表头有背景色
            if (!headerRow.style.backgroundColor) {
              headerRow.style.backgroundColor = '#f5f5f5';
            }

            // 获取表头单元格
            const headerCells = headerRow.querySelectorAll('th, td');

            // 找到第一个没有a标签的表头单元格作为样式参考
            let referenceCell = null;
            let referenceStyle = null;

            for (let cell of headerCells) {
              if (!cell.querySelector('a')) {
                referenceCell = cell;
                referenceStyle = window.getComputedStyle(cell);
                break;
              }
            }

            // 如果没找到参考单元格，使用默认样式
            if (!referenceStyle) {
              referenceStyle = {
                getPropertyValue: (prop) => {
                  const defaults = {
                    'font-weight': 'bold',
                    'font-size': '14px',
                    'font-family': 'Arial, sans-serif',
                    'color': '#000000',
                    'background-color': '#f5f5f5',
                    'text-align': 'left'
                  };
                  return defaults[prop] || '';
                }
              };
            }

            console.log('参考样式:', {
              fontWeight: referenceStyle.getPropertyValue('font-weight'),
              fontSize: referenceStyle.getPropertyValue('font-size'),
              fontFamily: referenceStyle.getPropertyValue('font-family'),
              color: referenceStyle.getPropertyValue('color'),
              backgroundColor: referenceStyle.getPropertyValue('background-color'),
              textAlign: referenceStyle.getPropertyValue('text-align')
            });

            // 处理所有表头单元格
            headerCells.forEach(cell => {
              // 确保表头单元格有背景色
              if (!cell.style.backgroundColor) {
                cell.style.backgroundColor = '#f5f5f5';
              }

              // 获取单元格的原始对齐方式
              const cellComputedStyle = window.getComputedStyle(cell);
              const originalTextAlign = cellComputedStyle.getPropertyValue('text-align') || 
                                       cell.style.textAlign || 
                                       referenceStyle.getPropertyValue('text-align') || 'left';

              // 处理单元格内的超链接
              const cellLinks = cell.querySelectorAll('a');
              cellLinks.forEach(cellLink => {
                const span = document.createElement('span');
                
                // 获取链接的文本内容，并彻底清理中间的换行符
                let linkText = cellLink.textContent;
                
                // 彻底清理文本中间的换行符和多余空白，但保持单词间的单个空格
                // 使用更严格的正则表达式来确保清理所有类型的空白字符
                linkText = linkText.replace(/[\s\n\r\t\f\v]+/g, ' ').trim();
                
                span.textContent = linkText;

                // 应用参考样式
                span.style.fontWeight = referenceStyle.getPropertyValue('font-weight') || 'bold';
                span.style.fontSize = referenceStyle.getPropertyValue('font-size') || '14px';
                span.style.fontFamily = referenceStyle.getPropertyValue('font-family') || 'Arial, sans-serif';
                span.style.color = referenceStyle.getPropertyValue('color') || '#000000';
                
                // 保持原始的对齐方式
                span.style.textAlign = originalTextAlign;

                // 移除链接样式
                span.style.textDecoration = 'none';
                span.style.cursor = 'default';

                console.log('替换a标签，应用样式:', {
                  fontWeight: span.style.fontWeight,
                  fontSize: span.style.fontSize,
                  fontFamily: span.style.fontFamily,
                  color: span.style.color,
                  textAlign: span.style.textAlign,
                  originalTextAlign: originalTextAlign
                });

                cellLink.parentNode.replaceChild(span, cellLink);
              });

              // 确保单元格本身保持正确的对齐方式
              if (!cell.style.textAlign && originalTextAlign !== 'left') {
                cell.style.textAlign = originalTextAlign;
              }
            });
          });

          // 处理表格单元格中的超链接（非表头）
          const cellLinks = table.querySelectorAll('td a, tbody a');
          cellLinks.forEach(cellLink => {
            const span = document.createElement('span');
            span.textContent = cellLink.textContent;

            // 保持单元格的默认样式
            span.style.color = 'inherit';
            span.style.textDecoration = 'none';
            span.style.cursor = 'default';

            cellLink.parentNode.replaceChild(span, cellLink);
          });
        });

        // 处理表格外的超链接
        const links = tempDiv.querySelectorAll('a:not(table a)');
        links.forEach(link => {
          const span = document.createElement('span');
          span.textContent = link.textContent;

          // 获取父元素的样式
          const parentElement = link.parentElement;
          if (parentElement) {
            const parentStyles = window.getComputedStyle(parentElement);

            // 复制重要的样式属性
            const stylesToCopy = [
              'background-color', 'background', 'font-family', 'font-size',
              'font-weight', 'font-style', 'text-align', 'padding', 'margin',
              'border', 'border-color', 'border-width', 'border-style',
              'color', 'text-decoration'
            ];

            stylesToCopy.forEach(styleProp => {
              const value = parentStyles.getPropertyValue(styleProp);
              if (value && value !== 'initial' && value !== 'inherit' && value !== 'transparent') {
                span.style.setProperty(styleProp, value);
              }
            });
          }

          // 设置文本样式为普通文本，移除链接样式
          span.style.textDecoration = 'none';
          span.style.cursor = 'default';

          // 替换超链接元素
          link.parentNode.replaceChild(span, link);
        });

        // 过滤末尾的空格和换行
        let result = this.filterTrailingWhitespace(tempDiv.innerHTML);
        
        // 额外安全措施：对所有表头进行最终的换行符清理
        result = this.finalHeaderCleanup(result);
        
        // 专门清理包含br标签的span元素
        result = this.cleanSpanWithBrTags(result);
        
        console.log('处理完成后的HTML:', result);
        return result;
      } catch (error) {
        console.error('处理内容时出错:', error);
        return htmlContent; // 如果处理失败，返回原始内容
      }
    },

    // 专门清理包含br标签的span元素 - 只处理表格内的内容
    cleanSpanWithBrTags(htmlContent) {
      try {
        if (!htmlContent) return htmlContent;

        // 创建临时DOM元素来解析HTML
        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = htmlContent;

        // 只处理表格内的span元素
        const tables = tempDiv.querySelectorAll('table');
        tables.forEach(table => {
          // 只处理表格内的span元素
          const spansWithBr = table.querySelectorAll('span');
          spansWithBr.forEach(span => {
            const innerHTML = span.innerHTML.trim();
            // 检查是否只包含br标签
            if (innerHTML === '<br>' || innerHTML === '<br/>' || innerHTML === '<br />' || 
                /^\s*(<br\s*\/?>)+\s*$/.test(innerHTML)) {
              span.remove();
              console.log('清理表格内的span br标签:', span);
            }
          });
        });

        return tempDiv.innerHTML;
      } catch (error) {
        console.error('清理span br标签时出错:', error);
        return htmlContent;
      }
    },

    // 最终的表头清理方法，确保所有表头文本都没有中间的换行符
    finalHeaderCleanup(htmlContent) {
      try {
        if (!htmlContent) return htmlContent;

        // 创建临时DOM元素来解析HTML
        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = htmlContent;

        // 处理所有表格的表头
        const tables = tempDiv.querySelectorAll('table');
        tables.forEach(table => {
          // 处理所有表头单元格
          const headerCells = table.querySelectorAll('th, thead td, tr:first-child td');
          
          headerCells.forEach(cell => {
            // 获取所有文本节点
            const textNodes = [];
            const walker = document.createTreeWalker(
              cell,
              NodeFilter.SHOW_TEXT,
              null,
              false
            );
            
            let textNode;
            while (textNode = walker.nextNode()) {
              textNodes.push(textNode);
            }
            
            // 清理所有文本节点
            textNodes.forEach(node => {
              const originalText = node.textContent;
              // 使用最严格的正则表达式清理所有空白字符
              const cleanedText = originalText.replace(/[\s\n\r\t\f\v]+/g, ' ').trim();
              
              if (originalText !== cleanedText) {
                node.textContent = cleanedText;
                console.log('最终清理表头文本:', `"${originalText}" -> "${cleanedText}"`);
              }
            });
            
            // 清理可能存在的空元素和包含br的span
            const emptyElements = cell.querySelectorAll('span, div, p');
            emptyElements.forEach(element => {
              const textContent = element.textContent.trim();
              const hasOnlyBr = element.innerHTML.trim() === '<br>' || 
                               element.innerHTML.trim() === '<br/>' || 
                               element.innerHTML.trim() === '<br />';
              const isEmpty = textContent === '';
              
              if ((isEmpty || hasOnlyBr) && !element.querySelector('img')) {
                element.remove();
                console.log('最终清理：移除空的表头元素:', element, 'innerHTML:', element.innerHTML);
              }
            });
            
            // 特别处理：清理所有包含br标签的span元素
            const spansWithBr = cell.querySelectorAll('span');
            spansWithBr.forEach(span => {
              const innerHTML = span.innerHTML.trim();
              if (innerHTML === '<br>' || innerHTML === '<br/>' || innerHTML === '<br />') {
                span.remove();
                console.log('最终清理：移除只包含br的span元素:', span);
              }
            });
          });
        });

        return tempDiv.innerHTML;
      } catch (error) {
        console.error('最终表头清理时出错:', error);
        return htmlContent;
      }
    },

    // 专门处理表头内容，防止在表头中间添加换行符（适用于所有对齐方式）
    processHeaderContent(headerCell) {
      try {
        // 获取单元格的原始对齐方式
        const cellComputedStyle = window.getComputedStyle(headerCell);
        const textAlign = cellComputedStyle.getPropertyValue('text-align') || 'left';
        
        console.log('处理表头单元格对齐方式:', textAlign, headerCell);
        
        // 获取所有文本节点
        const textNodes = [];
        const walker = document.createTreeWalker(
          headerCell,
          NodeFilter.SHOW_TEXT,
          null,
          false
        );
        
        let textNode;
        while (textNode = walker.nextNode()) {
          textNodes.push(textNode);
        }
        
        // 清理所有文本节点中的换行符和多余空白
        textNodes.forEach(node => {
          const originalText = node.textContent;
          
          // 清理文本中间的换行符和多余空白，但保持单词间的单个空格
          // 这个正则表达式会：
          // 1. 将多个连续的空白字符（包括换行符、制表符、空格）替换为单个空格
          // 2. 清理开头和结尾的空白
          const cleanedText = originalText.replace(/\s+/g, ' ').trim();
          
          if (originalText !== cleanedText) {
            node.textContent = cleanedText;
            console.log('清理表头文本:', `"${originalText}" -> "${cleanedText}"`);
          }
        });
        
        // 确保单元格保持原始的对齐方式
        if (!headerCell.style.textAlign && textAlign !== 'left') {
          headerCell.style.textAlign = textAlign;
        }
        
        // 额外处理：清理单元格内可能存在的空元素和包含br的span
        const emptyElements = headerCell.querySelectorAll('span, div, p');
        emptyElements.forEach(element => {
          // 检查是否为空元素或只包含br标签的span
          const textContent = element.textContent.trim();
          const hasOnlyBr = element.innerHTML.trim() === '<br>' || element.innerHTML.trim() === '<br/>';
          const isEmpty = textContent === '';
          
          if ((isEmpty || hasOnlyBr) && !element.querySelector('img')) {
            element.remove();
            console.log('移除空的表头元素:', element, 'innerHTML:', element.innerHTML);
          }
        });
        
        // 特别处理：清理包含br标签的span元素
        const spansWithBr = headerCell.querySelectorAll('span');
        spansWithBr.forEach(span => {
          // 检查span是否只包含br标签
          const innerHTML = span.innerHTML.trim();
          if (innerHTML === '<br>' || innerHTML === '<br/>' || innerHTML === '<br />') {
            span.remove();
            console.log('移除只包含br的span元素:', span);
          }
        });
        
        return headerCell;
      } catch (error) {
        console.error('处理表头内容时出错:', error);
        return headerCell;
      }
    },

    // 过滤末尾空格和换行的方法 - 特别优化表格内容处理
    // 过滤末尾空格和换行的方法 - 只处理非表头内容
    filterTrailingWhitespace(htmlContent) {
      try {
        if (!htmlContent) return htmlContent;

        // 创建临时DOM元素来解析HTML
        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = htmlContent;

        // 专门处理表格单元格内容的函数 - 只处理非表头单元格
        const processTableCellContent = (cell) => {
          console.log('处理非表头单元格:', cell, '内容:', cell.innerHTML);

          // 递归处理所有文本节点的末尾空白
          const processTextNodes = (node) => {
            if (node.nodeType === Node.TEXT_NODE) {
              // 清理文本节点末尾的空白字符（包括换行符和空格）
              // 但不清除文本中间的空白，只清除末尾的
              const original = node.textContent;
              node.textContent = node.textContent.replace(/[\s\n\r\t]+$/, '');
              if (original !== node.textContent) {
                console.log('清理文本节点:', `"${original}" -> "${node.textContent}"`);
              }
            } else if (node.nodeType === Node.ELEMENT_NODE) {
              // 递归处理所有子节点
              Array.from(node.childNodes).forEach(processTextNodes);
            }
          };

          // 处理单元格内的所有文本节点
          Array.from(cell.childNodes).forEach(processTextNodes);

          // 特别处理：清理单元格内嵌套元素末尾的br标签和空白
          const nestedElements = cell.querySelectorAll('span, div, p, strong, em, b, i, a');
          nestedElements.forEach(element => {
            // 递归处理嵌套元素的文本节点
            Array.from(element.childNodes).forEach(processTextNodes);

            // 清理元素末尾的br标签
            let innerHTML = element.innerHTML;
            const originalInnerHTML = innerHTML;

            // 移除末尾的br标签
            innerHTML = innerHTML.replace(/(<br\s*\/?>)+$/gi, '');
            // 移除末尾的空白字符
            innerHTML = innerHTML.replace(/[\s\n\r\t]+$/, '');

            if (innerHTML !== originalInnerHTML) {
              element.innerHTML = innerHTML;
              console.log('清理嵌套元素:', element.tagName, `"${originalInnerHTML}" -> "${innerHTML}"`);
            }
          });

          // 最终清理：直接处理单元格的innerHTML来移除末尾的br和空白
          let cellHTML = cell.innerHTML;
          const originalCellHTML = cellHTML;

          // 多次处理确保彻底清理
          let previousHTML;
          do {
            previousHTML = cellHTML;
            // 移除末尾的br标签
            cellHTML = cellHTML.replace(/(<br\s*\/?>)+$/gi, '');
            // 移除末尾的空白字符（包括换行、空格等）
            cellHTML = cellHTML.replace(/[\s\n\r\t]+$/, '');
            // 移除末尾的空span、div等标签
            cellHTML = cellHTML.replace(/<(span|div|p)[^>]*>\s*<\/\1>$/gi, '');
          } while (cellHTML !== previousHTML);

          if (cellHTML !== originalCellHTML) {
            cell.innerHTML = cellHTML;
            console.log('最终清理非表头单元格:', `"${originalCellHTML}" -> "${cellHTML}"`);
          }

          // 清理单元格内可能存在的空文本节点
          const walker = document.createTreeWalker(
            cell,
            NodeFilter.SHOW_TEXT,
            null,
            false
          );

          let textNode;
          const nodesToRemove = [];
          while (textNode = walker.nextNode()) {
            if (textNode.textContent.trim() === '') {
              nodesToRemove.push(textNode);
            }
          }

          nodesToRemove.forEach(node => node.remove());
        };

        // 处理所有表格，但只处理非表头内容
        const allTables = tempDiv.querySelectorAll('table');
        allTables.forEach(table => {
          console.log('处理表格，但保护表头:', table);

          // 1. 明确保护表头内容：不处理thead中的任何单元格，但需要处理居中对齐的换行符问题
          const theadCells = table.querySelectorAll('thead th, thead td');
          console.log('保护表头单元格数量:', theadCells.length);
          theadCells.forEach(cell => {
            console.log('跳过表头单元格:', cell, '内容:', cell.innerHTML);
            // 使用专门的方法处理表头内容，防止居中表头中间出现换行符
            this.processHeaderContent(cell);
          });

          // 2. 明确保护表格标题行（通常是第一行包含th的行）
          const allRows = table.querySelectorAll('tr');
          const headerRows = [];

          // 识别可能的表头行（包含th的行或第一行）
          allRows.forEach((row, index) => {
            const hasTh = row.querySelector('th');
            const isFirstRow = index === 0;
            if (hasTh || isFirstRow) {
              headerRows.push(row);
              console.log('识别为表头行:', row);
            }
          });

          // 保护表头行中的所有单元格，但需要处理居中对齐的换行符问题
          headerRows.forEach(row => {
            const headerCells = row.querySelectorAll('th, td');
            headerCells.forEach(cell => {
              console.log('保护表头行中的单元格:', cell, '内容:', cell.innerHTML);
              // 使用专门的方法处理表头内容，防止居中表头中间出现换行符
              this.processHeaderContent(cell);
            });
          });

          // 3. 只处理tbody中的非表头td单元格
          const tbodyTds = table.querySelectorAll('tbody td');
          tbodyTds.forEach(td => {
            // 双重检查：确保这个td不在任何表头行中
            const parentRow = td.closest('tr');
            const isInHeaderRow = headerRows.includes(parentRow);

            if (!isInHeaderRow) {
              processTableCellContent(td);
            } else {
              console.log('跳过表头行中的td:', td);
            }
          });

          // 4. 处理没有tbody的表格：只处理非表头行的td
          const hasTbody = table.querySelector('tbody');
          if (!hasTbody) {
            console.log('表格没有tbody，处理非表头行');

            allRows.forEach((row, index) => {
              const isHeaderRow = headerRows.includes(row);

              if (!isHeaderRow) {
                console.log('处理非表头行:', row);
                const cells = row.querySelectorAll('td');
                cells.forEach(cell => {
                  processTableCellContent(cell);
                });
              } else {
                console.log('跳过表头行:', row);
              }
            });
          }

          // 5. 额外安全措施：明确不处理任何th元素，但需要处理居中对齐的换行符问题
          const allThs = table.querySelectorAll('th');
          allThs.forEach(th => {
            console.log('保护所有th元素:', th, '内容:', th.innerHTML);
            // 使用专门的方法处理表头内容，防止居中表头中间出现换行符
            this.processHeaderContent(th);
          });

          // 6. 额外检查：确保没有遗漏需要保护的单元格
          const allCells = table.querySelectorAll('td, th');
          allCells.forEach(cell => {
            const parentRow = cell.closest('tr');
            const isTh = cell.tagName.toLowerCase() === 'th';
            const isInHeaderRow = headerRows.includes(parentRow);
            const isInThead = cell.closest('thead');

            if (isTh || isInHeaderRow || isInThead) {
              console.log('确认保护单元格:', cell.tagName, '在表头中:', cell);
            }
          });
        });

        // 跳过非表格内容的处理，保留原始格式（如流程图等）
        // 不处理非表格内容的文本节点，保持原始格式
        
        // 获取处理后的HTML
        let result = tempDiv.innerHTML;

        console.log('初步处理结果:', result);

        // 只对表格内容进行最终清理，不影响非表格内容
        // 使用正则表达式只匹配和处理表格内的内容
        result = result.replace(
          /(<table[^>]*>[\s\S]*?<\/table>)/gi,
          (tableMatch) => {
            // 只清理表格末尾的空白和br标签
            let cleanedTable = tableMatch;
            let previousTable;
            do {
              previousTable = cleanedTable;
              // 清理表格末尾的空白字符（但保留表格结构）
              cleanedTable = cleanedTable.replace(/(<\/td>|<\/th>|<\/tr>|<\/tbody>|<\/thead>|<\/table>)\s+$/gm, '$1');
              // 清理表格末尾的br标签（但保留表格结构）
              cleanedTable = cleanedTable.replace(/(<\/td>|<\/th>|<\/tr>|<\/tbody>|<\/thead>|<\/table>)(<br\s*\/?>)+$/gm, '$1');
            } while (cleanedTable !== previousTable);
            return cleanedTable;
          }
        );

        console.log('最终结果:', result);

        return result;
      } catch (error) {
        console.error('过滤末尾空白时出错:', error);
        return htmlContent; // 如果处理失败，返回原始内容
      }
    },

    // 修改 handleContentSubmit 方法
    async handleContentSubmit() {
      try {
        // 获取编辑器的最新内容
        const editorContent = this.$refs.wordEditor.editorRef.command.getHTML();

        // 获取当前的字体样式配置
        const fontStyle = this.editorOptions || {
          font: 'Arial',
          size: 14,
          align: 'left'
        };

        // 创建样式字符串
        const styleString = `font-family: ${fontStyle.font}; font-size: ${fontStyle.size}px; text-align: ${fontStyle.align};}`;

        // 处理表格内容
        const processedContent = editorContent.main.replace(
          /<table[^>]*>([\s\S]*?)<\/table>/g,
          (tableMatch) => {
            // 首先处理表格级别的空白和换行
            const cleanTableMatch = tableMatch
              .replace(/>\s+</g, '><') // 移除标签之间的空白
              .replace(/\n/g, '') // 移除所有换行符
              .replace(/<div style="text-align: justify;">([\s\S]*?)<\/div>/g, '$1') // 移除对齐div标签
              .replace(/<a[^>]*>([\s\S]*?)<\/a>/g, (match, content) => {
                // 使用配置的字体样式替换超链接文本
                return `<span style="${styleString}">${content}</span>`;
              });

            return cleanTableMatch.replace(
              /(<td[^>]*>)([\s\S]*?)(<\/td>)/g,
              (tdMatch, tdOpen, content, tdClose) => {
                // 处理单元格内容
                const cleanContent = content
                  .replace(/<div style="text-align: justify;">([\s\S]*?)<\/div>/g, '$1') // 移除对齐div标签
                  .replace(/<a[^>]*>([\s\S]*?)<\/a>/g, (match, linkContent) => {
                    // 使用配置的字体样式替换超链接文本
                    return `<span style="${styleString}">${linkContent}</span>`;
                  })
                  .replace(/\n/g, '') // 移除所有换行
                  .replace(/\s+/g, ' ') // 多个空格变成一个
                  .replace(/^\s+|\s+$/g, '') // 移除首尾空格
                  .replace(/—\s+/g, '— ') // 处理破折号后的空格
                  .replace(/\s+—/g, ' —') // 处理破折号前的空格
                  .replace(/\s*([,.])\s*/g, '$1 '); // 处理标点符号周围的空格

                return tdOpen + cleanContent + tdClose;
              }
            );
          }
        );

        // 更新 contentForm
        this.contentForm.content = this.processContentForSave(editorContent.main);

        const submitData = {
          ...this.contentForm,
          id: this.contentForm.id,
          content: this.contentForm.content,
          font_style: this.editorOptions // 保存字体样式配置
        };

        await projectUpdate(submitData);
        this.$message.success("内容更新成功");
        this.contentDialogVisible = false;

        // 检查数据是否有变化，如果有则标记为已修改
        const originalData = this.originalData.get(this.contentForm.id);
        if (this.checkDataChanged(submitData, originalData)) {
          this.markAsModified(this.contentForm.id);
        }

        this.fetchGsprData();
      } catch (error) {
        this.$message.error("内容更新失败");
      }
    },

    // 修改现有的 handleEditRemark 方法
    handleEditRemark(row) {
      // 保存原始数据用于对比
      this.saveOriginalData(row);

      // 只复制需要的字段
      this.remarkForm = {
        id: row.id,
        remarks: row.remarks || "",
        sequence: row.sequence,
        project: row.project,
        content: row.content,
        name: row.name,
        department: row.department
      };
      this.remarkDialogVisible = true;
    },

    // 修改备注提交方法
    async handleRemarkSubmit() {
      try {
        console.log(this.remarkForm);
        // 只更新必要的字段
        const updateData = {
          ...this.remarkForm,
          remarks: this.remarkForm.remarks,
          id: this.remarkForm.id,
        };

        await projectUpdate(updateData);
        this.$message.success("备注更新成功");
        this.remarkDialogVisible = false;

        // 检查数据是否有变化，如果有则标记为已修改
        const originalData = this.originalData.get(this.remarkForm.id);
        if (this.checkDataChanged(updateData, originalData)) {
          this.markAsModified(this.remarkForm.id);
        }

        this.fetchGsprData();
      } catch (error) {
        this.$message.error("备注更新失败");
      }
    },
    /* 修改评分 */
    async rateScope(value, row) {
      try {
        // 保存原始数据用于对比
        if (!this.originalData.has(row.id)) {
          this.saveOriginalData(row);
        }

        const response = await rateScope({
          id: row.id,
          score: value,
        });

        if (response.status === 200) {
          this.$message.success("评分更新成功");
          // 更新本地数据
          const index = this.gsprTableData.findIndex(
            (item) => item.id === row.id
          );
          if (index !== -1) {
            this.gsprTableData[index].score = value;
          }

          // 检查数据是否有变化，如果有则标记为已修改
          const originalData = this.originalData.get(row.id);
          if (originalData && originalData.score !== value) {
            this.markAsModified(row.id);
          }
        } else {
          throw new Error(response.message || "评分更新失败");
        }
      } catch (error) {
        this.$message.error(error.message || "评分更新失败");
        // 恢复原始评分
        row.score = row.score || 0;
      }
    },
    /* 修改序号 */
    handleEditSequence(row) {
      // 保存原始数据用于对比
      this.saveOriginalData(row);

      this.sequenceForm.sequence = row.sequence;
      this.sequenceForm.id = row.id;
      this.dialogVisible = true;
    },
    // 提交序号修改
    async submitSequence() {
      try {
        await sequence({
          id: this.sequenceForm.id,
          new_sequence: this.sequenceForm.sequence,
        });
        this.$message.success("修改序号成功");
        this.dialogVisible = false;

        // 检查数据是否有变化，如果有则标记为已修改
        const originalData = this.originalData.get(this.sequenceForm.id);
        if (originalData && originalData.sequence !== this.sequenceForm.sequence) {
          this.markAsModified(this.sequenceForm.id);
        }

        // 重新加载数据
        this.fetchGsprData();
      } catch (error) {
        this.$message.error("修改序号失败：" + error.message);
      }
    },

    /* 项目导出 */
    async handleExport() {
      const loading = this.$loading({
        lock: true,
        text: "导出中...",
      });

      try {
        const response = await axios({
          url: `${process.env.VUE_APP_BASE_API}/project-input/export`,
          method: "post",
          data: { project_id: this.selectedProjectId },
          headers: {
            "Content-Type": "application/json",
            Authorization: "Bearer " + localStorage.getItem("token"), // 根据实际token获取方式调整
          },
        });
        // 检查响应数据
        if (
          !response.data ||
          !response.data.data ||
          !response.data.data.data.file_content
        ) {
          throw new Error("导出失败：返回数据格式错误");
        }

        // 获取文件内容和文件名
        const { file_content, file_name } = response.data.data.data;

        // 将base64转换为blob
        const byteCharacters = atob(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.spreadsheetml.sheet",
        });

        // 下载文件
        const link = document.createElement("a");
        link.href = window.URL.createObjectURL(blob);
        link.download = file_name;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        window.URL.revokeObjectURL(link.href);

        this.$message.success(response.data.message || "导出成功");
      } catch (error) {
        console.error("导出错误:", error);
        let errorMessage = "导出失败，请稍后重试";

        if (error.response) {
          switch (error.response.status) {
            case 401:
              errorMessage = "导出失败：未授权，请重新登录";
              break;
            case 403:
              errorMessage = "导出失败：没有导出权限";
              break;
            case 404:
              errorMessage = "导出失败：导出接口不存在";
              break;
            case 500:
              errorMessage = "导出失败：服务器内部错误";
              break;
            default:
              errorMessage = `导出失败：${error.response.status}`;
          }
        }

        this.$message.error(errorMessage);
      } finally {
        loading.close();
      }
    },
    /* 删除 */
    async handleDeleteGspr(row) {
      try {
        await this.$confirm("确认删除该记录?", "提示", {
          type: "warning",
        });
        // 替换为实际的删除API调用
        await projectDelete({ id: row.id });
        this.$message.success("删除成功");
        this.fetchGsprData();
      } catch (error) {
        if (error !== "cancel") {
          this.$message.error("删除失败");
        }
      }
    },
    /* 文档预览 */
    async handleDocViewGspr(row) {
      try {
        const loading = this.$loading({
          lock: true,
          text: "加载文档预览...",
          spinner: "el-icon-loading",
          background: "rgba(0, 0, 0, 0.7)",
        });
        searchTemplateList({ ids: this.documentIds.join(",") || 0 }).then(
          (res) => {
            if (res.status !== 200) return;
            this.boundTemplateList = res.data;
            loading.close();
            this.docPreviewDialogVisible = true;
          }
        );
      } catch (error) {
        loading.close();
        this.$message.error(
          "获取文档预览失败：" + (error.message || "未知错误")
        );
      }
    },

    /* 查看 */
    handleViewGspr(row) {
      this.viewForm = {
        name: row.name,
        tech_report_location: row.tech_report_location,
        department: row.department,
        score: row.score || 0,
        remarks: row.remarks,
        content: row.content,
      };

      this.viewDialogVisible = true;
    },
    /* 编辑 */
    handleEditGspr(row) {
      this.gsprDialogTitle = "编辑文献项目";
      this.gsprForm = { ...row };
      this.gsprDialogVisible = true;
    },
    // 修改回显方法，解析样式
    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}" class="${tableClass}">`;

          rows.forEach((row) => {
            tableHtml += "<tr>";
            const cells = row.split("|").map((cell) => {
              const cellMatch = cell.match(
                /(.*?)(?:\[style=(.*?)\|class=(.*?)\])?$/
              );
              if (cellMatch) {
                const [_, content, style = "", className = ""] = cellMatch;
                return `<td style="${style}" class="${className}">${content.trim()}</td>`;
              }
              return `<td>${cell.trim()}</td>`;
            });
            tableHtml += cells.join("") + "</tr>";
          });

          tableHtml += "</table>";
          return tableHtml;
        }
      );

      // 2. 处理图片标记（保持不变）
      html = html.replace(
        /\[图片:(.*?)\|style=(.*?)\|class=(.*?)\]/g,
        (match, src, style, className) => {
          return `<img src="${src}" alt="图片" style="${style}" class="${className}">`;
        }
      );

      // 3. 处理文本样式（保持不变）
      html = html.replace(
        /\[文本:(.*?)\|style=(.*?)\|class=(.*?)\]/g,
        (match, content, style, className) => {
          return `<span style="${style}" class="${className}">${content}</span>`;
        }
      );

      // 4. 处理换行
      html = html.replace(/\n/g, "<br>");

      return html;
    },

    // 添加辅助方法：清理空样式属性
    cleanEmptyStyles(html) {
      return html
        .replace(/style=""/g, "")
        .replace(/class=""/g, "")
        .replace(/\s+>/g, ">");
    },
    /*  */
    /*   async handleContentSubmit() {
      try {
        // 创建一个函数来处理富文本内容，保留样式
        const processContent = (htmlContent) => {
          const tempDiv = document.createElement("div");
          tempDiv.innerHTML = htmlContent;

          // 处理图片：保留样式属性
          const images = tempDiv.getElementsByTagName("img");
          Array.from(images).forEach((img) => {
            const style = img.getAttribute("style") || "";
            const className = img.getAttribute("class") || "";
            const imgPlaceholder = `[图片:${img.src}|style=${style}|class=${className}]`;
            img.replaceWith(document.createTextNode(imgPlaceholder));
          });

          // 处理表格：保留完整的样式属性，包括边框
          const tables = tempDiv.getElementsByTagName("table");
          Array.from(tables).forEach((table) => {
            const tableStyle = table.getAttribute("style") || "";
            const tableClass = table.getAttribute("class") || "";
            const tableBorder = table.getAttribute("border") || "";

            const rows = Array.from(table.rows).map((row) => {
              return Array.from(row.cells)
                .map((cell) => {
                  const cellStyle = cell.getAttribute("style") || "";
                  const cellClass = cell.getAttribute("class") || "";
                  const cellBorder = cell.getAttribute("border") || "";
                  const content = cell.textContent.trim();

                  // 合并所有样式属性
                  const cellStyles = [
                    cellStyle,
                    cellBorder ? `border: ${cellBorder}px solid #000;` : "",
                  ]
                    .filter(Boolean)
                    .join(" ");

                  return `${content}${
                    cellStyles || cellClass
                      ? `[style=${cellStyles}|class=${cellClass}]`
                      : ""
                  }`;
                })
                .join("|");
            });

            // 合并表格的样式属性
            const tableStyles = [
              tableStyle,
              tableBorder ? `border: ${tableBorder}px solid #000;` : "",
            ]
              .filter(Boolean)
              .join(" ");

            const tablePlaceholder = `[表格|style=${tableStyles}|class=${tableClass}]\n${rows.join(
              "\n"
            )}`;
            table.replaceWith(document.createTextNode(tablePlaceholder));
          });

          // 处理文本样式
          const styledSpans = tempDiv.getElementsByTagName("span");
          Array.from(styledSpans).forEach((span) => {
            const style = span.getAttribute("style") || "";
            const className = span.getAttribute("class") || "";
            if (style || className) {
              const content = span.textContent;
              span.replaceWith(
                document.createTextNode(
                  `[文本:${content}|style=${style}|class=${className}]`
                )
              );
            }
          });

          return tempDiv.textContent || tempDiv.innerText;
        };

        const submitData = {
          ...this.contentForm,
          content: processContent(this.contentForm.content),
        };

        await projectUpdate(submitData);
        this.$message.success("内容更新成功");
        this.contentDialogVisible = false;
        this.fetchGsprData();
      } catch (error) {
        this.$message.error("内容更新失败");
      }
    }, */

    // 同样修改handleGsprSubmit方法
    async handleGsprSubmit() {
      try {
        await this.$refs.gsprForm.validate();

        // 处理富文本内容
        const processContent = (htmlContent) => {
          const tempDiv = document.createElement("div");
          tempDiv.innerHTML = htmlContent;

          // 处理图片
          const images = tempDiv.getElementsByTagName("img");
          Array.from(images).forEach((img) => {
            const imgPlaceholder = `[图片:${img.src}]`;
            img.replaceWith(document.createTextNode(imgPlaceholder));
          });

          // 处理表格
          const tables = tempDiv.getElementsByTagName("table");
          Array.from(tables).forEach((table) => {
            const rows = Array.from(table.rows).map((row) =>
              Array.from(row.cells)
                .map((cell) => cell.textContent.trim())
                .join(" | ")
            );
            const tablePlaceholder = "[表格]\n" + rows.join("\n");
            table.replaceWith(document.createTextNode(tablePlaceholder));
          });

          return tempDiv.textContent || tempDiv.innerText;
        };

        // 创建新对象避免修改原始数据
        const submitData = {
          ...this.gsprForm,
          content: processContent(this.gsprForm.content),
        };

        if (this.gsprForm.id) {
          await projectUpdate(submitData);
        } else {
          await projectAdd(submitData);
        }

        this.$message.success(this.gsprForm.id ? "更新成功" : "创建成功");
        this.gsprDialogVisible = false;
        this.fetchGsprData();
      } catch (error) {
        if (error !== false) {
          this.$message.error("保存失败");
        }
      }
    },
    /*  */
    // async handleGsprSubmit() {
    //   try {
    //     await this.$refs.gsprForm.validate()
    //     if (this.gsprForm.id) {
    //       await projectUpdate(this.gsprForm)
    //     } else {
    //       await projectAdd(this.gsprForm)
    //     }
    //     this.$message.success(this.gsprForm.id ? '更新成功' : '创建成功')
    //     this.gsprDialogVisible = false
    //     this.fetchGsprData()
    //   } catch (error) {
    //     if (error !== false) {
    //       this.$message.error('保存失败')
    //     }
    //   }
    // },
    /* 初始化项目列表 */
    async fetchProjects() {
      try {
        const response = await searchProject({ page: 1, pageSize: 999 });
        if (response.status === 200) {
          this.projectOptions = response.data.dataList;

          // 如果有当前项目ID但没有选中项目，自动选中
          // 如果有当前项目ID但没有选中项目，自动选中
          if (!this.selectedProjectId && this.$route.query.id) {
            this.selectedProjectId = parseInt(this.$route.query.id);
            this.handleProjectConfirm();
          }
        }
      } catch (error) {
        this.$message.error("获取项目列表失败");
      }
    },
    async handleProjectConfirm() {
      if (!this.selectedProjectId) {
        this.$message.warning("请先选择一个项目");
        return;
      }
      const selectedProject = this.projectOptions.find(
        (p) => p.id === this.selectedProjectId
      );
      if (!selectedProject) {
        this.$message.error("未找到选中的项目");
        return;
      }

      this.$store.dispatch("project/setCurrentProject", {
        id: selectedProject.id,
        name: selectedProject.name,
      });

      localStorage.setItem(
        "currentProject",
        JSON.stringify({
          id: selectedProject.id,
          name: selectedProject.name,
        })
      );

      // 恢复该项目上次的分页设置
      try {
        const savedPage = Number(
          localStorage.getItem(`gspr_page_${this.selectedProjectId}`)
        );
        const savedPageSize = Number(
          localStorage.getItem(`gspr_page_size_${this.selectedProjectId}`)
        );
        if (!Number.isNaN(savedPage) && savedPage > 0) {
          this.currentPage = savedPage;
        }
        if (!Number.isNaN(savedPageSize) && savedPageSize > 0) {
          this.pageSize = savedPageSize;
        }
      } catch (e) {
        // 忽略本地存储异常
      }

      this.gsprSearchForm.project_id = this.selectedProjectId;
      this.fetchGsprData();
    },
    // 创建项目
    async handleAddGspr() {
      if (!this.selectedProjectId) {
        this.$message.warning("请先选择一个项目");
        return;
      }

      const loading = this.$loading({
        lock: true,
        text: "正在创建项目...",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)",
      });

      try {
        const res = await projectListFromTemplate(
          /* create_items */ {
            project_id: this.selectedProjectId,
          }
        );

        if (res.status === 200) {
          this.$message.success("输入项目创建成功");
          await this.fetchGsprData();
        }
      } catch (error) {
        this.$message.error("创建失败: " + (error.message || "未知错误"));
      } finally {
        loading.close();
      }
    },

    // 更新项目
    async handleUpdateGspr() {
      if (!this.selectedProjectId) {
        this.$message.warning("请先选择一个项目");
        return;
      }
      const selectedProject = this.projectOptions.find(
        (p) => p.id === this.selectedProjectId
      );

      try {
        await this.$confirm(
          "此操作将更新当前项目的所有输入项目，是否继续？",
          "提示",
          {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
          }
        );

        const loading = this.$loading({
          lock: true,
          text: "正在更新项目...",
          spinner: "el-icon-loading",
          background: "rgba(0, 0, 0, 0.7)",
        });

        try {
          const res = await projectListFromTemplate(
            /* update_items */ {
              // 假设有一个update_items的API
              project_id: selectedProject.id,
              /* project_name: selectedProject.name */
            }
          );
          console.log(res);
          if (res.status !== 200) {
            throw new Error("更新失败");
          }

          this.$message.success(`输入项目更新成功`);
          await this.fetchGsprData();
        } finally {
          loading.close();
        }
      } catch (error) {
        if (error !== "cancel") {
          this.$message.error("更新失败: " + (error.message || "未知错误"));
        }
      }
    },

    // 删除项目
    async handleDeleteItems() {
      if (!this.selectedProjectId) {
        this.$message.warning("请先选择一个项目");
        return;
      }

      const selectedProject = this.projectOptions.find(
        (p) => p.id === this.selectedProjectId
      );

      this.$confirm(
        `您确定要删除项目 "${selectedProject.name}" 的所有输入项目吗？此操作不可恢复。`,
        "警告",
        {
          confirmButtonText: "继续删除",
          cancelButtonText: "取消",
          type: "warning",
        }
      )
        .then(() => {
          this.deleteForm.confirmText = "";
          this.deleteDialogVisible = true;
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
    // 确认删除
    confirmDelete() {
      this.$refs.deleteForm.validate(async (valid) => {
        if (!valid) {
          return false;
        }

        try {
          const loading = this.$loading({
            lock: true,
            text: "正在删除...",
            spinner: "el-icon-loading",
            background: "rgba(0, 0, 0, 0.7)",
          });

          const response = await delete_items({
            project_id: this.selectedProjectId,
          });

          loading.close();

          if (response.status === 200) {
            this.$message.success("删除成功");
            this.deleteDialogVisible = false;
            // 重新加载数据
            this.fetchGsprData();
          } else {
            this.$message.error(response.message || "删除失败");
          }
        } catch (error) {
          this.$message.error("删除失败：" + (error.message || "未知错误"));
        }
      });
    },

    // 修改获取数据的方法
    async fetchGsprData() {
      this.gsprTableData = [];
      if (!this.selectedProjectId) {
        this.$message.warning("请先选择项目");
        return;
      }

      const loading = this.$loading({
        lock: true,
        text: "加载中...",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)",
      });

      try {
        const params = {
          project_id: this.selectedProjectId,
          page: this.currentPage,
          page_size: this.pageSize,
          sort_field: this.sort_field,
          sort_order: this.sort_order,
          ...this.gsprPageForm,
          ...this.gsprSearchForm,
          start_date: this.gsprSearchForm.dateRange?.[0] || null,
          end_date: this.gsprSearchForm.dateRange?.[1] || null,
        };

        const response = await projectList(params);

        if (!response || !response.data) {
          throw new Error("API响应数据格式错误");
        }
        response.data.list.map((el) => {
          if (el.score == null) {
            el.score = 0;
          }
        });

        const responseData = response.data;

        // 过滤掉 tech_report_locations 为空的数据
        /* const filteredItems = responseData.items
          .filter(item => item.tech_report_locations)
          .map(item => ({
            id: item.id,
            location: item.location || '',
            tech_report_location: item.tech_report_locations || '',
            name: item.name || '',
            department: item.department || '',
            sequence: item.sequence || 0,
            remarks: item.remarks || '',
            content: item.content || '',
            project: item.project || '',
            project_name: item.project_name || '',
            create_time: item.create_time || '',
            update_time: item.update_time || '',
            score: item.score || 0
          })) */
        this.gsprTableData = responseData.list; //filteredItems
        this.gsprTotal = responseData.total; // 使用API返回的总数
        this.hasExistingData = this.gsprTableData.length > 0;

        // 保存原始数据用于后续对比
        this.gsprTableData.forEach(item => {
          if (!this.originalData.has(item.id)) {
            this.saveOriginalData(item);
          }
        });
      } catch (error) {
        console.error("数据加载失败:", error);
        this.$message.error(error.message || "获取数据失败");
        this.gsprTableData = [];
        this.gsprTotal = 0;
        this.hasExistingData = false;
      } finally {
        loading.close();
      }
    },

    // 添加一个辅助方法来检查位置是否匹配
    isLocationMatched(location) {
      if (!location) return false;
      const cleanLocation = location.replace(/[\[\]【】]/g, "");
      return !!this.matchedContents[cleanLocation];
    },

    handleGsprSearch() {
      this.currentPage = Number(
        localStorage.getItem(`gspr_page_${this.selectedProjectId}`)
      ); // 搜索时重置到第一页
      console.log(this.currentPage);
      this.searchList();
      /* this.fetchGsprData(); */
    },
    /* 搜索 */
    async searchList() {
      this.gsprTableData = [];
      const loading = this.$loading({
        lock: true,
        text: "加载中...",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)",
      });
      try {
        const params = {
          project_id: this.selectedProjectId,
          page: this.currentPage,
          page_size: this.pageSize,
          sort_field: this.sort_field,
          sort_order: this.sort_order,
          ...this.gsprPageForm,
          ...this.gsprSearchForm,
          start_date: this.gsprSearchForm.dateRange?.[0] || null,
          end_date: this.gsprSearchForm.dateRange?.[1] || null,
        };
        const response = await projectList(params);
        response.data.list.map((el) => {
          if (el.score == null) {
            el.score = 0;
          }
        });
        this.gsprTableData = response.data.list; //filteredItems
        this.gsprTotal = response.data.total; // 使用API返回的总数
        /* this.currentPage = response.data.current_page; */
        this.hasExistingData = this.gsprTableData.length > 0;

        // 保存原始数据用于后续对比
        this.gsprTableData.forEach(item => {
          if (!this.originalData.has(item.id)) {
            this.saveOriginalData(item);
          }
        });

        console.log(response);
      } finally {
        loading.close();
      }
    },
    handleGsprReset() {
      this.gsprSearchForm = {
        keyword: "",
        department: "",
        project_id: this.selectedProjectId,
        dateRange: [],
        content_empty: null,
      };
      this.handleGsprSearch();
    },

    // 排序处理
    handleSortChange({ prop, order }) {
      this.sort_field = prop;
      this.sort_order = order === "ascending" ? "asc" : "desc";
      if (!order) {
        this.sort_field = "name";
        this.sort_order = "desc";
      }
      this.fetchGsprData();
    },
    /* 获取字段 */
    init() {
      departments().then((res) => {
        if (res.status !== 200) return;
        this.departList = res.data.departments;
      });
      /* 获取当前项目绑定的文档 */
      getProjectInfo({ id: this.$route.query.id }).then((res) => {
        this.documentIds = res.data.documentIds;
      });
    },

    handleGsprSizeChange(val) {
      this.pageSize = val;
      // this.currentPage = 1; // 切换每页显示数量时重置到第一页
      try {
        localStorage.setItem(
          `gspr_page_size_${this.selectedProjectId}`,
          String(this.pageSize)
        );
        localStorage.setItem(
          `gspr_page_${this.selectedProjectId}`,
          String(this.currentPage)
        );
      } catch (e) {
        // 忽略本地存储异常
      }
      this.fetchGsprData();
    },

    handleGsprCurrentChange(val) {
      this.currentPage = val;
      try {
        localStorage.setItem(
          `gspr_page_${this.selectedProjectId}`,
          String(this.currentPage)
        );
      } catch (e) {
        // 忽略本地存储异常
      }
      this.fetchGsprData();
    },

    // 获取行样式类名
    getRowClassName({ row }) {
      if (this.currentModifiedItem === row.id) {
        return 'modified-row';
      }
      return '';
    },

    // 标记项为已修改（只保持一个高亮）
    markAsModified(itemId) {
      // 清除之前的定时器
      if (this.clearTimer) {
        clearTimeout(this.clearTimer);
        this.clearTimer = null;
      }

      // 设置新的高亮项
      this.currentModifiedItem = itemId;

      // 设置10秒后自动清除
      this.clearTimer = setTimeout(() => {
        this.currentModifiedItem = null;
        this.clearTimer = null;
      }, 10000); // 10秒
    },

    // 清除修改标记
    clearModifiedMark() {
      if (this.clearTimer) {
        clearTimeout(this.clearTimer);
        this.clearTimer = null;
      }
      this.currentModifiedItem = null;
    },

    // 检查数据是否有变化
    checkDataChanged(newData, originalData) {
      if (!originalData) return true;

      const fieldsToCheck = ['name', 'tech_report_location', 'department', 'content', 'remarks', 'score'];
      return fieldsToCheck.some(field => newData[field] !== originalData[field]);
    },

    // 保存原始数据
    saveOriginalData(item) {
      this.originalData.set(item.id, { ...item });
    },
  },

  // 组件销毁时清理定时器
  beforeDestroy() {
    if (this.clearTimer) {
      clearTimeout(this.clearTimer);
      this.clearTimer = null;
    }
  },
};
</script>
<style lang="scss">
.project-input-container {
  padding: 20px;
}

.editor-area {
  ::v-deep .cke_top {
    display: block; // Hide the original toolbar
  }
}

.project-input-container {
  padding: 20px;
}

.pagination-container {
  display: flex;
  justify-content: flex-end;
}

/* 添加编辑器工具栏样式 */
.editor-area {
  .cke_top {
    display: flex !important;
    justify-content: space-between;
    align-items: center;
    padding: 6px 8px !important;

    /* 工具栏组样式 */
    .cke_toolgroup {
      margin: 0 2px;
      display: flex;
      align-items: center;
    }

    /* 工具栏按钮样式 */
    .cke_toolbar {
      float: none !important;
      display: inline-flex;
      align-items: center;
    }
  }
}

/* 如果需要调整编辑器容器宽度 */
.cke_chrome {
  width: 100% !important;
}

/* 内容部分样式 */
.content-cell {
  display: flex;
  align-items: center;
  justify-content: space-between;

  .content-text {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 430px; // 可以根据需要调整最大宽度
  }
}

/* 自定义 Tooltip 样式 */
.custom-tooltip {
  min-width: 200px !important; // 设置最大宽度
  /* background-color: rgba(232, 232, 232, 0.9) !important; */
  line-height: 1.5; // 设置行高
  word-break: break-all; // 允许在任意字符间断行
  white-space: pre-wrap; // 保留空格和换行

  .el-tooltip__popper {
    padding: 10px !important; // 增加内边距
    font-size: 12px; // 设置字体大小
  }
}

::v-deep .el-dialog {
  margin-top: 0 !important;
}

/* 修改项高亮样式 */
.modified-row {
  background-color: #e6f7ff !important;
  /* 浅蓝色背景 */
  border-left: 4px solid #1890ff !important;
  /* 左侧蓝色边框 */
  transition: all 0.3s ease;
  /* 添加过渡效果 */
}

.modified-row:hover {
  background-color: #bae7ff !important;
  /* 悬停时更深的蓝色 */
}



@keyframes pulse {
  0% {
    opacity: 1;
    transform: scale(1);
  }

  50% {
    opacity: 0.7;
    transform: scale(1.1);
  }

  100% {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes fadeOut {
  0% {
    opacity: 1;
  }

  90% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}
</style>
