<template>
  <div class="table-page">
    <!-- 添加列设置按钮 -->
    <div class="table-settings" v-if="showColumnSetting">
      <el-button type="text" @click="showColumnSettings"> <i class="el-icon-setting"></i> 列设置 </el-button>
    </div>

    <el-table
      :key="renderKey"
      ref="elTablet"
      :row-key="getRowKey"
      v-loading="options.loading"
      :data="dataSource"
      :max-height="options.maxHeight"
      :height="options.height"
      :stripe="options.stripe"
      :border="options.border"
      @select="handleSelect"
      @select-all="selectAll"
      @row-click="handleRowClick"
      @selection-change="handleSelectionChange"
      @current-change="handleCurrentChange"
      @header-dragend="handleHeaderDragend"
      highlight-current-row
      default-expand-all
      :cell-style="cellStyle"
      :header-cell-style="{ color: '#515a6e', background: '#f5f5f5' }"
      :tree-props="options.treeProps"
      :row-style="{ cursor: options.cursor || '' }"
      :resizable="true"
      :fit="true"
    >
      <!--selection选择框-->
      <el-table-column v-if="options.mutiSelect" type="selection" :reserve-selection="true" style="width: 50px" align="center"> </el-table-column>
      <!--序号-->
      <el-table-column v-if="options.index" label="序号" type="index" width="100" align="center"> </el-table-column>
      <!--数据列-->
      <template v-for="(column, index) in localTableColumns">
        <el-table-column :key="index" :prop="column.prop" :label="column.label" :align="column.align || 'center'" :width="column.width" :fixed="column.fixed" show-overflow-tooltip v-if="!column.isHidden">
          <template slot-scope="scope">
            <!--  含有click函数 -->
            <template v-if="column.onClick && !column.edit">
              <span @click.stop="column.onClick(scope.row, scope.$index, scope)">{{ scope.row[column.prop] }}</span>
            </template>

            <!-- 带编辑功能列 -->
            <template v-else-if="column.edit">
              <!-- 编辑状态 -->
              <template v-if="scope.row[scope.column.property + 'isShow']">
                <el-input :ref="scope.column.property" @blur="handleEditBlur(column, scope)" v-model="scope.row[column.prop]"></el-input>
              </template>

              <!-- 非编辑状态  -->
              <template v-else>
                <span class="el-table-edit-text" @click="editCell(scope.row, scope.column)"><i class="el-icon-edit"></i>{{ scope.row[column.prop] }}</span>
              </template>
            </template>

            <!-- 含有render函数 -->
            <template v-else-if="column.render">
              <RenderDom :row="scope.row" :index="index" :render="column.render" />
            </template>

            <!-- 有img图片显示 -->
            <template v-else-if="column.img">
              <img v-if="scope.row[column.prop] && scope.row[column.prop].length > 0" :src="scope.row[column.prop][0]" class="w-img" alt="加载失败" />
              <img v-else :src="logo" class="w-img" alt="加载失败" />
            </template>

            <!-- 字典展示 -->
            <template v-else-if="column.dictData">
              <span>{{ scope.row[column.prop] | dictFind(dictData, column.dictData, column.dictLabel, column.dictValue) }}</span>
            </template>

            <!-- 没有render函数且没有图片要显示 -->
            <template v-else>
              <span>{{ scope.row[column.prop] }}</span>
            </template>
            <!-- button 操作按钮  btn.statusKey 判断启用的字段 | btn.disableKey 判断禁用的值 | disableKey在启用和禁用时相反-->
            <!-- 禁用分两种情况   一种是 disableKey  disableKey 是指状态值是 disableKey 的时候禁用 -->
            <!-- 另一种是 unDisableKey  unDisableKey 是指状态值不是 unDisableKey 的时候禁用 -->
            <!-- btn.isChildShow 控制子级是否显示，isParentShow控制父级是否显示  -->
            <!--  v-show="hasChildren(scope.row, btn.showType)" -->
            <template v-if="column.button">
              <template v-for="(btn, i) in column.group">
                <el-button
                  v-show="hasChildren(scope.row, btn.showType)"
                  v-if="btn.statusKey"
                  :key="i"
                  :type="btn.type"
                  :round="btn.round"
                  :size="btn.size || 'mini'"
                  :icon="btn.icon"
                  :plain="btn.plain"
                  @click.stop="btn.onClick(scope.row, scope.$index, scope)"
                  :disabled="unDisabled(scope.row[btn.statusKey], btn.unDisableKey, btn.disableKey)"
                  >{{ btn.name }}</el-button
                >
                <el-button
                  v-show="hasChildren(scope.row, btn.showType)"
                  v-if="!btn.statusKey"
                  :key="i"
                  :type="btn.type"
                  :round="btn.round"
                  :size="btn.size || 'mini'"
                  :icon="btn.icon"
                  :plain="btn.plain"
                  @click.stop="btn.onClick(scope.row, scope.$index, scope)"
                  :disabled="btn.isDisabled"
                  >{{ btn.name }}</el-button
                >
              </template>
            </template>

            <!-- slot 你可以其他常用项 -->
          </template>
        </el-table-column>
      </template>
    </el-table>

    <!-- 分页 -->
    <el-pagination
      v-if="pagination"
      background
      :total="pagination.total"
      :page-size="pagination.pageSize"
      :page-sizes="[10, 20, 30, 40, 50]"
      layout="sizes,total, prev, pager, next, jumper"
      @size-change="handleSizeChange"
      @current-change="handleIndexChange"
      style="padding: 20px; text-align: center"
    ></el-pagination>

    <!-- 添加列设置弹窗 -->
    <el-dialog v-if="showColumnSetting" title="列设置" :visible.sync="columnSettingsVisible" width="500px">
      <div class="dialog-header">
        <el-checkbox v-model="showAllColumns" @change="toggleAllColumns">全选</el-checkbox>
        <el-button type="text" @click="handleInitConfig">初始化配置</el-button>
      </div>
      <el-divider></el-divider>
      <draggable v-model="localColumns" handle=".drag-handle" @end="handleDragEnd">
        <div v-for="(col, index) in localColumns" :key="index" class="column-item">
          <i class="el-icon-rank drag-handle"></i>
          <el-checkbox v-model="col.isShow" @change="handleColumnChange">
            {{ col.label }}
          </el-checkbox>
        </div>
      </draggable>
      <span slot="footer">
        <el-button @click="columnSettingsVisible = false">取消</el-button>
        <el-button type="primary" @click="saveColumnSettings">确定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import { deepClone } from '@/utils'
