<template>
  <el-container class="e_c auto_height fullheight ">
    <el-container class="fullheight">
      <div class="ht-header__search">
        <el-input
          size="small"
          style="max-width:200px"
          class="ht-header__input"
          clearable
          @clear="clear"
          :placeholder="searchPlaceholder"
          prefix-icon="el-icon-search"
          @keyup.enter.native="search"
          v-model="searchWord"
        ></el-input>
        <div class="ht-search__btn">
          <el-button
            size="small"
            type="primary"
            icon="el-icon-search"
            @click="search"
            :disabled="loading"
            >{{ t("ht.common.search") }}</el-button
          >
          <el-button
            size="small"
            :disabled="loading"
            @click="reset"
            icon="el-icon-refresh"
            >{{ t("ht.common.reset") }}</el-button
          >
        </div>
      </div>
      <el-main style="padding:0">
        <el-table
          :data="data"
          v-loading="loading"
          ref="selectorTable"
          stripe
          border
          :highlight-current-row="single"
          @row-click="handleRowClick"
          @select="handleTableSelect"
          @select-all="handleTableSelect"
          class="ht-selector__table"
          :size="sizeType"
        >
          <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
            v-if="sizeType == 'small'"
            type="index"
            width="60"
            align="center"
            :label="t('ht.common.index')"
          ></el-table-column>
          <el-table-column
            align="center"
            :prop="column.prop"
            :label="column.label"
            :width="column.width"
            v-for="(column, index) in tableColumns"
            :key="index"
          >
            <template slot-scope="scope">
              <el-tooltip
                class="item"
                effect="dark"
                :disabled="hideTip(column.tipField, scope.row[column.tipField])"
                :content="scope.row[column.tipField]"
                placement="top-end"
              >
                <div class="cell" v-if="column.type == 'timestamp'">
                  {{
                    scope.row[column.prop] | dateformat("YYYY-MM-DD HH:mm:ss")
                  }}
                </div>
                <div class="cell" v-else>{{ scope.row[column.prop] }}</div>
              </el-tooltip>
            </template>
          </el-table-column>
        </el-table>
      </el-main>
      <el-footer class="ht-footer__pagination" 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="5"
            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="sizeType" @click="move('up')">{{
          t("ht.common.up")
        }}</el-button>
        <el-button :size="sizeType" @click="move('down')">{{
          t("ht.common.down")
        }}</el-button>
        <el-button :size="sizeType" @click="removeSelected">{{
          t("ht.common.remove")
        }}</el-button>
        <el-button :size="sizeType" @click="clearAllSelects">{{
          t("ht.common.clear")
        }}</el-button>
      </div>
    </el-aside>
    <el-aside width="140px" class="select-aside">
      <el-header class="select-header">
        <span style="font-size: 14px;">{{ t("ht.common.selected") }}</span>
      </el-header>
      <div class="select-tree-div">
        <el-tree
          small
          ref="selectTree"
          node-key="id"
          :props="treeProps"
          :data="selects"
          :default-checked-keys="defaultCheckedKeys"
          show-checkbox
          check-on-click-node
        ></el-tree>
      </div>
    </el-aside>
  </el-container>
</template>
<script>
import utils from "@/utils.js";
import { setTimeout } from "timers";
import Locale from "@/mixins/locale";

