diff --git a/src/components/common/Table.vue b/src/components/common/Table.vue index 74dabd0..e35fc5d 100644 --- a/src/components/common/Table.vue +++ b/src/components/common/Table.vue @@ -279,15 +279,26 @@ const emit = defineEmits<{ (e: 'filter-change', filters: { [key: string]: any }): void }>() -// 获取路由和用户 Store const route = useRoute() const userStore = useUserStore() +// 缓存 key 版本号(当列配置结构升级时可手动改这个值,使旧缓存失效) +const CACHE_VERSION = 'v1' + // 生成缓存 key const getCacheKey = () => { - const baseKey = props.columnSettingStorageKey || String(route.name || route.path) - const userId = String(userStore.userInfo?.id || 'guest') - return `table-column-setting-${baseKey}-${userId}` + const baseKey = props.columnSettingStorageKey + || String((route.name as string) || route.path || 'default') + const userId = String((userStore.userInfo as any)?.id || 'guest') + return `table-column-setting-${CACHE_VERSION}-${baseKey}-${userId}` +} + +// 获取列的唯一标识(用于匹配缓存中的列) +const getColumnKey = (col: TableColumn): string => { + if (col.prop) return `prop:${col.prop}` + if (col.slotName) return `slot:${col.slotName}` + if (col.type) return `type:${col.type}` + return `label:${col.label}` } // 气泡确认框显示状态 @@ -306,63 +317,59 @@ const finalColumns = computed(() => { }) // 初始化列配置(从缓存或默认值) +// 逻辑:原始 props.columns 为准,缓存只控制“可见性”和“顺序”。 +// - 原始列中与缓存匹配的项 → 应用缓存的 visible / sortOrder +// - 原始列中新增的项 → 追加到末尾,visible 默认 true +// - 缓存中存在但原始列已删除的项 → 丢弃 const initColumns = () => { if (!props.columns || props.columns.length === 0) { localColumns.value = [] return } + // 读取缓存(可能为空) const cacheKey = getCacheKey() + let cachedConfig: any[] = [] const cached = localStorage.getItem(cacheKey) - if (cached) { try { - const cachedConfig = JSON.parse(cached) - // 按 sortOrder 排序 - cachedConfig.sort((a: any, b: any) => (a.sortOrder || 0) - (b.sortOrder || 0)) - - // 合并缓存和原始配置,保持缓存的顺序 - localColumns.value = cachedConfig.map((cached: any) => { - // 优先按 prop 匹配 - const originalCol = props.columns?.find((c) => c.prop === cached.prop) - if (originalCol) { - return { ...originalCol, ...cached } - } - // 对于没有 prop 的列(如操作列),按 slotName 匹配 - if (cached.slotName) { - const slotCol = props.columns?.find((c) => c.slotName === cached.slotName) - if (slotCol) { - return { ...slotCol, ...cached } - } - } - return null - }).filter(Boolean) + const parsed = JSON.parse(cached) + if (Array.isArray(parsed)) cachedConfig = parsed } catch { - // 解析失败,使用默认配置 - localColumns.value = props.columns.map((col) => ({ - ...col, - visible: col.visible !== false, - fixed: col.fixed || false, - })) + cachedConfig = [] } - } else { - // 无缓存,使用默认配置 - localColumns.value = props.columns.map((col) => ({ - ...col, - visible: col.visible !== false, - fixed: col.fixed || false, - })) } + + // 构建缓存映射:key -> { visible, sortOrder } + const cachedMap = new Map() + cachedConfig.forEach((c, idx) => { + cachedMap.set(c.key || getColumnKey(c), { + visible: c.visible !== false, + sortOrder: typeof c.sortOrder === 'number' ? c.sortOrder : idx, + }) + }) + + // 以原始列为主,命中缓存则用缓存的 visible / sortOrder,否则追加到末尾 + const maxOrder = Math.max(-1, ...Array.from(cachedMap.values()).map((v) => v.sortOrder)) + let nextOrder = maxOrder + 1 + + localColumns.value = props.columns.map((col) => { + const hit = cachedMap.get(getColumnKey(col)) + if (hit) { + return { ...col, visible: hit.visible, sortOrder: hit.sortOrder } + } + return { ...col, visible: col.visible !== false, sortOrder: nextOrder++ } + }) + + // 按 sortOrder 排序 + localColumns.value.sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0)) } -// 保存配置到 localStorage +// 保存配置到 localStorage(仅缓存 key / visible / sortOrder) const saveToStorage = () => { const config = localColumns.value.map((col, index) => ({ - prop: col.prop, - visible: col.visible, - label: col.label, - width: col.width, - slotName: col.slotName, + key: getColumnKey(col), + visible: col.visible !== false, sortOrder: index, })) localStorage.setItem(getCacheKey(), JSON.stringify(config)) @@ -390,48 +397,33 @@ const handleReset = () => { } // 监听 columns 变化 +// 注意:当原始 columns 变化时(如父组件新增/删除了列配置), +// 需要重新合并缓存,否则新字段不会展示。 +let lastColumnsKey = '' watch( () => props.columns, (newColumns) => { - if (newColumns && newColumns.length > 0) { - // 只有在本地列为空时才初始化(不要覆盖已加载的缓存) - if (localColumns.value.length === 0) { - initColumns() - } - } + if (!newColumns || newColumns.length === 0) return + // 通过长度+关键字段生成 key,避免不必要的重新初始化 + const newKey = newColumns.map((c) => getColumnKey(c)).join('|') + if (newKey === lastColumnsKey && localColumns.value.length > 0) return + lastColumnsKey = newKey + initColumns() }, - { immediate: true } + { immediate: true, deep: true } ) -// 组件挂载时初始化列配置 +// 组件挂载时,如果列还没初始化,再次尝试 onMounted(() => { - // 延迟初始化,确保 props.columns 已准备好 - setTimeout(() => { - if (props.columns && props.columns.length > 0 && localColumns.value.length === 0) { - initColumns() - } - }, 100) + if (props.columns && props.columns.length > 0 && localColumns.value.length === 0) { + initColumns() + } }) -// 监听 tableData 变化,清除单选选中状态 -watch( - () => props.tableData, - () => { - if (props.singleSelect) { - selectedRadioRow.value = null - } - } -) +const tableRef = ref() -// 监听 tableData 变化,清除单选选中状态 -watch( - () => props.tableData, - () => { - if (props.singleSelect) { - selectedRadioRow.value = null - } - } -) +// 维护当前选中行状态 +const selectedRow = ref(null) // 处理勾选变化 const handleSelectionChange = (rows: any[]) => { @@ -444,11 +436,6 @@ const handleCurrentChange = (row: any) => { emit('current-change', row) } -const tableRef = ref() - -// 维护当前选中行状态 -const selectedRow = ref(null) - // 处理行点击事件 const handleRowClick = (row: any) => { if (!row) return @@ -467,23 +454,17 @@ const handleRowContextmenu = (row: any, column: any, event: MouseEvent) => { emit('row-contextmenu', row, column, event) } -// 监听 tableData 变化,清除单选选中状态 +// 监听 tableData 变化(清除单选/行选中状态) watch( () => props.tableData, () => { if (props.singleSelect) { selectedRadioRow.value = null } - } -) -// 监听 tableData 变化 -watch( - () => props.tableData, - () => { selectedRow.value = null tableRef.value?.setCurrentRow(null) }, - { deep: true }, + { deep: true } ) // 处理下拉筛选命令 diff --git a/src/stores/modules/transaction.ts b/src/stores/modules/transaction.ts index feed027..0bf7dc5 100644 --- a/src/stores/modules/transaction.ts +++ b/src/stores/modules/transaction.ts @@ -48,8 +48,6 @@ export const useTransactionStore = defineStore('transaction', () => { const positionList = ref([]) /** 做市商浮动盈亏数据 Map */ const marketFloatProfitMap = ref>(new Map()) - /** 做市商平仓盈亏数据 Map */ - const marketCloseProfitMap = ref>(new Map()) // ------------------ 初始化 ------------------ @@ -120,23 +118,20 @@ export const useTransactionStore = defineStore('transaction', () => { * 格式:account_id:float_profit_loss:close_profit_loss (例:84:0.000000:0.000000) */ const handleMarketFloatProfit = (data: string): void => { + console.log('data:', data); if (!data) return const fields = data.split(':') - if (fields.length < 3) return + if (fields.length < 2) return const account_id = fields[0] - const float_profit_loss = fields[1] as string - const close_profit_loss = fields[2] as string + const float_profit_loss = fields[1] as string // 更新浮动盈亏 Map marketFloatProfitMap.value.set(account_id, float_profit_loss) + console.log('marketFloatProfitMap.value:', marketFloatProfitMap.value); marketFloatProfitMap.value = new Map(marketFloatProfitMap.value) - - // 更新平仓盈亏 Map - marketCloseProfitMap.value.set(account_id, close_profit_loss) - marketCloseProfitMap.value = new Map(marketCloseProfitMap.value) } @@ -178,7 +173,6 @@ export const useTransactionStore = defineStore('transaction', () => { mqttClient?.disconnect() positionList.value = [] marketFloatProfitMap.value.clear() - marketCloseProfitMap.value.clear() } /** @@ -193,7 +187,6 @@ export const useTransactionStore = defineStore('transaction', () => { mqttClient, positionList, marketFloatProfitMap, - marketCloseProfitMap, initMarketConditionsMQTT, getPositionList, requestMarketFloatProfit,