<style>
.zee-table {
  width: 100%;
}
</style>

<template>
  <el-table
    class="zee-table"
    ref="table"
    :data="tableData"
    v-bind="{ size, ...tableProps }"
    v-on="tableEvents"
    @select="onSelect"
    @select-all="onSelectAll"
    @selection-change="onSelectionChange"
  >
    <!-- 默认表格插槽 -->
    <slot name="default"></slot>
    <!-- 根据配置列表生成表格列 -->
    <template v-if="tableList && tableList.length > 0">
      <template v-for="(item, index) in tableList">
        <template v-if="bindItemVisible(item.visible)">
          <!-- 如果有表格列具名插槽 -->
          <slot v-if="$scopedSlots[item.keyPath.join('-')]" :name="item.keyPath.join('-')" v-bind="item"></slot>
          <!-- 默认表格列渲染 -->
          <el-table-column v-else v-bind="{ ...item, type: undefined }" :prop="item.fullKey || item.key" :key="index" :min-width="minWidth || item.minWidth || item['min-width']">
            <template #default="{ row, column, $index }">
              <cell-render :row="row" :item="item">
                <!-- 如果有表格列值渲染具名插槽 -->
                <slot
                  v-if="$scopedSlots[`value-${item.keyPath.join('-')}`]"
                  :name="`value-${item.keyPath.join('-')}`"
                  v-bind="item"
                  :row="row"
                  :value="$_get(row, item.fullKey)"
                  :column="column"
                  :index="$index"
                ></slot>
                <!-- 如果表格列配置了值渲染参数 -->
                <cell-value-render v-else-if="item.render" :row="row" :column="column" :index="$index" :item="item" />
              </cell-render>
            </template>
          </el-table-column>
        </template>
      </template>
    </template>
    <!-- 已生成列表后的追加列插槽 -->
    <slot name="column-append"></slot>
    <!-- 末尾列插槽 -->
    <slot name="column-end"></slot>
  </el-table>
</template>

<script>
import { cloneDeep, get, set } from '../_utils';
import CellValueRender from './cell-value-render';

export default {
  name: 'Table',
  components: {
    CellRender: {
      props: { row: Object, item: Object },
      render(h) {
        if (this.$scopedSlots.default) {
          return h('span', this.$scopedSlots.default());
        } else {
          return h('span', get(this.row, this.item.agentKey || this.item.fullKey));
        }
      },
    },
    CellValueRender,
  },
  props: {
    // 用于实例化本组件绑定v-model的值
    value: Array,
    // 配置列表
    list: {
      type: Array,
      required: true,
    },
    // 表格参数
    tableProps: {
      type: Object,
      default: () => ({}),
    },
    // 表格事件
    tableEvents: Object,
    // 列宽
    minWidth: Number,
    // 大小
    size: {
      type: String,
      default: 'small',
    },
  },
  data() {
    return {
      tableList: [], // 表格配置列表
      tableData: [], // 表格数据
    };
  },
  computed: {
    // 表格实体
    instance: {
      get() {
        return this.$refs.table;
      },
    },
  },
  watch: {
    value: {
      handler(val = []) {
        this.tableData = val;
      },
      immediate: true,
    },
    list: {
      handler(val) {
        // 深度克隆传入的列表，避免原始值被修改
        const newList = cloneDeep(this.list);
        // 生成列表值的全路径key，即列表项为对象时，对象内的key与上一级的key合并作为全路径key
        const generateFullKey = (list, parentKey) => {
          list.forEach(item => {
            if (item.group && item.list) {
              if (item.group.key) {
                item.fullKey = `${parentKey ? `${parentKey}.${item.group.key}` : item.group.key}`;
              } else {
                item.fullKey = parentKey || item.key;
              }
              generateFullKey(item.list, item.fullKey);
            } else {
              item.fullKey = `${parentKey ? `${parentKey}.${item.key}` : item.key}`;
            }
          });
        };
        // 生成fullKey
        generateFullKey(newList);
        // 创建输出列表
        const result = [];
        // 生成列表值的全路径key，即列表项为对象时，对象内的key与上一级的key合并作为全路径key
        const generateFlatList = list => {
          list.forEach(item => {
            if (item.group && item.list) {
              generateFlatList(item.list);
            } else if (!item.group && !item.list) {
              result.push({ ...item, keyPath: item.fullKey.split('.') });
            }
          });
        };
        generateFlatList(newList);
        this.tableList = result;
      },
      immediate: true,
    },
  },
  methods: {
    $_get: get,
    // 绑定表格列显示隐藏状态
    bindItemVisible(visible = true) {
      let result = visible;
      if (typeof visible === 'function') {
        result = visible(this.tableData);
      }
      return result;
    },
    // 选中单行
    onSelect(selection, row) {
      if (selection.find(i => i.id === row.id)) {
        this.$emit('selection-change', [row], 'check');
      } else {
        this.$emit('selection-change', [row], 'uncheck');
      }
    },
    // 切换全选
    onSelectAll(selection) {
      if (selection && selection.length > 0) {
        this.$emit('selection-change', selection, 'check');
      } else {
        this.$emit('selection-change', this.tableData, 'uncheck');
      }
    },
    // 表格选中
    onSelectionChange(selection) {
      this.$emit('selection', selection);
    },
    // 切换某行选中状态
    toggleRowSelection(row, selected) {
      this.$refs.table && this.$refs.table.toggleRowSelection(row, selected);
    },
    // 清除表格选中
    clearSelection() {
      this.$refs.table && this.$refs.table.clearSelection();
    },
  },
};
</script>
