|
@@ -0,0 +1,419 @@
|
|
|
+<!--
|
|
|
+ * @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>
|