<template>
  <div class="xy-table">
    <!-- 搜索条件 -->
    <template
      v-if="table.searchForm ? (table.searchForm.hidden === undefined ? true : !table.searchForm.hidden) : false"
    >
      <xy-table-search-form
        ref="xy-table-search-form"
        :form="table.searchForm"
        @handleEvent="handleEvent"
        @handleQuery="handleQuery"
        @resetQuery="resetQuery"
      />
    </template>

    <div v-if="!table.hiddenLine" class="xy-hr-table" />

    <!-- 功能按钮 -->
    <el-row
      v-if="(table.toolbar && table.toolbar.length > 0) || table.columnSetting"
      :gutter="10"
      style="margin-bottom: 20px;"
    >
      <el-col v-for="(item, index) in table.toolbar" :key="index" :span="1.5">
        <template v-if="item.children && item.children.length > 0">
          <el-dropdown
            :trigger="item.trigger || 'click'"
            @command="(command) => handleCommandToolBar(command, item.children)"
          >
            <el-button
              :type="item.type"
              :plain="item.plain"
              :icon="item.icon"
              :size="item.size || 'small'"
            >
              {{ item.text }}
              <i class="el-icon-arrow-down el-icon--right" />
            </el-button>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item
                v-for="(item2, index2) in item.children"
                :key="index2"
                :icon="item2.icon"
                :command="item2.command || `toolbarCommand-${index2}`"
              >{{ item2.text }}</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
        <template v-else-if="item.hasRole && item.hasRole.length > 0">
          <el-button
            v-hasRole="item.hasRole"
            :type="item.type"
            :plain="item.plain"
            :icon="item.icon"
            :size="item.size || 'small'"
            :disabled="item.disabled || (item.isSingle ? single : false) || (item.isMultiple ? multiple : false)"
            @click="item.fun"
          >{{ item.text }}</el-button>
        </template>
        <template v-else>
          <el-button
            :type="item.type"
            :plain="item.plain"
            :icon="item.icon"
            :size="item.size || 'small'"
            :disabled="item.disabled || (item.isSingle ? single : false) || (item.isMultiple ? multiple : false)"
            @click="item.fun"
          >{{ item.text }}</el-button>
        </template>
      </el-col>
      <!-- 右侧表功能 -->
      <div v-if="table.columnSetting" class="header_right_wrap">
        <column-set v-bind="$attrs" :columns="columns" @columnSetting="v => columnSet = v" />
      </div>
    </el-row>

    <slot name="tabs" />

    <!-- 表格 -->
    <el-table
      ref="xy-table"
      v-loading="loading"
      :class="{ 'tableClass': true, 'radioStyle': (table.firstColumn && table.firstColumn.type === 'radio') }"
      :row-key="table.rowKey"
      :data="table.data"
      :height="table.height"
      :max-height="table.maxHeight"
      :stripe="table.stripe"
      :border="table.border === undefined ? false : table.border"
      :size="table.size"
      :fit="table.fit === undefined ? true : table.fit"
      :show-header="table.showHeader === undefined ? true : table.showHeader"
      :highlight-current-row="table.highlightCurrentRow || (table.firstColumn && table.firstColumn.type === 'radio')"
      :current-row-key="table.currentRowKey"
      :row-class-name="table.rowClassName"
      :row-style="table.rowStyle"
      :cell-class-name="table.cellClassName"
      :cell-style="table.cellStyle"
      :header-row-class-name="table.headerRowClassName"
      :header-row-style="table.headerRowStyle"
      :header-cell-class-name="table.headerCellClassName"
      :header-cell-style="table.headerCellStyle"
      :empty-text="table.emptyText"
      :default-expand-all="table.defaultExpandAll === undefined ? false : table.defaultExpandAll"
      :expand-row-keys="table.expandRowKeys"
      :tooltip-effect="table.tooltipEffect"
      :show-summary="table.showSummary === undefined ? false : table.showSummary"
      :sum-text="table.sumText || '合计'"
      :summary-method="table.summaryMethod"
      :span-method="table.spanMethod"
      :select-on-indeterminate="table.selectOnIndeterminate === undefined ? true : table.selectOnIndeterminate"
      :indent="table.indent || 16"
      :lazy="table.lazy"
      :load="table.load"
      :tree-props="table.treeProps || { hasChildren: 'hasChildren', children: 'children' }"
      @row-click="rowClick"
      @current-change="handleCurrentChange"
      @selection-change="handleSelectionChange"
    >
      <!-- 首列之 序列号/单选框/复选框 -->
      <div v-if="table.firstColumn">
        <!-- 复选框 -->
        <el-table-column
          v-if="table.firstColumn.type === 'selection'"
          :type="table.firstColumn.type"
          :width="table.firstColumn.width || 50"
          :label="table.firstColumn.label"
          :fixed="table.firstColumn.fixed"
          :align="table.firstColumn.align || 'center'"
          :reserve-selection="table.firstColumn.isPage || false"
        />
        <!-- 单选框 -->
        <el-table-column
          v-if="table.firstColumn.type === 'radio'"
          :width="table.firstColumn.width || 50"
          :label="table.firstColumn.label"
          :fixed="table.firstColumn.fixed"
          :align="table.firstColumn.align || 'center'"
        >
          <template slot-scope="scope">
            <el-radio v-model="radioVal" :label="scope.$index" @click.native.prevent="() => { }" />
          </template>
        </el-table-column>
        <!-- 序列号 -->
        <el-table-column
          v-if="table.firstColumn.type === 'index'"
          :type="table.firstColumn.type"
          :width="table.firstColumn.width || 50"
          :label="table.firstColumn.label || '序号'"
          :fixed="table.firstColumn.fixed"
          :align="table.firstColumn.align || 'center'"
        >
          <template slot-scope="scope">
            <span>{{ !table.page.hidden ? ((table.page.pageNum - 1) * table.page.pageSize + scope.$index + 1) : scope.$index + 1 }}</span>
          </template>
        </el-table-column>
      </div>

      <!-- 主体内容 -->
      <template>
        <el-table-column
          v-for="(item, index) in renderColumns"
          :key="table.rowKey ? item[table.rowKey] : index + 'i'"
          :type="item.type"
          :index="item.index"
          :column-key="item.columnKey"
          :label="item.label"
          :prop="item.prop"
          :width="item.width"
          :min-width="item['min-width'] || item.minWidth || 160"
          :fixed="item.fixed"
          :render-header="item.renderHeader || (item.headerRequired && renderHeader)"
          :sortable="item.sortable ? item.sortable : false"
          :sort-method="item.sortMethod"
          :sort-by="item.sortBy"
          :sort-orders="item.sortOrders || ['ascending', 'descending', null]"
          :resizable="item.resizable ? item.resizable : true"
          :show-overflow-tooltip="item.showOverflowTooltip ? item.showOverflowTooltip : false"
          :align="item.align || 'center'"
          :header-align="item.headerAlign"
          :class-name="item.className"
          :label-class-name="item.labelClassName"
          :selectable="item.selectable"
          :reserve-selection="item.reserveSelection ? item.reserveSelection : false"
          :filters="item.filters"
          :filter-placement="item.filterPlacement"
          :filter-multiple="item.filterMultiple ? item.filterMultiple : true"
          :filter-method="item.filterMethod"
          :filtered-value="item.filteredValue"
        >
          <template slot-scope="scope">
            <template v-if="item.slotName">
              <slot :name="item.slotName" :scope="scope" />
            </template>
            <template
              v-if="!item.slotName && item.formatter"
            >{{ item.formatter(scope.row, scope.column, scope.$index) }}</template>
            <template v-if="!item.slotName && !item.formatter">{{ scope.row[item.prop] }}</template>
          </template>

          <template v-if="item.children && item.children.length > 0">
            <children-column v-for="(item2, index2) in item.children" :key="index2" :item-children="item2" />
          </template>
        </el-table-column>
      </template>
      <!-- 操作按钮 -->

      <el-table-column
        v-if="table.operator && table.operator.length > 0"
        :fixed="(table.operatorConfig && table.operatorConfig.noFixed) ? undefined : ((table.operatorConfig && table.operatorConfig.fixed) || 'right')"
        :label="(table.operatorConfig && table.operatorConfig.label) || '操作'"
        :min-width="(table.operatorConfig && (table.operatorConfig.width || table.operatorConfig.minWidth)) || 160"
        :align="(table.operatorConfig && table.operatorConfig.align) || 'center'"
      >
        <template slot-scope="scope">
          <div class="operator-btn" :style="table.operatorConfig && table.operatorConfig.style">
            <el-button
              v-for="(item, index) in operatorButtons"
              v-show="checkIsShow(scope, item)"
              :key="index"
              :type="item.type || 'text'"
              :style="item.style"
              :icon="item.icon"
              :size="item.size || 'small'"
              @click="item.fun && item.fun(scope.row, scope.$index, table.data)"
            >{{ item.text }}</el-button>

            <el-dropdown
              v-if="operatorMoreButtons.length > 0"
              size="mini"
              @command="(command) => handleCommand(command, scope.row)"
            >
              <span class="el-dropdown-link">
                <i class="el-icon-d-arrow-right el-icon--right" />更多
              </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item
                  v-for="(item, index) in operatorMoreButtons"
                  :key="index"
                  :command="item.command"
                  :icon="item.icon"
                >{{ item.text }}</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </div>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页器 -->
    <xy-pagination
      v-if="table.page"
      :hidden="table.page.hidden"
      :total="table.page.total || 0"
      :page.sync="table.page.pageNum"
      :limit.sync="table.page.pageSize"
      :page-sizes="table.page.pageSizes"
      @pagination="requestPagination"
    />
  </div>
