<template>
  <a-table
    ref="tableRef"
    class="custom-table"
    :class="['custom-table', canSelect && multiple && mouseMoveSelect ? 'mouse-move-select' : '']"
    v-bind="$attrs"
    :data-source="list"
    :columns="columns"
    :size="size"
    :row-key="rowKey"
    :loading="loading"
    :pagination="pagination"
    :customRow="multiple && mouseMoveSelect ? customMouseMoveSelectRow : customRow"
    :rowClassName="(record, index) => innerRowClassName(record, index)"
    @change="handleTableChange"
  >
    <!-- 处理 scopedSlots -->
    <template v-for="slotName of scopedSlotsKeys" :slot="slotName" slot-scope="text, record, index">
      <slot :name="slotName" :text="text" :record="record" :index="index"></slot>
    </template>
  </a-table>
</template>
<script>
export default {
  props: {
    list: {
      type: Array,
      default: () => []
    },
    columns: {
      type: Array,
      default: () => []
    },
    size: {
      type: String,
      default: 'middle'
    },
    rowKey: {
      type: String,
      default: 'id'
    },
    loading: {
      type: Boolean
    },
    pagination: {
      type: [Object, Boolean]
    },
    selectedRowKeys: {
      type: Array
    },
    selectionRows: {
      type: Array
    },
    canSelect: {
      type: Boolean,
      default: true
    },
    canDeselect: {
      type: Boolean,
      default: true
    },
    // 多选
    multiple: {
      type: Boolean,
      default: false
    },
    // 鼠标移动选择
    mouseMoveSelect: {
      type: Boolean,
      default: true
    },
    customRowClassName: {
      type: Function
    }
  },
  data() {
    return {
      innerSelectedRowKeys: [],
      innerSelectedRows: []
    }
  },
  mounted() {
    if (this.canSelect && this.multiple && this.mouseMoveSelect) {
      const tbody = this.$el.querySelector('.ant-table-tbody')
      tbody.addEventListener('mouseleave', () => {
        this.mouseMoveStartIndex = undefined
      })
    }
  },
  methods: {
    innerRowClassName(record, index) {
      let className = ''
      if (this.customRowClassName) {
        className = this.customRowClassName({ record, index })
      }
      return (this.canSelect ? 'custom-table-row' : '') + ' ' + className
    },

    // 实现单击选中/反选功能
    customRow(record, index) {
      const key = record[this.rowKey]
      return {
        class: this.innerSelectedRowKeys.includes(key) ? 'ant-table-row-selected' : '',
        on: {
          click: () => {
            if (!this.canSelect) {
              return
            }
            // 反选
            if (this.innerSelectedRowKeys.includes(key)) {
              if (this.multiple || this.canDeselect) {
                const findIndex = this.innerSelectedRowKeys.findIndex(k => k == key)
                this.innerSelectedRowKeys.splice(findIndex, 1)
              }
            }
            // 选中
            else {
              if (this.multiple) {
                this.innerSelectedRowKeys.push(key)
              } else {
                this.innerSelectedRowKeys = [key]
              }
            }
            this.$emit('detail', record)

            this.$emit('rowClick', record, index)
          },
          dblclick: () => {
            this.$emit('rowDblClick', record, index)
          }
        }
      }
    },

    // 实现鼠标拖移动多选功能
    customMouseMoveSelectRow(record, index) {
      const key = record[this.rowKey]
      return {
        class: this.innerSelectedRowKeys.includes(key) ? 'ant-table-row-selected' : '',
        on: {
          mousedown: () => {
            this.innerSelectedRowKeys = []
            this.mouseMoveStartIndex = index
          },
          mouseenter: () => {
            if (this.mouseMoveStartIndex !== undefined) {
              const indexes = [this.mouseMoveStartIndex, index].sort((a, b) => a - b)
              this.innerSelectedRowKeys = this.list.slice(indexes[0], indexes[1] + 1).map(item => item[this.rowKey])
            }
          },
          mouseup: () => {
            // 开始和结束在同一个，相当于click
            if (this.mouseMoveStartIndex == index) {
              this.innerSelectedRowKeys = [key]
            }
            this.mouseMoveStartIndex = undefined
          }
        }
      }
    },

    handleTableChange(pagination, filters, sorter) {
      this.$emit('change', pagination, filters, sorter)
    },

    // 让第index行滚动到视野范围
    scrollIntoView(index) {
      const tableEle = this.$refs.tableRef.$el
      const tableBodyEle = tableEle.querySelector('.ant-table-body')
      const prevEle = tableBodyEle.querySelector(`.ant-table-row:nth-child(${index + 1})`)
      tableBodyEle.scrollTop = prevEle.offsetTop
    }
  },
  watch: {
    selectedRowKeys(val) {
      this.innerSelectedRowKeys = val
    },
    innerSelectedRowKeys() {
      this.$emit('update:selectedRowKeys', this.innerSelectedRowKeys)
      this.innerSelectedRows = this.innerSelectedRowKeys.map(key => {
        return this.list.find(item => item[this.rowKey] === key)
      })
      this.$emit('update:selectionRows', this.innerSelectedRows)
    }
  },
  computed: {
    scopedSlotsKeys() {
      return Object.keys(this.$scopedSlots)
    }
  }
}
</script>
<style lang="less" scoped>
::v-deep {
  .custom-table-row {
    cursor: pointer;
  }

  .ant-table-bordered .ant-table-header > table,
  .ant-table-bordered .ant-table-body > table,
  .ant-table-bordered .ant-table-fixed-left table,
  .ant-table-bordered .ant-table-fixed-right table {
    border-color: #416f7f;
  }

  .ant-table-bordered .ant-table-thead > tr > th,
  .ant-table-bordered .ant-table-tbody > tr > td {
    border-color: #416f7f;
  }
}

.mouse-move-select {
  user-select: none;

  ::v-deep {
    td {
      transition: none !important;
    }
  }
}
</style>
