<template>
  <div class="table-box">
    <div
      v-if="tableTitle||showRight"
      class="need-btn-line"
    >
      <div
        class="table-title"
      >{{ tableTitle }}</div>
      <div
        v-if="showRight"
        style="display:flex;align-items:center"
      >
        <!-- 自定义按钮 -->
        <div v-if="tableTopButton.length > 0">
          <template v-for="(value, i) in tableTopButton">
            <slot
              v-if="value.slot"
              :name="value.slot"
            />
            <el-button
              v-else
              :key="'$' + i"
              :style="{ fontSize: fontSize + 'px' }"
              size="small"
              :type="value.type || 'text'"
              :icon="value.icon"
              :class="value.class"
              @click="value.callback(value)"
            >{{ value.text }}</el-button>
          </template>
        </div>

        <el-dropdown
          v-if="isNeedCustomcolumn||isNeedImport||isNeedExport||dropCustomButtons.length>0"
          trigger="click"
          style="display:flex"
        >
          <i class="el-icon-setting setting-drop" />
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item v-if="isNeedCustomcolumn">
              <!-- 列定制按钮 -->
              <span
                @click="handlecustomcolumnOpen"
              >列定制</span>
            </el-dropdown-item>
            <el-dropdown-item v-if="isNeedImport">
              <!-- 导入按钮 -->
              <span
                @click="handleImport"
              >导入</span>
            </el-dropdown-item>
            <el-dropdown-item v-if="isNeedExport">
              <!-- 导出按钮 -->
              <span
                @click="handleExport"
              >导出</span>
            </el-dropdown-item>
            <el-dropdown-item
              v-for="item in dropCustomButtons"
              :key="item.slot"
            >
              <!-- 自定义按钮 -->
              <slot :name="item.slot" />
            </el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </div>
    </div>
    <el-table
      v-if="tableConfigs.length > 0"
      :ref="tableKey"
      v-loading="loading"
      class="table-list"
      size="default"
      :row-key="rowKey"
      :style="{ width: '100%', fontSize: fontSize + 'px' }"
      :show-header="showHeader"
      :data="tableData"
      :height="tableHeight"
      :cell-style="cellStyle"
      :cell-class-name="tableCellClass"
      :span-method="arraySpanMethod"
      :border="border"
      :highlight-current-row="highlightCurrentRow"
      v-bind="tableInfo"
      :stripe="isStripe"
      :tree-props="{
        children: treePropsChildren,
        hasChildren: treePropshasChildren,
      }"
      v-on="events"
      @selection-change="handleSelectionChange"
      @select-all="handleSelectionAllChange"
      @expand-change="handleExpandChange"
    >
      <slot name="expand" />
      <!-- 多选 -->
      <el-table-column
        v-if="needSelect"
        type="selection"
        width="40"
        :reserve-selection="isReserve"
        :selectable="selectable"
      />
      <!-- 序号 -->
      <el-table-column
        v-if="hasIndex"
        label="序号"
        width="50"
        type="index"
        fixed
      />

      <template v-for="(item, index) in tableConfigs">
        <el-table-column
          :key="'%' + index"
          :show-overflow-tooltip="!item.notTooltip"
          v-bind="item"
          v-on="events"
        >
          <!-- 头部 -->
          <template
            slot="header"
            slot-scope="scope"
          >
            <i
              v-if="item.tableTopColumnIcon"
              :class="item.tableTopColumnIcon"
              @click="handleTableTopColumnIconClick(item,index)"
            />
            {{ item.label }}
            <span v-if="item.tableTopColumnCheck">
              <el-checkbox
                v-model="item.tableTopColumnCheckValue"
                :v-bind="item.tableTopColumnCheckValue"
                :indeterminate="false"
                @change="(val)=>
                  handleTableTopColumncheckChange(item,index,val)"
              />
            </span>

          </template>

          <template slot-scope="scope">
            <!-- render 函数式 -->
            <template v-if="item.render">
              <ex-slot
                :render="item.render"
                :index="scope.$index"
                :row="scope.row"
                :column="item"
                :class="item.prop"
                :default-value="item.defaultValue"
              />
            </template>

            <!-- progress 进度条 -->
            <template v-else-if="item.progress">
              <el-progress :percentage="parseFloat(scope.row[item.prop])" />
            </template>

            <!-- formatter 自定义 -->
            <template v-else-if="item.formatter">
              <span v-html="item.formatter(scope.row, item)" />
            </template>

            <!-- checkbox -->
            <template v-else-if="item.tableTopColumnCheck">
              <el-checkbox
                v-model="scope.row[item.prop]"
                @change="(val)=>
                  handleTableTopColumnRowcheckChange(scope,index,val)"
              />
            </template>

            <!-- 正常列 -->
            <template v-else>
              <span>
                {{ scope.row[item.prop] }}
              </span>
            </template>
          </template>

        </el-table-column>
      </template>
      <!-- 操作 -->
      <el-table-column
        v-if="hasOperation"
        label="操作"
        :min-width="operationWidth"
        :fixed="operationFixed ? 'right' : false"
        align="center"
      >
        <template
          v-if="btnButton.length"
          slot-scope="{ row, column, $index }"
        >
          <el-button
            v-for="(value, i) in btnButton"
            :key="'$' + i"
            :style="{ fontSize: fontSize + 'px' }"
            size="small"
            :type="value.type || 'text'"
            :icon="value.icon"
            :class="value.class || 'el-text-color'"
            v-bind="value"
            @click="value.callback(row, column, $index)"
          >{{ value.text }}</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <div
      v-if="isNeedPagination"
      :style="{
        display: 'flex',
        justifyContent: operatedString ? 'space-between' : 'flex-end',
        alignItems: 'center',
        width: '100%',
      }"
    >
      <div
        v-if="operatedString"
        class="operated"
      >{{ operatedString }}</div>
      <el-pagination
        ref="pagination"
        class="no-border-top"
        :page-sizes="pageSizes"
        :page-size.sync="computedPageSize"
        :hide-on-single-page="isSinglePageHide"
        layout="total, sizes, prev, pager, next, jumper"
        :current-page.sync="computedCurrentPage"
        :total="total"
        :small="small"
        :pager-count="pagerCount"
        @current-change="currentChange"
        @size-change="sizeChange"
      />
    </div>
    <ExportDialog
      :show-dialog.sync="exportDialog"
      :export-params="exportParams"
    />
    <ImportDialog
      :show-dialog.sync="importDialog"
      :file-config="tableInfo?.fileConfig"
      @importCallBack="importCallBack"
    />

    <custom-table-subjects
      v-if="drawer&&defaultConfig.length>0"
      v-model="drawer"
      :table-key="tableKey"
      :table-configs="defaultConfig"
      :select-id="activeId"
      :list="planData"
      @change="handleRefresh"
    />
  </div>
