<template>
  <section class="AiTableSelect">
    <el-row type="flex">
      <ai-table v-if="isShowPagination" ref="PendingTable" :tableData="tableData" :total="page.total" :current.sync="page.current"
                :size.sync="page.size" class="fill" border height="330px" @getList="getTableData" tableSize="mini"
                :col-configs="[{slot: 'resident'}]" layout="slot,->, prev, pager, next, sizes" :pagerCount="5">
        <el-table-column slot="resident" class="ai-table__header">
          <template #header>
            <b v-text="tableTitle"/>
            <el-button type="text" @click="handleSelectAll">全选</el-button>
            <el-input class="fill searchbar" v-model="search[searchKey]" size="small" placeholder="搜索" clearable
                      @change="page.current=1,getTableData()"/>
          </template>
          <template slot-scope="{row}">
            <slot name="pending" v-if="$scopedSlots.pending" :row="row"/>
            <el-row v-else type="flex" justify="space-between" @click.native="handleSelect(row)" class="toggle"
                    :class="{selected:findSelected(row)>-1}">
              <span v-text="row[nodeName]"/>
              <slot name="extra" v-if="$scopedSlots.extra" :row="row"/>
              <span v-else v-text="getExtra(row)"/>
            </el-row>
          </template>
        </el-table-column>
      </ai-table>
      <ai-table v-else ref="PendingTable" :tableData="tableData" class="fill" border height="330px" @getList="getTableData" tableSize="mini"
                :col-configs="[{slot: 'resident'}]" :isShowPagination="false">
        <el-table-column slot="resident">
          <template #header>
            <b v-text="tableTitle"/>
            <el-button type="text" @click="handleSelectAll">全选</el-button>
            <el-input class="fill searchbar" v-model="search[searchKey]" size="small" placeholder="搜索" clearable
                      @change="page.current=1,getTableData()"/>
          </template>
          <template slot-scope="{row}">
            <slot name="pending" v-if="$scopedSlots.pending" :row="row"/>
            <el-row v-else type="flex" justify="space-between" @click.native="handleSelect(row)" class="toggle"
                    :class="{selected:findSelected(row)>-1}">
              <span v-text="row[nodeName]"/>
              <slot name="extra" v-if="$scopedSlots.extra" :row="row"/>
              <span v-else v-text="getExtra(row)"/>
            </el-row>
          </template>
        </el-table-column>
      </ai-table>
      <ai-table :tableData="selected" :col-configs="[{slot:'resident'}]" :isShowPagination="false" border
                height="330px" tableSize="mini" class="el-table--scrollable-y fill">
        <el-table-column slot="resident">
          <template #header>
            <b v-text="`已选择`"/>
            <el-button type="text" @click="selected=[]">清空</el-button>
          </template>
          <template slot-scope="{row,$index}">
            <slot name="selected" v-if="$scopedSlots.selected" :row="row" :index="$index"/>
            <el-row v-else type="flex" align="middle" justify="space-between">
              <div v-text="[row[nodeName], getExtra(row)].join(' ')"/>
              <el-button type="text" @click="selected.splice($index,1)">删除</el-button>
            </el-row>
          </template>
        </el-table-column>
      </ai-table>
    </el-row>
  </section>
</template>

<script>/**
 * 智能列表选择器
 * @displayName AiTableSelect
 */
import {ID} from "../../lib/js/utils";

export default {
  name: "AiTableSelect",
  model: {
    event: "change",
    prop: "value"
  },
  props: {
    /**
     * 接口方法类:必填
     */
    instance: {type: Function, required: true},
    /**
     * 接口方法地址:必填
     */
    action: {default: "", required: true},
    /**
     * 选择表格标题
     */
    tableTitle: {default: "选择列表"},
    /**
     * 选择项
     * @model
     */
    value: {default: ""},
    /**
     * 选择项绑定key
     */
    nodeKey: {default: "id"},
    /**
     * 选择项绑定展示值:必填
     */
    nodeName: {default: "name"},
    /**
     * 是否多选
     */
    multiple: Boolean,
    /**
     * 返回值为选择的对象而不是id
     */
    valueObj: Boolean,
    /**
     * 扩展字段,用于右侧展示
     */
    extra: {default: ""},
    /**
     * 搜索字段,用于搜索框
     */
    searchKey: {default: "con"},
    /**
     * 是否分页
     */
    isShowPagination: {default: true}
  },
  data() {
    return {
      page: {total: 0, current: 1, size: 10},
      search: {},
      tableData: [],
      selected: [],
    }
  },
  watch: {
    action(v) {
      v && (this.page.current = 1, this.getTableData())
    },
    selected: {
      deep: true, handler(v) {
        let ids = v.map(e => e[this.nodeKey] || e).filter(e => !!e)
        this.$emit("change", this.valueObj ? v : this.multiple ? ids : ids?.toString())
        this.$emit("select", v)
      }
    }
  },
  methods: {
    getExtra(row) {
      let {extra} = this
      return extra ? row[extra] : ID.hideId(row.idNumber)
    },
    initValue() {
      let unwatch = this.$watch('value', (v) => {
        if (this.selected.length > 0) unwatch && unwatch()
        else if (!!v) {
          this.selected = this.multiple ? [v].flat().filter(e => !!e) || [] : (v?.split(",") || [])
          unwatch && unwatch()
        }
      }, {immediate: true})
    },
    getTableData() {
      let {page, search, action} = this
      this.instance?.post(action, null, {
        params: {...page, ...search}
      }).then(res => {
        if (res?.data) {
          this.tableData = res.data.records || res.data || []
          this.isShowPagination && (this.page.total = res.data.total)
        }
      })
    },
    handleSelect(row) {
      let index = this.findSelected(row)
      if (index > -1) {
        this.selected.splice(index, 1)
      } else {
        if (this.multiple) {
          this.selected.push(row)
        } else {
          this.selected = [row]
        }
      }
      this.$forceUpdate()
    },
    findSelected(item) {
      let {nodeKey} = this
      return this.selected?.findIndex(e => e[nodeKey] == item[nodeKey])
    },
    handleSelectAll() {
      this.selected = this.$copy(this.tableData)
    }
  },
  created() {
    this.$set(this.search, this.searchKey, "")
    this.initValue()
    this.getTableData()
  }
}
</script>

<style lang="scss" scoped>
.AiTableSelect {
  .el-row {
    width: 100%;

    .ai-table + .ai-table {
      margin-left: 16px;
      width: 400px;

      .ai-table__header > .cell {
        line-height: 40px;
      }
    }
  }

  .toggle {
    cursor: pointer;

    &.selected {
      color: $primaryColor;
    }
  }

  .searchbar {
    padding-right: 0;
  }

  .ai-table__cell {
    .el-button--text {
      padding: 0 8px;
      height: 24px;
    }
  }

  :deep(.ai-table) {
    .ai-table__header {
      & > .cell {
        display: flex !important;
        align-items: center !important;
        justify-content: space-between !important;
      }
    }

    .el-table__header tr th:first-child .cell, .el-table__body tr td:first-child .cell {
      padding-left: 20px !important;
    }
  }

  :deep(.newPagination) {
    padding: 0 !important;

    .el-pagination__rightwrapper {
      flex: 1;

      .el-pagination__sizes {
        margin-right: 0;
      }
    }
  }
}
</style>
