<!--
 组件方法：
 getlist: 将分页组件合并，所以需要分页查询列表的数据的方法
 selectRow：选择行时触发 【配合selectable使用】
 callFunc： 操作按钮点击时触发 【配合tableBtns使用】 会传递按钮的方法名和行数据
 clickColumn： 点击表格列时触发 【配合clickColumns使用】 传递到父级时，接受两个参数，（column，row）点击的列名，行数据
 clickRow: 点击表格行时触发 ps: 建议不要与点击表格列方法同时使用
 changeSort: 表格列排序
-->

<template>
  <div>
    <div class="table-custom">
      <span class="custom-table-btn" @click="showCustomClick">自定义列表</span>
      <el-table v-loading="tableLoading" :data="tableList" border stripe max-height="500" @selection-change="handleSelectionChange" @sort-change="changeSort" @row-click="handleRowClick">
        <el-table-column v-if="selectable" type="selection" width="60" />
        <el-table-column type="index" :index="(index)=>((queryParams.pageNum - 1)*queryParams.pageSize + index + 1)" label="序号" width="60" />
        <el-table-column v-for="(item, index) in tableColumns" :key="index" :label="item.label" :width="item.width" :prop="item.prop" :sortable="sortableColumns.includes(item.prop)" :min-width="clickColumns.includes(item.prop)?150:100">
          <template slot-scope="{row}">
            <el-button v-if="clickColumns.includes(item.prop)" type="text" size="mini" @click="$emit('clickColumn', item.prop, row)">{{ row[item.prop] }}</el-button>
            <span v-else>{{ row[item.prop] }}</span>
          </template>
        </el-table-column>
        <slot name="appendColumn" />
        <el-table-column v-if="tableBtns.length > 0" label="操作" fixed="right" :width="getOpearateWidth()">
          <template slot-scope="{row}">
            <template v-if="tableBtns">
              <template v-for="(item, index) in tableBtns.slice(0, 2)">
                <el-button v-if="btnShow(row, item)" :key="index" type="text" @click.native.stop="call(item.buttonTrigger, row)">{{ item.buttonName }}</el-button>
              </template>
              <template v-if="tableBtns.length > 2">
                <el-dropdown class="ml0" trigger="click">
                  <el-button type="primary" size="mini">
                    更多
                    <i class="el-icon-arrow-down el-icon--right" />
                  </el-button>
                  <el-dropdown-menu slot="dropdown">
                    <template v-for="(btn, idx) in tableBtns.slice(2, tableBtns.length)">
                      <el-dropdown-item v-if="btnShow(row, item)" :key="idx" @click.native.stop="call(btn.buttonTrigger, row)">{{ btn.buttonName }}</el-dropdown-item>
                    </template>
                  </el-dropdown-menu>
                </el-dropdown>
              </template>
            </template>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <pagination :page-sizes="[10, 20, 30, 50, 100, 200]" :total="queryParams.total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="_getTableList" />
    <el-dialog title="自定义字段配置" :visible.sync="columnsetDialogShow" append-to-body class="dialog500" width="60%">
      <el-row :gutter="20">
        <el-col :span="18">
          <el-card shadow="never">
            <div slot="header">
              <el-checkbox v-model="columnCheckAll" @change="val => dialogSelectColumn = val ? tableAllFields.map(item=>item.prop):[] ">可选显示数据列</el-checkbox>
            </div>
            <el-checkbox-group v-model="dialogSelectColumn" style="line-height: 32px">
              <el-checkbox v-for="item in tableAllFields" :key="item.prop" :label="item.prop">{{ item.label }}</el-checkbox>
            </el-checkbox-group>
          </el-card>
        </el-col>
        <el-col :span="6">
          <el-card shadow="never">
            <div slot="header">
              已选{{ dialogSelectColumn.length }}项
              <span class="ml0" style="font-size: 8px">(可拖动排序)</span>
            </div>
            <draggable :list="dialogSelectColumn" :animation="340" group="column">
              <div v-for="item in dialogSelectColumn" :key="item" class="hover-pointer">
                <div style="line-height: 24px;">{{ tableAllFields.find(column=> column.prop === item).label }}</div>
              </div>
            </draggable>
          </el-card>
        </el-col>
      </el-row>

      <span slot="footer">
        <el-button @click="columnsetDialogShow = false">取消</el-button>
        <el-button type="primary" @click="handleChangeColumns">确定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import draggable from 'vuedraggable';