</template>
<script>
// 自定义组件的内容
const exSlot = {
  functional: true,
  props: {
    row: Object,
    render: Function,
    index: Number,
    column: {
      type: Object,
      default: null,
    },
  },
  render: (h, ctx) => {
    const params = {
      row: ctx.props.row,
      index: ctx.props.index,
    };
    if (ctx.props.column) params.column = ctx.props.column;
    return ctx.props.render(h, params);
  },
};
import ExportDialog from '@/components/exportDialog';
import ImportDialog from '@/components/importDialog';
import CustomTableManager from '@erayt/titanOne-component-vue/src/basic-packages/colcustomization/src/model/customTableManager.js';
import CustomTableSubjects from '@erayt/titanOne-component-vue/src/basic-packages/colcustomization/src/components/customTableSubjects.vue';
export default {
  name: 'PublicTable',
  components: {
    'ex-slot': exSlot,
    ExportDialog,
    ImportDialog,
    CustomTableSubjects,
  },
  props: {
    // key（唯一key值，和reserve-selection搭配使用）
    rowKey: {
      type: [Object, Function],
      default: () => ({}),
    },
    // 多选框是否记住上一页数据(必须与row-key唯一值搭配使用)
    isReserve: {
      type: Boolean,
      default: false,
    },
    // 单元格的 style 的回调方法
    cellStyle: {
      type: [Object, Function],
      default: () => ({}),
    },
    pagerCount: {
      type: Number,
      default: 7,
    },
    // 是否显示表头
    showHeader: {
      type: Boolean,
      default: true,
    },
    // 是否要高亮当前行
    highlightCurrentRow: {
      type: Boolean,
      default: true,
    },
    // 获取表格行列索引值
    tableCellClassName: {
      type: Function,
      default: () => {},
    },
    // 合并行或列
    arraySpanMethod: {
      type: Function,
      default: () => {},
    },
    // 是否需要多选
    needSelect: {
      type: Boolean,
      default: false,
    },
    // 是否需要序号
    hasIndex: {
      type: Boolean,
      default: false,
    },
    // 默认是否选中第一列
    isSetCurrentRow: {
      type: Boolean,
      default: false,
    },
    // 是否需要分页
    isNeedPagination: {
      type: Boolean,
      default: false,
    },
    // 是否需要 列定制 按钮
    isNeedCustomcolumn: {
      type: Boolean,
      default: false,
    },
    // 是否需要 导出 按钮
    isNeedExport: {
      type: Boolean,
      default: false,
    },
    // 自定义下拉 按钮
    dropCustomButtons: {
      type: Array,
      default: () => [],
    },
    // 导出参数
    exportParams: {
      type: Object,
      default: () => {},
    },
    // 是否需要 导入 按钮
    isNeedImport: {
      type: Boolean,
      default: false,
    },
    // 是否单页隐藏，默认为true
    isSinglePageHide: {
      type: Boolean,
      default: false,
    },
    // 当前页页码，支持.sync修饰符
    currentPage: {
      type: Number,
      default: 1,
    },
    // 每页数据条数, 支持.sync修饰符默认为每页10条
    pageSize: {
      type: Number,
      default: 20,
    },
    // 数据总条数
    total: {
      type: Number,
      default: 0,
    },
    // 每页多少数据
    pageSizes: {
      type: Array,
      required: false,
      default: () => [10, 20, 50, 100],
    },
    tableInfo: {
      type: Object,
      required: false,
      default: () => {},

    },
    // 获取数据时是否需要加载loading
    loading: {
      type: Boolean,
      default: false,
    },
    tableData: {
      type: Array,
      default: () => [],
    },
    // 表格展示数据
    tableColumn: {
      type: Array,
      default: () => [],
    },
    // 是否需要操作列
    hasOperation: {
      type: Boolean,
      default: true,
    },
    // 是否需要边框
    border: {
      type: Boolean,
      default: true,
    },
    // 操作 自定义按钮
    btnButton: {
      type: Array,
      default: () => [],
    },
    // 表格顶部自定义按钮
    tableTopButton: {
      type: Array,
      default: () => [],
    },
    // 操作列宽度
    operationWidth: {
      type: String,
      default: '60px',
    },
    // 固定操作栏
    operationFixed: {
      type: [Boolean, String],
      default: false,
    },
    // 表格方法
    events: {
      type: Object,
      default: () => {},
    },
    // 是否为斑马纹 table
    isStripe: {
      type: Boolean,
      default: false,
    },
    // 树结构(树结构必须有rowKey)
    treePropsChildren: {
      type: String,
      default: 'children',
    },
    // 树结构(树结构必须有rowKey)
    treePropshasChildren: {
      type: String,
      default: 'hasChildren',
    },
    // 点击图标计算的值
    operatedString: {
      type: String,
      default: '',
    },
    tableKey: {
      type: String,
      default: 'customTable',
    },
  },
  data() {
    return {
      isFirstLoad: true,
      defaultConfig: [],
      tableTitle: '',
      exportDialog: false,
      importDialog: false,
      drawer: false,
      fontSize: sessionStorage.getItem('fontSize') || '',
      planData: [],
      customManager: null,
      activeId: null,
      tableConfigs: [],
      notExpandRows: [],
    };
  },
  computed: {
    computedCurrentPage: {
      get() {
        return this.currentPage;
      },
      set(val) {
        this.$emit('update:currentPage', val);
      },
    },
    computedPageSize: {
      get() {
        return this.pageSize;
      },
      set(val) {
        this.$emit('update:pageSize', val);
      },
    },
    tableHeight() {
      return this.tableInfo?.tableHeight ? this.tableInfo?.tableHeight : !this.isNeedPagination ? '100%' : 'calc(100% - 47px)';
    },
    showRight() {
      return this.tableTopButton.length > 0 || this.isNeedCustomcolumn || this.isNeedImport || this.isNeedExport || this.dropCustomButtons.length > 0;
    },
  },
  watch: {
    tableColumn: {
      handler(val) {
        this.tableConfigs = val;
        this.customManager = new CustomTableManager(this.$route.meta, this.tableKey);
        this.getCache();
        if (this.isFirstLoad && val.length > 0) {
          this.defaultConfig = val;
          this.isFirstLoad = false;
        }
      },
      immediate: true,
      deep: true,
    },
    'tableInfo.selection': {
      handler(val) {
        if (val && val.length > 0) { // 设置默认选中项
          this.setDefaultSelection(val);
        }
      },
      deep: true,
    },
    tableData: {
      handler(val) {
        this.setNotExpandData(val);
      },
      immediate: true,
      deep: true,
    },
  },
  mounted() {
    this.tableTitle = this.tableInfo?.tableTitle;
    if (this.isSetCurrentRow) {
      setTimeout(() => {
        this.$refs[this.tableKey].setCurrentRow(this.tableData[0]);
      }, 500);
    }
  },
  activated() {
    console.log('activated');
    this.getCache();
  },
  methods: {
    setNotExpandData(val) { // 设置默认不展开的数据
      if (this.tableInfo?.defaultExpandAll) {
        return;
      }
      const arr = [];
      for (const v of val) { // 后续若设置了默认展开项 需做调整
        if (v.children) {
          arr.push(v.id);
        }
      }
      this.notExpandRows = [...new Set(arr)];
    },
    selectable(row) {
      return !row._disabled;
    },
    setDefaultSelection(selection) {
      const ids = selection.map((item) => item[this.rowKey]);
      const selectionE = [...this.tableData];
      console.log(ids, selectionE, 'iiii');
      if (selectionE.length) {
        this.$nextTick(() => {
          setTimeout(() => {
            selectionE.forEach((row) => {
              this.$refs[this.tableKey].toggleRowSelection(row, ids.includes(row[this.rowKey]));
            });
          }, 500);
        });
      }
    },
    async getCache() {
      try {
        // this.tableConfigs = [];
        const { value } = await Eui.service.cloudStorage.get(
          this.customManager.getCloudStorageKey(),
        );
        if (value) {
          const { activeId, list } = JSON.parse(value);
          this.activeId = activeId;
          this.planData = this.customManager.overridePlanData(this.tableColumn.map(v => {
            return {
              ...v,
              name: v.prop,
            };
          }) || [], list || []);
          console.log('getCache', this.planData, this.tableColumn);
          this.getCurrentSubject();
        }
      } catch (error) {
        console.log(error, 'eeeee');
        // this.tableConfigs = this.tableColumn;
      } finally {
        if (this.tableConfigs.length === 0) {
          this.setSystemConfig();
        }
        this.$nextTick(() => {
          const wrapper = this.getBodyWrapper();
          if (wrapper && this.mouseHighlight) {
            wrapper.addEventListener('mousedown', this.mouseDownHandler);
          }
        });
      }
    },
    setSystemConfig() {
      const tree2Array = [];
      this.customManager.treeToArr(this.tableColumn, null, tree2Array);
      this.tableConfigs = this.customManager.flatArrayToTree(tree2Array);
    },
    getBodyWrapper(type = 'dom') {
      let wrapper = null;
      if (this.$refs && this.$refs[this.tableKey]) {
        if (type === 'dom') wrapper = this.$refs[this.tableKey]?.$refs['bodyWrapper'] || null;
        if (type === 'wrapper') wrapper = this.$refs[this.tableKey]?.bodyWrapper || null;
      }
      return wrapper;
    },
    async handleRefresh(tag) {
      console.log('handleRefresh', tag);
      await this.getCache();
    },
    getCurrentSubject() {
      if (!this.activeId) {
        // this.tableConfigs = this.tableColumn;
        this.setSystemConfig();
        return;
      }
      const idx = this.planData.findIndex(item => item.subjectId === this.activeId);
      if (idx > -1) {
        const { settings } = this.planData[idx];
        if (settings) {
          if (this.activeId === 'system') {
            this.setSystemConfig();
          } else {
            this.tableConfigs = settings.filter(v => v.show);
          }
          console.log('getConfigs', this.tableConfigs);
        }
        this.$nextTick(() => {
          this.$refs[this.tableKey].doLayout();
        });
      }
    },
    getTableRef() {
      return this.$refs[this.tableKey];
    },
    currentChange(val) {
      this.$emit('currentChange', val);
    },
    sizeChange(val) {
      this.$emit('sizeChange', val);
    },
    handlecustomcolumnOpen() {
      this.drawer = true;
    },
    handleExport() {
      this.exportDialog = true;
    },
    handleImport() {
      this.importDialog = true;
    },
    importCallBack(file) { // 导入回调
      console.log(file, '导入回调');
    },
    handleTableTopColumnIconClick(item, index) { // 点击当前列前的图标事件
      this.$emit('handleTableTopColumnIconClick', item, index);
    },
    handleTableTopColumncheckChange(item, index, val) {
      this.$emit('handleTableTopColumncheckChange', item, index, val);
    },
    handleTableTopColumnRowcheckChange(item, index, val) {
      this.$emit('handleTableTopColumnRowcheckChange', item, index, val);
    },
    handleSelectionChange(row) { // 多选事件
      this.$emit('handleSelectionChange', row);
    },
    handleSelectionAllChange(row) {
      this.$emit('handleSelectionAllChange', row);
    },
    handleExpandChange(row, val) {
      if (val === false) { // 不展开
        this.notExpandRows = [...new Set([...this.notExpandRows, row.id])];
        if (row.children) {
          this.removeDescendants(row.children);
        }
      } else {
        console.log(row, 'rrr');
        let arr = this.notExpandRows.filter(v => v !== row.id);
        if (row.children) {
          for (const v of row.children) { // 展开的节点含有子节点 则添加
            if (v.children) {
              arr = [...arr, v.id];
            }
          }
        }
        this.notExpandRows = [...new Set(arr)];
      }
      console.log(this.notExpandRows, 'this.notExpandRows');
      this.$emit('handleExpandChange', row, val);
    },
    removeDescendants(children) {
      for (const child of children) {
        // 从 notExpandRows 中移除该子节点的 ID
        this.notExpandRows = this.notExpandRows.filter(v => v !== child.id);
        if (child.children) {
          this.removeDescendants(child.children);
        }
      }
    },
    tableCellClass({ row, column, rowIndex, columnIndex }) { // 树形数据层级背景设置
      if (typeof this.tableCellClassName === Function) {
        return this.tableCellClassName;
      }
      let cIndex = 0;
      if (this.hasIndex) {
        cIndex++;
      } if (this.needSelect) {
        cIndex++;
      }
      if (column.type !== 'selection' && column.type !== 'index' && columnIndex <= cIndex) {
        return 'el-table-tree-color';
      }
    },
  },
};
</script>
<style lang="scss" scoped>
:deep(.el-table__row--level-0 .el-table-tree-color){
     background:rgb(32,43,58) !important
}
:deep(.el-table__row--level-1 .el-table-tree-color){
     background:rgb(38,35,56) !important
}
:deep(.el-table__row--level-2 .el-table-tree-color){
     background:rgb(38,38,40) !important
}
.table-box {
  padding:16px;
  background-color: var(--bg-color-2);
  border-radius: 4px;
}
.table-list{
  border: 1px solid var(--white-7);
  border-radius: 4px;
}

.need-btn-line {
  // padding: 8px;
  // text-align: right;
  line-height: 24px;
  margin-bottom:12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  .table-title{
    color:var(--text-color-1)
  }
}

::v-deep .el-table td {
  padding: 0;
  height: 28px;
}

// // table选中行高亮
// ::v-deep .el-table__body tr.current-row {
//   .flex_div {
//     background: rgba(21, 91, 212, 0.3) !important;
//   }
//   td {
//     background: rgba(21, 91, 212, 0.3) !important;
//   }
//   td {
//     background: rgba(21, 91, 212, 0.2) !important;
//   }
// }

::v-deep .el-pagination {
  margin-right: 8px;
}

.drawer-footer {
  position: absolute;
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 60px;
  .drawer-footer-confirm-btn,
  .drawer-footer-cancel-btn {
    margin-right: 12px;
  }
}
.operated {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 12px;
  width: 50%;
}
.setting-drop{
  color:var(--text-color-4);
  font-size:14px;
  cursor:pointer;
  margin-left:10px
}
.el-dropdown-menu{
  padding:0
}

:deep(.el-drawer__header){
  color:var(--text-color-1)
}
</style>
