<template>
  <div ref="tableContainer" style="margin-top: 10px; position: relative">
    <!-- 合并选择框 -->
    <div v-if="isSelecting" class="selection-box" :style="selectionStyle"></div>

    <!-- 操作按钮 -->
    <div v-if="edit">
      <el-button type="primary" @click="addColumn(-1)">新增列</el-button>
      <el-button type="primary" @click="addRow(-1)">新增行</el-button>
      <el-button type="primary" @click="copy">复制表格</el-button>
      <el-button type="primary" @click="printTable">预览表格</el-button>
      <el-checkbox v-model="isMerge" style="margin-left: 10px"
        >合并单元格</el-checkbox
      >
    </div>

    <!-- 表格主体 -->
    <div class="table" style="margin-top: 10px">
      <table
        class="custom-table"
        @mousedown="startSelecting"
        @mousemove="updateSelection"
        @mouseup="stopSelecting"
      >
        <tbody>
          <tr v-for="(row, rowIndex) in tableData" :key="'row-' + rowIndex">
            <template v-for="(cell, colIndex) in row">
              <td
                v-if="visibleMap[rowIndex + '-' + colIndex]"
                :key="cell.id"
                :rowspan="cell.rowspan"
                :colspan="cell.colspan"
                :style="getCellStyle(cell)"
                class="tableTd"
                :data-row="rowIndex"
                :data-col="colIndex"
                @mouseenter="onCellEnter(rowIndex, colIndex)"
                @contextmenu.prevent="onRightClick($event, rowIndex, colIndex)"
              >
                <!-- 表头操作图标（已注释） -->
                <!-- <i ... ></i> -->

                <div style="display: flex; align-items: center">
                  <span>{{ cell.label }}</span>
                  <template v-if="cell.mode === 'checkbox'">
                    <div class="checkbox-group" style="flex: 1">
                      <div
                        v-for="cb in cell.checkboxes"
                        :key="cb.id"
                        class="checkbox-item"
                      >
                        <input type="checkbox" v-model="cb.checked" />
                        <input
                          v-if="edit"
                          type="text"
                          v-model="cb.label"
                          class="checkbox-label-input"
                          @input="
                            onCheckboxLabelInput(rowIndex, colIndex, cb.id)
                          "
                        />
                        <span v-else>{{ cb.label }}</span>
                        <i
                          v-if="edit"
                          class="el-icon-delete"
                          @click.stop="
                            removeCheckbox(rowIndex, colIndex, cb.id)
                          "
                        ></i>
                      </div>
                      <div
                        v-if="edit"
                        class="add-checkbox"
                        @click="addCheckbox(rowIndex, colIndex)"
                      >
                        <i class="el-icon-circle-plus-outline"></i> 新增选项
                      </div>
                    </div>
                  </template>

                  <!-- ========== 🆕 人员选择模式 ========== -->
                  <template v-else-if="cell.mode === 'person'">
                    <div
                      style="
                        width: 100%;
                        position: relative;
                        min-height: 30px;
                        flex: 1;
                      "
                    >
                      <!-- 人员选择组件 -->
                      <personSelect
                        v-model="cell.value"
                          :disabled="readonly || cell.readonly === 2"
                        :readonly="readonly || cell.readonly === 2"
                        @change="onPersonChange(rowIndex, colIndex)"
                        style="width: 95%"
                        :init="false"
                        :selectList="userPage"
                      />
                      <!-- 编辑图标（仅在编辑模式下显示） -->
                      <i
                        v-if="edit"
                        class="el-icon-edit person-edit-icon"
                        @click.stop="openPersonConfig(cell, rowIndex, colIndex)"
                      ></i>
                    </div>
                  </template>
                  <!-- ========== 🆕 部门选择模式 ========== -->
                  <template v-else-if="cell.mode === 'dept'">
                    <div
                      style="
                        width: 100%;
                        position: relative;
                        min-height: 30px;
                        flex: 1;
                      "
                    >
                      <deptSelect
                        v-model="cell.value"
                        :disabled="readonly || cell.readonly === 2"
                        :isBindPlan="readonly || cell.readonly === 2"
                        @change="onDeptChange(rowIndex, colIndex)"
                        style="width: 95%"
                        placeholder="请选择部门"
                        :init="false"
                        :selectList="deptList"
                      />
                      <i
                        v-if="edit"
                        class="el-icon-edit person-edit-icon"
                        @click.stop="openPersonConfig(cell, rowIndex, colIndex)"
                      ></i>
                    </div>
                  </template>

                  <!-- ========== 文本模式 ========== -->
                  <template v-else>
                    <textarea
                      v-model="cell.value"
                      class="templateInput"
                      :style="{
                        textAlign: cell.textAlign || 'left',
                        flex: 1
                      }"
                      :id="cell.id"
                      :ref="cell.id + 'ref'"
                      :readonly="cell.readonly === 2 || readonly"
                      @mousedown="onCellMouseDown"
                      @click="
                        inputClick(
                          cell,
                          rowIndex === 0 ? 'columns' : null,
                          $event
                        )
                      "
                      @input="onInput($event)"
                      autocomplete="off"
                    ></textarea>
                  </template>
                </div>

                <!-- ========== 复选框模式 ========== -->
              </td>
            </template>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>

