<template>
  <el-container style="background: #fff;width: 1000px;border: 1px solid #eee;">
    <el-container>
      <el-header class="middle-header">
        <div style="padding: 10px 0">
          <el-input
            size="small"
            style="width:376px"
            clearable
            placeholder="名称、编码"
            prefix-icon="el-icon-search"
            @keyup.enter.native="search"
            v-model="searchWord"
          ></el-input>
          <el-button
            style="margin-left: 20px"
            size="small"
            type="primary"
            icon="el-icon-search"
            @click="search"
            :disabled="loading"
            >查询</el-button
          >
          <el-button
            size="small"
            :disabled="loading"
            @click="reset"
            icon="el-icon-refresh"
            >重置</el-button
          >
        </div>
      </el-header>
      <el-main style="padding:0">
        <el-table
          :data="data"
          v-loading="loading"
          ref="demTable"
          stripe
          border
          height="490"
          @row-click="handleRowClick"
          @select="handleTableSelect"
          @select-all="handleTableSelect"
          class="dem-table"
          size="small"
        >
          <el-table-column
            type="selection"
            align="center"
            width="45"
            v-if="!this.single"
          ></el-table-column>
          <el-table-column align="center" width="50" v-if="this.single">
            <template slot-scope="scope">
              <el-radio v-model="selectedId" :label="scope.row.id"></el-radio>
            </template>
          </el-table-column>
          <el-table-column
            type="index"
            width="50"
            align="center"
            label="序号"
          ></el-table-column>
          <el-table-column
            prop="name"
            label="名称"
            width="300"
          ></el-table-column>
          <el-table-column prop="code" label="编码"></el-table-column>
        </el-table>
      </el-main>
      <el-footer height="50px">
        <el-row type="flex" justify="end">
          <el-pagination
            small
            :disabled="loading"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="pagination.page"
            :page-sizes="[10, 50, 100, 200, 300]"
            :page-size="pagination.pageSize"
            :pager-count="11"
            layout="total, sizes, prev, pager, next, jumper"
            :total="pagination.total"
          ></el-pagination>
        </el-row>
      </el-footer>
    </el-container>
    <el-aside width="80px" class="right-aside">
      <div class="selector-button-group">
        <el-button size="small" @click="move('up')">上移</el-button>
        <el-button size="small" @click="move('down')">下移</el-button>
        <el-button size="small" @click="removeSelected">删除</el-button>
        <el-button size="small" @click="clearAllSelects">清空</el-button>
      </div>
    </el-aside>
    <el-aside width="140px" class="select-aside">
      <el-header class="select-header">
        <span style="font-size: 14px;">已选择维度</span>
      </el-header>
      <div class="select-tree-div">
        <el-tree
          small
          ref="selectTree"
          node-key="name"
          :props="{ label: 'name' }"
          :data="selects"
          show-checkbox
          check-on-click-node
        ></el-tree>
      </div>
    </el-aside>
  </el-container>
</template>
<script>
import utils from '@/utils.js'
import { setTimeout } from 'timers'

