<template>
  <div
    class="box"
    v-if="render"
  >
    <template v-if="empty !== false">
      <template v-if="customData.length > 0">
        <Table
          :border="customData.length > 0"
          :loading="loading&&showLoading"
          :columns="customColumn"
          :data="customData"
          v-bind="$attrs"
          v-on="$listeners"
        >
          <template
            v-for="column in customColumn"
            v-slot:[column.slot]="params"
          >
            <slot
              :name="column.slot?column.slot:''"
              v-bind="params"
            ></slot>
          </template>
        </Table>
        <Page
          v-if="(keepPage || totalSize > pageSize) && page"
          class="mt-15"
          transfer
          :total="totalSize"
          :current="pageNumber"
          :page-size="pageSize"
          :show-elevator="showElevator"
          :show-sizer="showSizer"
          :show-total="showTotal"
          @on-change="pageNumChange"
          @on-page-size-change="pageSizeChange"
          v-bind="$attrs"
          v-on="$listeners"
        />
      </template>
      <wEmpty
        v-else
        :title="empty"
        :loading="loading"
      />
    </template>
    <template v-else>
      <Table
        :border="customData.length > 0"
        :loading="loading&&showLoading"
        :columns="customColumn"
        :data="customData"
        v-bind="$attrs"
        v-on="$listeners"
      >
        <template
          v-for="column in customColumn"
          v-slot:[column.slot]="params"
        >
          <slot
            :name="column.slot?column.slot:''"
            v-bind="params"
          ></slot>
        </template>
      </Table>
      <Page
        v-if="(keepPage || totalSize > pageSize) && page"
        class="mt-15"
        transfer
        :total="totalSize"
        :current="pageNumber"
        :page-size="pageSize"
        :show-elevator="showElevator"
        :show-sizer="showSizer"
        :show-total="showTotal"
        @on-change="pageNumChange"
        @on-page-size-change="pageSizeChange"
        v-bind="$attrs"
        v-on="$listeners"
      />
    </template>
  </div>
</template>

<script>
import { typeOf } from "@/libs/tools";
import { prefix } from "@/libs/config";
/**
 * on-finished 请求完成事件返回请求参数，接口相应的数据
 *
 * on-params-change 参数变化事件，返回变化后的参数
 *
 * 支持iTable,iPage 原生事件和属性具体参见iview api
 */
import wEmpty from '../../empty'
export default {
  components: { wEmpty },
  name: `${prefix}Table`,
  props: {
    /**
     * 内部特定的请求函数
     */
    service: Function,
    /**
     * 请求前的钩子，支持Promise，传入object将通过Object.assign合并请求参数，返回false阻止请求
     */
    beforeQuery: Function,
    /**组件列定义 */
    columns: {
      required: true,
      type: Array
    },
    /**请求函数回调，return ?:{list:Array,total:Number} */
    onLoad: Function,
    /**
     * 分页设置：false不开启分页；object:覆盖分页参数名默认：pageNumber，pageSize
     */
    page: {
      type: [Boolean, Object],
      default: true
    },
    /**是否始终显示分页 */
    keepPage: {
      type: [Boolean, Object],
      default: true
    },
    /**
     * 显示电梯，可以快速切换到某一页
     */
    showElevator: {
      type: Boolean,
      default: true
    },
    // 显示分页，用来改变page- size
    showSizer: {
      type: Boolean,
      default: true
    },
    // 是否显示加载状态
    showLoading: {
      type: Boolean,
      default: true
    },
    // 显示总数
    showTotal: {
      type: Boolean,
      default: true
    },
    //总数
    total: {
      type: Number,
      default: 0
    },
    //初始页数
    pageNumberStart: {
      type: Number,
      default: 1
    },
    //初始分页数量
    pageSizeStart: {
      type: Number,
      default: 10
    },
    //tabel数据
    data: {
      type: Array,
      default: () => []
    },
    /**
     * 无数据时提示，默认使用empty组件；false:使用表格默认提示
     */
    empty: {
      type: [String, Boolean],
      default: "暂无数据"
    }
  },
  watch: {
    data(now) {
      if (typeOf(now) === "array") {
        this.customData = now;
        if (now.length === 0) {
          this.totalSize = 0;
        }
      }
    },
    total(now) {
      this.totalSize = now
    },
    columns: {
      handler(now) {
        this.customColumn = now
      }
    }
  },
  data() {
    return {
      loading: false,
      render: true,
      customData: this.data,
      pageNumber: this.pageNumberStart,
      pageSize: this.pageSizeStart,
      params: undefined,
      customParams: {},
      customColumn: this.columns,
      totalSize: this.total
    };
  },
  methods: {
    pageNumChange(num) {
      this.pageNumber = num;
      this.query();
    },
    pageSizeChange(num) {
      this.pageSize = num;
      this.pageNumber = this.pageNumberStart;
      this.query();
    },
    reset() {
      this.pageNumber = this.pageNumberStart;
      //   this.pageSize = this.pageSizeStart;
    },
    reload() {
      this.render = false;
      this.$nextTick(() => {
        this.render = true;
      })
    },
    //增加清除数据的方法
    clear(fn) {
      this.pageNumber = this.pageNumberStart;
      this.pageSize = this.pageSizeStart;
      this.customData = [];
      if (typeOf(fn) === 'function') {
        fn(this.customParams)
      }
    },
    async setParams(params = this.customParams) {
      if (this.page) {
        if (typeOf(this.page) === "object") {
          this.customParams = {
            ...params,
            [this.page.pageSize]: this.pageSize,
            [this.page.pageNumber]: this.pageNumber
          };
        } else {
          this.customParams = {
            ...params,
            pageSize: this.pageSize,
            pageNumber: this.pageNumber
          };
        }
      } else {
        this.customParams = params;
      }

      //增加参数变化钩子,如果返回object 将覆盖参数,返回false将取消请求
      if (typeOf(this.beforeQuery) === 'function') {
        const result = await this.beforeQuery(this.customParams)
        if (typeOf(result) === 'object') {
          this.params = this.customParams = Object.assign({}, this.customParams, result)
        }
        if (typeOf(result) === 'boolean') {
          return result;
        }
      }
      this.params = this.customParams;
      this.$emit('on-params-change', this.params)
    },
    async query(params, reload = false, callback) {
      if (this.loading) return;
      if (reload) this.reset();
      const cancel = await this.setParams(params);
      if (cancel === false) return;
      this.loading = true;
      if (typeOf(this.onLoad) === "function") {
        let result = await this.onLoad(this.params);
        if (!result) result = {};
        let { data, total } = result;
        if (typeOf(data) === "array") {
          this.customData = data;
        }
        if (typeOf(total) === "number") {
          this.totalSize = total;
        }
        this.loading = false;
        this.$emit('on-finished', this.params, data)
      } else {
        const [err, data] = await this.service(this.params);
        this.loading = false;
        if (err) {
          this.errors(err);
          return;
        }
        if (typeOf(callback) === "function") {
          callback(data);
        }
        if (typeOf(data) === "null") return;
        this.totalSize = data.totalSize;
        this.customData = data.rows;
        this.$emit('on-finished', this.params, data)
        return data;
      }
    }
  }
};
</script>

<style lang="stylus" scoped>
.box {
  .mt-15 {
    margin-top: 15px;
  }
}

.row {
  display: flex;
  justify-content: space-between;
}
</style>
