<template>
  <div class="table-list">
    <div class="table-list-hd">
      <!-- 筛选 -->
      <div class="table-list-filter" v-if="filters.length">
        <el-form :inline="true" :model="params" ref="filterForm">
          <template v-for="item in filters">
            <el-form-item :label="item.label" :prop="item.prop" :key="item.prop">
              <template v-if="item.slots">
                <slot :name="item.slots" v-bind="{ params }"></slot>
              </template>
              <template v-else>
                <!-- input -->
                <el-input v-model="params[item.prop]" v-bind="item" clearable v-if="item.type === 'input'" />
                <!-- select -->
                <el-select
                  v-model="params[item.prop]"
                  clearable
                  v-bind="item"
                  v-if="item.type === 'select'"
                  @change="search"
                >
                  <template v-for="(option, index) in item.options">
                    <el-option
                      :label="option[item.labelKey] || option.label"
                      :value="option[item.valueKey] || option.value"
                      :key="index"
                    ></el-option>
                  </template>
                </el-select>
              </template>
            </el-form-item>
          </template>
          <el-form-item class="filter-buttons">
            <el-button type="primary" icon="el-icon-search" @click="search">搜索</el-button>
            <el-button icon="el-icon-refresh-left" @click="reset">重置</el-button>
            <el-button @click="showMoreFilter" v-if="hasMoreFilter">更多筛选</el-button>
          </el-form-item>
        </el-form>
      </div>
      <div class="table-list-hd-aside"><slot name="header-aside" /></div>
    </div>
    <slot></slot>
    <!-- 主体 -->
    <div class="table-list-bd">
      <slot name="body" v-bind="{ data: dataList }">
        <el-table
          :data="dataList"
          v-loading="loading"
          v-bind="$attrs"
          v-on="$listeners"
          style="height: 100%"
          ref="table"
        >
          <template v-for="item in columns">
            <el-table-column v-bind="item" :key="item.prop" v-if="visible(item)">
              <template v-slot:default="scope" v-if="item.slots || item.computed">
                <slot :name="item.slots" v-bind="scope" v-if="item.slots"></slot>
                <div v-html="item.computed(scope)" v-if="item.computed"></div>
              </template>
            </el-table-column>
          </template>
        </el-table>
      </slot>
    </div>
    <!-- 底部 -->
    <div class="table-list-ft">
      <div style="padding: 10px 0">
        <slot name="footer"></slot>
      </div>
      <el-pagination
        class="table-list-pagination"
        layout="total, prev, pager, next, sizes, jumper"
        :page-sizes="[10, 20, 30, 50, 100]"
        :page-size="page.size"
        :total="page.total"
        :current-page.sync="page.currentPage"
        @size-change="pageSizeChange"
        @current-change="fetchList()"
        :hide-on-single-page="true"
        v-if="hasPagination"
      >
      </el-pagination>
    </div>
    <!-- 更多筛选 -->
    <el-drawer title="更多筛选" :visible.sync="moreFilterVisible" ref="drawer">
      <div class="more-filter-drawer">
        <div class="more-filter">
          <el-form :model="params" ref="moreFilterForm">
            <template v-for="item in moreFilters">
              <el-form-item :label="item.label" :prop="item.prop" :key="item.prop">
                <template v-if="item.slots">
                  <slot :name="item.slots" v-bind="{ params }"></slot>
                </template>
                <template v-else>
                  <!-- input -->
                  <el-input v-model="params[item.prop]" v-bind="item" clearable v-if="item.type === 'input'" />
                  <!-- select -->
                  <el-select
                    v-model="params[item.prop]"
                    clearable
                    v-bind="item"
                    v-if="item.type === 'select'"
                    style="width: 100%"
                  >
                    <template v-for="(option, index) in item.options">
                      <el-option
                        :label="option[item.labelKey] || option.label"
                        :value="option[item.valueKey] || option.value"
                        :key="index"
                      ></el-option>
                    </template>
                  </el-select>
                </template>
              </el-form-item>
            </template>
          </el-form>
        </div>
        <div class="more-filter-buttons">
          <el-button @click="cancelMoreFilter">取 消</el-button>
          <el-button type="primary" @click="primaryMoreFilter">确定</el-button>
        </div>
      </div>
    </el-drawer>
  </div>
