44 :max-height =" tableHeight"
55 v-bind =" $attrs"
66 ref =" appTableRef"
7+ @header-dragend =" handleHeaderDragend"
78 :tooltip-options =" {
89 popperClass: 'max-w-350',
910 }"
5455 </div >
5556</template >
5657<script setup lang="ts">
57- import { ref , nextTick , watch , computed , onMounted } from ' vue'
58+ import { ref , nextTick , watch , computed , onMounted , useAttrs } from ' vue'
5859import { MsgError } from ' @/utils/message'
5960import { t } from ' @/locales'
6061
@@ -64,6 +65,8 @@ import useStore from '@/stores'
6465
6566const { common } = useStore ()
6667
68+ const attrs = useAttrs ()
69+
6770const props = defineProps ({
6871 paginationConfig: {
6972 type: Object ,
@@ -148,6 +151,78 @@ function clearSelection() {
148151 appTableRef .value ?.clearSelection ()
149152}
150153
154+ /* ----------------- 列宽拖拽持久化 ----------------- */
155+ const COLUMN_WIDTH_PREFIX = ' app-table-column-width:'
156+
157+ function widthStorageKey() {
158+ return ` ${COLUMN_WIDTH_PREFIX }${props .storeKey } `
159+ }
160+
161+ function loadWidthMap(): Record <string , number > {
162+ try {
163+ return JSON .parse (localStorage .getItem (widthStorageKey ()) || ' {}' )
164+ } catch {
165+ return {}
166+ }
167+ }
168+
169+ function saveWidthMap(map : Record <string , number >) {
170+ try {
171+ localStorage .setItem (widthStorageKey (), JSON .stringify (map ))
172+ } catch {
173+ /* ignore quota / serialization errors */
174+ }
175+ }
176+
177+ /**
178+ * 列的稳定标识:优先用 prop / column-key,其次回退到渲染顺序下标。
179+ */
180+ function getColumnKey(column : any , index : number ) {
181+ return column ?.property || column ?.columnKey || ` __col_${index }__ `
182+ }
183+
184+ /**
185+ * 拖拽结束后,记录该列的最新宽度
186+ */
187+ function handleHeaderDragend(newWidth : number , _oldWidth : number , column : any ) {
188+ if (! props .storeKey || ! column || ! newWidth ) {
189+ return
190+ }
191+ const cols = appTableRef .value ?.columns || []
192+ const index = cols .findIndex ((c : any ) => c .id === column .id )
193+ const key = getColumnKey (column , index )
194+ const map = loadWidthMap ()
195+ map [key ] = Math .round (newWidth )
196+ saveWidthMap (map )
197+ }
198+
199+ /**
200+ * 表格渲染后,把缓存的列宽应用回去
201+ */
202+ function restoreColumnWidths() {
203+ if (! props .storeKey ) {
204+ return
205+ }
206+ const map = loadWidthMap ()
207+ if (! map || ! Object .keys (map ).length ) {
208+ return
209+ }
210+ const table = appTableRef .value
211+ const cols = table ?.columns || []
212+ let changed = false
213+ cols .forEach ((column : any , index : number ) => {
214+ const w = map [getColumnKey (column , index )]
215+ if (typeof w === ' number' && w > 0 && column .realWidth !== w ) {
216+ column .width = w
217+ column .realWidth = w
218+ changed = true
219+ }
220+ })
221+ if (changed ) {
222+ table ?.doLayout ?.()
223+ }
224+ }
225+
151226function toggleRowSelection(row : any , selected ? : boolean , ignoreSelectable = true ) {
152227 appTableRef .value ?.toggleRowSelection (row , selected , ignoreSelectable )
153228}
@@ -169,7 +244,19 @@ onMounted(() => {
169244 tableHeight .value = window .innerHeight - props .maxTableHeight
170245 })()
171246 }
247+
248+ // 首次渲染后恢复缓存的列宽
249+ nextTick (restoreColumnWidths )
172250})
251+
252+ // 数据变化(翻页 / 筛选 / 轮询刷新)会重建列,重新应用缓存列宽
253+ watch (
254+ () => attrs .data ,
255+ () => {
256+ nextTick (restoreColumnWidths )
257+ },
258+ )
259+
173260 </script >
174261
175262<style lang="scss" scoped>
0 commit comments