From 6d1abed421e78c8b7b685fc21be52866976c6ff6 Mon Sep 17 00:00:00 2001 From: "gary.fu" Date: Fri, 5 Jan 2024 18:26:07 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=AE=8C=E6=88=90=E6=8E=A7?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/main.css | 27 ++- src/components/common-autocomplete/index.vue | 191 +++++++++++++++++-- src/components/common-table/index.vue | 15 +- src/messages/common_cn.js | 1 + src/messages/common_en.js | 1 + src/services/city/CityService.js | 22 +++ src/views/tools/Tables.vue | 2 +- src/views/tools/TestPage.vue | 78 +++++++- 8 files changed, 310 insertions(+), 27 deletions(-) create mode 100644 src/services/city/CityService.js diff --git a/src/assets/main.css b/src/assets/main.css index ab9dc0a..53f7822 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -99,11 +99,36 @@ html, body, #app, .index-container { .form-edit-width-100 { width:100% } -.autocomplete-table .el-table__cell{ + +.common-autocomplete .el-popover__title{ + font-size: 14px; + font-weight: 500; +} + +.common-autocomplete .autocomplete-table .el-table__cell{ padding: 3px 0; cursor: pointer; } +.common-autocomplete .el-tabs__nav-next, .el-tabs__nav-prev { + line-height: 30px; +} + +.common-autocomplete .common-select-page .el-tabs__item { + height: 30px; +} + +.common-autocomplete .common-select-page .common-select-page-btn { + overflow: hidden; + width: 100%; + padding: 0; + margin: 5px; +} + +.common-autocomplete .common-select-page .el-tabs__content { + padding: 5px; +} + /** * slide-fade动画 */ diff --git a/src/components/common-autocomplete/index.vue b/src/components/common-autocomplete/index.vue index 1dbc0a4..7a0b56c 100644 --- a/src/components/common-autocomplete/index.vue +++ b/src/components/common-autocomplete/index.vue @@ -5,6 +5,11 @@ * @property {string} emptyMessage 没有数据的提示信息 * @method searchMethod 搜索方法 */ +/** + * @typedef {Object} CommonSelectPageOption 默认选择页面配置信息 + * @property {[{ id:string, label:string }]} tabs 显示tabs配置 + * @method searchMethod 搜索方法 + */ /** * @typedef {Object} CommonSelectPageOption 默认选择页配置 */ @@ -25,11 +30,15 @@ * @property {CommonPage} page 分页数据 * @property {string} autocompleteWidth 宽度 * @property {CommonSelectPageOption} selectPageConfig 分页 + * @property {Number} colSize 显示几列 + * @property {string} loadingText 加载提示loading + * @property {string} minHeight 高度自定义 * @property {Object} inputAttrs 输入框配置项 */ -import { nextTick, onMounted, ref, watch } from 'vue' +import { computed, nextTick, onMounted, ref, watch } from 'vue' import { debounce } from 'lodash' import { onClickOutside, onKeyStroke, useVModel } from '@vueuse/core' +import chunk from 'lodash/chunk' /** * @type {CommonAutocompleteProps} @@ -65,7 +74,7 @@ const props = defineProps({ }, autocompleteWidth: { type: String, - default: '600px' + default: '500px' }, page: { type: Object, @@ -79,6 +88,10 @@ const props = defineProps({ type: Object, default: null }, + colSize: { + type: Number, + default: 4 + }, clearable: { type: Boolean, default: true @@ -98,35 +111,79 @@ const props = defineProps({ emptySearchEnabled: { type: Boolean, default: false + }, + loadingText: { + type: String, + default: '' + }, + minHeight: { + type: String, + default: '100px' } }) const emit = defineEmits(['update:modelValue', 'onSelectData', 'update:page', 'update:autocompleteLabel']) - +// 关键字搜索 const keywords = ref(props.autocompleteLabel) +// 上次搜索记录 const lastAutocompleteLabel = ref(props.autocompleteLabel) -const pageAttrs = { layout: 'total, prev, pager, next', small: true } +// 分页条 +const pageAttrs = { layout: 'total, prev, pager, next', small: true, background: true } +const selectPageAttrs = { layout: 'prev, pager, next', small: true, background: true } +// 自动完成数据 const dataList = ref([]) +// 选项表数据 +const selectPageData = ref({}) +const selectPageTab = ref(null) const popoverVisible = ref(false) const autocompletePopover = ref() const pageConfig = useVModel(props, 'page', emit) +const loadingData = ref(false) + +const showSelectPage = computed(() => { + return props.selectPageConfig && (!keywords.value || lastAutocompleteLabel.value === keywords.value) +}) + +const loadAutoDataList = (val) => { + if (val || props.emptySearchEnabled) { + popoverVisible.value = true + loadingData.value = true + props.autocompleteConfig.searchMethod(val, (result) => { + dataList.value = result.items || [] + if (props.page) { + pageConfig.value = { ...result.page } + } + loadingData.value = false + }) + } +} + +const loadSelectData = () => { + const tabId = selectPageTab.value || props.selectPageConfig?.tabs?.[0]?.id + if (tabId && !selectPageData.value[tabId]) { + selectPageTab.value = tabId + loadingData.value = true + props.selectPageConfig?.searchMethod(tabId, (result) => { + selectPageData.value[tabId] = result + loadingData.value = false + }) + } +} + /** * @type {function(boolean?)} */ const onInputKeywords = debounce((input) => { if (!props.disabled && !props.readonly) { - if (input && pageConfig.value) { - pageConfig.value = { ...pageConfig.value, pageNumber: 1 } - } const val = keywords.value - if (val || props.emptySearchEnabled) { + if (showSelectPage.value) { popoverVisible.value = true - props.autocompleteConfig.searchMethod(val, (result) => { - dataList.value = result.items || [] - if (props.page) { - pageConfig.value = { ...result.page } - } - }) + loadSelectData() + } else { + if (input && pageConfig.value) { + pageConfig.value = { ...pageConfig.value, pageNumber: 1 } + } + loadAutoDataList(val) } if (!val && input) { onSelectData() @@ -189,14 +246,15 @@ const moveSelection = function (down) { currentOnIndex.value = 0 } } else { - if (currentOnIndex.value > 1) { + if (currentOnIndex.value > 0) { currentOnIndex.value-- } else { - currentOnIndex.value = 0 + currentOnIndex.value = dataList.value.length - 1 } } currentOnRow.value = dataList.value[currentOnIndex.value] } else { + currentOnIndex.value = -1 currentOnRow.value = null } console.info('=================', tableRef.value.table, currentOnIndex.value, currentOnRow.value) @@ -206,21 +264,57 @@ const moveSelection = function (down) { // 向下按键移动元素 onKeyStroke('ArrowDown', e => moveSelection(true)) // 向上按键移动元素 -onKeyStroke('ArrowUp', e => moveSelection(true)) +onKeyStroke('ArrowUp', e => moveSelection(false)) // 选中回车 onKeyStroke('Enter', e => { onSelectData(currentOnRow.value) }) +//= ===============selectPage处理=================// +const selectPagePageConfig = ref({}) +const parsedSelectPageData = computed(() => { + const result = {} + if (selectPageData.value) { + Object.entries(selectPageData.value).forEach(([key, value]) => { + const chunkPages = chunk(value, props.colSize) + const pager = selectPagePageConfig.value[key] = selectPagePageConfig.value[key] || getSelectPage(chunkPages.length) + result[key] = chunkPages.slice((pager.pageNumber - 1) * pager.pageSize, pager.pageNumber * pager.pageSize) + }) + } + return result +}) + +const getSelectPage = (totalCount) => { + const pageSize = 5 + const pageCount = Math.ceil((totalCount + pageSize - 1) / pageSize) + return { + pageNumber: 1, + pageSize, + totalCount, + pageCount + } +} + +const selectPagePagination = (tab) => { + const pager = selectPagePageConfig.value?.[tab.id] + return pager && pager.pageCount && pager.pageCount > 1 +} + +const selectPagePaginationChange = (tab, pageNumber) => { + const pager = selectPagePageConfig.value?.[tab.id] + pager.pageNumber = pageNumber + console.info('==================selectPagePaginationChange', tab, pageNumber, pager) + selectPageData.value = { ...selectPageData.value } +} +