diff --git a/apps/backend-mock/api/table/list.ts b/apps/backend-mock/api/table/list.ts index 4a0db94ec8e..55b88eaaa06 100644 --- a/apps/backend-mock/api/table/list.ts +++ b/apps/backend-mock/api/table/list.ts @@ -43,6 +43,31 @@ export default eventHandler(async (event) => { await sleep(600); - const { page, pageSize } = getQuery(event); - return usePageResponseSuccess(page as string, pageSize as string, mockData); + const { page, pageSize, sortBy, sortOrder } = getQuery(event); + const listData = structuredClone(mockData); + if (sortBy && Reflect.has(listData[0], sortBy as string)) { + listData.sort((a, b) => { + if (sortOrder === 'asc') { + if (sortBy === 'price') { + return ( + Number.parseFloat(a[sortBy as string]) - + Number.parseFloat(b[sortBy as string]) + ); + } else { + return a[sortBy as string] > b[sortBy as string] ? 1 : -1; + } + } else { + if (sortBy === 'price') { + return ( + Number.parseFloat(b[sortBy as string]) - + Number.parseFloat(a[sortBy as string]) + ); + } else { + return a[sortBy as string] < b[sortBy as string] ? 1 : -1; + } + } + }); + } + + return usePageResponseSuccess(page as string, pageSize as string, listData); }); diff --git a/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue b/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue index 91749835dea..e30c3bd713c 100644 --- a/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue +++ b/packages/effects/plugins/src/vxe-table/use-vxe-grid.vue @@ -15,6 +15,7 @@ import { nextTick, onMounted, onUnmounted, + ref, toRaw, useSlots, useTemplateRef, @@ -140,6 +141,8 @@ const toolbarOptions = computed(() => { return { toolbarConfig }; }); +const isLoaded = ref(false); + const options = computed(() => { const globalGridConfig = VxeUI?.getConfig()?.grid ?? {}; @@ -157,6 +160,16 @@ const options = computed(() => { mergedOptions.proxyConfig.enabled = !!ajax; // 不自动加载数据, 由组件控制 mergedOptions.proxyConfig.autoLoad = false; + // 修复第一次加载数据时会丢失排序参数等问题,后续如果VxeTable修复了此BUG,可以去掉这些代码 + if (mergedOptions.proxyConfig.ajax?.query && !isLoaded.value) { + mergedOptions.proxyConfig.ajax.query = async () => { + isLoaded.value = true; + await nextTick(); + setTimeout(() => { + props.api.query(); + }, 0); + }; + } } if (mergedOptions.pagerConfig) { @@ -239,6 +252,7 @@ async function init() { toRaw(gridOptions.value), toRaw(globalGridConfig), ); + // 内部主动加载数据,防止form的默认值影响 const autoLoad = defaultGridOptions.proxyConfig?.autoLoad; const enableProxyConfig = options.value.proxyConfig?.enabled; diff --git a/playground/src/views/examples/vxe-table/remote.vue b/playground/src/views/examples/vxe-table/remote.vue index 7fc98a08b35..24a979b844e 100644 --- a/playground/src/views/examples/vxe-table/remote.vue +++ b/playground/src/views/examples/vxe-table/remote.vue @@ -25,10 +25,10 @@ const gridOptions: VxeGridProps = { columns: [ { title: '序号', type: 'seq', width: 50 }, { align: 'left', title: 'Name', type: 'checkbox', width: 100 }, - { field: 'category', title: 'Category' }, + { field: 'category', sortable: true, title: 'Category' }, { field: 'color', title: 'Color' }, - { field: 'productName', title: 'Product Name' }, - { field: 'price', title: 'Price' }, + { field: 'productName', sortable: true, title: 'Product Name' }, + { field: 'price', sortable: true, title: 'Price' }, { field: 'releaseDate', formatter: 'formatDateTime', title: 'DateTime' }, ], exportConfig: {}, @@ -36,19 +36,26 @@ const gridOptions: VxeGridProps = { keepSource: true, proxyConfig: { ajax: { - query: async ({ page }) => { + query: async ({ page, sort }) => { return await getExampleTableApi({ page: page.currentPage, pageSize: page.pageSize, + sortBy: sort.field, + sortOrder: sort.order, }); }, }, + sort: true, + }, + sortConfig: { + defaultSort: { field: 'category', order: 'desc' }, + remote: true, }, toolbarConfig: { custom: true, export: true, // import: true, - refresh: true, + refresh: { code: 'query' }, zoom: true, }, };