export default {
  name: 'demension-selector',
  props: {
    value: {
      type: Array,
      default: () => {
        return []
      }
    },
    data: Array,
    single: {
      type: Boolean,
      default: false
    },
    // 服务端分页
    pagination: {
      type: Object,
      default: () => {
        return {
          page: 1,
          pageSize: 50,
          total: 31214
        }
      }
    }
  },
  data() {
    return {
      loading: false,
      searchWord: null,
      // 客户端分页
      paging: {
        page: 1,
        pageSize: 50
      },
      selectedId: null,
      selects: []
    }
  },
  watch: {
    data: function(newVal) {
      if (newVal && newVal.length > 0) {
        this.syncCheckedStatus()
      }
    }
  },
  created() {
    // 组件初始化时，复制一份分页信息
    this.oldPaging = { ...this.paging }
  },
  methods: {
    // 同步已选行到已选数据中去
    syncSelection2selects() {
      // 复制一份当前已选数据
      let tmpSelects = [...this.selects]
      // 先将当前页中的数据从已选数据中移除
      this.data.forEach(m => {
        tmpSelects.remove(m)
      })
      // 将剩余的已选数据与当前页选中的数据合并
      tmpSelects = [...tmpSelects, ...this.$refs.demTable.selection]
      // 数组去重
      this.selects = tmpSelects.unique('id')
    },
    // 同步已选数据在Table中的选中状态
    syncCheckedStatus() {
      this.selectedId = null
      if (this.single) {
        this.selects.length === 1 && (this.selectedId = this.selects[0].id)
      } else {
        if (!this.$refs.demTable || !this.$refs.demTable.selection) {
          throw '未获取到维度列表，无法选择维度。'
        }
        this.$refs.demTable.clearSelection()
        this.selects.length > 0 &&
          setTimeout(() => {
            this.selects.forEach(m => {
              if (
                this.data.some(n => {
                  return utils.objectEquals(m, n)
                })
              ) {
                this.$refs.demTable.toggleRowSelection(m)
              }
            })
          })
      }
    },
    onShow() {
      // 每一次显示选择器时，重置当前选中数据为外部的v-model对象
      this.selects = [...this.value]
      this.reset()
    },
    onHide(sure) {
      // 在隐藏选择器时，如果点击的是确定按钮，则将当前选中数据更新到外部的v-model对象上
      if (sure) {
        this.$emit('input', this.selects)
      }
    },
    // 加载数据，根据当前的搜索关键词及分页条件
    load() {
      this.loading = true
      this.$emit(
        'load',
        {
          searchWord: this.searchWord,
          paging: this.paging
        },
        () => {
          this.loading = false
        }
      )
    },
    // 搜索事件
    search() {
      if (!this.searchWord || this.loading) {
        return
      }
      this.paging = this.oldPaging
      this.load()
    },
    // 重置事件
    reset() {
      this.searchWord = null
      this.paging = this.oldPaging
      this.load()
    },
    handleRowClick(row, column, event) {
      if (this.single) {
        this.selects = [row]
        this.selectedId = row.id
      } else {
        if (!this.$refs.demTable || !this.$refs.demTable.selection) {
          throw '未获取到维度列表，无法选择维度。'
        }
        let _tag = true
        this.$refs.demTable.selection.forEach(m => {
          if (m === row) {
            // 已选中该行时，取消选中状态
            this.$refs.demTable.toggleRowSelection(row, false)
            _tag = false
          }
        })
        // 非取消选中情况下，将当前行设置为选中状态
        _tag && this.$refs.demTable.toggleRowSelection(row)
        this.syncSelection2selects()
      }
    },
    handleTableSelect() {
      this.syncSelection2selects()
    },
    handleSizeChange(size) {
      this.paging.pageSize = size
      this.load()
    },
    handleCurrentChange(currentPage) {
      this.paging.page = currentPage
      this.load()
    },
    move(direct) {
      let selectedAry = this.$refs.selectTree.getCheckedNodes()
      // 将调整顺序之后的数组赋值给Tree
      this.selects = utils.arrayMove(this.selects, selectedAry, direct)
      setTimeout(() => {
        // 调整顺序后恢复勾选状态
        this.$refs.selectTree.setCheckedNodes(selectedAry)
      })
    },
    removeSelected() {
      let selectedAry = this.$refs.selectTree.getCheckedNodes()
      selectedAry.forEach(item => {
        this.selects.remove(item)
      })
      this.syncCheckedStatus()
    },
    clearAllSelects() {
      this.selects = []
      this.syncCheckedStatus()
    }
  }
}
</script>
<style lang="scss" scoped>
.middle-header {
  height: 52px !important;
}

.dem-table {
  width: 100%;
}

.right-aside {
  border-left: 1px solid #eee;
}

.select-aside {
  border-left: 1px solid #eee;
}

.select-header {
  border-bottom: 1px solid #eee;
  height: 52px !important;
}

.select-header > span {
  padding: 10px 0;
  line-height: 53px;
}

.select-tree-div {
  height: 500px;
  overflow-y: auto;
}

.selector-button-group {
  width: 60px;
  height: 170px;
  margin: 0px auto;
  position: relative;
  top: 50%;
  -webkit-transform: translateY(-50%);
  -moz-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  -o-transform: translateY(-50%);
  transform: translateY(-50%);
}

.selector-button-group > button {
  display: block;
  margin: 8px 0;
}

>>> .el-footer {
  padding: 10px 20px;
  overflow: hidden;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  -ms-flex-negative: 0;
  flex-shrink: 0;
}

>>> .el-tree__empty-text {
  font-size: 13px;
}

>>> .el-pagination__sizes {
  margin-top: -2px;
}

>>> span.el-radio__label {
  display: none;
}
</style>