export default {
  name: "ht-selector",
  mixins: [Locale],
  props: {
    searchPlaceholder: {
      type: String,
      default: ""
    },
    selectLabel: {
      type: String,
      default: "name"
    },
    tableColumns: {
      type: Array,
      default: () => {
        return [];
      }
    },
    value: {
      type: Array,
      default: () => {
        return [];
      }
    },
    data: Array,
    single: {
      type: Boolean,
      default: false
    },
    //服务端分页
    pagination: {
      type: Object,
      default: () => {
        return {
          page: 1,
          pageSize: 10,
          total: 31214,
          showTotal: true
        };
      }
    },
    quickSearchProps: {
      type: [String, Array],
      required: true
    },
    //唯一标识字段
    primaryField: {
      type: String,
      default: ""
    }
  },
  data() {
    return {
      sizeType: "small",
      loading: false,
      searchWord: null,
      //客户端分页
      paging: {
        page: 1,
        pageSize: 10
      },
      selectedId: null,
      selects: [],
      defaultCheckedKeys: [],
      currentSelectData: []
    };
  },
  computed: {
    treeProps: function() {
      return { label: this.selectLabel };
    }
  },
  watch: {
    data: function(newVal) {
      if (newVal && newVal.length > 0) {
        this.syncCheckedStatus();
      }
    },
    selects: {
      handler(val) {
        this.currentSelectData = val;
      },
      deep: true
    }
  },
  created() {
    // 组件初始化时，复制一份分页信息
    this.oldPaging = { ...this.paging };
    if (this.$smallScreenDialog) {
      this.sizeType = "mini";
    }
  },
  methods: {
    hideTip(tipField, val) {
      if (!tipField || !val) {
        return true;
      }
      return false;
    },
    getSelectedData() {
      return this.currentSelectData;
    },
    // 同步已选行到已选数据中去
    syncSelection2selects() {
      // 复制一份当前已选数据
      let tmpSelects = [...this.selects];
      // 先将当前页中的数据从已选数据中移除
      this.data.forEach(m => {
        tmpSelects.remove(m);
      });
      // 将剩余的已选数据与当前页选中的数据合并
      tmpSelects = [...tmpSelects, ...this.$refs.selectorTable.selection];
      // 数组去重
      this.selects = tmpSelects.unique(
        this.primaryField ? this.primaryField : "id"
      );

      this.defaultCheckedKeys = this.defaultCheckedKeys.concat(
        this.$refs.selectorTable.selection.extractByKey("id")
      );
    },
    // 同步已选数据在Table中的选中状态
    syncCheckedStatus() {
      this.selectedId = null;
      if (this.single) {
        this.selects.length === 1 && (this.selectedId = this.selects[0].id);
      } else {
        if (!this.$refs.selectorTable || !this.$refs.selectorTable.selection) {
          throw "未获取到数据列表，无法选择数据。";
        }
        this.$refs.selectorTable.clearSelection();
        this.selects.length > 0 &&
          setTimeout(() => {
            this.selects.forEach(m => {
              if (
                this.data.some(n => {
                  return utils.objectEquals(m, n);
                })
              ) {
                this.$refs.selectorTable.toggleRowSelection(m);
              }
            });
          });
      }
    },
    onShow(initSelectors) {
      // 每一次显示选择器时，重置当前选中数据为外部的v-model对象
      if (!initSelectors) {
        this.selects = [...this.value];
      } else {
        this.selects = initSelectors;
      }
      this.defaultCheckedKeys = this.selects.extractByKey("id");
      this.reset();
    },
    onHide(sure) {
      // 在隐藏选择器时，如果点击的是确定按钮，则将当前选中数据更新到外部的v-model对象上
      if (sure) {
        this.$emit("input", this.selects);
      }
    },
    getQueryFilter(isPageChange) {
      let queryFilter = {
        querys: [],
        pageBean: this.paging
      };

      if (
        this.quickSearchProps &&
        this.quickSearchProps.constructor == String &&
        this.searchWord
      ) {
        //有搜索条件并且不是切换分页的时候，重置分页
        if (!isPageChange) {
          queryFilter.pageBean.page = 1;
        }

        let props = this.quickSearchProps.split(",");
        props.forEach(item => {
          let query = {
            property: item,
            value: this.searchWord,
            group: "main",
            operation: "LIKE",
            relation: "OR"
          };
          queryFilter.querys.push(query);
        });
      }

      return queryFilter;
    },
    // 加载数据，根据当前的搜索关键词及分页条件
    load(isPageChange) {
      this.loading = true;

      this.$emit("load", this.getQueryFilter(isPageChange), () => {
        this.loading = false;
      });
    },
    // 搜索事件
    search() {
      if (this.loading) {
        return;
      }
      this.paging = this.oldPaging;
      this.load();
    },
    // 重置事件
    reset() {
      this.$emit("reset");
      this.searchWord = null;
      this.paging = this.oldPaging;
      this.load();
    },
    clear() {
      this.reset();
    },
    handleRowClick(row, column, event) {
      if (this.single) {
        this.selects = [row];
        this.selectedId = row.id;
        this.defaultCheckedKeys = [];
        this.defaultCheckedKeys.push(this.selectedId);
      } else {
        if (!this.$refs.selectorTable || !this.$refs.selectorTable.selection) {
          throw "未获取到数据列表，无法选择数据。";
        }
        let _tag = true;
        this.$refs.selectorTable.selection.forEach(m => {
          if (m === row) {
            // 已选中该行时，取消选中状态
            this.$refs.selectorTable.toggleRowSelection(row, false);
            _tag = false;
          }
        });
        // 非取消选中情况下，将当前行设置为选中状态
        _tag && this.$refs.selectorTable.toggleRowSelection(row);
        this.syncSelection2selects();
      }
      this.$emit("row-click", row, column, event);
    },
    handleTableSelect(selection, row) {
      this.syncSelection2selects();
      this.$emit("select", selection, row);
    },
    handleSizeChange(size) {
      this.paging.pageSize = size;
      this.load();
    },
    handleCurrentChange(currentPage) {
      this.paging.page = currentPage;
      this.load(true);
    },
    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>
.el-table .cell {
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: normal;
  word-break: break-all;
  line-height: 23px;
  padding-left: 0px;
  padding-right: 0px;
}
.e_c {
  background: #fff;
  width: 100%;
  border: 1px solid #eee;
}

.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: calc(100% - 60px);
}

.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;
}

.pagination-class >>> {
  padding: 10px;
}

.pagination-class >>> .el-pagination__total {
  margin-right: 5px;
}

.pagination-class >>> .el-pagination__sizes {
  margin-right: 5px;
}

.pagination-class >>> .el-pagination__jump {
  margin-left: 10px;
}
</style>