</template>

<script>
export default {
  name: 'AppList',
  props: {
    // 接口请求
    remote: { type: Object, default: () => ({}) },
    // 筛选
    filters: { type: Array, default: () => [] },
    // 更多筛选
    moreFilters: { type: Array, default: () => [] },
    // 列表项
    columns: { type: Array, default: () => [] },
    // 列表数据
    data: { type: Array, default: () => [] },
    // 是否含有翻页
    hasPagination: { type: Boolean, default: true },
    // 每页多少条数据
    limit: { type: Number, default: 20 }
  },
  data() {
    return {
      loading: false,
      params: this.remote.params || {},
      dataList: this.data,
      page: { total: 0, size: this.limit, currentPage: 1 },
      moreFilterVisible: false
    }
  },
  watch: {
    'remote.params': {
      immediate: true,
      handler(data) {
        this.params = data || {}
      }
    },
    data: {
      immediate: true,
      handler(data) {
        this.dataList = data
      }
    }
  },
  computed: {
    table() {
      return this.$refs.table
    },
    hasMoreFilter() {
      return !!this.moreFilters.length
    }
  },
  methods: {
    fetchList(isReset) {
      /**
       * @param function httpRequest api接口
       * @param function beforeRequest 接口请求之前
       * @param function callback 接口请求成功回调
       */
      const { httpRequest, beforeRequest, callback } = this.remote
      if (!httpRequest) {
        return
      }
      // 参数设置
      let params = this.params
      // 翻页参数设置
      if (this.hasPagination) {
        params.page = (this.page.currentPage - 1).toString()
        params.page_size = this.page.size.toString()
      }
      // 接口请求之前
      if (beforeRequest) {
        params = beforeRequest(params, isReset)
      }
      // for (const key in params) {
      //   if (params[key] === '' || params[key] === undefined || params[key] === undefined) {
      //     delete params[key]
      //   }
      // }
      this.loading = true
      httpRequest(params)
        .then(res => {
          const { data = [], page_info: pageInfo = {} } = res || {}
          this.page.total = parseInt(pageInfo.total_number || '')
          this.dataList = callback ? callback(data) : data
        })
        .catch(() => {
          this.page.total = 0
          this.dataList = []
        })
        .finally(() => {
          this.loading = false
        })
    },
    // 搜索
    search() {
      this.page.currentPage = 1
      this.fetchList()
    },
    // 重置
    reset() {
      // 清空筛选条件
      this.$refs.filterForm && this.$refs.filterForm.resetFields()
      // 清空更多筛选条件
      this.hasMoreFilter && this.$refs.moreFilterForm && this.$refs.moreFilterForm.resetFields()
      // 初始化页码
      this.page.currentPage = 1
      // 刷新列表
      this.fetchList(true)
    },
    // 刷新
    refetch(isForce) {
      isForce ? this.reset() : this.fetchList()
    },
    // 页数改变
    pageSizeChange(value) {
      this.page.currentPage = 1
      this.page.size = value
      this.fetchList()
    },
    visible(item) {
      return Object.prototype.hasOwnProperty.call(item, 'visible') ? item.visible : true
    },
    // 显示更多筛选
    showMoreFilter() {
      this.moreFilterVisible = true
    },
    // 取消更多筛选
    cancelMoreFilter() {
      this.moreFilterVisible = false
      // 清空筛选条件
      this.$refs.moreFilterForm && this.$refs.moreFilterForm.resetFields()
    },
    // 确定更多筛选
    primaryMoreFilter() {
      this.moreFilterVisible = false
      this.search()
    }
  },
  beforeMount() {
    this.fetchList()
  }
}
</script>

<style lang="scss">
.table-list {
  height: 100%;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}
.table-list-hd {
  display: flex;
}
.table-list-filter {
  flex: 1;
}
.table-list-bd {
  flex: 1;
}
.table-list-ft {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.table-list-pagination {
  padding: 10px 0;
  text-align: right;
}
.el-table-column--selection .cell {
  padding: 0 14px !important;
}
.more-filter-drawer {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 0 20px 20px;
  box-sizing: border-box;
}
.more-filter {
  flex: 1;
  overflow-y: auto;
}
.more-filter-buttons {
  display: flex;
  .el-button {
    flex: 1;
  }
}
</style>