<script>
  import { generateRandomString } from '@/utils/util';
  import personSelect from '@/components/CommomSelect/person-select.vue';
  import deptSelect from '@/components/CommomSelect/dept-select.vue'; // 🆕 导入部门选择组件
  import { getUserPage } from '@/api/system/organization';
  import { listOrganizations } from '@/api/system/organization'; // 🆕 导入部门列表接口
  export default {
    // 🆕 注册人员选择组件
    components: { personSelect, deptSelect },
    props: {
      id: { type: String, default: '' },
      edit: { type: Boolean, default: true },
      readonly: { type: Boolean, default: false }
    },
    data() {
      return {
        userPage: [],
        deptList: [],
        form: null,
        valueObj: {},
        tableData: [],
        units: {},
        equation: {},
        domId: '',
        currentRowIndex: 0,
        currentColumnIndex: 0,
        // 合并相关
        isMerge: false,
        isSelecting: false,
        startX: 0,
        startY: 0,
        endX: 0,
        endY: 0,
        startRow: -1,
        startCol: -1,
        endRow: -1,
        endCol: -1,
        // 防抖定时器
        calcTimer: null,
        // 右键菜单关闭监听
        menuCloseHandler: null,
        userMap: {},
        userMapLoaded: false
      };
    },
    computed: {
      visibleMap() {
        const map = {};
        const rows = this.tableData.length;
        if (!rows) return map;
        const cols = this.tableData[0]?.length || 0;

        for (let r = 0; r < rows; r++) {
          for (let c = 0; c < cols; c++) {
            const key = `${r}-${c}`;
            let hidden = false;

            for (let rr = r - 1; rr >= 0; rr--) {
              for (let cc = 0; cc < this.tableData[rr].length; cc++) {
                const cell = this.tableData[rr][cc];
                if (
                  cell.rowspan > 1 &&
                  rr + cell.rowspan > r &&
                  cc <= c &&
                  cc + cell.colspan > c
                ) {
                  hidden = true;
                  break;
                }
              }
              if (hidden) break;
            }

            if (!hidden) {
              for (let cc = c - 1; cc >= 0; cc--) {
                const cell = this.tableData[r][cc];
                if (cell.colspan > 1 && cc + cell.colspan > c) {
                  hidden = true;
                  break;
                }
              }
            }

            map[key] = !hidden;
          }
        }
        return map;
      },

      selectionStyle() {
        const container = this.$refs.tableContainer;
        if (!container) return {};
        const rect = container.getBoundingClientRect();
        return {
          position: 'absolute',
          zIndex: 100,
          left: `${Math.min(this.startX, this.endX) - rect.left}px`,
          top: `${Math.min(this.startY, this.endY) - rect.top}px`,
          width: `${Math.abs(this.endX - this.startX)}px`,
          height: `${Math.abs(this.endY - this.startY)}px`,
          border: '2px dashed black',
          pointerEvents: 'none'
        };
      }
    },
    beforeDestroy() {
      if (this.calcTimer) {
        clearTimeout(this.calcTimer);
        this.calcTimer = null;
      }
      if (this.menuCloseHandler) {
        document.removeEventListener('click', this.menuCloseHandler);
        this.menuCloseHandler = null;
      }
    },
    created() {
      getUserPage({ pageNum: 1, size: -1 }).then((res) => {
        this.userPage = res.list;
      });
      listOrganizations({ pageNum: 1, size: -1 }).then((res) => {
        this.deptList = res
      });
    },
    methods: {
      getTransitions(key) {
        return [
          { target: 'text', label: '转为文本模式', method: 'disableDeptMode' },
          {
            target: 'checkbox',
            label: '转为复选框模式',
            method: 'enableCheckboxMode'
          },
          {
            target: 'person',
            label: '转为人员选择模式',
            method: 'enablePersonMode'
          },
          {
            target: 'dept',
            label: '转为部门选择模式',
            method: 'enableDeptMode'
          }
        ].filter((item) => item.target !== key);
      },

      // ========== 工具 ==========
      getCellStyle(cell) {
        let width = parseFloat(cell.style?.width || cell.width || 100);
        if (isNaN(width)) width = 100;
        return {
          ...cell.style,
          width: width + 'px',
          'text-align': cell.textAlign || 'left' // 默认居中
        };
      },

      getInput(width) {
        const w = parseFloat(width);
        const safeWidth = isNaN(w) ? 100 : w;
        return {
          id: generateRandomString(5),
          value: '',
          rowspan: 1,
          colspan: 1,
          label: '',
          width: safeWidth,
          style: { width: safeWidth },
          readonly: 1,
          mode: 'text', // 'text' | 'checkbox' | 'person'
          textAlign: 'left',
          checkboxes: []
        };
      },

      getIndex(id) {
        for (let r = 0; r < this.tableData.length; r++) {
          for (let c = 0; c < this.tableData[r].length; c++) {
            if (this.tableData[r][c].id === id)
              return { rowIndex: r, colIndex: c };
          }
        }
        return { rowIndex: -1, colIndex: -1 };
      },

      isLastVisibleCell(rowIndex, colIndex) {
        const row = this.tableData[rowIndex];
        for (let c = row.length - 1; c >= 0; c--) {
          if (this.visibleMap[`${rowIndex}-${c}`]) {
            return c === colIndex;
          }
        }
        return false;
      },
      /**
       * 检查指定 id 在当前表格中是否重复（排除某个单元格）
       * @param {string} id - 要检查的 id
       * @param {string} excludeId - 排除的单元格 id（通常是当前编辑的）
       * @returns {boolean} 是否重复
       */
      isIdDuplicate(id, excludeId) {
        // 遍历所有行和列
        for (let r = 0; r < this.tableData.length; r++) {
          for (let c = 0; c < this.tableData[r].length; c++) {
            const cell = this.tableData[r][c];
            if (cell.id === id && cell.id !== excludeId) {
              return true;
            }
          }
        }
        return false;
      },
      // ========== 自动调整高度 ==========
      autoResizeAll() {
        this.$nextTick(() => {
          this.$el.querySelectorAll('.templateInput').forEach((ta) => {
            ta.style.height = 'auto';
            ta.style.height = ta.scrollHeight + 'px';
          });
        });
      },

      // ========== 行列操作 ==========
      addColumn(colIndex) {
        if (colIndex === -1) {
          if (this.tableData.length === 0) {
            this.tableData = [[this.getInput()]];
          } else {
            this.tableData.forEach((row) => row.push(this.getInput()));
          }
          this.$nextTick(this.autoResizeAll);
          return;
        }

        let insertAt = colIndex + 1;
        this.tableData.forEach((row) => {
          const cell = row[colIndex];
          if (cell && cell.colspan > 1) {
            insertAt = Math.max(insertAt, colIndex + cell.colspan);
          }
        });

        this.tableData.forEach((row) => {
          let covered = false;
          for (let c = 0; c < insertAt && c < row.length; c++) {
            const cell = row[c];
            if (cell.colspan > 1 && c + cell.colspan > insertAt) {
              cell.colspan += 1;
              covered = true;
              break;
            }
          }
          if (!covered) {
            const raw =
              row[colIndex]?.style?.width ?? row[colIndex]?.width ?? 100;
            row.splice(insertAt, 0, this.getInput(raw));
          }
        });
        this.$nextTick(this.autoResizeAll);
      },

      removeColumn(colIndex) {
        for (let r = 0; r < this.tableData.length; r++) {
          const row = this.tableData[r];
          for (let rr = r - 1; rr >= 0; rr--) {
            for (let cc = 0; cc < this.tableData[rr].length; cc++) {
              const cell = this.tableData[rr][cc];
              if (
                cell.rowspan > 1 &&
                rr + cell.rowspan > r &&
                cell.colspan > 1 &&
                cc <= colIndex &&
                cc + cell.colspan > colIndex
              ) {
                cell.colspan -= 1;
                break;
              }
            }
          }
          for (let c = colIndex - 1; c >= 0; c--) {
            const leftCell = row[c];
            if (
              leftCell &&
              leftCell.colspan > 1 &&
              c + leftCell.colspan > colIndex
            ) {
              leftCell.colspan -= 1;
              break;
            }
          }
          const cell = row[colIndex];
          if (cell && cell.colspan > 1 && colIndex + 1 < row.length) {
            row[colIndex + 1].colspan = cell.colspan - 1;
            row[colIndex + 1].rowspan = cell.rowspan;
            row[colIndex + 1].style = { ...cell.style };
          }
          row.splice(colIndex, 1);
        }
        this.$nextTick(this.autoResizeAll);
      },

      addRow(rowIndex) {
        if (rowIndex === -1) {
          if (this.tableData.length === 0) {
            this.tableData = [[this.getInput()]];
          } else {
            this.tableData.push(this.tableData[0].map(() => this.getInput()));
          }
          this.$nextTick(this.autoResizeAll);
          return;
        }

        let insertAt = rowIndex + 1;
        for (let c = 0; c < this.tableData[rowIndex].length; c++) {
          const cell = this.tableData[rowIndex][c];
          if (cell.rowspan > 1) {
            insertAt = Math.max(insertAt, rowIndex + cell.rowspan);
          }
        }

        const newRow = [];
        for (let c = 0; c < this.tableData[0].length; c++) {
          let covered = false;
          for (let r = 0; r < insertAt && r < this.tableData.length; r++) {
            const cell = this.tableData[r][c];
            if (cell.rowspan > 1 && r + cell.rowspan > insertAt) {
              cell.rowspan += 1;
              covered = true;
              break;
            }
          }
          if (!covered) {
            const raw =
              this.tableData[0][c]?.style?.width ??
              this.tableData[0][c]?.width ??
              100;
            newRow.push(this.getInput(raw));
          }
        }
        this.tableData.splice(insertAt, 0, newRow);
        this.$nextTick(this.autoResizeAll);
      },

      removeRow(rowIndex) {
        for (let c = 0; c < this.tableData[rowIndex].length; c++) {
          const cell = this.tableData[rowIndex][c];
          if (cell.rowspan > 1) {
            const next = this.tableData[rowIndex + 1]?.[c];
            if (next) {
              next.rowspan = cell.rowspan - 1;
              next.colspan = cell.colspan;
              next.value = cell.value;
              next.style = { ...cell.style };
            }
          }
        }
        this.tableData.splice(rowIndex, 1);
        this.$nextTick(this.autoResizeAll);
      },

      // ========== 合并 ==========
      startSelecting(event) {
        if (!this.isMerge) return;
        this.isSelecting = true;
        const rect = this.$refs.tableContainer.getBoundingClientRect();
        this.startX = event.clientX;
        this.startY = event.clientY;
        this.endX = this.startX;
        this.endY = this.startY;

        const td = event.target.closest('td');
        if (td) {
          this.startRow = Number(td.dataset.row);
          this.startCol = Number(td.dataset.col);
          this.endRow = this.startRow;
          this.endCol = this.startCol;
        }
      },

      updateSelection(event) {
        if (this.isSelecting) {
          this.endX = event.clientX;
          this.endY = event.clientY;
        }
      },

      stopSelecting() {
        if (!this.isSelecting) return;
        this.isSelecting = false;
        this.calculateSelectedItems();
        this.startRow = this.startCol = this.endRow = this.endCol = -1;
      },

      onCellEnter(rowIndex, colIndex) {
        if (this.isSelecting) {
          this.endRow = rowIndex;
          this.endCol = colIndex;
        }
      },

      calculateSelectedItems() {
        if (
          this.startRow < 0 ||
          this.startCol < 0 ||
          this.endRow < 0 ||
          this.endCol < 0
        )
          return;
        if (this.startRow === this.endRow && this.startCol === this.endCol)
          return;

        const minRow = Math.min(this.startRow, this.endRow);
        const maxRow = Math.max(this.startRow, this.endRow);
        const minCol = Math.min(this.startCol, this.endCol);
        const maxCol = Math.max(this.startCol, this.endCol);

        if (minRow === 0 && maxRow > 0) return;

        for (let r = minRow; r <= maxRow; r++) {
          for (let c = minCol; c <= maxCol; c++) {
            const cell = this.tableData[r]?.[c];
            if (!cell) return;
            if (
              (cell.rowspan > 1 || cell.colspan > 1) &&
              (r !== minRow || c !== minCol)
            ) {
              return;
            }
          }
        }

        const cell = this.tableData[minRow][minCol];
        this.$set(cell, 'rowspan', maxRow - minRow + 1);
        this.$set(cell, 'colspan', maxCol - minCol + 1);

        this.$nextTick(() => {
          requestAnimationFrame(() => {
            const ref = this.$refs[cell.id + 'ref'];
            const ta = Array.isArray(ref) ? ref[0] : ref;
            const td = ta?.closest?.('td');
            if (td) {
              const realWidth = td.offsetWidth;
              this.$set(cell, 'width', realWidth);
              this.$set(cell.style, 'width', realWidth);
            }
          });
        });

        this.startRow = this.startCol = this.endRow = this.endCol = -1;
      },

      // ========== 右键菜单（修复内存泄漏 + 增加“人员选择”菜单项） ==========
      onRightClick(event, rowIndex, colIndex) {
        event.preventDefault();
        this.currentRowIndex = rowIndex;
        this.currentColumnIndex = colIndex;

        // 移除旧菜单和监听
        const existingMenu = document.querySelector('.custom-context-menu');
        if (existingMenu) existingMenu.remove();
        if (this.menuCloseHandler) {
          document.removeEventListener('click', this.menuCloseHandler);
          this.menuCloseHandler = null;
        }

        // 创建菜单容器
        const menu = document.createElement('div');
        menu.className = 'custom-context-menu';
        menu.style.cssText = `
    position: fixed;
    left: ${event.clientX}px;
    top: ${event.clientY}px;
    background: white;
    border: 1px solid #ccc;
    box-shadow: 2px 2px 8px rgba(0,0,0,0.2);
    z-index: 10000;
    padding: 5px 0;
    min-width: 120px;
  `;

        // 菜单项添加函数
        const addItem = (text, onClick, isSeparator = false) => {
          if (isSeparator) {
            const hr = document.createElement('hr');
            hr.style.margin = '5px 0';
            menu.appendChild(hr);
            return;
          }
          const item = document.createElement('div');
          item.textContent = text;
          item.style.cssText =
            'padding: 5px 15px; cursor: pointer; white-space: nowrap;';
          item.onmouseenter = () => (item.style.backgroundColor = '#f0f0f0');
          item.onmouseleave = () => (item.style.backgroundColor = '');
          item.onclick = () => {
            if (onClick) onClick();
            menu.remove();
            if (this.menuCloseHandler) {
              document.removeEventListener('click', this.menuCloseHandler);
              this.menuCloseHandler = null;
            }
          };
          menu.appendChild(item);
        };

        // 关闭菜单的全局监听
        this.menuCloseHandler = (e) => {
          if (!menu.contains(e.target)) {
            menu.remove();
            document.removeEventListener('click', this.menuCloseHandler);
            this.menuCloseHandler = null;
          }
        };

        // ---- 行操作菜单 ----
        if (rowIndex === 0) {
          addItem('插入列', () => this.addColumn(colIndex));
          addItem('删除列', () => this.removeColumn(colIndex));
          addItem('', null, true);
        } else {
          addItem('插入行', () => this.addRow(rowIndex));
          addItem('删除行', () => this.removeRow(rowIndex));
          addItem('', null, true);
        }

        // ---- 模式切换
        const cell = this.tableData[rowIndex][colIndex];
        if (cell) {
          const currentMode = cell.mode || 'text';
          this.getTransitions(currentMode).forEach(({ label, method }) => {
            addItem(label, () => this[method](rowIndex, colIndex));
          });
          // 复选框模式额外选项
          if (currentMode === 'checkbox') {
            addItem('添加复选框', () => this.addCheckbox(rowIndex, colIndex));
          }
        }

        // 渲染菜单
        document.body.appendChild(menu);
        setTimeout(() => {
          document.addEventListener('click', this.menuCloseHandler);
        }, 0);
      },
      // ========== 复选框 ==========
      enableCheckboxMode(rowIndex, colIndex) {
        const cell = this.tableData[rowIndex][colIndex];
        if (!cell) return;
        const currentText = cell.value || '';
        this.$set(cell, 'mode', 'checkbox');
        this.$set(cell, 'checkboxes', [
          { id: generateRandomString(6), label: currentText, checked: false }
        ]);
        cell.value = '';
      },

      disableCheckboxMode(rowIndex, colIndex) {
        const cell = this.tableData[rowIndex][colIndex];
        if (!cell) return;
        const text = cell.checkboxes
          .map((cb) => cb.label)
          .filter(Boolean)
          .join('; ');
        this.$set(cell, 'mode', 'text');
        this.$set(cell, 'value', text);
        this.$set(cell, 'checkboxes', []);
      },

      addCheckbox(rowIndex, colIndex) {
        const cell = this.tableData[rowIndex][colIndex];
        if (!cell || cell.mode !== 'checkbox') return;
        if (!cell.checkboxes) cell.checkboxes = [];
        cell.checkboxes.push({
          id: generateRandomString(6),
          label: '',
          checked: false
        });
        this.$forceUpdate();
      },

      removeCheckbox(rowIndex, colIndex, cbId) {
        const cell = this.tableData[rowIndex][colIndex];
        if (!cell || cell.mode !== 'checkbox') return;
        const idx = cell.checkboxes.findIndex((cb) => cb.id === cbId);
        if (idx !== -1) {
          cell.checkboxes.splice(idx, 1);
          if (cell.checkboxes.length === 0) {
            this.disableCheckboxMode(rowIndex, colIndex);
          } else {
            this.$forceUpdate();
          }
        }
      },

      onCheckboxLabelInput() {},

      enableDeptMode(rowIndex, colIndex) {
        const cell = this.tableData[rowIndex][colIndex];
        if (!cell) return;
        this.$set(cell, 'mode', 'dept');
        this.$forceUpdate();
      },

      disableDeptMode(rowIndex, colIndex) {
        const cell = this.tableData[rowIndex][colIndex];
        if (!cell) return;
        this.$set(cell, 'mode', 'text');
        this.$forceUpdate();
      },
      onDeptChange() {},
      // ========== 🆕 人员选择 ==========
      enablePersonMode(rowIndex, colIndex) {
        const cell = this.tableData[rowIndex][colIndex];
        if (!cell) return;
        // 保留当前文本作为选中值（如果 person-select 能解析，否则可置空）
        this.$set(cell, 'mode', 'person');
        // 如果希望保留当前值，可保留 cell.value
        this.$forceUpdate();
      },

      disablePersonMode(rowIndex, colIndex) {
        const cell = this.tableData[rowIndex][colIndex];
        if (!cell) return;
        // 将当前人员选择的值转换为文本（显示人员名称或ID）
        this.$set(cell, 'mode', 'text');
        // 注意：cell.value 存储的是人员ID或名称，如果希望显示标签，需要映射，这里直接显示原值
        this.$forceUpdate();
      },

      onPersonChange(rowIndex, colIndex) {
        // 触发公式计算
        // this.calculation();
      },

      // ========== 输入 ==========
      onInput(event) {
        const ta = event.target;
        ta.style.height = 'auto';
        ta.style.height = ta.scrollHeight + 'px';
        this.debouncedCalculation();
      },

      debouncedCalculation() {
        if (this.calcTimer) clearTimeout(this.calcTimer);
        this.calcTimer = setTimeout(() => {
          this.calculation();
          this.calcTimer = null;
        }, 300);
      },

      calculation() {
        this.$emit('calculation');
      },

      onCellMouseDown(event) {
        if (this.isMerge) event.preventDefault();
      },
      openPersonConfig(cell, rowIndex, colIndex) {
        if (!this.edit) return;
        this.domId = cell.id;
        // 获取单元格真实宽度
        let realWidth = cell.width || 100;
        const td = this.$el.querySelector(
          `td[data-row="${rowIndex}"][data-col="${colIndex}"]`
        );
        if (td) {
          realWidth = td.offsetWidth || realWidth;
        }
        this.$emit('editShow', {
          templateDivRef: 'customTextRef' + this.id,
          domObj: {
            ...cell,
            width: realWidth,
            isNoWidth: false,
            equation: this.equation[cell.id],
            units: this.units[cell.id] || {}
          }
        });
      },
      inputClick(item, type, event) {
        if (!this.edit) return;
        this.domId = item.id;
        const ref = this.$refs[item.id + 'ref'];
        const ta = Array.isArray(ref) ? ref[0] : ref;
        const td = ta?.closest?.('td');
        const realWidth = td
          ? td.offsetWidth
          : parseFloat(item.style?.width || item.width || 100);

        this.$emit('editShow', {
          templateDivRef: 'customTextRef' + this.id,
          domObj: {
            ...item,
            width: realWidth,
            isNoWidth: type === 'columns',
            equation: this.equation[item.id],
            units: this.units[item.id] || {}
          }
        });
      },

      // ========== 数据通信 ==========
      equationValue({ domId, value }) {
        const { rowIndex, colIndex } = this.getIndex(domId);
        if (rowIndex >= 0 && colIndex >= 0) {
          this.$set(this.tableData[rowIndex][colIndex], 'value', value);
        }
      },

      getValue() {
        return {
          form: null,
          equation: this.equation,
          units: this.units,
          valueObj: {
            tableData: this.tableData
          }
        };
      },

      init({ form, valueObj, equation, units }) {
        this.form = form;
        this.tableData = valueObj.tableData || valueObj.columns || [];
        this.equation = equation || {};
        this.units = units || {};
        this.autoResizeAll();
      },

      editInputChange(domObj) {
        const data = JSON.parse(JSON.stringify(domObj));
        if (data.equation) this.equation[data.id] = data.equation;
        if (data.units) this.units[data.id] = data.units;

        const w = Number(data.width);
        if (!isNaN(w)) {
          data.style = { ...(data.style || {}), width: w };
          data.width = w;
        } else if (data.style && data.style.width != null) {
          data.width = Number(data.style.width);
        }

        const { rowIndex, colIndex } = this.getIndex(this.domId);
        if (rowIndex >= 0 && colIndex >= 0) {
          this.$set(this.tableData[rowIndex], colIndex, data);
        }
      },

      copy() {
        const tableData = JSON.parse(JSON.stringify(this.tableData));
        tableData.forEach((row) =>
          row.forEach((cell) => (cell.id = generateRandomString(5)))
        );
        this.$emit('copy', {
          value: null,
          equation: { ...this.equation },
          units: { ...this.units },
          valueObj: { tableData }
        });
      },

      async fetchDeptMap() {
        if (this.deptMapLoaded) return;
        try {
          const res = await listOrganizations({ pageNum: 1, size: -1 });
          // 递归展平树形数据
          const flatten = (nodes) => {
            let result = [];
            nodes.forEach((node) => {
              result.push({ id: node.id, name: node.name });
              if (node.children && node.children.length) {
                result = result.concat(flatten(node.children));
              }
            });
            return result;
          };
          const flatList = flatten(res || []);
          const map = {};
          flatList.forEach((dept) => {
            map[dept.id] = dept.name || '未知部门';
          });
          this.deptMap = map;
          this.deptMapLoaded = true;
        } catch (error) {
          console.warn('获取部门列表失败，打印时将显示ID', error);
        }
      },

      // ========== 🆕 获取用户映射（供打印使用） ==========
      async fetchUserMap() {
        if (this.userMapLoaded) return;
        try {
          const res = await getUserPage({ pageNum: 1, size: -1 });
          if (res && res.list) {
            const map = {};
            res.list.forEach((user) => {
              map[user.id] =
                user.name || user.realName || user.username || '未知';
            });
            this.userMap = map;
            this.userMapLoaded = true;
          }
        } catch (error) {
          console.warn('获取人员列表失败，打印时将显示ID', error);
        }
      },
      // ========== 🆕 打印（异步 + 人员名称映射） ==========
      async printTable() {
        await this.fetchUserMap();
        await this.fetchDeptMap();
        const tableEl = this.$el.querySelector('.custom-table');
        if (!tableEl) return;

        const clone = tableEl.cloneNode(true);
        clone
          .querySelectorAll(
            '.delete, .add, .deleteRow, .addRow, .selection-box'
          )
          .forEach((el) => el.remove());

        // 遍历所有单元格，根据模式重新构建显示内容（保留 label）
        for (let r = 0; r < this.tableData.length; r++) {
          for (let c = 0; c < this.tableData[r].length; c++) {
            const cell = this.tableData[r][c];
            const td = clone.querySelector(
              `td[data-row="${r}"][data-col="${c}"]`
            );
            if (!td) continue;

            const label = cell.label || '';
            let displayHtml = '';
            td.style.padding = '3px';
            if (cell.mode === 'checkbox' && Array.isArray(cell.checkboxes)) {
              const items = cell.checkboxes
                .map((cb) => {
                  const symbol = cb.checked ? '☑' : '☐';
                  return `<span style="margin:0 4px;">${symbol} ${
                    cb.label || ''
                  }</span>`;
                })
                .join('');
              displayHtml = `<div style="display:flex; align-items:center; justify-content:center; gap:5px; flex-wrap:wrap;">${
                label ? `<span >${label}</span>` : ''
              }${items}</div>`;
            } else if (cell.mode === 'person') {
              const userName = this.userMap[cell.value] || cell.value || '';
              displayHtml = `<div style="display:flex; align-items:center; justify-content:center; gap:5px;">${
                label ? `<span >${label}</span>` : ''
              }<span style="flex:1">${userName}</span></div>`;
            } else if (cell.mode === 'dept') {
              const deptName = this.deptMap[cell.value] || cell.value || '';
              displayHtml = `<div style="display:flex; align-items:center; justify-content:center; gap:5px;">${
                label ? `<span >${label}</span>` : ''
              }<span style="flex:1">${deptName}</span></div>`;
            } else {
              console.log(cell.textAlign);
              // 文本模式
              displayHtml = `<div style="display:flex; align-items:center; justify-content:${
                cell.textAlign == 'left'
                  ? 'flex-start'
                  : cell.textAlign == 'right'
                  ? 'flex-end'
                  : 'center'
              };">${label ? `<span >${label}</span>` : ''}<span>${
                cell.value || ''
              }</span></div>`;
            }

            td.innerHTML = displayHtml;
          }
        }

        // 打印 iframe（保持不变）
        const iframe = document.createElement('iframe');
        iframe.style.cssText = 'position:absolute;width:0;height:0;border:0;';
        document.body.appendChild(iframe);
        const doc = iframe.contentWindow.document;
        doc.write(`
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <style>
          body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
          table { width: 100%; border-collapse: collapse; table-layout: auto; }
          td { border: 1px solid #000; vertical-align: middle;  padding: 1px; font-size: 12px; padding:0px; }
        </style>
      </head>
      <body>${clone.outerHTML}</body>
    </html>
  `);
        doc.close();
        iframe.contentWindow.focus();
        iframe.contentWindow.print();
        setTimeout(() => document.body.removeChild(iframe), 1000);
      }
    }
  };
