import XEUtils from 'xe-utils';
import GlobalConfig from '../../v-table/src/conf';
import VTable from '../../v-table';
import ElTablePlusHeader from '../../header';
import ElTablePlusBody from './body';
import ElTablePlusFooter from '../../footer';
import ElTableTooltip from '../../tooltip';
import vSize from '../../mixins/size';
import editMixins from '../../mixins/edit/src/mixin';
import filterMixins from '../../mixins/filter';
import { getFuncText } from '../../tools/utils';
import { createResizeEvent } from '../../tools/resize';
import { GlobalEvent } from '../../tools/event';
import { getSlotVNs } from '../../tools/vn';
import methods from './methods';
import { warnLog, errLog } from '../../tools/log';
// import VxeLoading from '../../loading/index';

/**
 * 渲染浮固定列
 * 分别渲染左边固定列和右边固定列
 * 如果宽度足够情况下，则不需要渲染固定列
 * @param {Function} h 创建 VNode 函数
 * @param {Object} $tablePlus 表格实例
 * @param {String} fixedType 固定列类型
 */
function renderFixed(h, $tablePlus, fixedType) {
  const {
    _e,
    tableData,
    tableColumn,
    tableGroupColumn,
    vSize,
    showHeader,
    showFooter,
    columnStore,
    footerTableData
  } = $tablePlus;
  const fixedColumn = columnStore[`${fixedType}List`];
  return h(
    'div',
    {
      class: `el-table-plus--fixed-${fixedType}-wrapper`,
      ref: `${fixedType}Container`
    },
    [
      showHeader
        ? h(ElTablePlusHeader, {
          props: {
            fixedType,
            tableData,
            tableColumn,
            tableGroupColumn,
            size: vSize,
            fixedColumn
          },
          ref: `${fixedType}Header`
        })
        : _e(),
      h('el-table-plus-body', {
        props: {
          fixedType,
          tableData,
          tableColumn,
          fixedColumn,
          size: vSize
        },
        ref: `${fixedType}Body`
      }),
      showFooter
        ? h('el-table-plus-footer', {
          props: {
            footerTableData,
            tableColumn,
            fixedColumn,
            fixedType,
            size: vSize
          },
          ref: `${fixedType}Footer`
        })
        : _e()
    ]
  );
}

function renderEmptyContenet(h, _vm) {
  const { $scopedSlots, emptyOpts } = _vm;
  let emptyContent = '';
  const params = { $table: _vm };
  if ($scopedSlots.empty) {
    emptyContent = $scopedSlots.empty.call(_vm, params, h);
  } else {
    const compConf = emptyOpts.name ? VTable.renderer.get(emptyOpts.name) : null;
    const renderEmpty = compConf ? compConf.renderEmpty : null;
    if (renderEmpty) {
      emptyContent = getSlotVNs(renderEmpty.call(_vm, h, emptyOpts, params));
    } else {
      emptyContent =
        getFuncText(_vm.emptyText) ||
        '暂无数据';
    }
  }
  return emptyContent;
}

function handleUupdateResize(_vm) {
  const { $el } = _vm;
  if ($el && $el.clientWidth && $el.clientHeight) {
    _vm.recalculate();
  }
}

