diff --git a/examples/views/table/TableTest2.vue b/examples/views/table/TableTest2.vue index d70021b1d..4941be276 100644 --- a/examples/views/table/TableTest2.vue +++ b/examples/views/table/TableTest2.vue @@ -9,6 +9,8 @@ highlight-hover-row height="400" ref="tableRef" + id="bbbbb" + :custom-config="{storage:true}" :loading="demo1.loading" :expand-config="{iconOpen: 'vxe-icon-question-circle-fill', iconClose: 'vxe-icon-question-circle-fill'}" :checkbox-config="{labelField: 'id', highlight: true, range: true}" @@ -23,7 +25,7 @@ - + @@ -46,19 +46,6 @@ export default defineComponent({ }, 300) } - const handleSaveStore = (type: 'confirm' | 'reset') => { - const { id } = tableProps - const customOpts = computeCustomOpts.value - const { storage, updateStore } = customOpts - if (storage && id && updateStore) { - updateStore({ - id, - type, - storeData: $xeTable.getCustomStoreData() - }) - } - } - const confirmCustomEvent = (evnt: Event) => { const { customColumnList } = reactData const customOpts = computeCustomOpts.value @@ -87,7 +74,7 @@ export default defineComponent({ }) $xeTable.closeCustom() $xeTable.emitCustomEvent('confirm', evnt) - handleSaveStore('confirm') + $xeTable.saveCustomStore('confirm') } const cancelCustomEvent = (evnt: Event) => { @@ -123,7 +110,6 @@ export default defineComponent({ $xeTable.resetColumn(true) $xeTable.closeCustom() $xeTable.emitCustomEvent('reset', evnt) - handleSaveStore('reset') } const resetCustomEvent = (evnt: Event) => { @@ -165,6 +151,7 @@ export default defineComponent({ handleOptionCheck(column) if (customOpts.immediate) { $xeTable.handleCustom() + $xeTable.saveCustomStore('update:visible') } $xeTable.checkCustomStatus() } @@ -498,8 +485,9 @@ export default defineComponent({ const { customStore } = props const { customColumnList } = reactData const customOpts = computeCustomOpts.value - const { allowVisible, allowSort, allowFixed, allowResizable, checkMethod, visibleMethod } = customOpts + const { modalOptions, allowVisible, allowSort, allowFixed, allowResizable, checkMethod, visibleMethod } = customOpts const columnOpts = computeColumnOpts.value + const modalOpts = Object.assign({}, modalOptions) const isMaxFixedColumn = computeIsMaxFixedColumn.value const trVNs: VNode[] = [] XEUtils.eachTree(customColumnList, (column, index, items, path, parent) => { @@ -618,13 +606,13 @@ export default defineComponent({ const isAllIndeterminate = customStore.isIndeterminate return h(resolveComponent('vxe-modal') as VxeModalComponent, { key: 'popup', - className: 'vxe-table-custom-popup-wrapper vxe-table--ignore-clear', + className: ['vxe-table-custom-popup-wrapper', 'vxe-table--ignore-clear', modalOpts.className || ''].join(' '), modelValue: customStore.visible, - title: getI18n('vxe.custom.cstmTitle'), - width: 900, - minWidth: 700, - height: 500, - minHeight: 400, + title: modalOpts.title || getI18n('vxe.custom.cstmTitle'), + width: modalOpts.width || '50vw', + minWidth: modalOpts.minWidth || 700, + height: modalOpts.height || '50vh', + minHeight: modalOpts.minHeight || 400, mask: true, lockView: true, showFooter: true, diff --git a/packages/table/src/header.ts b/packages/table/src/header.ts index 2b157e065..fb292a5b7 100644 --- a/packages/table/src/header.ts +++ b/packages/table/src/header.ts @@ -116,7 +116,7 @@ export default defineComponent({ tableInternalData._lastResizeTime = Date.now() $xeTable.analyColumnWidth() $xeTable.recalculate(true).then(() => { - $xeTable.saveCustomResizable() + $xeTable.saveCustomStore('update:visible') $xeTable.updateCellAreas() $xeTable.dispatchEvent('resizable-change', { ...params, resizeWidth }, evnt) }) diff --git a/packages/table/src/table.ts b/packages/table/src/table.ts index f19e36fe6..4ce920ca5 100644 --- a/packages/table/src/table.ts +++ b/packages/table/src/table.ts @@ -24,10 +24,7 @@ const { getConfig, getI18n, renderer, formats, createEvent, globalResize, interc const isWebkit = browse['-webkit'] && !browse.edge -const resizableStorageKey = 'VXE_TABLE_CUSTOM_COLUMN_WIDTH' -const visibleStorageKey = 'VXE_TABLE_CUSTOM_COLUMN_VISIBLE' -const fixedStorageKey = 'VXE_TABLE_CUSTOM_COLUMN_FIXED' -const sortStorageKey = 'VXE_TABLE_CUSTOM_COLUMN_SORT' +const customStorageKey = 'VXE_CUSTOM_STORE' export default defineComponent({ name: 'VxeTable', @@ -680,10 +677,19 @@ export default defineComponent({ return orders[oIndex < orders.length ? oIndex : 0] } - const getCustomStorageMap = (key: string) => { + const getCustomStorageMap = (id?: string) => { const version = getConfig().version - const rest = XEUtils.toStringJSON(localStorage.getItem(key) || '') - return rest && rest._v === version ? rest : { _v: version } + const rest = XEUtils.toStringJSON(localStorage.getItem(customStorageKey) || '') + const maps = rest && rest._v === version ? rest : { _v: version } + return (id ? maps[id] : maps) || {} + } + + const setCustomStorageMap = (id: string, data: any) => { + const version = getConfig().version + const maps = getCustomStorageMap() + maps[id] = data || undefined + maps._v = version + localStorage.setItem(customStorageKey, XEUtils.toJSONString(maps)) } const getRecoverRowMaps = (keyMaps: Record) => { @@ -888,8 +894,9 @@ export default defineComponent({ /** * 还原自定义列操作状态 */ - const restoreCustomStorage = () => { + const restoreCustomStorage = async () => { const { id, customConfig } = props + const { tableFullColumn } = internalData const customOpts = computeCustomOpts.value const { storage, restoreStore } = customOpts const isAllCustom = storage === true @@ -898,119 +905,45 @@ export default defineComponent({ const isCustomVisible = isAllCustom || storageOpts.visible const isCustomFixed = isAllCustom || storageOpts.fixed const isCustomSort = isAllCustom || storageOpts.sort - if (storage && id && restoreStore) { - restoreStore({ id }) - } if (customConfig && (isCustomResizable || isCustomVisible || isCustomFixed || isCustomSort)) { - const customMap: { - [key: string]: { - field?: VxeColumnPropTypes.Field - resizeWidth?: number - visible?: boolean - fixed?: string - renderSortNumber?: number - } - } = {} if (!id) { errLog('vxe.error.reqProp', ['id']) return } - // 自定义列宽 - if (isCustomResizable) { - const columnWidthStorage = getCustomStorageMap(resizableStorageKey)[id] - if (columnWidthStorage) { - XEUtils.each(columnWidthStorage, (resizeWidth: number, colKey) => { - customMap[colKey] = { resizeWidth } - }) - } + let storeData: VxeTableDefines.CustomStoreData = getCustomStorageMap(id) + if (restoreStore) { + storeData = await restoreStore({ id, type: 'restore', storeData }) } - // 自定义固定列 - if (isCustomFixed) { - const columnFixedStorage = getCustomStorageMap(fixedStorageKey)[id] - if (columnFixedStorage) { - const colFixeds = columnFixedStorage.split(',') - colFixeds.forEach((fixConf: any) => { - const [colKey, fixed] = fixConf.split('|') - if (customMap[colKey]) { - customMap[colKey].fixed = fixed - } else { - customMap[colKey] = { fixed } - } - }) - } - } - // 自定义顺序 - let hasCustomSort = false - if (isCustomSort) { - const columnSortStorage = getCustomStorageMap(sortStorageKey)[id] - if (columnSortStorage) { - XEUtils.each(columnSortStorage, (renderSortNumber: number, colKey) => { - if (customMap[colKey]) { - customMap[colKey].renderSortNumber = renderSortNumber - } else { - customMap[colKey] = { renderSortNumber } - } - if (!hasCustomSort) { - hasCustomSort = true - } - }) - } - } - // 自定义隐藏列 - if (isCustomVisible) { - const columnVisibleStorage = getCustomStorageMap(visibleStorageKey)[id] - if (columnVisibleStorage) { - const colVisibles = columnVisibleStorage.split('|') - const colHides: string[] = colVisibles[0] ? colVisibles[0].split(',') : [] - const colShows: string[] = colVisibles[1] ? colVisibles[1].split(',') : [] - colHides.forEach((colKey) => { - if (customMap[colKey]) { - customMap[colKey].visible = false - } else { - customMap[colKey] = { visible: false } - } - }) - colShows.forEach((colKey) => { - if (customMap[colKey]) { - customMap[colKey].visible = true - } else { - customMap[colKey] = { visible: true } - } - }) - } + if (!storeData) { + return } let { collectColumn } = internalData - const keyMap: { - [key: string]: VxeTableDefines.ColumnInfo - } = {} - XEUtils.eachTree(collectColumn, (column) => { - const colKey = column.getKey() - if (colKey) { - keyMap[colKey] = column + const { resizableData, sortData, visibleData, fixedData } = storeData + let hasCustomSort = false + // 处理还原 + if (resizableData || sortData || visibleData || fixedData) { + tableFullColumn.forEach(column => { + const colKey = column.getKey() + if (resizableData && XEUtils.isNumber(resizableData[colKey])) { + column.resizeWidth = resizableData[colKey] + } + if (visibleData && XEUtils.isBoolean(visibleData[colKey])) { + column.visible = visibleData[colKey] + } + if (fixedData && fixedData[colKey]) { + column.fixed = fixedData[colKey] + } + if (sortData && XEUtils.isNumber(sortData[colKey])) { + hasCustomSort = true + column.renderSortNumber = sortData[colKey] + } + }) + // 如果自定义了顺序 + if (hasCustomSort) { + collectColumn = XEUtils.orderBy(collectColumn, 'renderSortNumber') + internalData.collectColumn = collectColumn + internalData.tableFullColumn = getColumnList(collectColumn) } - }) - XEUtils.each(customMap, ({ visible, resizeWidth, fixed, renderSortNumber }, colKey) => { - const column = keyMap[colKey] - if (column) { - if (XEUtils.isNumber(resizeWidth)) { - column.resizeWidth = resizeWidth - } - if (XEUtils.isBoolean(visible)) { - column.visible = visible - } - if (fixed) { - column.fixed = fixed - } - if (renderSortNumber) { - column.renderSortNumber = Number(renderSortNumber) - } - } - }) - // 如果自定义了顺序 - if (hasCustomSort) { - collectColumn = XEUtils.orderBy(collectColumn, 'renderSortNumber') - internalData.collectColumn = collectColumn - internalData.tableFullColumn = getColumnList(collectColumn) } } } @@ -2561,26 +2494,27 @@ export default defineComponent({ const tableFullColumn = getColumnList(collectColumn) internalData.tableFullColumn = tableFullColumn initColumnSort() - restoreCustomStorage() - cacheColumnMap() - parseColumns().then(() => { - if (reactData.scrollXLoad) { - loadScrollXData() + return restoreCustomStorage().then(() => { + cacheColumnMap() + parseColumns().then(() => { + if (reactData.scrollXLoad) { + loadScrollXData() + } + }) + tableMethods.clearMergeCells() + tableMethods.clearMergeFooterItems() + tablePrivateMethods.handleTableData(true) + if (process.env.VUE_APP_VXE_ENV === 'development') { + if ((reactData.scrollXLoad || reactData.scrollYLoad) && reactData.expandColumn) { + warnLog('vxe.error.scrollErrProp', ['column.type=expand']) + } } - }) - tableMethods.clearMergeCells() - tableMethods.clearMergeFooterItems() - tablePrivateMethods.handleTableData(true) - if (process.env.VUE_APP_VXE_ENV === 'development') { - if ((reactData.scrollXLoad || reactData.scrollYLoad) && reactData.expandColumn) { - warnLog('vxe.error.scrollErrProp', ['column.type=expand']) - } - } - return nextTick().then(() => { - if ($xeToolbar) { - $xeToolbar.syncUpdate({ collectColumn, $table: $xeTable }) - } - return tableMethods.recalculate() + return nextTick().then(() => { + if ($xeToolbar) { + $xeToolbar.syncUpdate({ collectColumn, $table: $xeTable }) + } + return tableMethods.recalculate() + }) }) } @@ -3284,7 +3218,7 @@ export default defineComponent({ XEUtils.eachTree([targetColumn], (column) => { column.fixed = fixed }) - tablePrivateMethods.saveCustomFixed() + tablePrivateMethods.saveCustomStore('update:fixed') return tableMethods.refreshColumn() } return nextTick() @@ -3299,7 +3233,7 @@ export default defineComponent({ XEUtils.eachTree([targetColumn], (column) => { column.fixed = null }) - tablePrivateMethods.saveCustomFixed() + tablePrivateMethods.saveCustomStore('update:fixed') return tableMethods.refreshColumn() } return nextTick() @@ -3378,15 +3312,7 @@ export default defineComponent({ } column.renderResizeWidth = column.renderWidth }) - if (opts.resizable) { - tablePrivateMethods.saveCustomResizable(true) - } - if (opts.sort) { - tablePrivateMethods.saveCustomSort(true) - } - if (opts.fixed) { - tablePrivateMethods.saveCustomFixed() - } + $xeTable.saveCustomStore('reset') return tablePrivateMethods.handleCustom() }, /** @@ -4536,22 +4462,27 @@ export default defineComponent({ const sortData: Record = {} const visibleData: Record = {} const fixedData: Record = {} - const storeData = { - resizableData, - sortData, - visibleData, - fixedData + const storeData: VxeTableDefines.CustomStoreData = { + resizableData: undefined, + sortData: undefined, + visibleData: undefined, + fixedData: undefined } if (!id) { errLog('vxe.error.reqProp', ['id']) return storeData } + let hasResizable = 0 + let hasSort = 0 + let hasFixedt = 0 + let hasVisible = 0 XEUtils.eachTree(collectColumn, (column, index, items, path, parent) => { // 排序只支持一级 if (!parent) { collectColumn.forEach((column) => { const colKey = column.getKey() if (colKey) { + hasSort = 1 sortData[colKey] = column.renderSortNumber } }) @@ -4559,12 +4490,14 @@ export default defineComponent({ if (column.resizeWidth) { const colKey = column.getKey() if (colKey) { + hasResizable = 1 resizableData[colKey] = column.renderWidth } } if (column.fixed && column.fixed !== column.defaultFixed) { const colKey = column.getKey() if (colKey) { + hasFixedt = 1 fixedData[colKey] = column.fixed } } @@ -4572,16 +4505,30 @@ export default defineComponent({ if (!column.visible && column.defaultVisible) { const colKey = column.getKey() if (colKey) { + hasVisible = 1 visibleData[colKey] = false } } else if (column.visible && !column.defaultVisible) { const colKey = column.getKey() if (colKey) { + hasVisible = 1 visibleData[colKey] = true } } } }) + if (hasResizable) { + storeData.resizableData = resizableData + } + if (hasSort) { + storeData.sortData = sortData + } + if (hasFixedt) { + storeData.fixedData = fixedData + } + if (hasVisible) { + storeData.visibleData = visibleData + } return storeData }, focus () { @@ -5366,126 +5313,40 @@ export default defineComponent({ }) Object.assign(reactData.columnStore, { resizeList, pxList, pxMinList, scaleList, scaleMinList, autoList }) }, - saveCustomResizable (isReset?: boolean) { - const { id, customConfig } = props + saveCustomStore (type) { + const { id } = props const customOpts = computeCustomOpts.value - const { collectColumn } = internalData - const { storage } = customOpts - const isAllStorage = storage === true - const storageOpts = isAllStorage ? {} : Object.assign({}, storage || {}) - const isResizable = isAllStorage || storageOpts.resizable - if (customConfig && isResizable) { - const columnWidthStorageMap = getCustomStorageMap(resizableStorageKey) - let columnWidthStorage: any + const { updateStore, storage } = customOpts + const isAllCustom = storage === true + const storageOpts: VxeTableDefines.VxeTableCustomStorageObj = isAllCustom ? {} : Object.assign({}, storage || {}) + const isCustomResizable = isAllCustom || storageOpts.resizable + const isCustomVisible = isAllCustom || storageOpts.visible + const isCustomFixed = isAllCustom || storageOpts.fixed + const isCustomSort = isAllCustom || storageOpts.sort + if (isCustomResizable || isCustomVisible || isCustomFixed || isCustomSort) { if (!id) { errLog('vxe.error.reqProp', ['id']) - return + return nextTick() } - if (!isReset) { - columnWidthStorage = XEUtils.isPlainObject(columnWidthStorageMap[id]) ? columnWidthStorageMap[id] : {} - XEUtils.eachTree(collectColumn, (column) => { - if (column.resizeWidth) { - const colKey = column.getKey() - if (colKey) { - columnWidthStorage[colKey] = column.renderWidth - } + const storeData = type === 'reset' + ? { + resizableData: {}, + sortData: {}, + visibleData: {}, + fixedData: {} } + : tableMethods.getCustomStoreData() + if (updateStore) { + return updateStore({ + id, + type, + storeData }) + } else { + setCustomStorageMap(id, type === 'reset' ? null : storeData) } - columnWidthStorageMap[id] = XEUtils.isEmpty(columnWidthStorage) ? undefined : columnWidthStorage - localStorage.setItem(resizableStorageKey, XEUtils.toJSONString(columnWidthStorageMap)) - } - }, - saveCustomSort (isReset?: boolean) { - const { id, customConfig } = props - const customOpts = computeCustomOpts.value - const { collectColumn } = internalData - const { storage } = customOpts - const isAllStorage = storage === true - const storageOpts = isAllStorage ? {} : Object.assign({}, storage || {}) - const isSort = isAllStorage || storageOpts.sort - if (customConfig && isSort) { - const columnSortStorageMap = getCustomStorageMap(sortStorageKey) - let columnWidthStorage: any - if (!id) { - errLog('vxe.error.reqProp', ['id']) - return - } - if (!isReset) { - columnWidthStorage = XEUtils.isPlainObject(columnSortStorageMap[id]) ? columnSortStorageMap[id] : {} - // 排序只支持一级 - collectColumn.forEach((column) => { - const colKey = column.getKey() - if (colKey) { - columnWidthStorage[colKey] = column.renderSortNumber - } - }) - } - columnSortStorageMap[id] = XEUtils.isEmpty(columnWidthStorage) ? undefined : columnWidthStorage - localStorage.setItem(sortStorageKey, XEUtils.toJSONString(columnSortStorageMap)) - } - }, - saveCustomFixed () { - const { id, customConfig } = props - const { collectColumn } = internalData - const customOpts = computeCustomOpts.value - const { storage } = customOpts - const isAllStorage = storage === true - const storageOpts = isAllStorage ? {} : Object.assign({}, storage || {}) - const isCustomFixed = isAllStorage || storageOpts.fixed - if (customConfig && isCustomFixed) { - const columnFixedStorageMap = getCustomStorageMap(fixedStorageKey) - const colFixeds: any[] = [] - if (!id) { - errLog('vxe.error.reqProp', ['id']) - return - } - XEUtils.eachTree(collectColumn, (column) => { - if (column.fixed && column.fixed !== column.defaultFixed) { - const colKey = column.getKey() - if (colKey) { - colFixeds.push(`${colKey}|${column.fixed}`) - } - } - }) - columnFixedStorageMap[id] = colFixeds.join(',') || undefined - localStorage.setItem(fixedStorageKey, XEUtils.toJSONString(columnFixedStorageMap)) - } - }, - saveCustomVisible () { - const { id, customConfig } = props - const { collectColumn } = internalData - const customOpts = computeCustomOpts.value - const { checkMethod, storage } = customOpts - const isAllStorage = storage === true - const storageOpts = isAllStorage ? {} : Object.assign({}, storage || {}) - const isCustomVisible = isAllStorage || storageOpts.visible - if (customConfig && isCustomVisible) { - const columnVisibleStorageMap = getCustomStorageMap(visibleStorageKey) - const colHides: any[] = [] - const colShows: any[] = [] - if (!id) { - errLog('vxe.error.reqProp', ['id']) - return - } - XEUtils.eachTree(collectColumn, (column) => { - if (!checkMethod || checkMethod({ column })) { - if (!column.visible && column.defaultVisible) { - const colKey = column.getKey() - if (colKey) { - colHides.push(colKey) - } - } else if (column.visible && !column.defaultVisible) { - const colKey = column.getKey() - if (colKey) { - colShows.push(colKey) - } - } - } - }) - columnVisibleStorageMap[id] = [colHides.join(',')].concat(colShows.length ? [colShows.join(',')] : []).join('|') || undefined - localStorage.setItem(visibleStorageKey, XEUtils.toJSONString(columnVisibleStorageMap)) } + return nextTick() }, handleCustom () { const { mouseConfig } = props @@ -5498,10 +5359,7 @@ export default defineComponent({ $xeTable.clearCopyCellArea() } } - tablePrivateMethods.saveCustomVisible() - tablePrivateMethods.saveCustomSort() tablePrivateMethods.analyColumnWidth() - tablePrivateMethods.saveCustomResizable() return tableMethods.refreshColumn(true) }, handleUpdateDataQueue () {