<template>
  <component
    v-show="showTable"
    class="es-data-table"
    label-width="0"
    ref="component"
    v-loading="tableLoading"
    element-loading-background="rgba(0, 0, 0, 0.65)"
    :is="tag"
    :model="tag === 'div' ? '' : list"
    :element-loading-text="tableLoadingText"
  >
    <es-toolbar
      v-if="showToolbar"
      ref="toolbar"
      :class="{
        'es-table-toolbar-plus': mode == 'plus'
      }"
      v-bind="{
        contents: toolbars,
        showLabel: showLabel,
        close: close,
        callBack: resetHeight,
        showFormBtn: showFormBtn,
        searchValue: searchValue,
        advanceValue: advanceValue
      }"
      v-on="{
        click: handleClick,
        search: hanleSearch,
        submit: hanleSubmit,
        tabs: handleTabs,
        reset: hanleReset,
        cancel: hanleCancel,
        toolbarChange: toolbarChange,
        ...toolbarEvents
      }"
    ></es-toolbar>
    <p v-if="title" ref="title" class="es-table-title" v-html="title"></p>
    <div
      v-if="show"
      :style="styles"
      class="es-data-table-content"
      :class="{
        'es-table-border-none': border == 'none',
        'es-table-plus': mode == 'plus'
      }"
      ref="esTableContent"
    >
      <el-table
        ref="oaTable"
        v-bind="{
          ...$attrs,
          emptyText: emptyText,
          showSummary: showTotal,
          sumText: sumText || totalText,
          totalRow: restotalRow || totalRow,
          height:
            tableHeight !== 'auto' && tableHeight !== false
              ? tableHeight
              : undefined,
          border: _border,
          infiniteScroll: getTableData,
          infiniteScrollDisabled: infiniteDisabled,
          dragSort: dragSort,
          dragSortClass: dragSortIcon
        }"
        :data.sync="list"
        v-on="{
          ...$listeners,
          'row-click': rowClick,
          'selection-change': selectionChange,
          'filter-column': handleFilterColumn,
          'sort-change': handleSortChange,
          'update-drag-sort': handleUpdateDragSort
        }"
        :class="
          'es-table' +
          (theadBorder && border != 'none' ? ' es-thead-border' : '')
        "
      >
        <slot name="suffix"></slot>
        <slot></slot>
        <template v-for="(item, index) in theads">
          <template v-if="item.hide !== true">
            <el-table-column
              v-if="item.type === 'sort'"
              width="32"
              prop="id"
              :key="item.key || item.label || item.title || index"
              label=" "
            >
              <template slot-scope="scope">
                <es-icon
                  v-if="!scope.row.fixed"
                  class="es-move"
                  :contents="dragSortIcon"
                ></es-icon>
              </template>
            </el-table-column>
            <template
              v-else-if="item.type === 'index' || item.type === 'selection'"
            >
              <el-table-column
                :key="item.key || item.label || item.title || index"
                v-bind="dragSort ? { ...item, fixed: false } : item"
              ></el-table-column>
            </template>
            <template v-else>
              <children
                :key="item.key || item.label || item.title || index"
                :tag="item.tag"
                v-bind="{
                  mode: mode,
                  name: name,
                  indexs: index,
                  form: form,
                  readonly: readonly,
                  optionData: optionDatas,
                  dragSort: dragSort,
                  ...(dragSort ? { ...item, fixed: false } : { ...item })
                }"
                v-on="{
                  handleClick: handleClick,
                  formBlur: formBlur,
                  formFocus: formFocus,
                  formChange: formChange
                }"
              ></children>
            </template>
          </template>
        </template>
        <slot name="prefix"></slot>
        <el-table-column
          v-if="editable && !readonly"
          width="80"
          type="handle"
          align="center"
          label="操作"
          fixed="right"
          class="eoss-ui-eidt-column"
          :button="headButton"
          :total="false"
        >
          <template slot-scope="scope">
            <el-button
              v-if="!scope.row.cantAdd"
              type="text"
              @click="handleClickAddData(scope)"
            >
              <i class="el-icon-circle-plus-outline"></i>
            </el-button>
            <el-button
              v-if="!scope.row.cantDelete && !isLeast"
              type="text"
              @click="handleClickDeleteData(scope)"
            >
              <i class="el-icon-remove-outline"></i>
            </el-button>
          </template>
        </el-table-column>
        <template slot="append"><slot name="append"></slot></template>
      </el-table>
      <div v-if="infiniteScroll" class="es-table-page es-loading-page">
        <span>共{{ config.totalCount }}条，</span>
        <span>已加载{{ list.length }}条</span>
      </div>
      <es-pagination
        v-else-if="page !== false && showPage !== false"
        ref="pagination"
        v-bind="config"
        class="es-table-page"
        :position="page.position"
        :style="{ 'text-align': page.position }"
        v-on="{
          change: sizeChange,
          current: currentChange,
          prev: preClick,
          next: nextClick
        }"
      ></es-pagination>
      <slot name="dialog"></slot>
      <slot name="other"></slot>
    </div>
    <es-dialog v-if="theads.length" title="列表设置" :visible.sync="showSizer">
      <sizer
        v-if="showSizer"
        :data="theads"
        :mode="mode"
        @confirm="mergeThead"
      ></sizer>
    </es-dialog>
    <i
      class="el-icon-setting es-table-setting"
      title="页面配置"
      v-if="isShow"
      @click="openEditPage"
    ></i>

    <es-dialog title="页面配置" :visible.sync="showEditPage" size="full">
      <iframe
        v-if="showEditPage"
        width="100%"
        height="100%"
        frameborder="0"
        :src="editPage"
      ></iframe>
    </es-dialog>
  </component>
