From 92d22b0bef407ea81668955d9234f03e5139076e Mon Sep 17 00:00:00 2001 From: hzm <934585316@qq.com> Date: Sun, 1 Mar 2026 21:03:42 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E5=88=86=E7=BB=84=E4=B8=8B?= =?UTF-8?q?=E4=B8=AA=E6=80=A7=E5=8C=96=E6=95=B0=E6=8D=AE=E7=8B=AC=E7=AB=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/MobileFundTable.jsx | 168 +++++++++++-------- app/components/PcFundTable.jsx | 257 +++++++++++++++-------------- app/globals.css | 2 +- app/page.jsx | 33 +++- 4 files changed, 265 insertions(+), 195 deletions(-) diff --git a/app/components/MobileFundTable.jsx b/app/components/MobileFundTable.jsx index 9e31718..d2b613f 100644 --- a/app/components/MobileFundTable.jsx +++ b/app/components/MobileFundTable.jsx @@ -141,78 +141,112 @@ export default function MobileFundTable({ setActiveId(null); }; - const getStoredMobileColumnOrder = () => { - if (typeof window === 'undefined') return null; + const groupKey = currentTab ?? 'all'; + + const getCustomSettingsWithMigration = () => { + if (typeof window === 'undefined') return {}; try { const raw = window.localStorage.getItem('customSettings'); - if (!raw) return null; - const parsed = JSON.parse(raw); - const order = parsed?.mobileTableColumnOrder; - if (!Array.isArray(order) || order.length === 0) return null; - const valid = order.filter((id) => MOBILE_NON_FROZEN_COLUMN_IDS.includes(id)); - const missing = MOBILE_NON_FROZEN_COLUMN_IDS.filter((id) => !valid.includes(id)); - return [...valid, ...missing]; + const parsed = raw ? JSON.parse(raw) : {}; + if (!parsed || typeof parsed !== 'object') return {}; + if (parsed.pcTableColumnOrder != null || parsed.pcTableColumnVisibility != null || parsed.pcTableColumns != null || parsed.mobileTableColumnOrder != null || parsed.mobileTableColumnVisibility != null) { + const all = { + ...(parsed.all && typeof parsed.all === 'object' ? parsed.all : {}), + pcTableColumnOrder: parsed.pcTableColumnOrder, + pcTableColumnVisibility: parsed.pcTableColumnVisibility, + pcTableColumns: parsed.pcTableColumns, + mobileTableColumnOrder: parsed.mobileTableColumnOrder, + mobileTableColumnVisibility: parsed.mobileTableColumnVisibility, + }; + delete parsed.pcTableColumnOrder; + delete parsed.pcTableColumnVisibility; + delete parsed.pcTableColumns; + delete parsed.mobileTableColumnOrder; + delete parsed.mobileTableColumnVisibility; + parsed.all = all; + window.localStorage.setItem('customSettings', JSON.stringify(parsed)); + } + return parsed; } catch { - return null; + return {}; } }; - const persistMobileColumnOrder = (nextOrder) => { + + const getInitialMobileConfigByGroup = () => { + const parsed = getCustomSettingsWithMigration(); + const byGroup = {}; + Object.keys(parsed).forEach((k) => { + if (k === 'pcContainerWidth') return; + const group = parsed[k]; + if (!group || typeof group !== 'object') return; + const order = Array.isArray(group.mobileTableColumnOrder) && group.mobileTableColumnOrder.length > 0 + ? group.mobileTableColumnOrder + : null; + const visibility = group.mobileTableColumnVisibility && typeof group.mobileTableColumnVisibility === 'object' + ? group.mobileTableColumnVisibility + : null; + byGroup[k] = { + mobileTableColumnOrder: order ? (() => { + const valid = order.filter((id) => MOBILE_NON_FROZEN_COLUMN_IDS.includes(id)); + const missing = MOBILE_NON_FROZEN_COLUMN_IDS.filter((id) => !valid.includes(id)); + return [...valid, ...missing]; + })() : null, + mobileTableColumnVisibility: visibility, + }; + }); + return byGroup; + }; + + const [configByGroup, setConfigByGroup] = useState(getInitialMobileConfigByGroup); + + const currentGroupMobile = configByGroup[groupKey]; + const defaultOrder = [...MOBILE_NON_FROZEN_COLUMN_IDS]; + const defaultVisibility = (() => { + const o = {}; + MOBILE_NON_FROZEN_COLUMN_IDS.forEach((id) => { o[id] = true; }); + return o; + })(); + + const mobileColumnOrder = (() => { + const order = currentGroupMobile?.mobileTableColumnOrder ?? defaultOrder; + if (!Array.isArray(order) || order.length === 0) return [...MOBILE_NON_FROZEN_COLUMN_IDS]; + const valid = order.filter((id) => MOBILE_NON_FROZEN_COLUMN_IDS.includes(id)); + const missing = MOBILE_NON_FROZEN_COLUMN_IDS.filter((id) => !valid.includes(id)); + return [...valid, ...missing]; + })(); + const mobileColumnVisibility = (() => { + const vis = currentGroupMobile?.mobileTableColumnVisibility ?? null; + if (vis && typeof vis === 'object' && Object.keys(vis).length > 0) return vis; + return defaultVisibility; + })(); + + const persistMobileGroupConfig = (updates) => { if (typeof window === 'undefined') return; try { const raw = window.localStorage.getItem('customSettings'); const parsed = raw ? JSON.parse(raw) : {}; - const nextSettings = - parsed && typeof parsed === 'object' - ? { ...parsed, mobileTableColumnOrder: nextOrder } - : { mobileTableColumnOrder: nextOrder }; - window.localStorage.setItem('customSettings', JSON.stringify(nextSettings)); - onCustomSettingsChange?.(); - } catch {} - }; - const getStoredMobileColumnVisibility = () => { - if (typeof window === 'undefined') return null; - try { - const raw = window.localStorage.getItem('customSettings'); - if (!raw) return null; - const parsed = JSON.parse(raw); - const visibility = parsed?.mobileTableColumnVisibility; - if (!visibility || typeof visibility !== 'object') return null; - const normalized = {}; - MOBILE_NON_FROZEN_COLUMN_IDS.forEach((id) => { - const value = visibility[id]; - if (typeof value === 'boolean') normalized[id] = value; - }); - return Object.keys(normalized).length ? normalized : null; - } catch { - return null; - } - }; - const persistMobileColumnVisibility = (nextVisibility) => { - if (typeof window === 'undefined') return; - try { - const raw = window.localStorage.getItem('customSettings'); - const parsed = raw ? JSON.parse(raw) : {}; - const nextSettings = - parsed && typeof parsed === 'object' - ? { ...parsed, mobileTableColumnVisibility: nextVisibility } - : { mobileTableColumnVisibility: nextVisibility }; - window.localStorage.setItem('customSettings', JSON.stringify(nextSettings)); + const group = parsed[groupKey] && typeof parsed[groupKey] === 'object' ? { ...parsed[groupKey] } : {}; + if (updates.mobileTableColumnOrder !== undefined) group.mobileTableColumnOrder = updates.mobileTableColumnOrder; + if (updates.mobileTableColumnVisibility !== undefined) group.mobileTableColumnVisibility = updates.mobileTableColumnVisibility; + parsed[groupKey] = group; + window.localStorage.setItem('customSettings', JSON.stringify(parsed)); + setConfigByGroup((prev) => ({ ...prev, [groupKey]: { ...prev[groupKey], ...updates } })); onCustomSettingsChange?.(); } catch {} }; - const [mobileColumnOrder, setMobileColumnOrder] = useState( - () => getStoredMobileColumnOrder() ?? [...MOBILE_NON_FROZEN_COLUMN_IDS] - ); - const [mobileColumnVisibility, setMobileColumnVisibility] = useState(() => { - const stored = getStoredMobileColumnVisibility(); - if (stored) return stored; - const allVisible = {}; - MOBILE_NON_FROZEN_COLUMN_IDS.forEach((id) => { - allVisible[id] = true; - }); - return allVisible; - }); + const setMobileColumnOrder = (nextOrderOrUpdater) => { + const next = typeof nextOrderOrUpdater === 'function' + ? nextOrderOrUpdater(mobileColumnOrder) + : nextOrderOrUpdater; + persistMobileGroupConfig({ mobileTableColumnOrder: next }); + }; + const setMobileColumnVisibility = (nextOrUpdater) => { + const next = typeof nextOrUpdater === 'function' + ? nextOrUpdater(mobileColumnVisibility) + : nextOrUpdater; + persistMobileGroupConfig({ mobileTableColumnVisibility: next }); + }; const [settingModalOpen, setSettingModalOpen] = useState(false); const tableContainerRef = useRef(null); const [tableContainerWidth, setTableContainerWidth] = useState(0); @@ -258,9 +292,7 @@ export default function MobileFundTable({ }, [tableContainerWidth, mobileColumnOrder, mobileColumnVisibility]); const handleResetMobileColumnOrder = () => { - const defaultOrder = [...MOBILE_NON_FROZEN_COLUMN_IDS]; - setMobileColumnOrder(defaultOrder); - persistMobileColumnOrder(defaultOrder); + setMobileColumnOrder([...MOBILE_NON_FROZEN_COLUMN_IDS]); }; const handleResetMobileColumnVisibility = () => { const allVisible = {}; @@ -268,14 +300,9 @@ export default function MobileFundTable({ allVisible[id] = true; }); setMobileColumnVisibility(allVisible); - persistMobileColumnVisibility(allVisible); }; const handleToggleMobileColumnVisibility = (columnId, visible) => { - setMobileColumnVisibility((prev = {}) => { - const next = { ...prev, [columnId]: visible }; - persistMobileColumnVisibility(next); - return next; - }); + setMobileColumnVisibility((prev = {}) => ({ ...prev, [columnId]: visible })); }; // 移动端名称列:无拖拽把手,长按整行触发排序 @@ -298,6 +325,7 @@ export default function MobileFundTable({ onRemoveFromGroupRef.current?.(original); }} title="从当前分组移除" + style={{ backgroundColor: 'transparent'}} > @@ -309,6 +337,7 @@ export default function MobileFundTable({ onToggleFavoriteRef.current?.(original); }} title={isFavorites ? '取消自选' : '添加自选'} + style={{ backgroundColor: 'transparent'}} > @@ -538,7 +567,6 @@ export default function MobileFundTable({ const newNonFrozen = next.filter((id) => id !== 'fundName'); if (newNonFrozen.length) { setMobileColumnOrder(newNonFrozen); - persistMobileColumnOrder(newNonFrozen); } }, onColumnVisibilityChange: (updater) => { @@ -546,7 +574,6 @@ export default function MobileFundTable({ const rest = { ...next }; delete rest.fundName; setMobileColumnVisibility(rest); - persistMobileColumnVisibility(rest); }, initialState: { columnPinning: { @@ -738,7 +765,6 @@ export default function MobileFundTable({ columnVisibility={mobileColumnVisibility} onColumnReorder={(newOrder) => { setMobileColumnOrder(newOrder); - persistMobileColumnOrder(newOrder); }} onToggleColumnVisibility={handleToggleMobileColumnVisibility} onResetColumnOrder={handleResetMobileColumnOrder} diff --git a/app/components/PcFundTable.jsx b/app/components/PcFundTable.jsx index fc681c2..f966124 100644 --- a/app/components/PcFundTable.jsx +++ b/app/components/PcFundTable.jsx @@ -161,131 +161,160 @@ export default function PcFundTable({ } setActiveId(null); }; - const getStoredColumnSizing = () => { + const groupKey = currentTab ?? 'all'; + + const getCustomSettingsWithMigration = () => { if (typeof window === 'undefined') return {}; try { const raw = window.localStorage.getItem('customSettings'); - if (!raw) return {}; - const parsed = JSON.parse(raw); - const sizing = parsed?.pcTableColumns; - if (!sizing || typeof sizing !== 'object') return {}; - return Object.fromEntries( - Object.entries(sizing).filter(([, value]) => Number.isFinite(value)), - ); + const parsed = raw ? JSON.parse(raw) : {}; + if (!parsed || typeof parsed !== 'object') return {}; + if (parsed.pcTableColumnOrder != null || parsed.pcTableColumnVisibility != null || parsed.pcTableColumns != null || parsed.mobileTableColumnOrder != null || parsed.mobileTableColumnVisibility != null) { + const all = { + ...(parsed.all && typeof parsed.all === 'object' ? parsed.all : {}), + pcTableColumnOrder: parsed.pcTableColumnOrder, + pcTableColumnVisibility: parsed.pcTableColumnVisibility, + pcTableColumns: parsed.pcTableColumns, + mobileTableColumnOrder: parsed.mobileTableColumnOrder, + mobileTableColumnVisibility: parsed.mobileTableColumnVisibility, + }; + delete parsed.pcTableColumnOrder; + delete parsed.pcTableColumnVisibility; + delete parsed.pcTableColumns; + delete parsed.mobileTableColumnOrder; + delete parsed.mobileTableColumnVisibility; + parsed.all = all; + window.localStorage.setItem('customSettings', JSON.stringify(parsed)); + } + return parsed; } catch { return {}; } }; - const persistColumnSizing = (nextSizing) => { - if (typeof window === 'undefined') return; - try { - const raw = window.localStorage.getItem('customSettings'); - const parsed = raw ? JSON.parse(raw) : {}; - const nextSettings = - parsed && typeof parsed === 'object' - ? { ...parsed, pcTableColumns: nextSizing } - : { pcTableColumns: nextSizing }; - window.localStorage.setItem('customSettings', JSON.stringify(nextSettings)); - onCustomSettingsChange?.(); - } catch { } - }; - - const getStoredColumnOrder = () => { - if (typeof window === 'undefined') return null; - try { - const raw = window.localStorage.getItem('customSettings'); - if (!raw) return null; - const parsed = JSON.parse(raw); - const order = parsed?.pcTableColumnOrder; - if (!Array.isArray(order) || order.length === 0) return null; - const valid = order.filter((id) => NON_FROZEN_COLUMN_IDS.includes(id)); - const missing = NON_FROZEN_COLUMN_IDS.filter((id) => !valid.includes(id)); - return [...valid, ...missing]; - } catch { - return null; + const buildPcConfigFromGroup = (group) => { + if (!group || typeof group !== 'object') return null; + const sizing = group.pcTableColumns; + const sizingObj = sizing && typeof sizing === 'object' + ? Object.fromEntries(Object.entries(sizing).filter(([, v]) => Number.isFinite(v))) + : {}; + if (sizingObj.actions) { + const { actions, ...rest } = sizingObj; + Object.assign(sizingObj, rest); + delete sizingObj.actions; } + const order = Array.isArray(group.pcTableColumnOrder) && group.pcTableColumnOrder.length > 0 + ? group.pcTableColumnOrder + : null; + const visibility = group.pcTableColumnVisibility && typeof group.pcTableColumnVisibility === 'object' + ? group.pcTableColumnVisibility + : null; + return { sizing: sizingObj, order, visibility }; }; - const persistColumnOrder = (nextOrder) => { - if (typeof window === 'undefined') return; - try { - const raw = window.localStorage.getItem('customSettings'); - const parsed = raw ? JSON.parse(raw) : {}; - const nextSettings = - parsed && typeof parsed === 'object' - ? { ...parsed, pcTableColumnOrder: nextOrder } - : { pcTableColumnOrder: nextOrder }; - window.localStorage.setItem('customSettings', JSON.stringify(nextSettings)); - onCustomSettingsChange?.(); - } catch { } - }; - - const getStoredColumnVisibility = () => { - if (typeof window === 'undefined') return null; - try { - const raw = window.localStorage.getItem('customSettings'); - if (!raw) return null; - const parsed = JSON.parse(raw); - const visibility = parsed?.pcTableColumnVisibility; - if (!visibility || typeof visibility !== 'object') return null; - const normalized = {}; - NON_FROZEN_COLUMN_IDS.forEach((id) => { - const value = visibility[id]; - if (typeof value === 'boolean') { - normalized[id] = value; - } - }); - return Object.keys(normalized).length ? normalized : null; - } catch { - return null; - } - }; - - const persistColumnVisibility = (nextVisibility) => { - if (typeof window === 'undefined') return; - try { - const raw = window.localStorage.getItem('customSettings'); - const parsed = raw ? JSON.parse(raw) : {}; - const nextSettings = - parsed && typeof parsed === 'object' - ? { ...parsed, pcTableColumnVisibility: nextVisibility } - : { pcTableColumnVisibility: nextVisibility }; - window.localStorage.setItem('customSettings', JSON.stringify(nextSettings)); - onCustomSettingsChange?.(); - } catch { } - }; - - const [columnSizing, setColumnSizing] = useState(() => { - const stored = getStoredColumnSizing(); - if (stored.actions) { - const { actions, ...rest } = stored; - return rest; - } - return stored; + const getDefaultPcGroupConfig = () => ({ + order: [...NON_FROZEN_COLUMN_IDS], + visibility: null, + sizing: {}, }); - const [columnOrder, setColumnOrder] = useState(() => getStoredColumnOrder() ?? [...NON_FROZEN_COLUMN_IDS]); - const [columnVisibility, setColumnVisibility] = useState(() => { - const stored = getStoredColumnVisibility(); - if (stored) return stored; - const allVisible = {}; - NON_FROZEN_COLUMN_IDS.forEach((id) => { - allVisible[id] = true; + + const getInitialConfigByGroup = () => { + const parsed = getCustomSettingsWithMigration(); + const byGroup = {}; + Object.keys(parsed).forEach((k) => { + if (k === 'pcContainerWidth') return; + const group = parsed[k]; + const pc = buildPcConfigFromGroup(group); + if (pc) { + byGroup[k] = { + pcTableColumnOrder: pc.order ? (() => { + const valid = pc.order.filter((id) => NON_FROZEN_COLUMN_IDS.includes(id)); + const missing = NON_FROZEN_COLUMN_IDS.filter((id) => !valid.includes(id)); + return [...valid, ...missing]; + })() : null, + pcTableColumnVisibility: pc.visibility, + pcTableColumns: Object.keys(pc.sizing).length ? pc.sizing : null, + }; + } }); + return byGroup; + }; + + const [configByGroup, setConfigByGroup] = useState(getInitialConfigByGroup); + + const currentGroupPc = configByGroup[groupKey]; + const defaultPc = getDefaultPcGroupConfig(); + const columnOrder = (() => { + const order = currentGroupPc?.pcTableColumnOrder ?? defaultPc.order; + if (!Array.isArray(order) || order.length === 0) return [...NON_FROZEN_COLUMN_IDS]; + const valid = order.filter((id) => NON_FROZEN_COLUMN_IDS.includes(id)); + const missing = NON_FROZEN_COLUMN_IDS.filter((id) => !valid.includes(id)); + return [...valid, ...missing]; + })(); + const columnVisibility = (() => { + const vis = currentGroupPc?.pcTableColumnVisibility ?? null; + if (vis && typeof vis === 'object' && Object.keys(vis).length > 0) return vis; + const allVisible = {}; + NON_FROZEN_COLUMN_IDS.forEach((id) => { allVisible[id] = true; }); return allVisible; - }); + })(); + const columnSizing = (() => { + const s = currentGroupPc?.pcTableColumns; + if (s && typeof s === 'object') { + const out = Object.fromEntries(Object.entries(s).filter(([, v]) => Number.isFinite(v))); + if (out.actions) { + const { actions, ...rest } = out; + return rest; + } + return out; + } + return {}; + })(); + + const persistPcGroupConfig = (updates) => { + if (typeof window === 'undefined') return; + try { + const raw = window.localStorage.getItem('customSettings'); + const parsed = raw ? JSON.parse(raw) : {}; + const group = parsed[groupKey] && typeof parsed[groupKey] === 'object' ? { ...parsed[groupKey] } : {}; + if (updates.pcTableColumnOrder !== undefined) group.pcTableColumnOrder = updates.pcTableColumnOrder; + if (updates.pcTableColumnVisibility !== undefined) group.pcTableColumnVisibility = updates.pcTableColumnVisibility; + if (updates.pcTableColumns !== undefined) group.pcTableColumns = updates.pcTableColumns; + parsed[groupKey] = group; + window.localStorage.setItem('customSettings', JSON.stringify(parsed)); + setConfigByGroup((prev) => ({ ...prev, [groupKey]: { ...prev[groupKey], ...updates } })); + onCustomSettingsChange?.(); + } catch { } + }; + + const setColumnOrder = (nextOrderOrUpdater) => { + const next = typeof nextOrderOrUpdater === 'function' + ? nextOrderOrUpdater(columnOrder) + : nextOrderOrUpdater; + persistPcGroupConfig({ pcTableColumnOrder: next }); + }; + const setColumnVisibility = (nextOrUpdater) => { + const next = typeof nextOrUpdater === 'function' + ? nextOrUpdater(columnVisibility) + : nextOrUpdater; + persistPcGroupConfig({ pcTableColumnVisibility: next }); + }; + const setColumnSizing = (nextOrUpdater) => { + const next = typeof nextOrUpdater === 'function' + ? nextOrUpdater(columnSizing) + : nextOrUpdater; + const { actions, ...rest } = next || {}; + persistPcGroupConfig({ pcTableColumns: rest || {} }); + }; const [settingModalOpen, setSettingModalOpen] = useState(false); const [resetConfirmOpen, setResetConfirmOpen] = useState(false); const handleResetSizing = () => { setColumnSizing({}); - persistColumnSizing({}); setResetConfirmOpen(false); }; const handleResetColumnOrder = () => { - const defaultOrder = [...NON_FROZEN_COLUMN_IDS]; - setColumnOrder(defaultOrder); - persistColumnOrder(defaultOrder); + setColumnOrder([...NON_FROZEN_COLUMN_IDS]); }; const handleResetColumnVisibility = () => { @@ -294,14 +323,9 @@ export default function PcFundTable({ allVisible[id] = true; }); setColumnVisibility(allVisible); - persistColumnVisibility(allVisible); }; const handleToggleColumnVisibility = (columnId, visible) => { - setColumnVisibility((prev = {}) => { - const next = { ...prev, [columnId]: visible }; - persistColumnVisibility(next); - return next; - }); + setColumnVisibility((prev = {}) => ({ ...prev, [columnId]: visible })); }; const onRemoveFundRef = useRef(onRemoveFund); const onToggleFavoriteRef = useRef(onToggleFavorite); @@ -350,6 +374,7 @@ export default function PcFundTable({ onRemoveFromGroupRef.current?.(original); }} title="从小分组移除" + style={{ backgroundColor: 'transparent'}} > @@ -676,7 +701,6 @@ export default function PcFundTable({ setColumnSizing((prev) => { const next = typeof updater === 'function' ? updater(prev) : updater; const { actions, ...rest } = next || {}; - persistColumnSizing(rest || {}); return rest || {}; }); }, @@ -686,18 +710,10 @@ export default function PcFundTable({ columnVisibility, }, onColumnOrderChange: (updater) => { - setColumnOrder((prev) => { - const next = typeof updater === 'function' ? updater(prev) : prev; - persistColumnOrder(next); - return next; - }); + setColumnOrder(updater); }, onColumnVisibilityChange: (updater) => { - setColumnVisibility((prev = {}) => { - const next = typeof updater === 'function' ? updater(prev) : (updater || {}); - persistColumnVisibility(next); - return next; - }); + setColumnVisibility(updater); }, initialState: { columnPinning: { @@ -927,7 +943,6 @@ export default function PcFundTable({ columns={columnOrder.map((id) => ({ id, header: COLUMN_HEADERS[id] ?? id }))} onColumnReorder={(newOrder) => { setColumnOrder(newOrder); - persistColumnOrder(newOrder); }} columnVisibility={columnVisibility} onToggleColumnVisibility={handleToggleColumnVisibility} diff --git a/app/globals.css b/app/globals.css index 4069e5d..b113b7e 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1900,7 +1900,7 @@ input[type="number"] { .mobile-setting-drawer { width: 100%; - max-height: 75vh; + max-height: 90vh; display: flex; flex-direction: column; border-radius: 20px 20px 0 0; diff --git a/app/page.jsx b/app/page.jsx index f787693..5f363ea 100644 --- a/app/page.jsx +++ b/app/page.jsx @@ -1751,15 +1751,44 @@ export default function HomePage() { setGroups(next); storageHelper.setItem('groups', JSON.stringify(next)); if (currentTab === id) setCurrentTab('all'); + try { + const raw = window.localStorage.getItem('customSettings'); + const parsed = raw ? JSON.parse(raw) : {}; + if (parsed && typeof parsed === 'object' && parsed[id] !== undefined) { + delete parsed[id]; + window.localStorage.setItem('customSettings', JSON.stringify(parsed)); + triggerCustomSettingsSync(); + } + } catch { } }; const handleUpdateGroups = (newGroups) => { + const removedIds = groups.filter((g) => !newGroups.find((ng) => ng.id === g.id)).map((g) => g.id); setGroups(newGroups); storageHelper.setItem('groups', JSON.stringify(newGroups)); // 如果当前选中的分组被删除了,切换回“全部” if (currentTab !== 'all' && currentTab !== 'fav' && !newGroups.find(g => g.id === currentTab)) { setCurrentTab('all'); } + if (removedIds.length > 0) { + try { + const raw = window.localStorage.getItem('customSettings'); + const parsed = raw ? JSON.parse(raw) : {}; + if (parsed && typeof parsed === 'object') { + let changed = false; + removedIds.forEach((groupId) => { + if (parsed[groupId] !== undefined) { + delete parsed[groupId]; + changed = true; + } + }); + if (changed) { + window.localStorage.setItem('customSettings', JSON.stringify(parsed)); + triggerCustomSettingsSync(); + } + } + } catch { } + } }; const handleAddFundsToGroup = (codes) => { @@ -3906,7 +3935,7 @@ export default function HomePage() { style={{ width: '100%', height: '48px', - border: '2px dashed rgba(255,255,255,0.1)', + border: '2px dashed var(--border)', background: 'transparent', borderRadius: '12px', color: 'var(--muted)', @@ -3926,7 +3955,7 @@ export default function HomePage() { e.currentTarget.style.background = 'rgba(34, 211, 238, 0.05)'; }} onMouseLeave={(e) => { - e.currentTarget.style.borderColor = 'rgba(255,255,255,0.1)'; + e.currentTarget.style.borderColor = 'var(--border)'; e.currentTarget.style.color = 'var(--muted)'; e.currentTarget.style.background = 'transparent'; }}