export default {
  components: { draggable },
  props: {
    tableList: {
      type: Array,
      default: () => []
    },
    tableLoading: {
      type: Boolean,
      default: false
    },
    queryParams: {
      required: true,
      type: Object,
      default: () => ({
        pageNum: 1,
        pageSize: 10,
        total: 0
      })
    },
    // 表格操作按钮
    tableBtns: {
      type: Array,
      default: () => []
    },
    // 表格可选
    selectable: {
      type: Boolean,
      default: false
    },
    /**
     * 接口访问得到的所有表格列/或者写死的表格列格
     * 格式是： { pror: '', label: '' }
     */
    tableAllFields: {
      required: true,
      type: Array,
      default: () => []
    },
    /**
     * 默认表格列
     * 字符串数组： prop 对应值（字段名）
     */
    defaultColumns: {
      type: Array,
      default: () => []
    },
    tablename: {
      type: String,
      default: ''
    },
    // 可点击的列
    clickColumns: {
      type: Array,
      default: () => []
    },
    // 控制按钮隐藏
    btnShowValid: {
      type: Array,
      default: () => []
    },
    // 可排序的列
    sortableColumns: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      columnsetDialogShow: false,
      columnCheckAll: false,
      dialogSelectColumn: [],
      name: this.tablename || this.$route.name,
      customColumns: [], // 本地缓存的表格列
      tableColumns: [] // 实际展示表格列
    };
  },
  watch: {
    tableAllFields: {
      handler(val) {
        const localStr = localStorage.getItem(this.name);
        const arr = localStr ? localStr.split(',') : [];
        if (this.isNullOrEmpty(arr)) {
          this.tableColumns = val
            .filter((item) => this.defaultColumns.includes(item.prop))
            .sort((a, b) => this.defaultColumns.indexOf(a.prop) - this.defaultColumns.indexOf(b.prop));
          this.customColumns = this.defaultColumns;
        } else {
          this.tableColumns = val.filter((item) => arr.includes(item.prop)).sort((a, b) => arr.indexOf(a.prop) - arr.indexOf(b.prop));
        }
      },
      immediate: true,
      deep: true
    }
  },
  created() {
    if (this.isNullOrEmpty(this.customColumns)) {
      const localStr = localStorage.getItem(this.name);
      this.customColumns = localStr ? localStr.split(',') : [];
    }
  },
  methods: {
    showCustomClick() {
      this.columnsetDialogShow = true;
      this.dialogSelectColumn = [...this.customColumns];
    },
    handleChangeColumns() {
      this.customColumns = this.dialogSelectColumn;
      this.tableColumns = this.tableAllFields
        .filter((item) => this.customColumns.includes(item.prop))
        .sort((a, b) => this.customColumns.indexOf(a.prop) - this.customColumns.indexOf(b.prop));
      localStorage.setItem(this.name, this.customColumns.join(','));
      this.columnsetDialogShow = false;
    },
    _getTableList() {
      this.$emit('update:queryParams', this.queryParams);
      this.$emit('getlist');
    },
    handleSelectionChange(row) {
      this.selectable && this.$emit('selectRow', row);
    },
    changeSort(val) {
      this.$emit('changeSort', val);
    },
    handleRowClick(row) {
      this.$emit('clickRow', row);
    },
    call(funcName, row) {
      this.$emit('callFunc', funcName, row);
    },
    getOpearateWidth() {
      let width = 30;
      for (let index = 0; index < this.tableBtns.length; index++) {
        if (index < 2) {
          const column = this.tableBtns[index];
          width += column.buttonName.length * 15;
          column.buttonColor !== 'text' && (width += 30);
        } else {
          width += 70; // 更多
          break;
        }
      }
      return width;
    },
    btnShow(row, btn) {
      if (this.isNullOrEmpty(this.btnShowValid)) {
        return true;
      } else {
        let show = true;
        for (let i = 0; i < this.btnShowValid.length; i++) {
          const valid = this.btnShowValid[i];
          if (row[valid.key] === valid.value) {
            show = btn.buttonName !== valid.btnName;
          }
        }
        return show;
      }
    }
  }
};
</script>

<style scoped>
.table-custom {
  width: calc(100% - 30px);
  position: relative;
}
.custom-table-btn {
  width: 30px;
  display: block;
  position: absolute;
  right: -31px;
  top: 0;
  text-align: center;
  color: cadetblue;
  border: 1px solid #e6ebf5;
  font-size: 14px;
  padding: 5px;
  box-sizing: border-box;
  cursor: pointer;
}
</style>
