<template>
  <div v-loading="loading">
    <el-table ref="ElTable" style="width: 100%" v-bind="bindTableProps()" v-on="$listeners"
              @row-click="handlerRowClick">
      <!-- 索引列 -->
      <slot name="indexColumn">
        <!-- 索引列 - 单选 -->
        <el-table-column v-if="isRadio" :type="indexType" align="center" width="50">
          <template v-slot:default="scope">
            <el-radio v-model="radioVal" :label="scope.row"></el-radio>
          </template>
        </el-table-column>

        <!-- 索引列 - 多选、索引值 -->
        <el-table-column v-if="isDefault" :type="indexType" align="center" width="50"></el-table-column>

        <!-- 索引列 - 自定义 -->
        <el-table-column v-if="isCustom" :type="indexType" align="center" width="50">
          <template v-slot:default="scope">
            <slot name="customRow" v-bind="scope"></slot>
          </template>
        </el-table-column>
      </slot>

      <!-- 默认列 -->
      <el-table-column v-for="(column, index) in tableColumns" :key="index" v-bind="column">
        <template v-slot:default="scope">
          <slot :name="slotName(column)" v-bind="scope">
            <table-column-item :scope="scope"></table-column-item>
          </slot>
        </template>
      </el-table-column>

      <!-- 操作列 -->
      <el-table-column v-if="$scopedSlots.hasOwnProperty('operate') && isOperate" :fixed="operateFixed"
                       :minWidth="minWidth" align="center" label="操作">
        <template v-slot:default="scope">
          <slot name="operate" v-bind="scope"></slot>
        </template>
      </el-table-column>
    </el-table>

    <table-pagination v-if="pagination" ref="TablePagination" :pagination.sync="pagination"
                      @change="handlePaginationChange"></table-pagination>
  </div>
</template>

<script>
import props, {TableProps} from './Props'
import TablePagination     from "./components/TablePagination";
import TableColumnItem     from "./components/TableColumnItem";

/**
 * 统一的表格组件
 * - 示例
 *
 * ```vue
 * <ed-table ref="ElsTable" v-model="elsTableData" :columns="elsTableColumns" :pagination="elsTablePagination">
 * </ed-table>
 * ```
 *
 * [](./EdTableProps.md ':include')
 *
 * [](./EdTableBasicProps.md ':include')
 */
export default {
  name: "EdTable",
  components: {TablePagination, TableColumnItem},
  props: props,
  data() {
    return {
      // 查询条件参数
      tableColumns: [],
      radioVal: "",
      minWidth: this.operateWidth
    }
  },
  watch: {
    columns: {
      deep: true,
      immediate: true,
      handler(newVal, oldVal) {
        if (newVal && newVal !== oldVal) {
          //在最后添加操作栏列
          this.tableColumns = newVal.map(t => this.bindTableColumnProps(t));
        }
      }
    },
    data: {
      deep: true,
      immediate: true,
      handler(newVal, oldVal) {
        if (newVal && newVal !== oldVal && newVal.length === 0) {
          this.$emit('update:loading', false)
        }
        if (newVal && newVal !== oldVal && newVal.length > 0) {
          this.$emit('update:loading', false)

          // 主动设置操作栏宽度
          this.$nextTick(() => {
            this.$refs.ElTable.doLayout()
            if (this.operateWidth === 140) {
              let dom = this.$el.querySelectorAll('.operation')[0]
              if (dom && Object.prototype.hasOwnProperty.call(dom.dataset, 'width')) {
                this.minWidth = dom.dataset.width
              }
            }
          })
        }
      }
    },
  },
  computed: {
    /**
     * @private
     * 处理索引列的类型
     * @returns {string}
     */
    indexType() {
      return this.columnType === 'radio' ? 'index' : this.columnType
    },
    // 是否单选
    isRadio() {
      return this.columnType && this.columnType === 'radio'
    },
    // 是否多选，索引
    isDefault() {
      return this.columnType && (this.columnType === 'index' || this.columnType === "selection")
    },
    // 是否使用索引列插槽
    isCustom() {
      let slots = Object.assign({}, this.$slots, this.$scopedSlots)
      return this.columnType && Object.keys(slots).includes("customRow")
    },
  },
  methods: {
    /**
     * @private
     * 动态插槽
     * @returns {function(*): *}
     */
    slotName(column) {
      const name = column.prop.includes('.') ? column.prop.split('.').pop() : column.prop;
      return Object.prototype.hasOwnProperty.call(column, 'scopedSlots') ? column.scopedSlots : name + 'Column';
    },

    /**
     * @name bindTableProps
     * @return {{}}
     * @private
     */
    bindTableProps() {
      let props = {}
      let $props = Object.assign({}, this.$attrs, this.$props);
      Object.keys($props).map(key => {
        if (Object.prototype.hasOwnProperty.call(TableProps, key)) {
          props[key] = $props[key]
        }
      })
      props.data = this.data;
      return props
    },

    /**
     * @name bindTableColumnProps
     * @param col
     * @return Object
     * @private
     */
    bindTableColumnProps(col) {
      return {
        align: 'center',
        minWidth: 120,
        showOverflowTooltip: true,
        ...col,
      }
    },

    /**
     * @name handlePaginationChange
     * @param e
     * @description 页码改变
     * @private
     */
    handlePaginationChange(e) {
      this.$emit('change', {pagination: e})
    },


    /**
     * @name handlerRowClick
     * @param row
     * @param column
     * @param event
     * @description 当某一行被点击时会触发该事件
     */
    handlerRowClick(row, column, event) {
      this.radioVal = row
      this.$emit('row-click', row, column, event)
    },

    /**
     * @name setCurrentRow
     * @param row
     * @desc 用于单选表格，设定某一行为选中行，如果调用时不加参数，则会取消目前高亮行的选中状态。
     */
    setCurrentRow(row) {
      this.radioVal = row
      this.$refs.ElTable.setCurrentRow(row);
    },

    /**
     * @name toggleRowSelection
     * @param row
     * @param selected
     * @desc 用于多选表格，切换某一行的选中状态，如果使用了第二个参数，则是设置这一行选中与否（selected 为 true 则选中）
     */
    toggleRowSelection(row, selected) {
      this.$refs.ElTable.toggleRowSelection(row, selected);
    }
  }
}
</script>
<style lang="scss" scoped>
::v-deep {
  .el-scrollbar__wrap {
    overflow-x: hidden;
  }

  .el-radio {
    margin-left: 6px;
  }

  .el-radio .el-radio__label {
    display: none;
  }
}

</style>

