feat:分组资产增加眼睛以及移动端粘性布局
This commit is contained in:
@@ -111,6 +111,25 @@ export function MailIcon(props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function EyeIcon(props) {
|
||||||
|
return (
|
||||||
|
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
|
||||||
|
<path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||||
|
<circle cx="12" cy="12" r="3" stroke="currentColor" strokeWidth="2" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function EyeOffIcon(props) {
|
||||||
|
return (
|
||||||
|
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
|
||||||
|
<path d="M3 3l18 18" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
|
||||||
|
<path d="M2 12s4-6 10-6 10 6 10 6" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||||
|
<path d="M7 9.5l-2-2M10 8.5l-.5-2.5M14 8.5l.5-2.5M17 9.5l2-2" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function GridIcon(props) {
|
export function GridIcon(props) {
|
||||||
return (
|
return (
|
||||||
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
|
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
|
||||||
|
|||||||
@@ -676,6 +676,22 @@ input[type="number"] {
|
|||||||
backdrop-filter: none;
|
backdrop-filter: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group-summary-sticky {
|
||||||
|
position: sticky;
|
||||||
|
top: 175px;
|
||||||
|
z-index: 35;
|
||||||
|
width: calc(100% + 32px);
|
||||||
|
margin: 0 -16px 16px -16px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
background: rgba(15, 23, 42, 0.9);
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-summary-sticky .group-summary-card {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 禁止移动端输入框自动缩放 */
|
/* 禁止移动端输入框自动缩放 */
|
||||||
@@ -753,7 +769,7 @@ input[type="number"] {
|
|||||||
.chips {
|
.chips {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 8px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chip {
|
.chip {
|
||||||
|
|||||||
71
app/page.jsx
71
app/page.jsx
@@ -9,7 +9,7 @@ import utc from 'dayjs/plugin/utc';
|
|||||||
import timezone from 'dayjs/plugin/timezone';
|
import timezone from 'dayjs/plugin/timezone';
|
||||||
import Announcement from "./components/Announcement";
|
import Announcement from "./components/Announcement";
|
||||||
import { DatePicker, DonateTabs, NumericInput, Stat } from "./components/Common";
|
import { DatePicker, DonateTabs, NumericInput, Stat } from "./components/Common";
|
||||||
import { ChevronIcon, CloseIcon, CloudIcon, DragIcon, ExitIcon, GridIcon, ListIcon, LoginIcon, LogoutIcon, MailIcon, PlusIcon, RefreshIcon, SettingsIcon, SortIcon, StarIcon, TrashIcon, UpdateIcon, UserIcon } from "./components/Icons";
|
import { ChevronIcon, CloseIcon, CloudIcon, DragIcon, ExitIcon, EyeIcon, EyeOffIcon, GridIcon, ListIcon, LoginIcon, LogoutIcon, MailIcon, PlusIcon, RefreshIcon, SettingsIcon, SortIcon, StarIcon, TrashIcon, UpdateIcon, UserIcon } from "./components/Icons";
|
||||||
import githubImg from "./assets/github.svg";
|
import githubImg from "./assets/github.svg";
|
||||||
import weChatGroupImg from "./assets/weChatGroup.png";
|
import weChatGroupImg from "./assets/weChatGroup.png";
|
||||||
import { supabase, isSupabaseConfigured } from './lib/supabase';
|
import { supabase, isSupabaseConfigured } from './lib/supabase';
|
||||||
@@ -1728,6 +1728,7 @@ function CountUp({ value, prefix = '', suffix = '', decimals = 2, className = ''
|
|||||||
|
|
||||||
function GroupSummary({ funds, holdings, groupName, getProfit }) {
|
function GroupSummary({ funds, holdings, groupName, getProfit }) {
|
||||||
const [showPercent, setShowPercent] = useState(true);
|
const [showPercent, setShowPercent] = useState(true);
|
||||||
|
const [isMasked, setIsMasked] = useState(false);
|
||||||
const rowRef = useRef(null);
|
const rowRef = useRef(null);
|
||||||
const [assetSize, setAssetSize] = useState(24);
|
const [assetSize, setAssetSize] = useState(24);
|
||||||
const [metricSize, setMetricSize] = useState(18);
|
const [metricSize, setMetricSize] = useState(18);
|
||||||
@@ -1789,13 +1790,27 @@ function GroupSummary({ funds, holdings, groupName, getProfit }) {
|
|||||||
if (!summary.hasHolding) return null;
|
if (!summary.hasHolding) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="glass card" style={{ marginBottom: 16, padding: '16px 20px', background: 'rgba(255, 255, 255, 0.03)' }}>
|
<div className="glass card group-summary-card" style={{ marginBottom: 8, padding: '16px 20px', background: 'rgba(255, 255, 255, 0.03)' }}>
|
||||||
<div ref={rowRef} className="row" style={{ alignItems: 'flex-end', justifyContent: 'space-between' }}>
|
<div ref={rowRef} className="row" style={{ alignItems: 'flex-end', justifyContent: 'space-between' }}>
|
||||||
<div>
|
<div>
|
||||||
<div className="muted" style={{ fontSize: '12px', marginBottom: 4 }}>{groupName}</div>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
|
||||||
|
<div className="muted" style={{ fontSize: '12px' }}>{groupName}</div>
|
||||||
|
<button
|
||||||
|
className="fav-button"
|
||||||
|
onClick={() => setIsMasked(value => !value)}
|
||||||
|
aria-label={isMasked ? '显示资产' : '隐藏资产'}
|
||||||
|
style={{ margin: 0, padding: 2, display: 'inline-flex', alignItems: 'center' }}
|
||||||
|
>
|
||||||
|
{isMasked ? <EyeOffIcon width="16" height="16" /> : <EyeIcon width="16" height="16" />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div style={{ fontSize: '24px', fontWeight: 700, fontFamily: 'var(--font-mono)' }}>
|
<div style={{ fontSize: '24px', fontWeight: 700, fontFamily: 'var(--font-mono)' }}>
|
||||||
<span style={{ fontSize: '16px', marginRight: 2 }}>¥</span>
|
<span style={{ fontSize: '16px', marginRight: 2 }}>¥</span>
|
||||||
|
{isMasked ? (
|
||||||
|
<span style={{ fontSize: assetSize, position: 'relative', top: 4 }}>******</span>
|
||||||
|
) : (
|
||||||
<CountUp value={summary.totalAsset} style={{ fontSize: assetSize }} />
|
<CountUp value={summary.totalAsset} style={{ fontSize: assetSize }} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', gap: 24 }}>
|
<div style={{ display: 'flex', gap: 24 }}>
|
||||||
@@ -1805,8 +1820,14 @@ function GroupSummary({ funds, holdings, groupName, getProfit }) {
|
|||||||
className={summary.totalProfitToday > 0 ? 'up' : summary.totalProfitToday < 0 ? 'down' : ''}
|
className={summary.totalProfitToday > 0 ? 'up' : summary.totalProfitToday < 0 ? 'down' : ''}
|
||||||
style={{ fontSize: '18px', fontWeight: 700, fontFamily: 'var(--font-mono)' }}
|
style={{ fontSize: '18px', fontWeight: 700, fontFamily: 'var(--font-mono)' }}
|
||||||
>
|
>
|
||||||
|
{isMasked ? (
|
||||||
|
<span style={{ fontSize: metricSize }}>******</span>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<span style={{ marginRight: 1 }}>{summary.totalProfitToday > 0 ? '+' : summary.totalProfitToday < 0 ? '-' : ''}</span>
|
<span style={{ marginRight: 1 }}>{summary.totalProfitToday > 0 ? '+' : summary.totalProfitToday < 0 ? '-' : ''}</span>
|
||||||
<CountUp value={Math.abs(summary.totalProfitToday)} style={{ fontSize: metricSize }} />
|
<CountUp value={Math.abs(summary.totalProfitToday)} style={{ fontSize: metricSize }} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ textAlign: 'right' }}>
|
<div style={{ textAlign: 'right' }}>
|
||||||
@@ -1817,12 +1838,16 @@ function GroupSummary({ funds, holdings, groupName, getProfit }) {
|
|||||||
onClick={() => setShowPercent(!showPercent)}
|
onClick={() => setShowPercent(!showPercent)}
|
||||||
title="点击切换金额/百分比"
|
title="点击切换金额/百分比"
|
||||||
>
|
>
|
||||||
|
{isMasked ? (
|
||||||
|
<span style={{ fontSize: metricSize }}>******</span>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<span style={{ marginRight: 1 }}>{summary.totalHoldingReturn > 0 ? '+' : summary.totalHoldingReturn < 0 ? '-' : ''}</span>
|
<span style={{ marginRight: 1 }}>{summary.totalHoldingReturn > 0 ? '+' : summary.totalHoldingReturn < 0 ? '-' : ''}</span>
|
||||||
{showPercent ? (
|
{showPercent ? (
|
||||||
<CountUp value={Math.abs(summary.returnRate)} suffix="%" style={{ fontSize: metricSize }} />
|
<CountUp value={Math.abs(summary.returnRate)} suffix="%" style={{ fontSize: metricSize }} />
|
||||||
) : (
|
) : (
|
||||||
<>
|
|
||||||
<CountUp value={Math.abs(summary.totalHoldingReturn)} style={{ fontSize: metricSize }} />
|
<CountUp value={Math.abs(summary.totalHoldingReturn)} style={{ fontSize: metricSize }} />
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -2387,13 +2412,12 @@ export default function HomePage() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const storageHelper = useMemo(() => {
|
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) => {
|
const triggerSync = (key, prevValue, nextValue) => {
|
||||||
if (keys.has(key)) {
|
if (keys.has(key)) {
|
||||||
if (key === 'funds') {
|
if (key === 'funds') {
|
||||||
const prevSig = getFundCodesSignature(prevValue);
|
const prevSig = getFundCodesSignature(prevValue);
|
||||||
const nextSig = getFundCodesSignature(nextValue);
|
const nextSig = getFundCodesSignature(nextValue);
|
||||||
debugger
|
|
||||||
if (prevSig === nextSig) return;
|
if (prevSig === nextSig) return;
|
||||||
}
|
}
|
||||||
if (!skipSyncRef.current) {
|
if (!skipSyncRef.current) {
|
||||||
@@ -2424,7 +2448,7 @@ export default function HomePage() {
|
|||||||
}, [getFundCodesSignature, scheduleSync]);
|
}, [getFundCodesSignature, scheduleSync]);
|
||||||
|
|
||||||
useEffect(() => {
|
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) => {
|
const onStorage = (e) => {
|
||||||
if (!e.key) return;
|
if (!e.key) return;
|
||||||
if (!keys.has(e.key)) return;
|
if (!keys.has(e.key)) return;
|
||||||
@@ -2442,6 +2466,12 @@ export default function HomePage() {
|
|||||||
};
|
};
|
||||||
}, [getFundCodesSignature, scheduleSync]);
|
}, [getFundCodesSignature, scheduleSync]);
|
||||||
|
|
||||||
|
const applyViewMode = useCallback((mode) => {
|
||||||
|
if (mode !== 'card' && mode !== 'list') return;
|
||||||
|
setViewMode(mode);
|
||||||
|
storageHelper.setItem('viewMode', mode);
|
||||||
|
}, [storageHelper]);
|
||||||
|
|
||||||
const toggleFavorite = (code) => {
|
const toggleFavorite = (code) => {
|
||||||
setFavorites(prev => {
|
setFavorites(prev => {
|
||||||
const next = new Set(prev);
|
const next = new Set(prev);
|
||||||
@@ -2596,6 +2626,10 @@ export default function HomePage() {
|
|||||||
if (savedHoldings && typeof savedHoldings === 'object') {
|
if (savedHoldings && typeof savedHoldings === 'object') {
|
||||||
setHoldings(savedHoldings);
|
setHoldings(savedHoldings);
|
||||||
}
|
}
|
||||||
|
const savedViewMode = localStorage.getItem('viewMode');
|
||||||
|
if (savedViewMode === 'card' || savedViewMode === 'list') {
|
||||||
|
setViewMode(savedViewMode);
|
||||||
|
}
|
||||||
} catch { }
|
} catch { }
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -2968,7 +3002,7 @@ export default function HomePage() {
|
|||||||
|
|
||||||
const toggleViewMode = () => {
|
const toggleViewMode = () => {
|
||||||
const nextMode = viewMode === 'card' ? 'list' : 'card';
|
const nextMode = viewMode === 'card' ? 'list' : 'card';
|
||||||
setViewMode(nextMode);
|
applyViewMode(nextMode);
|
||||||
};
|
};
|
||||||
|
|
||||||
const requestRemoveFund = (fund) => {
|
const requestRemoveFund = (fund) => {
|
||||||
@@ -3179,6 +3213,8 @@ export default function HomePage() {
|
|||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
|
const viewMode = payload.viewMode === 'list' ? 'list' : 'card';
|
||||||
|
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
funds: uniqueFundCodes,
|
funds: uniqueFundCodes,
|
||||||
favorites,
|
favorites,
|
||||||
@@ -3186,7 +3222,8 @@ export default function HomePage() {
|
|||||||
collapsedCodes,
|
collapsedCodes,
|
||||||
refreshMs: Number.isFinite(payload.refreshMs) ? payload.refreshMs : 30000,
|
refreshMs: Number.isFinite(payload.refreshMs) ? payload.refreshMs : 30000,
|
||||||
holdings,
|
holdings,
|
||||||
pendingTrades
|
pendingTrades,
|
||||||
|
viewMode
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3196,6 +3233,7 @@ export default function HomePage() {
|
|||||||
const favorites = JSON.parse(localStorage.getItem('favorites') || '[]');
|
const favorites = JSON.parse(localStorage.getItem('favorites') || '[]');
|
||||||
const groups = JSON.parse(localStorage.getItem('groups') || '[]');
|
const groups = JSON.parse(localStorage.getItem('groups') || '[]');
|
||||||
const collapsedCodes = JSON.parse(localStorage.getItem('collapsedCodes') || '[]');
|
const collapsedCodes = JSON.parse(localStorage.getItem('collapsedCodes') || '[]');
|
||||||
|
const viewMode = localStorage.getItem('viewMode') === 'list' ? 'list' : 'card';
|
||||||
const fundCodes = new Set(
|
const fundCodes = new Set(
|
||||||
Array.isArray(funds)
|
Array.isArray(funds)
|
||||||
? funds.map((f) => f?.code).filter(Boolean)
|
? funds.map((f) => f?.code).filter(Boolean)
|
||||||
@@ -3252,6 +3290,7 @@ export default function HomePage() {
|
|||||||
refreshMs: parseInt(localStorage.getItem('refreshMs') || '30000', 10),
|
refreshMs: parseInt(localStorage.getItem('refreshMs') || '30000', 10),
|
||||||
holdings: cleanedHoldings,
|
holdings: cleanedHoldings,
|
||||||
pendingTrades: cleanedPendingTrades,
|
pendingTrades: cleanedPendingTrades,
|
||||||
|
viewMode,
|
||||||
exportedAt: nowInTz().toISOString()
|
exportedAt: nowInTz().toISOString()
|
||||||
};
|
};
|
||||||
} catch {
|
} catch {
|
||||||
@@ -3263,6 +3302,7 @@ export default function HomePage() {
|
|||||||
refreshMs: 30000,
|
refreshMs: 30000,
|
||||||
holdings: {},
|
holdings: {},
|
||||||
pendingTrades: [],
|
pendingTrades: [],
|
||||||
|
viewMode: 'card',
|
||||||
exportedAt: nowInTz().toISOString()
|
exportedAt: nowInTz().toISOString()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -3298,7 +3338,7 @@ export default function HomePage() {
|
|||||||
storageHelper.setItem('refreshMs', String(nextRefreshMs));
|
storageHelper.setItem('refreshMs', String(nextRefreshMs));
|
||||||
|
|
||||||
if (cloudData.viewMode === 'card' || cloudData.viewMode === 'list') {
|
if (cloudData.viewMode === 'card' || cloudData.viewMode === 'list') {
|
||||||
setViewMode(cloudData.viewMode);
|
applyViewMode(cloudData.viewMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextHoldings = cloudData.holdings && typeof cloudData.holdings === 'object' ? cloudData.holdings : {};
|
const nextHoldings = cloudData.holdings && typeof cloudData.holdings === 'object' ? cloudData.holdings : {};
|
||||||
@@ -3415,6 +3455,7 @@ export default function HomePage() {
|
|||||||
groups: JSON.parse(localStorage.getItem('groups') || '[]'),
|
groups: JSON.parse(localStorage.getItem('groups') || '[]'),
|
||||||
collapsedCodes: JSON.parse(localStorage.getItem('collapsedCodes') || '[]'),
|
collapsedCodes: JSON.parse(localStorage.getItem('collapsedCodes') || '[]'),
|
||||||
refreshMs: parseInt(localStorage.getItem('refreshMs') || '30000', 10),
|
refreshMs: parseInt(localStorage.getItem('refreshMs') || '30000', 10),
|
||||||
|
viewMode: localStorage.getItem('viewMode') === 'list' ? 'list' : 'card',
|
||||||
holdings: JSON.parse(localStorage.getItem('holdings') || '{}'),
|
holdings: JSON.parse(localStorage.getItem('holdings') || '{}'),
|
||||||
pendingTrades: JSON.parse(localStorage.getItem('pendingTrades') || '[]'),
|
pendingTrades: JSON.parse(localStorage.getItem('pendingTrades') || '[]'),
|
||||||
exportedAt: nowInTz().toISOString()
|
exportedAt: nowInTz().toISOString()
|
||||||
@@ -3520,7 +3561,7 @@ export default function HomePage() {
|
|||||||
storageHelper.setItem('refreshMs', String(data.refreshMs));
|
storageHelper.setItem('refreshMs', String(data.refreshMs));
|
||||||
}
|
}
|
||||||
if (data.viewMode === 'card' || data.viewMode === 'list') {
|
if (data.viewMode === 'card' || data.viewMode === 'list') {
|
||||||
setViewMode(data.viewMode);
|
applyViewMode(data.viewMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.holdings && typeof data.holdings === 'object') {
|
if (data.holdings && typeof data.holdings === 'object') {
|
||||||
@@ -3907,7 +3948,7 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="filter-bar" style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 12 }}>
|
<div className="filter-bar" style={{ marginBottom: 8, display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 12 }}>
|
||||||
<div className="tabs-container">
|
<div className="tabs-container">
|
||||||
<div
|
<div
|
||||||
className="tabs-scroll-area"
|
className="tabs-scroll-area"
|
||||||
@@ -3988,7 +4029,7 @@ export default function HomePage() {
|
|||||||
<div className="view-toggle" style={{ display: 'flex', background: 'rgba(255,255,255,0.05)', borderRadius: '10px', padding: '2px' }}>
|
<div className="view-toggle" style={{ display: 'flex', background: 'rgba(255,255,255,0.05)', borderRadius: '10px', padding: '2px' }}>
|
||||||
<button
|
<button
|
||||||
className={`icon-button ${viewMode === 'card' ? 'active' : ''}`}
|
className={`icon-button ${viewMode === 'card' ? 'active' : ''}`}
|
||||||
onClick={() => { setViewMode('card'); }}
|
onClick={() => { applyViewMode('card'); }}
|
||||||
style={{ border: 'none', width: '32px', height: '32px', background: viewMode === 'card' ? 'var(--primary)' : 'transparent', color: viewMode === 'card' ? '#05263b' : 'var(--muted)' }}
|
style={{ border: 'none', width: '32px', height: '32px', background: viewMode === 'card' ? 'var(--primary)' : 'transparent', color: viewMode === 'card' ? '#05263b' : 'var(--muted)' }}
|
||||||
title="卡片视图"
|
title="卡片视图"
|
||||||
>
|
>
|
||||||
@@ -3996,7 +4037,7 @@ export default function HomePage() {
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`icon-button ${viewMode === 'list' ? 'active' : ''}`}
|
className={`icon-button ${viewMode === 'list' ? 'active' : ''}`}
|
||||||
onClick={() => { setViewMode('list'); }}
|
onClick={() => { applyViewMode('list'); }}
|
||||||
style={{ border: 'none', width: '32px', height: '32px', background: viewMode === 'list' ? 'var(--primary)' : 'transparent', color: viewMode === 'list' ? '#05263b' : 'var(--muted)' }}
|
style={{ border: 'none', width: '32px', height: '32px', background: viewMode === 'list' ? 'var(--primary)' : 'transparent', color: viewMode === 'list' ? '#05263b' : 'var(--muted)' }}
|
||||||
title="表格视图"
|
title="表格视图"
|
||||||
>
|
>
|
||||||
@@ -4066,12 +4107,14 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
<div className={'group-summary-sticky'}>
|
||||||
<GroupSummary
|
<GroupSummary
|
||||||
funds={displayFunds}
|
funds={displayFunds}
|
||||||
holdings={holdings}
|
holdings={holdings}
|
||||||
groupName={getGroupName()}
|
groupName={getGroupName()}
|
||||||
getProfit={getHoldingProfit}
|
getProfit={getHoldingProfit}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{currentTab !== 'all' && currentTab !== 'fav' && (
|
{currentTab !== 'all' && currentTab !== 'fav' && (
|
||||||
<motion.button
|
<motion.button
|
||||||
|
|||||||
Reference in New Issue
Block a user