</script>

<style lang="scss" scoped>
  .custom-table {
    border-collapse: collapse;
    width: auto;
    td {
      border: 1px solid #ddd;
      padding: 0;
      min-height: 20px;
      position: relative;
    }
  }
  :deep(.templateInput) {
    width: 100%;
    min-height: 20px;
    height: auto;
    border: none;
    text-align: center;
    background-color: #fff;
    resize: none;
    padding: 4px;
    box-sizing: border-box;
    overflow: hidden;
    display: block;
    &:focus {
      border-color: #66afe9;
      outline: none;
    }
  }
  .deleteRow {
    display: block !important;
    position: absolute;
    bottom: 0px;
    right: -15px;
    color: #f56c6c;
    z-index: 10;
  }
  .delete,
  .add,
  .addRow {
    display: none !important;
  }
  .tableTd:hover {
    .delete {
      display: block !important;
      position: absolute;
      right: 0;
      top: 0;
      color: #f56c6c;
      z-index: 10;
    }
    .add {
      display: block !important;
      position: absolute;
      right: 20px;
      top: 0;
      color: #409eff;
      z-index: 10;
    }
    .addRow {
      display: block !important;
      position: absolute;
      bottom: 0px;
      right: 10px;
      color: #409eff;
      z-index: 10;
    }
  }
  .checkbox-group {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 4px;
    .checkbox-item {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      background: #fff;
      input[type='checkbox'] {
        margin: 0;
        flex-shrink: 0;
      }
      .checkbox-label-input {
        border: 1px solid #dcdfe6;
        border-radius: 2px;
        padding: 2px 4px;
        font-size: 12px;
        min-width: 4em;
        width: auto;
        background: #fff;
        &:focus {
          outline: none;
          border-color: #409eff;
        }
      }
      .el-icon-delete {
        color: #f56c6c;
        cursor: pointer;
        font-size: 14px;
        flex-shrink: 0;
        &:hover {
          opacity: 0.8;
        }
      }
    }
    .add-checkbox {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      color: #409eff;
      cursor: pointer;
      font-size: 12px;
      white-space: nowrap;
      &:hover {
        text-decoration: underline;
      }
    }
  }
  @media print {
    .add-checkbox,
    .checkbox-item .el-icon-delete {
      display: none !important;
    }
    .checkbox-label-input {
      border: none !important;
      background: transparent !important;
      padding: 0 !important;
      min-width: auto !important;
      width: auto !important;
    }
    .checkbox-item {
      break-inside: avoid;
    }
  }
  .person-edit-icon {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    color: #409eff;
    font-size: 14px;
    cursor: pointer;
    opacity: 0.6;
    transition: opacity 0.2s;
    &:hover {
      opacity: 1;
    }
  }
</style>
