11<script setup lang="ts">
22import type { StdTableColumn } from ' ../types'
3+ import type { ManagedTableColumn , StoredColumnSetting } from ' ../utils'
34import { HolderOutlined , SettingOutlined } from ' @antdv-next/icons'
45import { Button , Checkbox , Dropdown } from ' antdv-next'
56import { cloneDeep } from ' lodash-es'
67import Sortable from ' sortablejs'
7- import { computed , h , nextTick , onMounted , ref , watch } from ' vue'
8+ import { computed , h , nextTick , onMounted , ref , shallowRef , toRaw , watch } from ' vue'
89import { useLocale } from ' ../composables'
9- import { getColumnKey , getRealContent } from ' ../utils'
10+ import {
11+ createManagedColumns ,
12+ getRealContent ,
13+ normalizeTableColumnKeys ,
14+ parseColumnSettings ,
15+ restoreColumnSettings ,
16+ serializeColumnSettings ,
17+ } from ' ../utils'
1018
1119const props = defineProps <{
1220 columns: StdTableColumn []
13- tableId: string
1421}>()
1522
1623const emit = defineEmits <{
@@ -21,10 +28,11 @@ const { t } = useLocale()
2128
2229const visible = ref (false )
2330const sortableContainer = ref <HTMLElement >()
24- const localColumns = ref < StdTableColumn []>([])
31+ const localColumns = shallowRef < ManagedTableColumn []>([])
2532const slashRegex = / \/ / g
2633// 临时配置(用于在确认前预览)
27- const tempColumns = ref <StdTableColumn []>([])
34+ const tempColumns = shallowRef <ManagedTableColumn []>([])
35+ const orphanedSettings = shallowRef <StoredColumnSetting []>([])
2836
2937// 获取存储键 - 基于页面路径,确保配置持久化(去除查询参数)
3038const storageKey = computed (() => {
@@ -34,68 +42,25 @@ const storageKey = computed(() => {
3442
3543// 初始化列配置
3644function initializeColumns() {
37- const savedColumnKeys = getSavedConfig ()
38- const availableColumns = props .columns .filter (column => ! isSystemColumn (column ))
39-
40- if (savedColumnKeys && savedColumnKeys .length > 0 ) {
41- // 使用保存的配置:基于保存的key数组重新排序和筛选
42- const columnsMap = new Map (availableColumns .map (col => [getColumnKey (col ), col ]))
43-
44- // 创建已保存列的顺序和可见性映射
45- const savedOrderMap = new Map <string , number >()
46- const savedVisibilityMap = new Map <string , boolean >()
47- savedColumnKeys .forEach ((col , index ) => {
48- savedOrderMap .set (col .key , index )
49- savedVisibilityMap .set (col .key , col .hiddenInTable )
50- })
51-
52- // 追踪已处理的保存列索引
53- const processedSavedIndices = new Set <number >()
54- const orderedColumns: StdTableColumn [] = []
45+ const availableColumns = createManagedColumns (
46+ props .columns .filter (column => ! isSystemColumn (column )),
47+ )
48+ const savedConfig = getSavedConfig ()
5549
56- // 遍历原始列顺序,保持新列在原始位置
57- availableColumns .forEach ((column ) => {
58- const key = getColumnKey (column )
59- const savedIndex = savedOrderMap .get (key as string )
60-
61- if (savedIndex !== undefined ) {
62- // 这是一个已保存的列
63- // 检查是否已经被处理过(可能在之前的循环中被插入了)
64- if (processedSavedIndices .has (savedIndex )) {
65- return // 跳过已处理的列
66- }
67-
68- // 先插入所有应该在它之前但还未处理的已保存列
69- for (let i = 0 ; i < savedIndex ; i ++ ) {
70- if (! processedSavedIndices .has (i )) {
71- const savedKey = savedColumnKeys [i ].key
72- const savedColumn = columnsMap .get (savedKey )
73- if (savedColumn ) {
74- savedColumn .hiddenInTable = savedColumnKeys [i ].hiddenInTable
75- orderedColumns .push (savedColumn )
76- processedSavedIndices .add (i )
77- }
78- }
79- }
80-
81- // 插入当前列
82- column .hiddenInTable = savedVisibilityMap .get (key as string ) ?? false
83- orderedColumns .push (column )
84- processedSavedIndices .add (savedIndex )
85- }
86- else {
87- // 这是一个新列,按原始顺序直接插入
88- orderedColumns .push (column )
89- }
90- })
91-
92- localColumns .value = orderedColumns
93- tempColumns .value = cloneDeep (orderedColumns )
94- }
95- else {
50+ if (! savedConfig ) {
9651 localColumns .value = availableColumns
97- tempColumns .value = availableColumns
52+ tempColumns .value = cloneDeep (availableColumns )
53+ orphanedSettings .value = []
54+ return
9855 }
56+
57+ const restored = restoreColumnSettings (availableColumns , savedConfig .columns )
58+ localColumns .value = restored .columns
59+ tempColumns .value = cloneDeep (restored .columns )
60+ orphanedSettings .value = restored .orphaned
61+
62+ if (savedConfig .needsMigration )
63+ saveConfig ()
9964}
10065
10166// 判断是否为系统列(如操作列、拖拽列等)
@@ -104,36 +69,29 @@ function isSystemColumn(column: StdTableColumn): boolean {
10469 return dataIndex === ' actions' || dataIndex === ' drag' || column .key === ' actions'
10570}
10671
107- // 获取保存的配置 - 现在返回字符串数组
108- function getSavedConfig(): { key: string , hiddenInTable: boolean }[] | null {
109- try {
110- const saved = localStorage .getItem (storageKey .value )
111- return saved ? JSON .parse (saved ) : null
112- }
113- catch {
114- return null
115- }
72+ // 同时读取旧数组格式与当前版本配置
73+ function getSavedConfig() {
74+ return parseColumnSettings (localStorage .getItem (storageKey .value ))
11675}
11776
118- // 保存配置 - 现在只保存显示列的key数组
77+ // 原位置升级配置,保留未出现在当前列定义中的历史设置
11978function saveConfig() {
120- const visibleColumnKeys = (localColumns .value as any [])
121- .map (column => ({
122- key: getColumnKey (column ) as string ,
123- hiddenInTable: column .hiddenInTable ,
124- }))
125-
126- localStorage .setItem (storageKey .value , JSON .stringify (visibleColumnKeys ))
79+ const columns = toRaw (localColumns .value ) as ManagedTableColumn []
80+ const orphaned = toRaw (orphanedSettings .value ) as StoredColumnSetting []
81+ const config = serializeColumnSettings (columns , orphaned )
82+ localStorage .setItem (storageKey .value , JSON .stringify (config ))
12783}
12884
12985// 生成最终的列配置
13086function generateFinalColumns(): StdTableColumn [] {
131- const visibleColumns = (localColumns .value as any []).filter (column => ! column .hiddenInTable )
87+ const visibleColumns = localColumns .value
88+ .filter (column => ! column .column .hiddenInTable )
89+ .map (column => column .column )
13290
13391 // 添加系统列
13492 const systemColumns = props .columns .filter (column => isSystemColumn (column ))
13593
136- return [... visibleColumns , ... systemColumns ]
94+ return normalizeTableColumnKeys ( [... visibleColumns , ... systemColumns ])
13795}
13896
13997// 确认应用设置
@@ -152,32 +110,46 @@ function cancelSettings() {
152110
153111// 全选/取消全选
154112const checkAll = computed ({
155- get : (): boolean => ( tempColumns .value as any []) .every (column => ! column .hiddenInTable ),
113+ get : (): boolean => tempColumns .value .every (column => ! column . column .hiddenInTable ),
156114 set : (value : boolean ): void => {
157- (tempColumns .value as any []).forEach ((column ) => {
158- column .hiddenInTable = ! value // 修复:全选时应该显示所有列(hiddenInTable为false)
159- })
115+ tempColumns .value = tempColumns .value .map (column => ({
116+ ... column ,
117+ column: {
118+ ... column .column ,
119+ hiddenInTable: ! value ,
120+ },
121+ }))
160122 },
161123})
162124
163125// 半选状态
164126const indeterminate = computed (() => {
165- const visibleCount = ( tempColumns .value as any []) .filter (column => ! column .hiddenInTable ).length
127+ const visibleCount = tempColumns .value .filter (column => ! column . column .hiddenInTable ).length
166128 return visibleCount > 0 && visibleCount < tempColumns .value .length
167129})
168130
131+ function updateColumnVisibility(id : string , checked : boolean ) {
132+ tempColumns .value = tempColumns .value .map (column => column .id === id
133+ ? {
134+ ... column ,
135+ column: {
136+ ... column .column ,
137+ hiddenInTable: ! checked ,
138+ },
139+ }
140+ : column )
141+ }
142+
169143let sortableInstance: Sortable | null = null
170144
171145// 重置列配置
172146function resetColumns() {
173- const defaultColumns = props .columns
174- .filter (column => ! isSystemColumn (column ))
175- .map ((column ) => {
176- // 重置时所有列都默认显示
177- const col = cloneDeep (column )
178- col .hiddenInTable = false
179- return col
180- })
147+ const defaultColumns = createManagedColumns (
148+ props .columns .filter (column => ! isSystemColumn (column )),
149+ )
150+ defaultColumns .forEach ((column ) => {
151+ column .column .hiddenInTable = false
152+ })
181153 tempColumns .value = defaultColumns
182154}
183155
@@ -195,8 +167,10 @@ function initSortable() {
195167 const { oldIndex, newIndex } = evt
196168 if (oldIndex !== undefined && newIndex !== undefined && oldIndex !== newIndex ) {
197169 // 更新临时列顺序
198- const movedColumn = tempColumns .value .splice (oldIndex , 1 )[0 ]
199- tempColumns .value .splice (newIndex , 0 , movedColumn )
170+ const reorderedColumns = [... tempColumns .value ]
171+ const movedColumn = reorderedColumns .splice (oldIndex , 1 )[0 ]
172+ reorderedColumns .splice (newIndex , 0 , movedColumn )
173+ tempColumns .value = reorderedColumns
200174 }
201175 },
202176 })
@@ -255,19 +229,19 @@ watch(visible, async (newVisible) => {
255229 class =" column-list"
256230 >
257231 <div
258- v-for =" column in tempColumns"
259- :key =" String(column.key || column.dataIndex) "
232+ v-for =" managedColumn in tempColumns"
233+ :key =" managedColumn.id "
260234 class =" column-item"
261- :data-key =" String(column.key || column.dataIndex) "
235+ :data-key =" managedColumn.id "
262236 >
263237 <div class =" column-drag-handle" >
264238 <HolderOutlined />
265239 </div >
266240 <Checkbox
267- :checked =" ! column .hiddenInTable "
268- @change =" (e ) => column . hiddenInTable = ! e .target .checked "
241+ :checked =" ! managedColumn . column .hiddenInTable "
242+ @change =" (e ) => updateColumnVisibility ( managedColumn . id , e .target .checked ) "
269243 >
270- <span class =" column-title" >{{ getRealContent(column.title) }}</span >
244+ <span class =" column-title" >{{ getRealContent(managedColumn. column.title) }}</span >
271245 </Checkbox >
272246 </div >
273247 </div >
0 commit comments