<!--
 * @Tite: 支持分页远程搜索功能的[el-select]下拉框
 * @Author: Rockery <1113269755@qq.com>
-->

<template>
  <div class="paginationselect">
    <el-select
      v-model="selectModelValue"
      ref="paginationSelectRef"
      filterable
      remote
      :clearable="clearable"
      reserve-keyword
      :size="size"
      style="width: 100%;"
      :popper-class="purposeType != 'QUERY'?'paginationselect-select paginationselect-noquery':'paginationselect-select'"
      placeholder="请选择路段或输入关键词搜索"
      :remote-method="handleSelectRemoteMethod"
      :loading="remoteLoading"
      @change="handleSelectChange"
      @visible-change="handleSelectVisibleChange"
    >
      <div class="paginationselect-currentselectoption">
        <el-divider>选中选项</el-divider>
        <el-option
          :key="currentSelectOption.id"
          :label="currentSelectOption.label"
          remote
          disabled
          :value="currentSelectOption.value"
          placeholder="当前选中值"
        />
      </div>

      <el-option
        v-for="item in selectOptiones"
        :key="item.id || getComponentKey('OPTION_KEY-')"
        :label="item.label"
        remote
        :value="item.value"
        placeholder="请选择"
      />

      <el-pagination
        v-show="total>0"
        small
        class="fr mt5 mb10"
        :total="total"
        @current-change="handleCurrentChange"
        :current-page.sync="currentPage"
        :page-size.sync="currentPageSize"
        layout="total, prev, pager, next"
      />
    </el-select>
  </div>
</template>

<script>

