-
{groupName}
+
+
{groupName}
+
+
¥
-
+ {isMasked ? (
+ ******
+ ) : (
+
+ )}
@@ -1805,8 +1820,14 @@ function GroupSummary({ funds, holdings, groupName, getProfit }) {
className={summary.totalProfitToday > 0 ? 'up' : summary.totalProfitToday < 0 ? 'down' : ''}
style={{ fontSize: '18px', fontWeight: 700, fontFamily: 'var(--font-mono)' }}
>
- {summary.totalProfitToday > 0 ? '+' : summary.totalProfitToday < 0 ? '-' : ''}
-
+ {isMasked ? (
+ ******
+ ) : (
+ <>
+ {summary.totalProfitToday > 0 ? '+' : summary.totalProfitToday < 0 ? '-' : ''}
+
+ >
+ )}
@@ -1817,12 +1838,16 @@ function GroupSummary({ funds, holdings, groupName, getProfit }) {
onClick={() => setShowPercent(!showPercent)}
title="点击切换金额/百分比"
>
- {summary.totalHoldingReturn > 0 ? '+' : summary.totalHoldingReturn < 0 ? '-' : ''}
- {showPercent ? (
-
+ {isMasked ? (
+ ******
) : (
<>
-
+ {summary.totalHoldingReturn > 0 ? '+' : summary.totalHoldingReturn < 0 ? '-' : ''}
+ {showPercent ? (
+
+ ) : (
+
+ )}
>
)}
@@ -2387,13 +2412,12 @@ export default function HomePage() {
}, []);
const storageHelper = useMemo(() => {
- const keys = new Set(['funds', 'favorites', 'groups', 'collapsedCodes', 'refreshMs', 'holdings', 'pendingTrades']);
+ const keys = new Set(['funds', 'favorites', 'groups', 'collapsedCodes', 'refreshMs', 'holdings', 'pendingTrades', 'viewMode']);
const triggerSync = (key, prevValue, nextValue) => {
if (keys.has(key)) {
if (key === 'funds') {
const prevSig = getFundCodesSignature(prevValue);
const nextSig = getFundCodesSignature(nextValue);
- debugger
if (prevSig === nextSig) return;
}
if (!skipSyncRef.current) {
@@ -2424,7 +2448,7 @@ export default function HomePage() {
}, [getFundCodesSignature, scheduleSync]);
useEffect(() => {
- const keys = new Set(['funds', 'favorites', 'groups', 'collapsedCodes', 'refreshMs', 'holdings', 'pendingTrades']);
+ const keys = new Set(['funds', 'favorites', 'groups', 'collapsedCodes', 'refreshMs', 'holdings', 'pendingTrades', 'viewMode']);
const onStorage = (e) => {
if (!e.key) return;
if (!keys.has(e.key)) return;
@@ -2442,6 +2466,12 @@ export default function HomePage() {
};
}, [getFundCodesSignature, scheduleSync]);
+ const applyViewMode = useCallback((mode) => {
+ if (mode !== 'card' && mode !== 'list') return;
+ setViewMode(mode);
+ storageHelper.setItem('viewMode', mode);
+ }, [storageHelper]);
+
const toggleFavorite = (code) => {
setFavorites(prev => {
const next = new Set(prev);
@@ -2596,6 +2626,10 @@ export default function HomePage() {
if (savedHoldings && typeof savedHoldings === 'object') {
setHoldings(savedHoldings);
}
+ const savedViewMode = localStorage.getItem('viewMode');
+ if (savedViewMode === 'card' || savedViewMode === 'list') {
+ setViewMode(savedViewMode);
+ }
} catch { }
}, []);
@@ -2968,7 +3002,7 @@ export default function HomePage() {
const toggleViewMode = () => {
const nextMode = viewMode === 'card' ? 'list' : 'card';
- setViewMode(nextMode);
+ applyViewMode(nextMode);
};
const requestRemoveFund = (fund) => {
@@ -3179,6 +3213,8 @@ export default function HomePage() {
})
: [];
+ const viewMode = payload.viewMode === 'list' ? 'list' : 'card';
+
return JSON.stringify({
funds: uniqueFundCodes,
favorites,
@@ -3186,7 +3222,8 @@ export default function HomePage() {
collapsedCodes,
refreshMs: Number.isFinite(payload.refreshMs) ? payload.refreshMs : 30000,
holdings,
- pendingTrades
+ pendingTrades,
+ viewMode
});
}
@@ -3196,6 +3233,7 @@ export default function HomePage() {
const favorites = JSON.parse(localStorage.getItem('favorites') || '[]');
const groups = JSON.parse(localStorage.getItem('groups') || '[]');
const collapsedCodes = JSON.parse(localStorage.getItem('collapsedCodes') || '[]');
+ const viewMode = localStorage.getItem('viewMode') === 'list' ? 'list' : 'card';
const fundCodes = new Set(
Array.isArray(funds)
? funds.map((f) => f?.code).filter(Boolean)
@@ -3252,6 +3290,7 @@ export default function HomePage() {
refreshMs: parseInt(localStorage.getItem('refreshMs') || '30000', 10),
holdings: cleanedHoldings,
pendingTrades: cleanedPendingTrades,
+ viewMode,
exportedAt: nowInTz().toISOString()
};
} catch {
@@ -3263,6 +3302,7 @@ export default function HomePage() {
refreshMs: 30000,
holdings: {},
pendingTrades: [],
+ viewMode: 'card',
exportedAt: nowInTz().toISOString()
};
}
@@ -3298,7 +3338,7 @@ export default function HomePage() {
storageHelper.setItem('refreshMs', String(nextRefreshMs));
if (cloudData.viewMode === 'card' || cloudData.viewMode === 'list') {
- setViewMode(cloudData.viewMode);
+ applyViewMode(cloudData.viewMode);
}
const nextHoldings = cloudData.holdings && typeof cloudData.holdings === 'object' ? cloudData.holdings : {};
@@ -3415,6 +3455,7 @@ export default function HomePage() {
groups: JSON.parse(localStorage.getItem('groups') || '[]'),
collapsedCodes: JSON.parse(localStorage.getItem('collapsedCodes') || '[]'),
refreshMs: parseInt(localStorage.getItem('refreshMs') || '30000', 10),
+ viewMode: localStorage.getItem('viewMode') === 'list' ? 'list' : 'card',
holdings: JSON.parse(localStorage.getItem('holdings') || '{}'),
pendingTrades: JSON.parse(localStorage.getItem('pendingTrades') || '[]'),
exportedAt: nowInTz().toISOString()
@@ -3520,7 +3561,7 @@ export default function HomePage() {
storageHelper.setItem('refreshMs', String(data.refreshMs));
}
if (data.viewMode === 'card' || data.viewMode === 'list') {
- setViewMode(data.viewMode);
+ applyViewMode(data.viewMode);
}
if (data.holdings && typeof data.holdings === 'object') {
@@ -3907,7 +3948,7 @@ export default function HomePage() {