</template>

<script>
import ColumnSet from './ColumnSet.vue'
import ChildrenColumn from './ChildrenColumn.vue'

export default {
  name: 'XyTable',
  components: {
    ColumnSet,
    ChildrenColumn
  },
  props: {
    // table所需数据
    table: {
      type: Object,
      default: () => {
        return {}
      },
      required: true
    },
    // 表头数据
    columns: {
      type: Array,
      default: () => {
        return []
      }
      // required: true
    }
  },
  data() {
    return {
      radioVal: '',
      rowData: '',
      columnSet: [],
      currentRow: undefined,
      multipleSelection: undefined,
      // 表格加载
      loading: false,
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true
    }
  },
  computed: {
    columnByProp() {
      return this.columns.reduce((acc, cur) => {
        acc[cur.prop] = cur
        return acc
      }, {})
    },
    renderColumns() {
      return this.columnSet.length > 0
        ? this.columnSet.reduce((acc, cur) => {
          if (!cur.hidden) {
            acc.push(this.columnByProp[cur.prop])
          }
          return acc
        }, [])
        : this.columns
    },
    // 操作按钮
    operatorButtons() {
      return (
        (this.table.operator &&
          this.table.operator.filter((item) => !item.isMore)) ||
        []
      )
    },
    // 更多操作按钮
    operatorMoreButtons() {
      return (
        (this.table.operator &&
          this.table.operator.filter((item) => item.isMore)) ||
        []
      )
    }
  },
  watch: {
    table: {
      immediate: true,
      handler(newV, oldV) {
        if (newV === oldV) return
        this.initTable()
      }
    }
  },
  methods: {
    // 更多操作
    handleCommand(command, row) {
      const commands = this.operatorMoreButtons.filter(
        (item) => item.command === command
      )
      if (commands.length > 0) {
        commands[0].fun(row)
      }
    },
    // 工具栏更多操作
    handleCommandToolBar(command, children) {
      const commandIndex = command.split('-')[1]
      children[commandIndex].fun()
    },
    initTable() {
      if (
        this.table.requestImmediate === undefined
          ? true
          : this.table.requestImmediate
      ) {
        try {
          this.getData().then((data) => {
            // 第一次加载的数据(供tree下拉使用)
            this.$set(this.table, 'initData', data)
          })
        } catch (error) { }
      }
    },
    // 获取表格数据
    getData() {
      const request = this.table.request

      if (!request || typeof request !== 'function') return

      if (!this.table.hiddenLoading) {
        this.loading = true
      }

      let requestParams = Object.assign(
        this.table.page
          ? {
            pageSize: this.table.page.pageSize,
            pageNum: this.table.page.pageNum
          } : {},
        this.table.searchForm ? this.table.searchForm.formData : {}
      )

      // 处理请求参数
      if (this.table.searchForm && this.table.searchForm.fieldList) {
        this.table.searchForm.fieldList.forEach((item) => {
          if (item.type === 'daterange') {
            requestParams = this.addDateRange(
              requestParams,
              this.table.searchForm.formData[item.prop]
            )
            delete requestParams[item.prop]
          }
        })
      }

      // 搜索之前对搜索条件进行修改
      if (
        this.table.searchForm && this.table.searchForm.beforeHandleQuery &&
        typeof this.table.searchForm.beforeHandleQuery === 'function'
      ) {
        requestParams = this.table.searchForm.beforeHandleQuery(requestParams)
      }

      return request(requestParams)
        .then((res) => {
          console.log(res)
          const { rows, total, data } = res

          let dataList = rows || data
          // 表格赋值前操作需要返回data
          if (
            this.table.beforeSetData &&
            typeof this.table.beforeSetData === 'function'
          ) {
            dataList = this.table.beforeSetData(dataList)
          }
          // console.log(dataList)
          this.table.data = dataList
          this.table.page.total = total
          // setTimeout(() => {
          this.loading = false
          // }, 300)
          // 表格赋值之后的操作不需要返回
          if (
            this.table.afterSetData &&
            typeof this.table.afterSetData === 'function'
          ) {
            this.$nextTick(() => {
              this.table.afterSetData(dataList)
            })
          }

          return Promise.resolve(dataList)
        })
        .catch(() => (this.loading = false))
    },
    // 切换分页
    requestPagination(params) {
      this.table.page.pageNum = params.page
      this.table.page.pageSize = params.limit
      this.$nextTick(() => {
        this.getData()
      })
    },
    // 是否显示表格操作按钮
    checkIsShow(scope, item) {
      // 自定义show
      if (item.customShow && typeof item.customShow === 'function') {
        return item.customShow(scope.row) || false
      }

      // show  noShow控制
      let showFlag = false
      if (item.show && item.show.val.includes(scope.row[item.show.key])) {
        showFlag = true
      }

      let noShowFlag = true
      if (item.noShow) {
        item.noShow.forEach((rs) => {
          if (rs.val.includes(scope.row[rs.key])) {
            noShowFlag = false
          }
        })
      }

      if (item.show && item.noShow) {
        return noShowFlag && showFlag
      } else if (item.show) {
        return showFlag
      } else if (item.noShow) {
        return noShowFlag
      }
      return true
    },
    // 头部标题是否需要加头部必填*符号
    renderHeader(h, { column }) {
      const style = {
        color: '#F56C6C',
        fontSize: '16px',
        marginRight: '3px'
      }
      // 头部标题是否需要加头部必填*符号
      return (
        <div style='display: inline'>
          <span style={style}>*</span>
          <span>{column.label}</span>
        </div>
      )
    },
    // 查询
    handleQuery() {
      this.table.page.pageNum = 1
      this.$nextTick(() => {
        this.getData()
      })
    },
    // 重置
    resetQuery() {
      if (
        this.table.searchForm.beforeResetQuery &&
        typeof this.table.searchForm.beforeResetQuery === 'function'
      ) {
        this.table.searchForm.beforeResetQuery()
      }
      this.table.page.pageNum = 1
      this.$nextTick(() => {
        this.getData()
      })
    },
    // 获取table的ref
    getTable() {
      return this.$refs['xy-table']
    },
    // 获取form的ref
    getSearchForm() {
      return this.$refs['xy-table-search-form']
    },
    // 给查询条件添加属性
    setSearchFormData(key, val) {
      if (Object.keys(this.table.searchForm.formData).includes(key)) {
        this.table.searchForm.formData[key] = val
      } else {
        this.$set(this.table.searchForm.formData, key, val)
      }
    },
    // 搜索表单值变化返回
    handleEvent(value, prop) {
      this.$emit('changeSearchForm', value, prop)
    },
    // 点击行
    rowClick(row) {
      this.radioVal = this.table.data.indexOf(row)
      this.rowData = row
      this.$emit('radioChange', row, this.radioVal)
      // row.selectFlag = !row.selectFlag
      // if (row.selectFlag) {
      //   this.$refs['el-table'].setCurrentRow(row)
      // } else {
      //   this.$refs['el-table'].setCurrentRow()
      // }
    },
    // 选中行配合highlight-current-row使用
    handleCurrentChange(val) {
      this.currentRow = val
    },
    // 多选的值
    handleSelectionChange(val) {
      this.multipleSelection = val
      this.single = val.length !== 1
      this.multiple = !val.length
      this.$emit('selectionChange', val)
    },
    // 获取单选返回行对象
    getSelectedRow() {
      return this.currentRow
    },
    // 获取多选返回行对象数组
    getSelectedRows() {
      return this.multipleSelection
    },
    // 获取单选返回行对象的key
    getSelectedKey() {
      return this.table.rowKey ? this.currentRow[this.table.rowKey] : undefined
    },
    // 获取多选返回行对象key的数组
    getSelectedKeys() {
      return this.table.rowKey
        ? this.multipleSelection.map((item) => item[this.table.rowKey])
        : []
    },
    setExpandRowKeys(keys) {
      this.table.expandRowKeys = keys
    }
  }
}
</script>

<style scoped lang="scss">
.xy-hr-table {
  margin-bottom: 20px;
  width: 100%;
  height: 1px;
  border-bottom: 1px dashed #d9d9d9;
}

// 单选样式
.radioStyle {
  ::v-deep .el-radio {
    .el-radio__label {
      display: none;
    }
    &:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner {
      box-shadow: none;
    }
  }
  ::v-deep tbody {
    .el-table__row {
      cursor: pointer;
    }
  }
}

.tableClass {
  //table的class
  ::v-deep .el-table__fixed,
  ::v-deep .el-table__fixed-right {
    height: 100% !important; //设置高优先，以覆盖内联样式
  }
}
</style>