export default {
  name: "CustPaginationSelect",
  props: {
    // 向父组件传递查询参数数据
    value: String,
    // 远程查询方法
    queryFun: {
      type: Function,
      require: true
    },
    // 父组件操作方式
    parentOperationType: {
      type: String,
      require: false,
      default: ''
    },
    // 下拉框大小
    size: {
      type: String,
      require: false
    },
    // 起始页码
    pageNum: {
      type: Number,
      default: 1
    },
    // 每一页目录条数
    pageSize: {
      type: Number,
      default: 10
    },
    // 查询条件
    queryConditions: {
      required: false,
      type: Object,
      default: () => ({})
    },
    // 关键字
    keywordField: {
      type: String,
      require: false,
      default() {
        return 'label';
      }
    },
    // 选项对象属性
    defaultProps: {
      required: false,
      type: Object,
      default() {
        return {
          id: 'id',
          value: 'value',
          label: 'label'
        };
      }
    },
    // 应用类型
    purposeType: {
      type: String,
      require: false,
      default() {
        return 'QUERY';
      }
    },
    // 是否立即查询
    isImmediatelyQuery: {
      type: Boolean,
      require: false,
      default: true
    },
    // 是否设置默认值
    isSetDefaultValue: {
      type: Boolean,
      require: false,
      default: false
    },
    // 是否可以清空
    clearable: {
      type: Boolean,
      require: false,
      default: true
    }
  },
  data() {
    return {
      // 当前选中选项
      currentSelectOption: {},
      // 远程搜索定时器
      handleRemoteTimeout: null,
      // 下拉框选项列表
      selectOptiones: [],
      // 是否正在从远程获取数据
      remoteLoading: false,
      // 列表查询入参
      queryParams: {},
      // 操作方式
      operationType: '',
      // 数据总数
      total: 0
    };
  },
  computed: {
    // 组件绑定值
    selectModelValue: {
      get() {
        return this.value;
      },
      set(value) {
        this.$emit('input', value);
      }
    },
    // 当前页码
    currentPage: {
      get() {
        return this.pageNum;
      },
      set(val) {
        this.$emit('update:pageNum', val);
      }
    },
    // 当前每一页目录条数
    currentPageSize: {
      get() {
        return this.pageSize;
      },
      set(val) {
        this.$emit('update:pageSize', val);
      }
    },
    // 查询条件
    currentQueryConditions: {
      get() {
        return this.queryConditions;
      },
      set(val) {
        this.$emit('update:queryConditions', val);
      }
    }
  },
  watch: {
    value(newValue, oldValue) {
      if (!this.operationType) {
        this.parentOperationType != 'CANCEL' && this.initData(newValue);
      } else {
        this.parentOperationType != '';
      }
    },
    isImmediatelyQuery() {
      this.initData();
    }
  },
  created() {
    if (this.parentOperationType == 'EDIT') {
      this.value && this.initData(this.value);
    } else {
      this.initData(this.value);
    }
  },
  mounted() {

  },
  methods: {
    /** 初始化数据 */
    initData(currModelValue) {
      this.initCurrentOption(currModelValue);
      this.assembleQueryParams();
      if (this.isImmediatelyQuery) {
        this.selectOptiones = [];
        this.option = 0;
        this.getOptiones();
      }
    },
    /** 组装查询条件 */
    assembleQueryParams() {
      this.queryParams[this.keywordField] = '';
      this.queryParams['pageNum'] = this.currentPage;
      this.queryParams['pageSize'] = this.currentPageSize;
      for (let item in this.currentQueryConditions) {
        this.queryParams[item] = this.currentQueryConditions[item];
      }
    },
    /** 初始化当前数据项 */
    initCurrentOption(param) {
      if (param) {
        this.getCurrentOption(param);
      } else {
        this.currentSelectOption = { id: `curr_page_select_${new Date().getTime()}`, value: `curr_page_select_${new Date().getTime()}`, label: '暂无选中数据' };
      }
    },
    /** 初始化拉框选项数据 */
    initGetOptiones() {
      // 开启加载状态
      this.remoteLoading = true;
      this.selectOptiones = [];
      this.option = 0;
      this.getOptiones();
    },
    /** 获取当前选中选项数据 */
    getCurrentOption(param) {
      let queryCurrReq = { pageNum: 1, pageSize: 2 };
      queryCurrReq[this.defaultProps.value] = param;

      this.queryFun(queryCurrReq).then(
        response => {
          let currentOptiones = (response?.rows || []).map((item, index) => {
            return Object.assign({}, { id: `curr_page_select_${new Date().getTime()}`, value: item[this.defaultProps?.value], label: item[this.defaultProps?.label] });
          });
          this.currentSelectOption = (currentOptiones?.length > 0) ? currentOptiones[0] : { id: `curr_page_select_${new Date().getTime()}`, value: `curr_page_select_${new Date().getTime()}`, label: '暂无选中数据' };
        }
      );
    },
    /** 获取下拉框选项数据 */
    getOptiones() {
      // 通过查询条件远程获取选项
      this.queryFun(this.queryParams).then( // 成功返回数据
        response => {
          // 定义是否含当前数据项标识
          let isHasCurrentSelectOption = false;

          // 处理返回数据
          this.selectOptiones = (response?.rows || []).map((item, index) => {

            // 组装新元素对象
            let tempItemObj = Object.assign({}, { id: item[this.defaultProps.id], value: item[this.defaultProps.value], label: item[this.defaultProps.label] });

            // 判断是否存在当前选项数据
            if (!isHasCurrentSelectOption && tempItemObj.value == this.currentSelectOption?.value) {
              isHasCurrentSelectOption = true;
              this.currentSelectOption = { ...tempItemObj };
            }

            return tempItemObj;
          });

          // 如果存在当前数据，更改数据id
          if (isHasCurrentSelectOption) {
            this.currentSelectOption.id = `curr_page_select_${new Date().getTime()}`;
          }

          // 数目总条数
          this.total = response?.total ?? 0;

          if (this.isSetDefaultValue && !this.selectModelValue && this.selectOptiones?.length > 0) {
            this.selectModelValue = this.selectOptiones?.[0]?.value;
            this.$nextTick(() => {
              this.$emit('component-rendering-complete', this.$refs.paginationSelectRef);
            });
          }

          // 关闭加载状态
          this.remoteLoading = false;

          this.handleRemoteTimeout != null && clearTimeout(this.handleRemoteTimeout);
        }
      ).catch(() => { // 异常返回数据
        this.selectOptiones = [];
        this.total = 0;
        this.remoteLoading = false;
      });
    },
    /** 远程搜索方法 */
    handleSelectRemoteMethod(query) {
      // 更新操作方式
      this.operationType = 'HANDLEREMOTEMETHOD';

      // 绑定关键字查询条件
      this.queryParams[this.keywordField] = query;
      this.currentPage = 1;
      this.queryParams.pageNum = 1;

      // 开启加载状态
      this.remoteLoading = true;

      // 设置定时器
      this.handleRemoteTimeout = setTimeout(() => {
        this.selectOptiones = [];
        this.option = 0;
        this.getOptiones();
      }, 500);
    },
    /** 分页当前页码改变操作 */
    handleCurrentChange(val) {
      // 更新操作方式
      this.operationType = 'HANDLEREMOTEMETHOD';

      // 设置当前页码
      this.queryParams.pageNum = val;
      this.currentPage = val;
      this.initGetOptiones();
    },
    /** 选中值操作事件 */
    handleSelectChange(val) {
      // 更新操作方式
      this.operationType = 'HANDLESELECTCHANGE';

      // 处理选中数据
      if (val) {
        for (let index = 0; index < this.selectOptiones?.length; index++) {
          if (val == this.selectOptiones[index]?.value) {
            this.currentSelectOption = {
              id: `curr_page_select_${new Date().getTime()}`,
              value: this.selectOptiones[index]?.value,
              label: this.selectOptiones[index]?.label
            };
            this.$emit('pagination-select-change', this.selectOptiones[index]);
            break;
          }
        }
      } else {
        this.currentPage = 1;
        this.queryParams.pageNum = 1;
        this.queryParams[this.keywordField] = '';
        this.currentSelectOption = { id: `curr_page_select_${new Date().getTime()}`, value: `curr_page_select_${new Date().getTime()}`, label: '暂无选中数据' };
        this.selectOptiones = [];
        this.option = 0;
        this.getOptiones();
      }
      this.$emit('handleSelectChange', val)
    },
    handleSelectVisibleChange(val) {
      if (this.isImmediatelyQuery && val) {
        this.currentPage = 1;
        this.queryParams.pageNum = 1;
        this.queryParams[this.keywordField] = '';
        this.selectOptiones = [];
        this.option = 0;
        this.getOptiones();
      }
    },
    /** 获取随机唯一标识 */
    getComponentKey(param) {
      return `${param}${new Date().getTime()}_${this.option++}`
    },
  },
  beforeDestroy() {
    this.handleRemoteTimeout != null && clearTimeout(this.handleRemoteTimeout);
  }
};
</script>

<style lang="scss" scoped>
.paginationselect {
  &-currentselectoption {
    border-bottom: 1px solid #e7eaec;

    .el-divider--horizontal {
      margin: 10px 0 !important;
    }

    .el-select-dropdown__item.selected {
      font-size: 14px;
      color: #c0c4cc;
      cursor: text;
      font-weight: normal;
    }
  }
}
</style>