export default {
  name: 'ElTablePlus',
  mixins: [vSize, editMixins, filterMixins],
  props: {
    /** 基本属性 */
    id: String,
    // 数据
    data: Array,
    // 表格的高度
    height: [Number, String],
    // 表格的最小高度
    minHeight: {
      type: [Number, String],
      default: () => GlobalConfig.table.minHeight
    },
    // 表格的最大高度
    maxHeight: [Number, String],
    // 同 column-config.resizable
    resizable: { type: Boolean, default: () => GlobalConfig.table.resizable },
    // 是否带有斑马纹
    stripe: { type: Boolean, default: () => GlobalConfig.table.stripe },
    // 是否带有边框
    border: {
      type: [Boolean, String],
      default: () => GlobalConfig.table.border
    },
    // 是否圆角边框
    round: { type: Boolean, default: () => GlobalConfig.table.round },
    // 表格的尺寸
    size: {
      type: String,
      default: () => GlobalConfig.table.size || GlobalConfig.size
    },
    // 列的宽度是否自撑开
    fit: { type: Boolean, default: () => GlobalConfig.table.fit },
    // 表格是否加载中
    loading: Boolean,
    // 所有的列对其方式
    align: { type: String, default: () => GlobalConfig.table.align },
    // 所有的表头列的对齐方式
    headerAlign: {
      type: String,
      default: () => GlobalConfig.table.headerAlign
    },
    // 所有的表尾列的对齐方式
    footerAlign: {
      type: String,
      default: () => GlobalConfig.table.footerAlign
    },
    // 是否显示表头
    showHeader: { type: Boolean, default: () => GlobalConfig.table.showHeader },
    // 同 row-config.isCurrent
    highlightCurrentRow: {
      type: Boolean,
      default: () => GlobalConfig.table.highlightCurrentRow
    },
    // 同 row-config.isHover
    highlightHoverRow: {
      type: Boolean,
      default: () => GlobalConfig.table.highlightHoverRow
    },
    // 同 column-config.isCurrent
    highlightCurrentColumn: {
      type: Boolean,
      default: () => GlobalConfig.table.highlightCurrentColumn
    },
    // 同 column-config.isHover
    highlightHoverColumn: {
      type: Boolean,
      default: () => GlobalConfig.table.highlightHoverColumn
    },
    highlightCell: Boolean,
    // 是否显示表尾合计
    showFooter: Boolean,
    // 表尾合计的计算方法
    footerMethod: Function,
    // 给行附加 className
    rowClassName: [String, Function],
    // 给单元格附加 className
    cellClassName: [String, Function],
    // 给表头的行附加 className
    headerRowClassName: [String, Function],
    // 给表头的单元格附加 className
    headerCellClassName: [String, Function],
    // 给表尾的行附加 className
    footerRowClassName: [String, Function],
    // 给表尾的单元格附加 className
    footerCellClassName: [String, Function],
    // 给单元格附加样式
    cellStyle: [Object, Function],
    // 给表头单元格附加样式
    headerCellStyle: [Object, Function],
    // 给表尾单元格附加样式
    footerCellStyle: [Object, Function],
    // 给行附加样式
    rowStyle: [Object, Function],
    // 给表头行附加样式
    headerRowStyle: [Object, Function],
    // 给表尾行附加样式
    footerRowStyle: [Object, Function],
    // 合并指定单元格
    mergeCells: Array,
    // 合并指定的表尾
    mergeFooterItems: Array,
    // 自定义合并行或列的方法
    spanMethod: Function,
    // 表尾合并行或列
    footerSpanMethod: Function,
    // 设置所有内容过长时显示为省略号
    showOverflow: {
      type: [Boolean, String],
      default: () => GlobalConfig.table.showOverflow
    },
    // 设置表头所有内容过长时显示为省略号
    showHeaderOverflow: {
      type: [Boolean, String],
      default: () => GlobalConfig.table.showHeaderOverflow
    },
    // 设置表尾所有内容过长时显示为省略号
    showFooterOverflow: {
      type: [Boolean, String],
      default: () => GlobalConfig.table.showFooterOverflow
    },

    /** 高级属性 */
    // 同 column-config.useKey
    columnKey: Boolean,
    // 同 row-config.useKey
    rowKey: Boolean,
    // 同 row-config.keyprop
    rowId: { type: String, default: () => GlobalConfig.table.rowId },
    zIndex: Number,
    emptyText: { type: String, default: () => GlobalConfig.table.emptyText },
    keepSource: { type: Boolean, default: () => GlobalConfig.table.keepSource },
    // 是否自动监听父容器变化去更新响应式表格宽高
    autoResize: { type: Boolean, default: () => GlobalConfig.table.autoResize },
    // 是否自动根据状态属性去更新响应式表格宽高
    syncResize: [Boolean, String, Number],
    // 响应式布局配置项
    resizeConfig: Object,
    // 列配置信息
    columnConfig: Object,
    // 行配置信息
    rowConfig: Object,
    // 列调整配置项
    resizableConfig: Object,
    // 序号配置项
    seqConfig: Object,
    // 排序配置项
    sortConfig: Object,
    // 筛选配置项
    filterConfig: Object,
    // 单选框配置
    radioConfig: Object,
    // 复选框配置项
    checkboxConfig: Object,
    // tooltip 配置项
    tooltipConfig: Object,
    // 导出配置项
    exportConfig: [Boolean, Object],
    // 导入配置项
    importConfig: [Boolean, Object],
    // 打印配置项
    printConfig: Object,
    // 展开行配置项
    expandConfig: Object,
    // 树形结构配置项
    treeConfig: [Boolean, Object],
    // 快捷菜单配置项
    menuConfig: [Boolean, Object],
    // 鼠标配置项
    mouseConfig: Object,
    // 区域配置项
    areaConfig: Object,
    // 按键配置项
    keyboardConfig: Object,
    // 复制/粘贴配置项
    clipConfig: Object,
    // 查找/替换配置项
    fnrConfig: Object,
    // 编辑配置项
    editConfig: [Boolean, Object],
    // 校验配置项
    validConfig: Object,
    // 校验规则配置项
    editRules: Object,
    // 加载中配置项
    loadingConfig: Object,
    // 空内容渲染配置项
    emptyRender: [Boolean, Object],
    // 自定义列配置项
    customConfig: [Boolean, Object],
    // 横向虚拟滚动配置项
    scrollX: Object,
    // 纵向虚拟滚动配置项
    scrollY: Object,
    // 优化相关
    animat: { type: Boolean, default: () => GlobalConfig.table.animat },
    // hover延迟
    delayHover: { type: Number, default: () => GlobalConfig.table.delayHover },
    // 额外的参数
    params: Object
  },
  components: {
    ElTablePlusFooter,
    ElTablePlusBody
  },
  provide() {
    return {
      $tablePlus: this,
      xecolgroup: null
    };
  },
  inject: {
    $xegrid: {
      default: null
    }
  },
  data() {
    return {
      tId: `${XEUtils.uniqueId()}`,
      // 低性能的静态列
      staticColumns: [],
      // 渲染的列分组
      tableGroupColumn: [],
      // 可视区渲染的列
      tableColumn: [],
      // 渲染中的数据
      tableData: [],
      // 是否启用了横向 X 可视渲染方式加载
      scrollXLoad: false,
      // 是否启用了纵向 Y 可视渲染方式加载
      scrollYLoad: false,
      // 是否存在纵向滚动条
      overflowY: true,
      // 是否存在横向滚动条
      overflowX: false,
      // 纵向滚动条的宽度
      scrollbarWidth: 0,
      // 横向滚动条的高度
      scrollbarHeight: 0,
      // 行高
      rowHeight: 0,
      // 表格父容器的高度
      parentHeight: 0,
      // 是否使用分组表头
      isGroup: false,
      isAllOverflow: false,
      // 复选框属性，是否全选
      isAllSelected: false,
      // 复选框属性，有选中且非全选状态
      isIndeterminate: false,
      // 复选框属性，已选中的行集合
      selectCheckboxMaps: {},
      // 当前行
      currentRow: null,
      // 单选框属性，选中列
      currentColumn: null,
      // 单选框属性，选中行
      selectRadioRow: null,
      // 表尾合计数据
      footerTableData: [],
      // 展开列信息
      expandColumn: null,
      hasFixedColumn: false,
      // 树节点列信息
      treeNodeColumn: null,
      // 已展开的行集合
      rowExpandedMaps: {},
      // 懒加载中的展开行的集合
      rowExpandLazyLoadedMaps: {},
      // 已展开树节点集合
      treeExpandedMaps: {},
      // 懒加载中的树节点的集合
      treeExpandLazyLoadedMaps: {},
      // 树节点不确定状态的集合
      treeIndeterminateMaps: {},
      // 合并单元格的对象集
      mergeList: [],
      // 合并表尾数据的对象集
      mergeFooterList: [],
      // 初始化标识
      initStore: {
        filter: false,
        import: false,
        export: false
      },
      // 刷新列标识，当列筛选被改变时，触发表格刷新数据
      upDataFlag: 0,
      // 刷新列标识，当列的特定属性被改变时，触发表格刷新列
      reColumnFlag: 0,
      // 当前选中的筛选列
      filterStore: {
        isAllSelected: false,
        isIndeterminate: false,
        style: null,
        options: [],
        column: null,
        multiple: false,
        visible: false,
        maxHeight: null
      },
      // 存放列相关的信息
      columnStore: {
        leftList: [],
        centerList: [],
        rightList: [],
        resizeList: [],
        pxList: [],
        pxMinList: [],
        scaleList: [],
        scaleMinList: [],
        autoList: []
      },
      // 存放快捷菜单的信息
      ctxMenuStore: {
        selected: null,
        visible: false,
        showChild: false,
        selectChild: null,
        list: [],
        style: null
      },
      // 存放可编辑相关信息
      editStore: {
        indexs: {
          columns: []
        },
        titles: {
          columns: []
        },
        // 选中源
        selected: {
          row: null,
          column: null
        },
        // 已复制源
        copyed: {
          cut: false,
          rows: [],
          columns: []
        },
        // 激活
        actived: {
          row: null,
          column: null
        },
        insertList: [],
        insertMaps: {},
        removeList: [],
        removeMaps: {}
      },
      // 存放 tooltip 相关信息
      tooltipStore: {
        row: null,
        column: null,
        visible: false,
        currOpts: null
      },
      // 存放数据校验相关信息
      validStore: {
        visible: false,
        row: null,
        column: null,
        content: '',
        rule: null,
        isArrow: false
      },
      // 导入相关信息
      importStore: {
        inited: false,
        file: null,
        type: '',
        modeList: [],
        typeList: [],
        filename: '',
        visible: false
      },
      importParams: {
        mode: '',
        types: null,
        message: true
      },
      // 导出相关信息
      exportStore: {
        inited: false,
        name: '',
        modeList: [],
        typeList: [],
        columns: [],
        isPrint: false,
        hasFooter: false,
        hasTree: false,
        hasMerge: false,
        hasColgroup: false,
        visible: false
      },
      exportParams: {
        filename: '',
        sheetName: '',
        mode: '',
        type: '',
        isColgroup: false,
        isMerge: false,
        isAllExpand: false,
        useStyle: false,
        original: false,
        message: true,
        isHeader: false,
        isFooter: false
      }
    };
  },
  computed: {
    validOpts() {
      return Object.assign(
        { message: 'default' },
        GlobalConfig.table.validConfig,
        this.validConfig
      );
    },
    sXOpts() {
      return Object.assign({}, GlobalConfig.table.scrollX, this.scrollX);
    },
    sYOpts() {
      return Object.assign({}, GlobalConfig.table.scrollY, this.scrollY);
    },
    rowHeightMaps() {
      return {
        default: 48,
        medium: 44,
        small: 40,
        mini: 36
      };
    },
    columnOpts() {
      return Object.assign(
        {},
        GlobalConfig.table.columnConfig,
        this.columnConfig
      );
    },
    rowOpts() {
      return Object.assign({}, GlobalConfig.table.rowConfig, this.rowConfig);
    },
    resizeOpts() {
      return Object.assign(
        {},
        GlobalConfig.table.resizeConfig,
        this.resizeConfig
      );
    },
    resizableOpts() {
      return Object.assign(
        {},
        GlobalConfig.table.resizableConfig,
        this.resizableConfig
      );
    },
    seqOpts() {
      return Object.assign(
        { startIndex: 0 },
        GlobalConfig.table.seqConfig,
        this.seqConfig
      );
    },
    radioOpts() {
      return Object.assign({}, GlobalConfig.table.radioConfig, this.radioConfig);
    },
    checkboxOpts() {
      return Object.assign(
        {},
        GlobalConfig.table.checkboxConfig,
        this.checkboxConfig
      );
    },
    tooltipOpts() {
      return Object.assign(
        {},
        GlobalConfig.tooltip,
        GlobalConfig.table.tooltipConfig,
        this.tooltipConfig
      );
    },
    tipConfig() {
      return { ...this.tooltipOpts, ...this.tooltipStore.currOpts };
    },
    validTipOpts() {
      return Object.assign({ isArrow: false }, this.tooltipOpts);
    },
    editOpts() {
      return Object.assign({}, GlobalConfig.table.editConfig, this.editConfig);
    },
    sortOpts() {
      return Object.assign(
        { orders: ['ascending', 'descending', null] },
        GlobalConfig.table.sortConfig,
        this.sortConfig
      );
    },
    filterOpts() {
      return Object.assign(
        {},
        GlobalConfig.table.filterConfig,
        this.filterConfig
      );
    },
    mouseOpts() {
      return Object.assign({}, GlobalConfig.table.mouseConfig, this.mouseConfig);
    },
    areaOpts() {
      return Object.assign({}, GlobalConfig.table.areaConfig, this.areaConfig);
    },
    keyboardOpts() {
      return Object.assign(
        {},
        GlobalConfig.table.keyboardConfig,
        this.keyboardConfig
      );
    },
    clipOpts() {
      return Object.assign({}, GlobalConfig.table.clipConfig, this.clipConfig);
    },
    fnrOpts() {
      return Object.assign({}, GlobalConfig.table.fnrConfig, this.fnrConfig);
    },
    hasTip() {
      return VTable._tooltip;
    },
    expandOpts() {
      return Object.assign(
        {},
        GlobalConfig.table.expandConfig,
        this.expandConfig
      );
    },
    treeOpts() {
      return Object.assign({}, GlobalConfig.table.treeConfig, this.treeConfig);
    },
    emptyOpts() {
      return Object.assign({}, GlobalConfig.table.emptyRender, this.emptyRender);
    },
    loadingOpts() {
      return Object.assign(
        {},
        GlobalConfig.table.loadingConfig,
        this.loadingConfig
      );
    },
    cellOffsetWidth() {
      return this.border
        ? Math.max(2, Math.ceil(this.scrollbarWidth / this.tableColumn.length))
        : 1;
    },
    customOpts() {
      return Object.assign(
        {},
        GlobalConfig.table.customConfig,
        this.customConfig
      );
    },
    fixedColumnSize() {
      const { tableFullColumn } = this;
      let fixedSize = 0;
      tableFullColumn.forEach((column) => {
        if (column.fixed) {
          fixedSize++;
        }
      });
      return fixedSize;
    },
    isMaxFixedColumn() {
      const { maxFixedSize } = this.columnOpts;
      if (maxFixedSize) {
        return this.fixedColumnSize >= maxFixedSize;
      }
      return false;
    },
    tableBorder() {
      const { border } = this;
      if (border === true) {
        return 'full';
      }
      if (border) {
        return border;
      }
      return 'default';
    },
    /**
     * 判断列全选的复选框是否禁用
     */
    isAllCheckboxDisabled() {
      const { tableFullData, tableData, treeConfig, checkboxOpts } = this;
      const { strict, checkMethod } = checkboxOpts;
      if (strict) {
        if (tableData.length || tableFullData.length) {
          if (checkMethod) {
            if (treeConfig) {
              // 暂时不支持树形结构
            }
            // 如果所有行都被禁用
            return tableFullData.every((row) => !checkMethod({ row }));
          }
          return false;
        }
        return true;
      }
      return false;
    }
  },
  watch: {
    data(value) {
      const { inited, initStatus } = this;
      this.loadTableData(value).then(() => {
        this.inited = true;
        this.initStatus = true;
        if (!initStatus) {
          this.handleLoadDefaults();
        }
        if (!inited) {
          this.handleInitDefaults();
        }
        // const checkboxColumn = this.tableFullColumn.find(column => column.type === 'selection')
        // if (checkboxColumn && this.tableFullData.length > 300 && !this.checkboxOpts.checkprop) {
        //   warnLog('tablePlus.error.checkProp', ['checkbox-config.checkprop'])
        // }
        if ((this.scrollXLoad || this.scrollYLoad) && this.expandColumn) {
          warnLog('tablePlus.error.scrollErrProp', ['column.type=expand']);
        }
        this.recalculate();
      });
    },
    staticColumns(value) {
      this.handleColumn(value);
    },
    tableColumn() {
      this.analyColumnWidth();
    },
    upDataFlag() {
      this.$nextTick().then(() => this.updateData());
    },
    reColumnFlag() {
      this.$nextTick().then(() => this.refreshColumn());
    },
    showHeader() {
      this.$nextTick(() => {
        this.recalculate(true).then(() => this.refreshScroll());
      });
    },
    showFooter() {
      this.$nextTick(() => {
        this.recalculate(true).then(() => this.refreshScroll());
      });
    },
    height() {
      this.$nextTick(() => this.recalculate(true));
    },
    maxHeight() {
      this.$nextTick(() => this.recalculate(true));
    },
    syncResize(value) {
      if (value) {
        handleUupdateResize(this);
        this.$nextTick(() => {
          handleUupdateResize(this);
          setTimeout(() => handleUupdateResize(this));
        });
      }
    },
    mergeCells(value) {
      this.clearMergeCells();
      this.$nextTick(() => this.setMergeCells(value));
    },
    mergeFooterItems(value) {
      this.clearMergeFooterItems();
      this.$nextTick(() => this.setMergeFooterItems(value));
    }
  },
  created() {
    const {
      scrollXStore,
      sYOpts,
      scrollYStore,
      data,
      editOpts,
      treeOpts,
      treeConfig,
      showOverflow,
      rowOpts
    } = Object.assign(this, {
      tZindex: 0,
      elemStore: {},
      // 存放横向 X 虚拟滚动相关的信息
      scrollXStore: {},
      // 存放纵向 Y 虚拟滚动相关信息
      scrollYStore: {},
      // 表格宽度
      tableWidth: 0,
      // 表格高度
      tableHeight: 0,
      // 表头高度
      headerHeight: 0,
      // 表尾高度
      footerHeight: 0,
      // 当前 hover 行
      // hoverRow: null,
      // 最后滚动位置
      lastScrollLeft: 0,
      lastScrollTop: 0,
      // 单选框属性，已选中保留的行
      radioReserveRow: null,
      // 复选框属性，已选中保留的行
      checkboxReserveRowMap: {},
      // 行数据，已展开保留的行
      rowExpandedReserveRowMap: {},
      // 树结构数据，已展开保留的行
      treeExpandedReserveRowMap: {},
      // 完整数据、条件处理后
      tableFullData: [],
      afterFullData: [],
      // 列表条件处理后数据集合
      afterFullRowMaps: {},
      // 收集的列配置（带分组）
      collectColumn: [],
      // 完整所有列（不带分组）
      tableFullColumn: [],
      // 渲染所有列
      visibleColumn: [],
      // 缓存数据集
      fullAllDataRowMap: new window.Map(),
      fullAllDataRowIdData: {},
      fullDataRowMap: new window.Map(),
      fullDataRowIdData: {},
      fullColumnMap: new window.Map(),
      fullColumnIdData: {},
      fullColumnpropData: {}
    });

    if (process.env.NODE_ENV === 'development') {
      // if (this.rowId) {
      //   warnLog('tablePlus.error.delProp', ['row-id', 'row-config.keyprop'])
      // }
      // if (this.rowKey) {
      //   warnLog('tablePlus.error.delProp', ['row-id', 'row-config.useKey'])
      // }
      // if (this.columnKey) {
      //   warnLog('tablePlus.error.delProp', ['row-id', 'column-config.useKey'])
      // }
      if (
        !(this.rowId || rowOpts.keyprop) &&
        (this.checkboxOpts.reserve ||
          this.checkboxOpts.checkRowKeys ||
          this.radioOpts.reserve ||
          this.radioOpts.checkRowKey ||
          this.expandOpts.expandRowKeys ||
          this.treeOpts.expandRowKeys)
      ) {
        warnLog('tablePlus.error.reqProp', ['row-config.keyprop']);
      }
      if (this.editConfig && editOpts.showStatus && !this.keepSource) {
        warnLog('tablePlus.error.reqProp', ['keep-source']);
      }
      if (
        treeConfig &&
        (treeOpts.showLine || treeOpts.line) &&
        (!(this.rowKey || rowOpts.useKey) || !showOverflow)
      ) {
        warnLog('tablePlus.error.reqProp', [
          'row-config.useKey | show-overflow'
        ]);
      }
      if (this.showFooter && !this.footerMethod) {
        warnLog('tablePlus.error.reqProp', ['footer-method']);
      }
      if (treeConfig && this.stripe) {
        warnLog('tablePlus.error.noTree', ['stripe']);
      }
      if (this.tooltipOpts.enabled) {
        warnLog('tablePlus.error.delProp', [
          'tooltip-config.enabled',
          'tooltip-config.showAll'
        ]);
      }
      // if (this.highlightCurrentRow) {
      //   warnLog('tablePlus.error.delProp', ['highlight-current-row', 'row-config.isCurrent'])
      // }
      // if (this.highlightHoverRow) {
      //   warnLog('tablePlus.error.delProp', ['highlight-hover-row', 'row-config.isHover'])
      // }
      // if (this.highlightCurrentColumn) {
      //   warnLog('tablePlus.error.delProp', ['highlight-current-column', 'column-config.isCurrent'])
      // }
      // if (this.highlightHoverColumn) {
      //   warnLog('tablePlus.error.delProp', ['highlight-hover-column', 'column-config.isHover'])
      // }
      // 检查导入导出类型，如果自定义导入导出方法，则不校验类型
      const { exportConfig, exportOpts, importConfig, importOpts } = this;
      if (
        importConfig &&
        importOpts.types &&
        !importOpts.importMethod &&
        !XEUtils.includeArrays(VTable.globalConfs.importTypes, importOpts.types)
      ) {
        warnLog('tablePlus.error.errProp', [
          `export-config.types=${importOpts.types.join(',')}`,
          importOpts.types
            .filter((type) =>
              XEUtils.includes(VTable.globalConfs.importTypes, type)
            )
            .join(',') || VTable.globalConfs.importTypes.join(',')
        ]);
      }
      if (
        exportConfig &&
        exportOpts.types &&
        !exportOpts.exportMethod &&
        !XEUtils.includeArrays(VTable.globalConfs.exportTypes, exportOpts.types)
      ) {
        warnLog('tablePlus.error.errProp', [
          `export-config.types=${exportOpts.types.join(',')}`,
          exportOpts.types
            .filter((type) =>
              XEUtils.includes(VTable.globalConfs.exportTypes, type)
            )
            .join(',') || VTable.globalConfs.exportTypes.join(',')
        ]);
      }
    }

    if (process.env.NODE_ENV === 'development') {
      const customOpts = this.customOpts;
      if (
        !this.id &&
        this.customConfig &&
        (customOpts.storage === true ||
          (customOpts.storage && customOpts.storage.resizable) ||
          (customOpts.storage && customOpts.storage.visible))
      ) {
        errLog('tablePlus.error.reqProp', ['id']);
      }
      if (this.treeConfig && this.checkboxOpts.range) {
        errLog('tablePlus.error.noTree', ['checkbox-config.range']);
      }
      if (this.rowOpts.height && !this.showOverflow) {
        warnLog('tablePlus.error.notProp', ['table.show-overflow']);
      }
      if (!this.handleUpdateCellAreas) {
        if (this.clipConfig) {
          warnLog('tablePlus.error.notProp', ['clip-config']);
        }
        if (this.fnrConfig) {
          warnLog('tablePlus.error.notProp', ['fnr-config']);
        }
        if (this.mouseOpts.area) {
          errLog('tablePlus.error.notProp', ['mouse-config.area']);
          return;
        }
      }
      if (this.treeConfig && treeOpts.children) {
        warnLog('tablePlus.error.delProp', [
          'tree-config.children',
          'tree-config.childrenprop'
        ]);
      }
      if (this.treeConfig && treeOpts.line) {
        warnLog('tablePlus.error.delProp', [
          'tree-config.line',
          'tree-config.showLine'
        ]);
      }
      if (this.mouseOpts.area && this.mouseOpts.selected) {
        warnLog('tablePlus.error.errConflicts', [
          'mouse-config.area',
          'mouse-config.selected'
        ]);
      }
      if (this.mouseOpts.area && this.checkboxOpts.range) {
        warnLog('tablePlus.error.errConflicts', [
          'mouse-config.area',
          'checkbox-config.range'
        ]);
      }
      if (this.treeConfig && this.mouseOpts.area) {
        errLog('tablePlus.error.noTree', ['mouse-config.area']);
      }
    }

    // v4 中只支持对象类型
    if (process.env.NODE_ENV === 'development') {
      if (this.menuConfig && !XEUtils.isObject(this.menuConfig)) {
        warnLog('tablePlus.error.errProp', [
          `table.menu-config=${this.menuConfig}`,
          'table.menu-config={}'
        ]);
      }
      if (this.exportConfig && !XEUtils.isObject(this.exportConfig)) {
        warnLog('tablePlus.error.errProp', [
          `table.export-config=${this.exportConfig}`,
          'table.export-config={}'
        ]);
      }
      if (this.importConfig && !XEUtils.isObject(this.importConfig)) {
        warnLog('tablePlus.error.errProp', [
          `table.import-config=${this.importConfig}`,
          'table.import-config={}'
        ]);
      }
      if (this.printConfig && !XEUtils.isObject(this.printConfig)) {
        warnLog('tablePlus.error.errProp', [
          `table.print-config=${this.printConfig}`,
          'table.print-config={}'
        ]);
      }
      if (this.treeConfig && !XEUtils.isObject(this.treeConfig)) {
        warnLog('tablePlus.error.errProp', [
          `table.tree-config=${this.treeConfig}`,
          'table.tree-config={}'
        ]);
      }
      if (this.customConfig && !XEUtils.isObject(this.customConfig)) {
        warnLog('tablePlus.error.errProp', [
          `table.custom-config=${this.customConfig}`,
          'table.custom-config={}'
        ]);
      }
      if (this.editConfig && !XEUtils.isObject(this.editConfig)) {
        warnLog('tablePlus.error.errProp', [
          `table.edit-config=${this.editConfig}`,
          'table.edit-config={}'
        ]);
      }
      if (this.emptyRender && !XEUtils.isObject(this.emptyRender)) {
        warnLog('tablePlus.error.errProp', [
          `table.empty-render=${this.emptyRender}`,
          'table.empty-render={}'
        ]);
      }
      if (this.editConfig && this.editOpts.activeMethod) {
        warnLog('tablePlus.error.delProp', [
          'table.edit-config.activeMethod',
          'table.edit-config.beforeEditMethod'
        ]);
      }
      if (this.treeConfig && this.checkboxOpts.isShiftKey) {
        errLog('tablePlus.error.errConflicts', [
          'tree-config',
          'checkbox-config.isShiftKey'
        ]);
      }
      if (this.checkboxOpts.halfprop) {
        warnLog('tablePlus.error.delProp', [
          'checkbox-config.halfprop',
          'checkbox-config.indeterminateprop'
        ]);
      }
    }

    // 检查是否有安装需要的模块
    if (process.env.NODE_ENV === 'development') {
      if (this.editConfig && !this._insert) {
        errLog('tablePlus.error.reqModule', ['Edit']);
      }
      if (this.editRules && !this._validate) {
        errLog('tablePlus.error.reqModule', ['Validator']);
      }
      if (
        (this.checkboxOpts.range || this.keyboardConfig || this.mouseConfig) &&
        !this.triggerCellMousedownEvent
      ) {
        errLog('tablePlus.error.reqModule', ['Keyboard']);
      }
      if (
        (this.printConfig || this.importConfig || this.exportConfig) &&
        !this._exportData
      ) {
        errLog('tablePlus.error.reqModule', ['Export']);
      }
    }

    Object.assign(scrollYStore, {
      startIndex: 0,
      endIndex: 1,
      visibleSize: 0,
      adaptive: sYOpts.adaptive !== false
    });
    Object.assign(scrollXStore, {
      startIndex: 0,
      endIndex: 1,
      visibleSize: 0
    });
    this.loadTableData(data).then(() => {
      if (data && data.length) {
        this.inited = true;
        this.initStatus = true;
        this.handleLoadDefaults();
        this.handleInitDefaults();
      }
      this.updateStyle();
    });
    GlobalEvent.on(this, 'paste', this.handleGlobalPasteEvent);
    GlobalEvent.on(this, 'copy', this.handleGlobalCopyEvent);
    GlobalEvent.on(this, 'cut', this.handleGlobalCutEvent);
    GlobalEvent.on(this, 'mousedown', this.handleGlobalMousedownEvent);
    GlobalEvent.on(this, 'blur', this.handleGlobalBlurEvent);
    GlobalEvent.on(this, 'mousewheel', this.handleGlobalMousewheelEvent);
    GlobalEvent.on(this, 'keydown', this.handleGlobalKeydownEvent);
    GlobalEvent.on(this, 'resize', this.handleGlobalResizeEvent);
    this.preventEvent(null, 'created');
  },
  mounted() {
    if (process.env.NODE_ENV === 'development') {
      const { $listeners } = this;
      if (
        !this.menuConfig &&
        ($listeners['menu-click'] ||
          $listeners['cell-menu'] ||
          $listeners['header-cell-menu'] ||
          $listeners['footer-cell-menu'])
      ) {
        warnLog('tablePlus.error.reqProp', ['menu-config']);
      }
      if (
        !this.tooltipConfig &&
        ($listeners['cell-mouseenter'] || $listeners['cell-mouseleave'])
      ) {
        warnLog('tablePlus.error.reqProp', ['tooltip-config']);
      }
    }
    if (this.autoResize) {
      const handleWarpperResize = this.resizeOpts.refreshDelay
        ? XEUtils.throttle(
          () => this.recalculate(true),
          this.resizeOpts.refreshDelay,
          { leading: true, trailing: true }
        )
        : null;
      const resizeObserver = createResizeEvent(
        handleWarpperResize
          ? () => {
            if (this.autoResize) {
              requestAnimationFrame(handleWarpperResize);
            }
          }
          : () => {
            if (this.autoResize) {
              this.recalculate(true);
            }
          }
      );
      resizeObserver.observe(this.$el);
      resizeObserver.observe(this.getParentElem());
      this.$resize = resizeObserver;
    }
    this.preventEvent(null, 'mounted');
  },
  activated() {
    this.recalculate().then(() => this.refreshScroll());
    this.preventEvent(null, 'activated');
  },
  deactivated() {
    this.preventEvent(null, 'deactivated');
  },
  beforeDestroy() {
    if (this.$resize) {
      this.$resize.disconnect();
    }
    this.closeFilter();
    this.closeMenu();
    this.preventEvent(null, 'beforeDestroy');
  },
  destroyed() {
    GlobalEvent.off(this, 'paste');
    GlobalEvent.off(this, 'copy');
    GlobalEvent.off(this, 'cut');
    GlobalEvent.off(this, 'mousedown');
    GlobalEvent.off(this, 'blur');
    GlobalEvent.off(this, 'mousewheel');
    GlobalEvent.off(this, 'keydown');
    GlobalEvent.off(this, 'resize');
    this.preventEvent(null, 'destroyed');
  },
  render(h) {
    const {
      _e,
      // $scopedSlots,
      tId,
      tableData,
      tableColumn,
      tableGroupColumn,
      isGroup,
      loading,
      stripe,
      showHeader,
      height,
      tableBorder,
      treeOpts,
      treeConfig,
      mouseConfig,
      mouseOpts,
      vSize,
      validOpts,
      showFooter,
      overflowX,
      overflowY,
      scrollXLoad,
      scrollYLoad,
      scrollbarHeight,
      highlightCell,
      highlightHoverRow,
      highlightHoverColumn,
      editConfig,
      validTipOpts,
      initStore,
      columnStore,
      filterStore,
      footerTableData,
      hasTip,
      columnOpts,
      rowOpts,
      // loadingOpts,
      editRules
    } = this;
    const { leftList, rightList } = columnStore;
    return h(
      'div',
      {
        class: [
          'el-table',
          'el-table-plus',
          'el-table-plus--render-default',
          `tid_${tId}`,
          vSize ? `size--${vSize}` : '',
          `border--${tableBorder}`,
          {
            [`vaild-msg--${validOpts.msgMode}`]: !!editRules,
            'table-plus-editable': !!editConfig,
            'cell--highlight': highlightCell,
            'cell--selected': mouseConfig && mouseOpts.selected,
            'cell--area': mouseConfig && mouseOpts.area,
            'row--highlight': rowOpts.isHover || highlightHoverRow,
            'column--highlight': columnOpts.isHover || highlightHoverColumn,
            'is--header': showHeader,
            'is--footer': showFooter,
            'is--group': isGroup,
            'is--tree-line': treeConfig && (treeOpts.showLine || treeOpts.line),
            'is--fixed-left': leftList.length,
            'is--fixed-right': rightList.length,
            'is--animat': !!this.animat,
            'is--round': this.round,
            'is--stripe': !treeConfig && stripe,
            'is--loading': loading,
            'is--empty': !loading && !tableData.length,
            'is--scroll-y': overflowY,
            'is--scroll-x': overflowX,
            'is--virtual-x': scrollXLoad,
            'is--virtual-y': scrollYLoad
          }
        ],
        on: {
          keydown: this.keydownEvent
        }
      },
      [
        /**
         * 隐藏列
         */
        h(
          'div',
          {
            class: 'el-table-plus-slots',
            ref: 'hideColumn'
          },
          this.$slots.default
        ),
        h(
          'div',
          {
            class: 'el-table-plus--render-wrapper'
          },
          [
            h(
              'div',
              {
                class: 'el-table-plus--main-wrapper'
              },
              [
                /**
                 * 表头
                 */
                showHeader
                  ? h(ElTablePlusHeader, {
                    ref: 'tableHeader',
                    props: {
                      tableData,
                      tableColumn,
                      tableGroupColumn,
                      size: vSize
                    }
                  })
                  : _e(),
                /**
                 * 表体
                 */
                h('el-table-plus-body', {
                  ref: 'tableBody',
                  props: {
                    tableData,
                    tableColumn,
                    size: vSize
                  }
                }),
                /**
                 * 表尾
                 */
                showFooter
                  ? h('el-table-plus-footer', {
                    ref: 'tableFooter',
                    props: {
                      footerTableData,
                      tableColumn,
                      size: vSize
                    }
                  })
                  : _e()
              ]
            ),
            h(
              'div',
              {
                class: 'el-table-plus--fixed-wrapper'
              },
              [
                /**
                 * 左侧固定区域
                 */
                leftList && leftList.length && overflowX
                  ? renderFixed(h, this, 'left')
                  : _e(),
                /**
                 * 右侧固定区域
                 */
                rightList && rightList.length && overflowX
                  ? renderFixed(h, this, 'right')
                  : _e()
              ]
            )
          ]
        ),
        /**
         * 空数据
         */
        h(
          'div',
          {
            ref: 'emptyPlaceholder',
            class: 'el-table-plus--empty-placeholder'
          },
          [
            h(
              'div',
              {
                class: 'el-table-plus--empty-content'
              },
              renderEmptyContenet(h, this)
            )
          ]
        ),
        /**
         * 边框线
         */
        h('div', {
          class: 'el-table-plus--border-line'
        }),
        /**
         * 列宽线
         */
        h('div', {
          class: 'el-table-plus--resizable-bar',
          style: overflowX
            ? {
              'padding-bottom': `${scrollbarHeight}px`
            }
            : null,
          ref: 'resizeBar'
        }),
        initStore.filter
          ? h('el-table-plus-filter', {
            ref: 'filterWrapper',
            props: {
              filterStore
            }
          })
          : _e(),
        /**
         * 通用提示
         */
        hasTip
          ? h(ElTableTooltip, {
            ref: 'commTip',
            props: {
              isArrow: false,
              enterable: false
            }
          })
          : _e(),
        /**
         * 工具提示
         */
        hasTip
          ? h(ElTableTooltip, {
            ref: 'tooltip',
            props: this.tipConfig
          })
          : _e(),
        /**
         * 校验提示
         */
        hasTip &&
        this.editRules &&
        validOpts.showMessage &&
        (validOpts.message === 'default'
          ? !height
          : validOpts.message === 'tooltip')
          ? h(ElTableTooltip, {
            ref: 'validTip',
            class: 'el-table-plus--valid-error',
            props:
                validOpts.message === 'tooltip' || tableData.length === 1
                  ? validTipOpts
                  : null
          })
          : _e()
      ]
    );
  },
  methods
};