import draggable from 'vuedraggable'
import request from '@/utils/request'

export default {
  name: 'LTable',
  components: {
    RenderDom: {
      functional: true,
      props: {
        row: Object,
        render: Function,
        index: Number,
        column: {
          type: Object,
          default: null
        }
      },

      render: (h, data) => {
        const params = {
          row: data.props.row,
          index: data.props.index
        }

        if (data.props.column) params.column = data.props.column
        return data.props.render(h, params)
      }
    },
    draggable
  },
  props: {
    dictData: Object, //字典对象
    dataSource: Array, // table内容数据
    options: Object, // 表格参数控制 maxHeight、stripe 等等...
    columns: Array, // 表头
    fetch: {
      type: Function,
      default: function () {}
    }, // 获取数据的函数
    pagination: Object, // 分页，不传则不显示
    typeTable: String,
    defaultFetch: {
      type: Boolean,
      default: true
    },
    RowKey: {
      type: String,
      default: 'id'
    },
    tableId: {
      // 表格唯一标识，用于保存和获取表格配置，为空时使用当前组件路径
      type: String,
      required: false, // 改为非必填
      default: '' // 默认为空字符串
    },
    showColumnSetting: {
      type: Boolean,
      required: false,
      default: true // 默认显示
    }
  },
  computed: {
    unDisabled() {
      return function (val, unDisableKey, disableKey) {
        if (unDisableKey || unDisableKey === 0) {
          if (typeof unDisableKey == 'object') {
            return !unDisableKey.includes(Number(val))
          } else {
            return val != unDisableKey
          }
        }
        if (disableKey) {
          if (typeof disableKey == 'object') {
            return disableKey.includes(Number(val))
          } else {
            return val == disableKey
          }
        }
      }
    }
  },
  data() {
    return {
      oldCellData: null,
      renderKey: Math.random(),
      logo: require('@/assets/logo.png'),
      checkedKeys: false,
      editStatusMap: {},
      columnSettingsVisible: false, // 控制列设置弹窗的显示/隐藏
      localColumns: [], // 用于列设置弹窗
      localTableColumns: [], // 用于实际表格渲染
      showAllColumns: true,
      currentTableId: ''
    }
  },
  filters: {
    dictFind(v, dictData, dictName, dictLabel, dictValue) {
      const item = dictData[dictName].find((e) => e[dictValue] == v)
      return item ? item[dictLabel] : v
    }
  },
  created() {
    // 初始化本地表格数据
    this.localTableColumns = this.columns.map((col) => ({
      ...col,
      isHidden: false
    }))
    this.initTableId()

    if (this.defaultFetch) {
      this.options.initTable && this.fetch()
    } else {
      this.options.initTable
    }
    this.initColumnSettings()
  },
  methods: {
    /**
     * 初始化表格ID
     * 使用父组件路由路径和当前组件name生成唯一标识
     */
    initTableId() {
      if (this.tableId) {
        this.currentTableId = this.tableId
      } else {
        // 获取父组件实例
        const parent = this.$parent
        let parentPath = ''

        // 获取父组件的路由路径
        if (parent && parent.$route) {
          parentPath = parent.$route.path
        }

        // 获取当前组件的name
        const componentName = parent.$options.name || ''

        // 生成唯一标识：父组件路径-组件名称-索引
        let instanceId = `${parentPath}-${componentName}`

        // 如果同一个父组件中有多个相同的表格组件，添加索引区分
        if (parent) {
          const siblings = parent.$children.filter((child) => child.$options.name === componentName)
          const index = siblings.indexOf(this)
          if (index > 0) {
            instanceId += `-${index}`
          }
        }

        this.currentTableId = instanceId
          .replace(/^\//, '') // 移除开头的斜杠
          .replace(/\//g, '-') // 将路径分隔符替换为横杠
          .replace(/[^a-zA-Z0-9\-_]/g, '-') // 只保留字母、数字、横杠和下划线
          .replace(/\-+/g, '-') // 将多个连续横杠替换为单个
          .replace(/^\-|\-$/g, '') // 移除首尾的横杠
          .toLowerCase() // 转为小写
      }

      // console.log('当前表格ID:', this.currentTableId)
    },
    hasChildren(row, showType) {
      //父级显示
      if (showType && showType == '0') {
        //父级判断
        if (row.parentId == null || row.parentId == '') {
          return true
        } else {
          return false
        }
      }
      //子级显示
      else if (showType && showType == '1') {
        //父级判断
        if ((row.parentId == null || row.parentId == '') && row.children && row.children.length > 0) {
          return false
        } else {
          return true
        }
      } else {
        return true
      }
    },
    editCell(row, column) {
      this.oldCellData = deepClone(row)
      this.$set(row, column.property + 'isShow', true)
      this.$nextTick(() => {
        this.$refs[column.property][0] && this.$refs[column.property][0].focus()
      })
    },

    handleEditBlur(column, scope) {
      scope.row[scope.column.property + 'isShow'] = false
      column.onChange(scope, this.oldCellData)
    },

    // table 文本颜色
    cellStyle(row, column, rowIndex, columnIndex) {
      if (row.column.label == '当前状态' && row.row.status == 1) {
        return 'color:#0ED1AA'
      } else if (row.column.label == '当前状态' && row.row.status == 2) {
        return 'color:#F3384F'
      }
    },

    // pageSize 改变时触发事件
    handleSizeChange(size) {
      this.pagination.pageSize = size || 10
      this.fetch()
    },
    // currentPage 改变时触发事件
    handleIndexChange(current) {
      this.pagination.pageIndex = current
      this.fetch()
    },

    handleSelect(selectRows, targetRow) {
      // 选中
      if (this.isObjectInArray(targetRow, selectRows)) {
        this.select(targetRow.children || [], true)
      } else {
        if (targetRow.children && targetRow.children.length) {
          let newTargetRow = this.flattenArray(targetRow.children)
          // 两个都选中 1个选中1个未选择 两个都未选中
          if (newTargetRow.every((itemB) => selectRows.some((itemA) => this.isEqual(itemA, itemB)))) {
            this.select(targetRow.children, false)
          } else {
            this.select(targetRow.children, true)
            this.$refs.elTablet.toggleRowSelection(targetRow, true)
          }
        }
      }
    },

    // 多选框选择变化触发事件
    handleSelectionChange(selection) {
      this.$emit('selection-change', selection)
    },

    // 单选框
    handleCurrentChange(selection) {
      this.$emit('current-change', selection)
    },

    // 点击table某一行时触发事件
    handleRowClick(row, event, column) {
      this.$emit('handleRowClick', row, event, column)
    },

    // 翻页时，记住上一页的勾选标识
    getRowKey(row) {
      return this.options.treeProps ? (this.options.rowKey ? row[this.options.rowKey] : row.id || row.value || row.avmatCategoriesCode) : null
    },

    // 控制 table 子级 全选
    selectAll(selection) {
      this.checkedKeys = !this.checkedKeys
      this.select(this.dataSource, this.checkedKeys)
      this.$emit('select-all', selection)
    },

    toggleRowSelection(row, toggle) {
      this.$refs.elTablet.toggleRowSelection(row, toggle)
    },
    // 控制 table 子级 全选
    select(d, c) {
      d.forEach((row) => {
        this.$refs.elTablet.toggleRowSelection(row, c)
        if (row.children && row.children.length > 0) {
          this.select(row.children, c)
        }
      })
    },
    // 设定某一行为选中行
    setCurrentRow(row) {
      this.$refs.elTablet.setCurrentRow(row)
    },

    clearSelection() {
      this.checkedKeys = false
      this.$refs.elTablet.clearSelection()
    },
    isObjectInArray(obj, arr) {
      return arr.some((item) => {
        return Object.keys(obj).every((key) => {
          return obj[key] === item[key]
        })
      })
    },
    isEqual(objA, objB) {
      return JSON.stringify(objA) === JSON.stringify(objB)
    },
    flattenArray(arr) {
      return [].concat(...arr.map((item) => (Array.isArray(item.children) ? this.flattenArray(item.children) : item)))
    },
    /**
     * 初始化列设置
     * 从后端获取用户保存的表格配置
     */
    async initColumnSettings() {
      try {
        const response = await request({
          url: '/tableConfig/userTableConfig/getUserTableConfig',
          method: 'post',
          data: {  tableName: this.currentTableId }
        })
        // const response = await post('/tableConfig/userTableConfig/getUserTableConfig', {
        //   tableName: this.currentTableId
        // })

        if (response.data) {
          const columnConfig = JSON.parse(response.data.columnConfig)

          // 更新 localColumns 和 localTableColumns
          this.localColumns = this.columns.map((col) => {
            const savedCol = columnConfig.columns.find((c) => c.prop === col.prop)
            return {
              ...col,
              isShow: savedCol ? savedCol.isShow : true,
              width: savedCol ? savedCol.width : col.width
            }
          })

          // 更新表格显示列
          this.updateTableColumns()
        } else {
          // 没有保存的配置，使用默认配置
          this.localColumns = this.columns.map((col) => ({
            ...col,
            isShow: true
          }))
          this.localTableColumns = [...this.columns]
        }

        this.$nextTick(() => {
          this.renderKey = Math.random()
        })
      } catch (error) {
        console.error('获取表格配置失败:', error)
        // 使用默认配置
        this.localColumns = this.columns.map((col) => ({
          ...col,
          isShow: true
        }))
        this.localTableColumns = [...this.columns]
      }
    },

    /**
     * 显示列设置弹窗
     */
    showColumnSettings() {
      this.columnSettingsVisible = true
      this.checkShowAllStatus()
    },

    /**
     * 切换全选状态
     * @param {Boolean} val - 是否全选
     */
    toggleAllColumns(val) {
      this.localColumns.forEach((col) => {
        col.isShow = val
      })
    },

    /**
     * 处理单个列显示状态变化
     */
    handleColumnChange() {
      this.checkShowAllStatus()
    },

    /**
     * 检查是否所有列都被选中，更新全选状态
     */
    checkShowAllStatus() {
      this.showAllColumns = this.localColumns.every((col) => col.isShow)
    },

    /**
     * 处理拖拽排序完成事件
     * 仅更新 localColumns 的顺序，不立即应用到表格
     */
    handleDragEnd() {
      // 拖拽排序时只记录新的顺序，不立即更新表格显示
      console.log('列顺序已更改，点击确定后生效')
    },

    /**
     * 保存列设置到后端
     * 包括列的显示状态、顺序和宽度
     */
    async saveColumnSettings() {
      const columnConfig = {
        columns: this.localColumns.map(({ prop, isShow, width }, index) => ({
          prop,
          isShow,
          width,
          order: index
        }))
      }

      try {
        await request({
          url: '/tableConfig/userTableConfig/save',
          method: 'post',
          data: { tableName: this.currentTableId,
            columnConfig: JSON.stringify(columnConfig) }
        })
        // await post('/tableConfig/userTableConfig/save', {
        //   tableName: this.currentTableId,
        //   columnConfig: JSON.stringify(columnConfig)
        // })

        // 更新表格显示列
        this.updateTableColumns()

        this.columnSettingsVisible = false
        this.$nextTick(() => {
          this.renderKey = Math.random()
        })

        this.$message.success('配置保存成功')
      } catch (error) {
        console.error('保存表格配置失败:', error)
        this.$message.error('配置保存失败')
      }
    },

    /**
     * 初始化列配置
     * 重置为系统默认配置
     */
    async handleInitConfig() {
      try {
        await this.$confirm('确定要初始化列配置吗？', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        await request({
          url: '/tableConfig/userTableConfig/initUserTableConfig',
          method: 'post',
          data: { tableName: this.currentTableId }
        })
        // await post('/tableConfig/userTableConfig/initUserTableConfig', {
        //   tableName: this.currentTableId
        // })

        // 重新获取配置
        await this.initColumnSettings()

        this.$message.success('初始化配置成功')
      } catch (error) {
        if (error !== 'cancel') {
          // 排除取消操作的错误
          console.error('初始化配置失败:', error)
          this.$message.error('初始化配置失败')
        }
      }
    },

    // 新增方法：根据 localColumns 更新表格显示列
    updateTableColumns() {
      this.localTableColumns = this.localColumns.map((col) => ({
        ...col,
        isHidden: !col.isShow
      }))
    },

    /**
     * 处理列宽拖动结束事件
     * @param {Number} newWidth - 新的宽度
     * @param {Number} oldWidth - 旧的宽度
     * @param {Object} column - 列对象
     */
    handleHeaderDragend(newWidth, oldWidth, column) {
      // 如果宽度没有变化，不处理
      if (newWidth === oldWidth) return

      // 更新本地配置
      const targetColumn = this.localColumns.find((col) => col.prop === column.property)
      if (targetColumn) {
        targetColumn.width = newWidth
      }

      // 更新表格显示列
      this.updateTableColumns()

      // 保存到后台
      this.saveColumnSettings()
    }
  },
  // 可选：添加 watch 来监听原始 columns 的变化
  watch: {
    columns: {
      handler(newColumns) {
        // 当原始列变化时，更新本地列
        this.localTableColumns = newColumns.map((col) => ({
          ...col,
          isHidden: false
        }))
      },
      deep: true
    }
  }
}
</script>
<style lang="scss" scoped>
@import './index.scss';

.table-settings {
  margin-bottom: 10px;
  text-align: right;
}

.column-item {
  display: flex;
  align-items: center;
  padding: 8px;
  border-bottom: 1px solid #ebeef5;

  .drag-handle {
    cursor: move; // 显示移动光标
    margin-right: 10px;
    color: #909399;
  }
}

.table-page {
  .el-table {
    // 添加过渡效果使宽度变化更平滑
    ::v-deep .el-table__header-wrapper,
    ::v-deep .el-table__body-wrapper {
      th,
      td {
        transition: width 0.2s;
      }
    }
  }
}

.dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 5px;
}
</style>