</template>
<script>
import {
  findSysCode,
  getDictList,
  formContents
} from 'eoss-ui/src/config/api.js';
import { debounce, throttle } from 'throttle-debounce';
import children from './children.vue';
import sizer from './sizer.vue';
import util from 'eoss-ui/src/utils/util';
import qs from 'qs';
const systemMode = util.getWinTopProperty('systemMode', 'default');
const pageView = util.getParams('pageView');
export default {
  name: 'EsDataTable',
  inheritAttrs: false,
  components: {
    children,
    sizer
  },
  provide() {
    return {
      table: this,
      tableReload: this.reload
    };
  },
  inject: {
    elForm: {
      default: ''
    },
    injector: {
      default: ''
    },
    scale: {
      default: ''
    }
  },
  props: {
    viewCode: {
      type: String,
      default: pageView
    },
    contentsUrl: {
      type: String,
      default: formContents
    },
    mode: {
      type: String,
      default: systemMode
    },
    service: String,
    loading: {
      type: Boolean,
      default: false
    },
    readonly: Boolean,
    allowToolbar: Boolean,
    url: {
      type: String,
      default: ''
    },
    defaults: {
      type: Boolean,
      default: false
    },
    param: {
      type: Object,
      default() {
        return {};
      }
    },
    method: {
      type: String,
      default: 'get'
    },
    isEncodeURI: Boolean,
    format: {
      type: Boolean,
      default: true
    },
    data: {
      type: Array,
      default() {
        return [];
      }
    },
    // 表格表单
    form: {
      type: Boolean,
      default: false
    },
    name: String,
    title: {
      type: String,
      default: ''
    },
    // 导出文件名
    fileName: {
      type: String,
      default: ''
    },
    // 工具栏配置
    toolbar: {
      type: [Array, Object, Boolean],
      default: false
    },
    showLabel: Boolean,
    searchValue: Object,
    advanceValue: Object,
    executeSearch: {
      type: Boolean,
      default: true
    },
    executeFilter: {
      type: Boolean,
      default: true
    },
    // 是否开启序号
    numbers: {
      type: Boolean,
      default: false
    },
    orders: {
      type: String,
      default: 'asc'
    },
    // 是否筛选列功能
    filter: {
      type: Boolean,
      default: false
    },
    // 是否开启多选
    checkbox: {
      type: Boolean,
      default: false
    },
    selectable: Function,
    reserveSelection: Boolean,
    // 默认选中,类型为Boolean时默认全(不)选
    checked: {
      type: [Boolean, Array],
      default: false
    },
    checkedKey: {
      type: String,
      default: 'id'
    },
    // 无数据时显示的文本
    emptyText: {
      type: String,
      default: '暂无数据'
    },
    // 是否开启合计行区域
    total: {
      type: Boolean,
      default: false
    },
    //本地数据总条数差值
    lose: {
      type: Number,
      default: 0
    },
    // 合计行显示文本
    totalText: {
      type: String,
      default: ''
    },
    showSummary: {
      type: Boolean,
      default: false
    },
    sumText: {
      type: String,
      default: ''
    },
    // 开启分页
    page: {
      type: [Boolean, Object],
      default() {
        return false;
      }
    },
    showPage: {
      type: Boolean,
      default: true
    },
    // 渲染树形数据指定field
    treeKey: {
      type: String,
      default: ''
    },
    // 单元格配置
    thead: {
      type: Array,
      default() {
        return [];
      }
    },
    optionData: Object,
    // 开启数据增加删除按钮
    editable: {
      type: Boolean,
      default: false
    },
    theadAdd: {
      type: Boolean,
      default: true
    },
    // 单元格点击事件
    click: {
      type: Boolean,
      default: false
    },
    totalRow: {
      type: Object,
      default() {
        return {};
      }
    },
    parseData: Function,
    close: Boolean,
    full: {
      type: Boolean,
      default: true
    },
    height: [Number, String],
    maxHeight: [Number, String],
    response: Function,
    minWidth: [Number, String],
    border: {
      type: [Boolean, String],
      default: false,
      validator: function (value) {
        return [true, false, 'none'].includes(value);
      }
    },
    theadBorder: {
      type: Boolean,
      default: true
    },
    checkboxParseData: Function,
    checkboxParse: Object,
    display: {
      type: Boolean,
      default: true
    },
    showFormBtn: {
      type: Boolean,
      default: true
    },
    index: {
      type: [Number, Function],
      default: 1
    },
    accumulated: {
      type: Boolean,
      default: true
    },
    immediate: {
      type: Boolean,
      default: true
    },
    zoom: false,
    exportExcludeLabel: {
      type: Array,
      default() {
        return [];
      }
    },
    rowData: [Object, Boolean],
    least: Boolean,
    //保留搜索参数
    retainSearh: Boolean,
    //无线滚动
    infiniteScroll: Boolean,
    isJoin: {
      type: Boolean,
      default: true
    },
    ajaxConfig: {
      type: Object,
      default() {
        return {};
      }
    },
    dragSort: Boolean,
    dragSortIcon: {
      type: String,
      default: 'es-icon-lanmu'
    },
    isFieldsEncryption: Boolean,
    contentSuccess: Function,
    resetScroll: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      isEncryption: this.isFieldsEncryption,
      requests: [],
      toolbars: [],
      toolbarEvents: {},
      hasThead: false,
      theadData: [],
      list: [],
      tableLoading: this.loading,
      tableLoadingText: '加载中...',
      isFirsetCheck: false,
      // 可修改表单的值
      editValue: {},
      restotalRow: null,
      showTotal: false,
      config: {
        pageNum: 1,
        pageSize: 20,
        totalCount: 0,
        layout:
          this.mode == 'plus'
            ? 'total, sizes, prev, pager, next, jumper'
            : undefined
      },
      searchWhere: {},
      advanceWhere: {},
      tableHeight: 'auto',
      styles: {},
      selected: null,
      options: {},
      icon: true,
      sysCodes: [],
      infiniteDisabled: !this.infiniteScroll,
      isReload: false,
      pageView: null,
      showSizer: false,
      show: true,
      isSetHeight: false,
      showTable: false,
      fields: null,
      showEditPage: false,
      editPage: ''
    };
  },
  computed: {
    wheres() {
      return { ...this.searchWhere, ...this.advanceWhere };
    },
    params() {
      return {
        ...(this.param || {}),
        ...(this.searchValue || {}),
        ...(this.advanceValue || {})
      };
    },
    tag() {
      return this.form && this.elForm == '' ? 'el-form' : 'div';
    },
    _border() {
      return this.border === true ? true : false;
    },
    theads: {
      get() {
        let types;
        types = this.theadData
          .filter((item) => {
            return (
              item.type == 'selection' ||
              item.type == 'index' ||
              item.type == 'sort' ||
              item.type == 'handle'
            );
          })
          .map((item) => {
            return item.type;
          });
        let thead = [];
        let addfilter = false;
        if (this.dragSort && !types.includes('sort')) {
          addfilter = true;
          thead.push({
            type: 'sort',
            key: 'es-sort'
          });
        }
        if (this.checkbox && !types.includes('selection')) {
          thead.push({
            type: 'selection',
            width: '55',
            align: 'center',
            fixed: 'left',
            selectable: this.selectable,
            reserveSelection: this.reserveSelection,
            filterIcon:
              this.filter && !addfilter ? 'es-icon-yingyong' : undefined,
            key: 'es-checkbox'
          });
          if (!addfilter) {
            addfilter = true;
          }
        }
        if (this.numbers && !types.includes('index')) {
          let index = 1;
          if (typeof this.index === 'function') {
            index = this.index;
          } else {
            if (this.orders == 'desc') {
              index = (num) => {
                return this.config.totalCount - num;
              };
            } else if (this.accumulated) {
              index =
                (this.config.pageNum - 1) * this.config.pageSize + this.index;
            } else {
              index = this.index;
            }
          }
          thead.push({
            type: 'index',
            label: '序号',
            width: '70',
            align: 'center',
            fixed: 'left',
            index: index,
            filterIcon:
              this.filter && !addfilter ? 'es-icon-yingyong' : undefined,
            key: 'es-index'
          });
          if (!addfilter) {
            addfilter = true;
          }
        }
        if (this.theadData.length) {
          let handle = this.thead.filter((item) => {
            return item.type == 'handle';
          });
          thead = [
            ...thead,
            ...this.theadData,
            ...(types.includes('handle') ? [] : handle)
          ];
        } else if (this.show) {
          thead = [...thead, ...this.thead];
        }
        return thead;
      },
      set(val) {
        return val;
      }
    },
    datas: {
      get() {
        if (this.list && this.list.length) {
          return this.list;
        }
        if (
          this.page &&
          ((typeof this.page === 'object' &&
            (!Object.prototype.hasOwnProperty.call(this.page, 'totalCount') ||
              this.page.totalCount == 0)) ||
            this.page === true)
        ) {
          this.config.totalCount = this.data.length - this.lose;
        }
        if (this.page && this.data.length > this.config.pageSize) {
          return this.data.filter((item, index) => {
            return (
              index > (this.config.pageNum - 1) * this.config.pageSize - 1 &&
              index < this.config.pageNum * this.config.pageSize
            );
          });
        }
        return this.data;
      },
      set(val) {
        if (this.list && this.list.length) {
          this.$nextTick(() => {
            this.list = val;
          });
        }
        this.$emit('update:data', val);
        return val;
      }
    },
    showToolbar() {
      if (this.readonly) {
        if (this.allowToolbar) {
          if (typeof this.toolbar === 'boolean') {
            if (this.toolbar) {
              this.toolbars = [
                {
                  type: 'search',
                  contents: [
                    {
                      type: 'text',
                      name: 'keyword',
                      placeholder: '请输入关键字'
                    }
                  ]
                }
              ];
            }
            return this.toolbar;
          } else if (Array.isArray(this.toolbar)) {
            this.toolbars = this.toolbar;
            return true;
          } else {
            this.toolbars = this.toolbar.contents;
            this.toolbarEvents = this.toolbar.events || {};
            return true;
          }
        } else {
          return false;
        }
      } else {
        if (typeof this.toolbar === 'boolean') {
          if (this.toolbar) {
            this.toolbars = [
              {
                type: 'search',
                contents: [
                  {
                    type: 'text',
                    name: 'keyword',
                    placeholder: '请输入关键字'
                  }
                ]
              }
            ];
          }
          return this.toolbar;
        } else if (Array.isArray(this.toolbar)) {
          this.toolbars = this.toolbar;
          return true;
        } else {
          this.toolbars = this.toolbar.contents;
          this.toolbarEvents = this.toolbar.events || {};
          return true;
        }
      }
    },
    optionDatas: {
      get() {
        let data = this.optionData
          ? { ...this.optionData, ...this.options }
          : this.options;
        return data;
      },
      set(val) {
        return val;
      }
    },
    headButton() {
      return this.theadAdd && !this.readonly
        ? {
            icon: 'el-icon-circle-plus-outline',
            type: 'text',
            event: this.handleClickAddData
          }
        : undefined;
    },
    isLeast() {
      return this.data.length < 2 && this.least;
    },
    findCode() {
      if (this.service) {
        return `/${this.service}${getDictList}`;
      }
      return findSysCode;
    },
    isShow() {
      let useCaseCodes = util.getStorage('useCaseCodes');
      return (
        this.viewCode &&
        useCaseCodes &&
        (useCaseCodes.indexOf('SuperAdminRoleID') > -1 ||
          useCaseCodes.indexOf('OrgAdminRoleID') > -1)
      );
    }
  },
  watch: {
    viewCode: {
      immediate: true,
      handler(val) {
        if (val) {
          this.hasThead = true;
          this.getContents();
        }
      }
    },
    showToolbar() {
      this.resetHeight();
      this.doLayout();
    },
    data: {
      deep: true,
      handler() {
        this.list = this.setData();
      }
    },
    scale: {
      deep: true,
      handler(val) {
        if (
          this.tableHeight != 'auto' &&
          this.tableHeight !== false &&
          this.display
        ) {
          this.resetHeight();
          this.doLayout();
        }
      }
    },
    zoom: {
      handler() {
        if (
          this.tableHeight != 'auto' &&
          this.tableHeight !== false &&
          this.display
        ) {
          this.resetHeight();
          this.doLayout();
        }
      }
    },
    checked(newVal) {
      this.list.length && this.checkSelect(newVal);
    },
    thead: {
      deep: true,
      handler(val, old) {
        if (!util.isObjectEqual(val, old)) {
          this.getOptions(val);
          this.chekOpenTotalArea();
          if (Array.isArray(val) && val.length && this.datas.length == 0) {
            this.getTableData();
          }
        }
      }
    },
    theads: {
      deep: true,
      handler() {
        this.chekOpenTotalArea();
      }
    },
    param: {
      handler(val, old) {
        if (!util.isObjectEqual(val, old)) {
          this.getTableData();
        }
      }
    },
    page: {
      immediate: true,
      deep: true,
      handler(val) {
        if (this.$el) {
          this.resetHeight();
          this.doLayout();
        }
        if (typeof val === 'object') {
          this.config = util.extend({}, this.config, val);
        }
      }
    },
    'config.pageNum'() {
      if (this.data.length) {
        this.resetScroll &&
          this.$refs.oaTable &&
          this.$refs.oaTable.resetScroll &&
          this.$refs.oaTable.resetScroll(0, 0);
        this.list = this.setData();
      }
    },
    height: {
      immediate: true,
      handler(val) {
        if (val) {
          this.tableHeight = val;
        }
      }
    },
    maxHeight: {
      immediate: true,
      handler(val) {
        if (val && this.height === undefined) {
          this.tableHeight = val;
        }
      }
    },
    display(val) {
      if (val) {
        this.resetHeight();
        this.doLayout();
      }
    },
    showEditPage(val) {
      if (val === false) {
        try {
          const topWin = util.getWinTop();
          topWin.refresh();
        } catch (error) {
          console.warn('Failed to refresh page:', error);
        }
      }
    }
  },
  beforeCreate() {
    this.getTableData = debounce(500, (res) => {
      this.getTableDatas(res);
    });
  },
  created() {
    if (Array.isArray(this.thead) && this.thead.length) {
      this.getOptions(this.thead);
      this.immediate && !this.viewCode && this.getTableData();
    }
    this.chekOpenTotalArea();
  },
  mounted() {
    this.showTable = true;
    if (this.data.length) {
      this.list = this.setData();
    }
    this.list.length && this.checkSelect(this.checked);
    this.resetHeight();
    if (util.getWinTop() != util.win.self) {
      util.win.onresize = throttle(500, this.resetHeight);
    }
  },
  methods: {
    setData() {
      if (
        this.page &&
        ((typeof this.page === 'object' &&
          (!Object.prototype.hasOwnProperty.call(this.page, 'totalCount') ||
            this.page.totalCount == 0)) ||
          this.page === true)
      ) {
        this.config.totalCount = this.data.length - this.lose;
      }
      if (this.page && this.data.length > this.config.pageSize) {
        return this.data.filter((item, index) => {
          return (
            index > (this.config.pageNum - 1) * this.config.pageSize - 1 &&
            index < this.config.pageNum * this.config.pageSize
          );
        });
      }
      return this.data;
    },
    getRequestKey(config) {
      const { method, url, params, data } = config;
      return [method, url, qs.stringify(params), qs.stringify(data)].join('&');
    },
    getContents() {
      util
        .ajax({
          url: this.contentsUrl,
          params: {
            formId: this.viewCode
          }
        })
        .then((res) => {
          if (res.rCode == 0) {
            if (this.contentSuccess) {
              this.contentSuccess(res.results);
            } else {
              let {
                results: { eossFormJson }
              } = res;
              eossFormJson = JSON.parse(eossFormJson);
              if (eossFormJson && eossFormJson.table) {
                this.isEncryption = true;
                this.theadData = eossFormJson.table.thead;
                this.getTableData();
              } else {
                this.hasThead = false;
              }
              this.$emit('init-contents', res.results);
            }
          }
        });
    },
    getOptions(res) {
      let sysCodes = [];
      res.forEach((item) => {
        if (item.sysCode || item.url) {
          item.sysCode && sysCodes.push(item.sysCode);
          let params = util.extend(
            {},
            item.sysCode
              ? { sysAppCode: item.sysCode, code: item.sysCode }
              : {},
            item.param ? item.param : {}
          );
          let key = this.getRequestKey({
            method: this.method,
            url: item.sysCode ? this.findCode : item.url,
            params: params,
            data: {}
          });
          if (!this.requests.includes(key)) {
            util
              .ajax({
                url: item.sysCode ? this.findCode : item.url,
                method: this.method,
                params: params,
                data: params
              })
              .then((res) => {
                console.log('res options', res);
                console.log('item', item);
                if (res.rCode === 0) {
                  if (item.type == 'ganged') {
                    this.$set(
                      this.options,
                      item.sysCode || item.field || item.prop,
                      [JSON.parse(JSON.stringify(res.results))]
                    );
                    if (item.sysCode) {
                      const bus = this.bus || this.$root.Bus;
                      bus &&
                        bus.$emit(
                          item.sysCode,
                          JSON.parse(JSON.stringify(this.options[item.sysCode]))
                        );
                    }
                  } else {
                    this.$set(
                      this.options,
                      item.sysCode || item.field || item.prop,
                      JSON.parse(JSON.stringify(res.results))
                    );
                    if (item.sysCode) {
                      const bus = this.bus || this.$root.Bus;
                      bus &&
                        bus.$emit(
                          item.sysCode,
                          JSON.parse(JSON.stringify(res.results))
                        );
                    }
                  }
                  this.requests.push(key);
                } else {
                  let msg = res.msg || '系统错误，请联系管理员！';
                  this.$message.error(msg);
                }
              })
              .catch((err) => {
                if (err.message && err.message !== 'canceled') {
                  this.$message.error(err.message);
                }
              });
          }
        } else {
          if (item.childHead && item.childHead.length) {
            this.getOptions(item.childHead);
          }
          if (item.children && item.children.length) {
            this.getOptions(item.children);
          }
        }
      });
      this.sysCodes = sysCodes;

      this.bindEventBus();
    },
    checkObject(item) {
      return util.getObjectType(item) === 'object';
    },
    chekOpenTotalArea() {
      if (this.total || this.showSummary) {
        this.showTotal = true;
        return;
      }
      if (!this.theads) {
        return;
      }
      const arr = JSON.parse(JSON.stringify(this.theads));
      let flag = false;
      arr.forEach((item) => {
        if (item.total) {
          flag = true;
          this.showTotal = true;
        }
      });
      if (this.showTotal !== flag) {
        this.showTotal = flag;
      }
    },
    rowClick(row, column, event) {
      this.$emit('click', row, column, event);
      this.$emit('row-click', row, column, event);
    },
    handleClickAddData(scope) {
      if (scope && scope.row) {
        const data = JSON.parse(JSON.stringify(scope.row));
        let index = scope.$index + 1;
        if (this.page) {
          index += (this.config.pageNum - 1) * this.config.pageSize;
        }
        this.data.splice(index, 0, data);
        this.$emit('dataChange', 'add', data);
        this.$emit('data-change', 'add', data);
        this.$emit('btnClick', {
          event: 'addRow',
          row: data,
          index: index,
          data: this.data
        });
        this.$emit('btn-click', {
          event: 'addRow',
          row: data,
          index: index,
          data: this.data
        });
      } else {
        let index = this.data.length;
        if (this.page) {
          index += (this.config.pageNum - 1) * this.config.pageSize;
        }
        let rows = {};
        if (this.rowData && typeof this.rowData == 'object') {
          rows = this.rowData;
        } else if (index && this.rowData === true) {
          rows = JSON.parse(JSON.stringify(this.data[index - 1]));
        } else {
          this.getRow(this.thead, rows);
        }
        this.data.splice(index, 0, rows);
      }
    },
    getRow(thead, obj) {
      thead.forEach((item) => {
        if (item.field) {
          obj[item['field']] = item.defaultValue || '';
        } else if (item.children && item.children.length) {
          this.getRow(item.children, obj);
        }
      });
    },
    handleClickDeleteData(scope) {
      const data = JSON.parse(JSON.stringify(scope.row));
      let index = scope.$index;
      if (this.page) {
        index += (this.config.pageNum - 1) * this.config.pageSize;
      }
      this.data.splice(index, 1);
      this.$emit('dataChange', 'delete', data);
      this.$emit('data-change', 'delete', data);
      this.$emit('btnClick', {
        event: 'deleteRow',
        row: data,
        index: index,
        data: this.data
      });
      this.$emit('btn-click', {
        event: 'deleteRow',
        row: data,
        index: index,
        data: this.data
      });
    },
    checkSelect(newVal) {
      this.$nextTick(() => {
        if (util.getObjectType(newVal) === 'array') {
          newVal.forEach((row) => {
            if (util.isObject(row)) {
              this.$refs.oaTable.toggleRowSelection(row, true);
            } else {
              this.setChecked(this.list, row);
            }
          });
        } else if (newVal === true) {
          this.toggleAllSelection();
        }
      });
    },
    setChecked(list, row) {
      list.forEach((item) => {
        if (item.children && item.children.length) {
          this.setChecked(item.children, row);
        }
        if (item[this.checkedKey] === row) {
          this.$refs.oaTable.toggleRowSelection(item, true);
          return;
        }
      });
    },
    getTableDatas(res) {
      let where;
      let first;
      if (res) {
        where = res.where;
        first = res.first;
      }
      if (!this.url) {
        return;
      }
      if (first !== false && !this.infiniteScroll) {
        this.config.pageNum = 1;
      }
      this.tableLoadingText = '加载中...';
      let reqData = util.extend(
        {},
        this.params,
        this.page
          ? {
              pageNum: this.config.pageNum,
              pageSize: this.config.pageSize
            }
          : {}
      );
      if (where) {
        reqData = util.extend({}, reqData, where);
      }
      //if (this.fields)
      if (this.retainSearh || first === false) {
        reqData = util.extend({}, reqData, this.wheres);
      }
      if (this.isJoin) {
        for (let i in reqData) {
          if (Array.isArray(reqData[i])) {
            reqData[i] = reqData[i].join(',');
          }
        }
      }
      if (this.isEncryption) {
        let fields = [];
        this.theads.forEach((item) => {
          if (item.field || item.prop) {
            fields.push(item.field || item.prop);
          }
        });
        let initLogin = util.getStorage('initLogin');
        initLogin && (initLogin = JSON.parse(initLogin));
        reqData['fields'] = initLogin.secret
          ? util.esmEncrypt({
              data: fields.join(','),
              key: initLogin.secret
            })
          : fields.join(',');
      }
      this.tableLoading = true;
      util
        .ajax({
          ...this.ajaxConfig,
          url: this.url,
          method: this.method,
          format: this.format,
          params: reqData,
          data: reqData
        })
        .then((res) => {
          this.tableLoading = false;
          if (res.rCode === 0 || res.status === 'success') {
            if (this.isReload) {
              this.list = [];
              this.isReload = false;
            }
            let results =
              this.parseData !== undefined
                ? this.parseData(res.results || res.data || res)
                : res.results || res.data;
            if (this.infiniteScroll) {
              this.list = this.list.concat(
                results.data || results.records || results.list
              );
              this.config.pageNum += 1;
            } else {
              this.list = results.data || results.records || results.list;
              this.$nextTick(() => {
                this.resetScroll &&
                  this.$refs.oaTable &&
                  this.$refs.oaTable.resetScroll &&
                  this.$refs.oaTable.resetScroll(0, 0);
              });
            }
            this.config.totalCount =
              results.count || results.total || results.totalCount;
            this.config.pageCount = results.pageCount;
            this.checked &&
              this.$nextTick(() => {
                this.checkSelect(this.checked);
              });
            if (
              this.infiniteScroll &&
              this.config.totalCount === this.list.length
            ) {
              this.infiniteDisabled = true;
            }
          } else {
            this.list = [];
            //this.tableHeight = false;
            let msg = res.msg || '系统错误，请联系管理员！';
            this.$message.error(msg);
          }
          this.$emit('success', res);
        })
        .catch((err) => {
          //this.tableHeight = false;
          if (err.message && err.message !== 'canceled') {
            this.$message.error(err.message);
          }
          this.tableLoading = false;
        });
    },
    selectionChange(data) {
      this.selected = JSON.parse(JSON.stringify(data));
      this.$emit('selection-change', data);
    },
    clearSelection() {
      this.$refs.oaTable.clearSelection();
    },
    toggleRowSelection(row, selected) {
      this.$refs.oaTable.toggleRowSelection(row, selected);
    },
    toggleAllSelection() {
      this.$refs.oaTable.toggleAllSelection();
    },
    toggleRowExpansion(row, expanded) {
      this.$refs.oaTable.toggleRowExpansion(row, expanded);
    },
    setCurrentRow(row) {
      this.$refs.oaTable.setCurrentRow(row);
    },

    clearSort() {
      this.$refs.oaTable.clearSort();
    },
    clearFilter(columnKey) {
      this.$refs.oaTable.clearFilter(columnKey);
    },
    doLayout() {
      this.$refs.oaTable && this.$refs.oaTable.doLayout();
    },
    sort(prop, order) {
      this.$refs.oaTable.sort(prop, order);
    },
    formBlur(data) {
      this.$emit('blur', data, this.list);
    },
    formFocus(data) {
      this.$emit('focus', data, this.list);
    },
    formChange(data) {
      this.$emit('edit', data, this.list);
      this.$emit('change', data, this.list);
    },
    toolbarChange(...args) {
      this.$emit('toolbar-change', ...args);
    },
    handleAjax(handle, row) {
      this.changeLoading(true, `${handle.text}中...`);
      let params = handle.param || {};
      if (handle.syncKeys) {
        if (typeof handle.syncKeys === 'string') {
          params[handle.syncKeys] = row[handle.syncKeys];
        } else if (Array.isArray(handle.syncKeys)) {
          for (let i in handle.syncKeys) {
            if (Array.isArray(row)) {
              let param = row.map((item) => {
                return item[handle.syncKeys[i]];
              });
              params[handle.syncKeys[i]] = param.join(',');
            } else {
              params[handle.syncKeys[i]] = row[handle.syncKeys[i]];
            }
          }
        } else {
          for (let i in handle.syncKeys) {
            if (Array.isArray(row)) {
              let param = row.map((item) => {
                return item[handle.syncKeys[i]];
              });
              params[i] = param.join(',');
            } else {
              params[i] = row[handle.syncKeys[i]];
            }
          }
        }
      } else {
        if (Array.isArray(row)) {
          let param = row.map((item) => {
            return item.id;
          });
          params.id = param.join(',');
        } else {
          params.id = row.id;
        }
      }
      let keys = Object.keys(params);
      util
        .ajax({
          ...(handle.ajaxConfig || {}),
          url: handle.action,
          data:
            keys.length == 1 && handle.format === false
              ? params[keys[0]].split(',')
              : params,
          params:
            keys.length == 1 && handle.format === false
              ? params[keys[0]].split(',')
              : params,
          method: handle.method,
          format: handle.format
        })
        .then((res) => {
          this.changeLoading(false);
          if (res.rCode === 0) {
            this.$message({
              message: `${handle.text}成功`,
              duration: 2000,
              type: 'success',
              onClose: () => {
                let first = Object.prototype.hasOwnProperty.call(
                  handle,
                  'first'
                )
                  ? handle.first
                  : false;
                let reload = handle.reload || true;
                if (handle.event == 'delete') {
                  let totalCount = this.config.totalCount - 1;
                  this.config.pageNum = Math.ceil(
                    totalCount / this.config.pageSize
                  );
                }

                if (reload) {
                  this.reload({}, first);
                }
              }
            });
          } else {
            this.$message.error(
              res.msg || `${handle.text}失败，请联系管理员！`
            );
          }
        })
        .catch((err) => {
          this.changeLoading(false);
          if (err.message && err.message !== 'canceled') {
            this.$message.error(err.message);
          }
        });
    },
    checkParse(data, parse) {
      if (Array.isArray(data)) {
        return data.map((items) => {
          let item = JSON.parse(JSON.stringify(items));
          let obj = {};
          for (let i in parse) {
            obj[i] = item[parse[i]];
            delete item[parse[i]];
          }
          return { ...obj, ...item };
        });
      }
      let item = JSON.parse(JSON.stringify(data));
      let obj = {};
      for (let i in parse) {
        obj[i] = item[parse[i]];
        delete item[parse[i]];
      }
      return { ...obj, ...item };
    },
    handleClick(res) {
      let { row, handle } = res;
      let rows;
      if (handle.checkbox) {
        if (!this.selected || !this.selected.length) {
          this.$alert('请选择数据', '提示', { type: 'warning' });
          return;
        } else {
          row = this.selected;
        }
      }
      if (this.checkboxParseData) {
        rows = this.checkboxParseData(JSON.parse(JSON.stringify(row)));
      } else if (this.checkboxParse) {
        rows = this.checkParse(row, this.checkboxParse);
      } else if (handle.checkboxParse) {
        rows = this.checkParse(row, handle.checkboxParse);
      } else if (row) {
        rows = JSON.parse(JSON.stringify(row));
      }
      let thead = this.theads;
      if (this.$refs.oaTable) {
        thead = this.$refs.oaTable.getThead().thead;
      }
      if (handle.action) {
        let isConfirm = handle.confirm || true;
        if (isConfirm) {
          let msg = handle.field ? row[handle.field] : '';
          this.$confirm(`确定要${handle.text}${msg}吗`, '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          })
            .then(() => {
              this.handleAjax(handle, rows);
            })
            .catch(() => {});
        } else {
          this.handleAjax(handle, rows);
        }
      } else if (handle.event) {
        if (typeof handle.event === 'function') {
          handle.event({
            ele: this,
            thead: thead,
            data: this.list,
            selected: rows,
            ...res
          });
        } else if (
          handle.event === 'add' ||
          handle.event === 'edit' ||
          handle.event === 'look'
        ) {
          let changes = {
            event: handle.event,
            title: handle.title || handle.text,
            value: handle.event === 'add' ? {} : rows,
            readonly: handle.event === 'look',
            actionType: handle.actionType
              ? handle.actionType
              : handle.event === 'add'
              ? 'save'
              : 'update',
            visible: true
          };
          if (handle.dialog) {
            let dialog;
            for (let i = 0; i < this.$children.length; i++) {
              let child = this.$children[i];
              if (child.$refs[handle.dialog]) {
                dialog = child.$refs[handle.dialog];
                break;
              }
            }
            dialog.setAttrs(changes);
          }
          this.injector && this.injector.handleChangeData(changes);
          if (handle.busEvent) {
            const bus = this.bus || this.$root.Bus;
            bus && bus.$emit(handle.busEvent, changes);
          }
        }
      } else if (handle.changeData) {
        let changeData = {};
        if (Array.isArray(handle.changeData)) {
          handle.changeData.forEach((item) => {
            if (util.isObject(item)) {
              for (let i in item) {
                if (typeof item[i] === 'boolean') {
                  changeData[i] = item[i];
                } else {
                  changeData[i] = handle[item[i]] || item[i];
                }
              }
            } else {
              changeData[item] =
                handle[item] || (Array.isArray(rows) ? rows : rows[item]);
            }
          });
        } else {
          for (let i in handle.changeData) {
            let item = handle.changeData[i];
            if (util.isObject(item)) {
              let obj = {};
              for (let e in item) {
                obj[e] =
                  handle[item[e]] ||
                  (Array.isArray(rows) ? rows : rows[item[e]]);
              }
              changeData[i] = obj;
            } else {
              if (typeof item === 'boolean') {
                changeData[i] = item;
              } else {
                changeData[i] =
                  handle[item] || (Array.isArray(rows) ? rows : rows[item]);
              }
            }
          }
        }
        if (handle.actionType) {
          changeData['actionType'] = handle.actionType;
        }
        this.injector && this.injector.handleChangeData(changeData);
        if (handle.busEvent) {
          const bus = this.bus || this.$root.Bus;
          bus && bus.$emit(handle.busEvent, changes);
        }
      } else {
        if (handle.exportXls) {
          let text = '操作';
          if (
            this.theads[this.theads.length - 1] &&
            this.theads[this.theads.length - 1].type === 'handle'
          ) {
            text = this.theads[this.theads.length - 1].title;
          }
          let type = ['selection', 'index', 'expand'];
          thead = thead.map((item) => {
            return item.filter((ele) => {
              return (
                !type.includes(ele.type) &&
                ele.label !== text &&
                !this.exportExcludeLabel.includes(ele.label)
              );
            });
          });
          util.exportXls({
            thead: thead,
            data: this.list,
            name: this.fileName,
            option: this.optionDatas
          });
        }
        this.$emit('btnClick', res, this.list, thead, rows);
        this.$emit('btn-click', res, this.list, thead, rows);
      }
    },
    sizeChange(res) {
      this.config.pageSize = res;
      this.config.pageNum = 1;
      this.checkSelect(this.checked);
      this.$emit('page-size-change', res);
      if (this.url) {
        this.getTableData({ where: this.wheres, first: false });
      }
    },
    currentChange(res) {
      this.config.pageNum = res;
      this.checkSelect(this.checked);
      this.$emit('page-current-change', res);
      this.$emit('current', res);
      if (this.url) {
        this.getTableData({ where: this.wheres, first: false });
      }
    },
    preClick(res) {
      this.config.pageNum = res;
      this.checkSelect(this.checked);
      this.$emit('prev', res);
    },
    nextClick(res) {
      this.config.pageNum = res;
      this.checkSelect(this.checked);
      this.$emit('next', res);
    },
    hanleSearch(data) {
      this.searchWhere =
        this.response !== undefined
          ? this.response({
              type: 'search',
              data: JSON.parse(JSON.stringify(data))
            })
          : data;
      if (this.url && this.executeSearch) {
        this.getTableData({ where: this.wheres });
      }
      this.$emit('search', this.searchWhere);
    },
    hanleReset() {
      this.searchWhere = {};
      this.advanceWhere = {};
      if (this.url) {
        this.getTableData();
      }
      this.$emit('reset', this.params);
    },
    hanleSubmit({ data, show }) {
      this.advanceWhere =
        this.response !== undefined
          ? this.response({
              type: 'filter',
              data: JSON.parse(JSON.stringify(data))
            })
          : data;

      if (this.url && this.executeFilter) {
        this.getTableData({ where: this.wheres });
      }
      this.$emit('submit', {
        data: this.advanceWhere,
        where: this.wheres,
        show
      });
    },
    hanleCancel() {
      this.$emit('cancel', this.params);
    },
    handleTabs({ item, index }) {
      if (this.url) {
        this.getTableData({ where: item });
      }
      this.$emit('tabs', { item, index });
    },
    reload(obj, first = false) {
      if (obj && obj.config) {
        this.config = util.extend({}, this.config, obj.config);
      }
      if (this.url) {
        this.isReload = true;
        this.getTableData({ where: obj && obj.where ? obj.where : {}, first });
      }
    },
    resetHeight(warn) {
      this.isSetHeight =
        util.getStyle(this.$el.parentNode, 'height') == '0px' ? false : true;
      this.$nextTick(() => {
        if (this.full && !this.height && !this.maxHeight && this.isSetHeight) {
          let height = this.$el.parentNode.offsetHeight;
          if (height) {
            height = parseInt(
              util.getStyle(this.$el.parentNode, 'height', '%'),
              10
            );
            height =
              (height == NaN ? 0 : height) -
              parseInt(util.getStyle(this.$el.parentNode, 'padding-top'), 10) -
              parseInt(
                util.getStyle(this.$el.parentNode, 'padding-bottom'),
                10
              );
            for (let i = 0; i < this.$el.parentNode.childNodes.length; i++) {
              let ele = this.$el.parentNode.childNodes[i];
              if (
                this.$el &&
                ele.offsetHeight !== undefined &&
                ele != this.$el
              ) {
                height =
                  height -
                  ele.offsetHeight -
                  parseInt(util.getStyle(ele, 'margin-top'), 10) -
                  parseInt(util.getStyle(ele, 'margin-bottom'), 10);
              }
            }
            height -= this.showToolbar
              ? this.$refs.toolbar.$el.offsetHeight
              : 0;
            height -=
              this.page === false || this.showPage == false
                ? 0
                : this.$refs.pagination.$el.offsetHeight;
            height -= this.title ? this.$refs.title.offsetHeight : 0;
            height -= parseInt(
              util.getStyle(this.$refs.esTableContent, 'padding-top'),
              10
            );
            height -= parseInt(
              util.getStyle(this.$refs.esTableContent, 'padding-bottom'),
              10
            );
            let emptyText = this.$refs.esTableContent.querySelector(
              '.el-table__empty-text'
            );
            if (this.total) {
              height -= 1;
            }
            let eht = 0;
            if (emptyText) {
              eht = emptyText.offsetHeight;
              let thead =
                this.$refs.esTableContent.querySelector('.el-table__header');
              thead && (eht += thead.offsetHeight);
            }
            if (height > 1 && height - eht > 1) {
              this.tableHeight = height;
            } else {
              console.warn(this.$el.parentNode, `获取不到高度！`);
            }
          } else if (!warn) {
            setTimeout(() => {
              this.resetHeight(true);
            }, 1000);
          }
        }
      });
    },
    validate(callback) {
      if (this.form) {
        let form = this.elForm || this.$children[0];
        form.validate((valid) => {
          callback(valid);
        });
      }
    },
    changeLoading(show, text) {
      this.tableLoading = show;
      if (text) {
        this.tableLoadingText = text;
      }
    },
    handleFilterColumn() {
      this.showSizer = true;
    },
    handleSortChange(res) {
      if (res.data && res.data.length) {
        this.list = res.data;
      }
      this.$emit('sort-change', res);
    },
    handleUpdateDragSort(data, event) {
      this.$emit('update-drag-sort', data, event);
    },
    mergeThead(res) {
      this.show = false;
      this.theadData = [];
      this.icon = true;
      this.showSizer = false;
      // if (!this.showTotal) {
      //   for (let i = 0; i < res.length; i++) {
      //     if (res[i].total) {
      //       this.showTotal = true;
      //       break;
      //     }
      //   }
      // }
      this.$nextTick(() => {
        this.theadData = res;
        setTimeout(() => {
          this.show = true;
        }, 500);
      });
    },
    setOptions(val, sysCode) {
      this.$set(this.options, sysCode, val);
    },
    bindEventBus() {
      this.sysCodes.forEach((item) => {
        const bus = this.bus || this.$root.Bus;
        bus &&
          bus.$on(item, (val) => {
            this.setOptions(val, item);
          });
      });
    },
    unbindEventBus() {
      this.sysCodes.forEach((item) => {
        const bus = this.bus || this.$root.Bus;
        bus && bus.$off(item, this.setOptions);
      });
    },
    reset() {
      this.$refs.toolbar && this.$refs.toolbar.reset();
    },
    openEditPage() {
      let fields = [];
      this.theads.forEach((item) => {
        if (item.field || item.prop) {
          fields.push(item.field || item.prop);
        }
      });
      fields = util.esEncode(fields.join(','));
      this.editPage = `/lowcode-ui/webpack/index.html#simpleEditOnlinePage?pageId=${this.viewCode}&fields=${fields}`;
      this.showEditPage = true;
    }
  }
};
</script>
