feat: 增加当日收益率切换
This commit is contained in:
@@ -53,6 +53,7 @@ export default function FundCard({
|
||||
dcaPlans,
|
||||
holdings,
|
||||
percentModes,
|
||||
todayPercentModes,
|
||||
valuationSeries,
|
||||
collapsedCodes,
|
||||
collapsedTrends,
|
||||
@@ -67,6 +68,7 @@ export default function FundCard({
|
||||
onHoldingClick,
|
||||
onActionClick,
|
||||
onPercentModeToggle,
|
||||
onTodayPercentModeToggle,
|
||||
onToggleCollapse,
|
||||
onToggleTrendCollapse,
|
||||
layoutMode = 'card', // 'card' | 'drawer',drawer 时前10重仓与业绩走势以 Tabs 展示
|
||||
@@ -281,8 +283,28 @@ export default function FundCard({
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
<div className="stat" style={{ flexDirection: 'column', gap: 4 }}>
|
||||
<span className="label">当日收益</span>
|
||||
<div
|
||||
className="stat"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (profit.profitToday != null) {
|
||||
onTodayPercentModeToggle?.(f.code);
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
cursor: profit.profitToday != null ? 'pointer' : 'default',
|
||||
flexDirection: 'column',
|
||||
gap: 4,
|
||||
}}
|
||||
title={profit.profitToday != null ? '点击切换金额/百分比' : ''}
|
||||
>
|
||||
<span
|
||||
className="label"
|
||||
style={{ display: 'flex', alignItems: 'center', gap: 1 }}
|
||||
>
|
||||
当日收益{todayPercentModes?.[f.code] ? '(%)' : ''}
|
||||
{profit.profitToday != null && <SwitchIcon />}
|
||||
</span>
|
||||
<span
|
||||
className={`value ${
|
||||
profit.profitToday != null
|
||||
@@ -297,7 +319,16 @@ export default function FundCard({
|
||||
{profit.profitToday != null
|
||||
? masked
|
||||
? '******'
|
||||
: `${profit.profitToday > 0 ? '+' : profit.profitToday < 0 ? '-' : ''}¥${Math.abs(profit.profitToday).toFixed(2)}`
|
||||
: <>
|
||||
{profit.profitToday > 0 ? '+' : profit.profitToday < 0 ? '-' : ''}
|
||||
{todayPercentModes?.[f.code]
|
||||
? `${Math.abs(
|
||||
holding?.cost * holding?.share
|
||||
? (profit.profitToday / (holding.cost * holding.share)) * 100
|
||||
: 0,
|
||||
).toFixed(2)}%`
|
||||
: `¥${Math.abs(profit.profitToday).toFixed(2)}`}
|
||||
</>
|
||||
: '--'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -64,6 +64,7 @@ export default function GroupSummary({
|
||||
navbarHeight
|
||||
}) {
|
||||
const [showPercent, setShowPercent] = useState(true);
|
||||
const [showTodayPercent, setShowTodayPercent] = useState(false);
|
||||
const [isMasked, setIsMasked] = useState(masked ?? false);
|
||||
const rowRef = useRef(null);
|
||||
const [assetSize, setAssetSize] = useState(24);
|
||||
@@ -137,6 +138,7 @@ export default function GroupSummary({
|
||||
const roundedTotalProfitToday = Math.round(totalProfitToday * 100) / 100;
|
||||
|
||||
const returnRate = totalCost > 0 ? (totalHoldingReturn / totalCost) * 100 : 0;
|
||||
const todayReturnRate = totalCost > 0 ? (roundedTotalProfitToday / totalCost) * 100 : 0;
|
||||
|
||||
return {
|
||||
totalAsset,
|
||||
@@ -144,6 +146,7 @@ export default function GroupSummary({
|
||||
totalHoldingReturn,
|
||||
hasHolding,
|
||||
returnRate,
|
||||
todayReturnRate,
|
||||
hasAnyTodayData,
|
||||
};
|
||||
}, [funds, holdings, getProfit]);
|
||||
@@ -277,9 +280,17 @@ export default function GroupSummary({
|
||||
<div style={{ textAlign: 'right' }}>
|
||||
<div
|
||||
className="muted"
|
||||
style={{ fontSize: '12px', marginBottom: 4 }}
|
||||
style={{
|
||||
fontSize: '12px',
|
||||
marginBottom: 4,
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
gap: 2,
|
||||
}}
|
||||
>
|
||||
当日收益
|
||||
当日收益{showTodayPercent ? '(%)' : ''}{' '}
|
||||
<SwitchIcon style={{ opacity: 0.4 }} />
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
@@ -295,7 +306,10 @@ export default function GroupSummary({
|
||||
fontSize: '18px',
|
||||
fontWeight: 700,
|
||||
fontFamily: 'var(--font-mono)',
|
||||
cursor: summary.hasAnyTodayData ? 'pointer' : 'default',
|
||||
}}
|
||||
onClick={() => summary.hasAnyTodayData && setShowTodayPercent(!showTodayPercent)}
|
||||
title="点击切换金额/百分比"
|
||||
>
|
||||
{isMasked ? (
|
||||
<span className="mask-text" style={{ fontSize: metricSize }}>
|
||||
@@ -310,10 +324,18 @@ export default function GroupSummary({
|
||||
? '-'
|
||||
: ''}
|
||||
</span>
|
||||
<CountUp
|
||||
value={Math.abs(summary.totalProfitToday)}
|
||||
style={{ fontSize: metricSize }}
|
||||
/>
|
||||
{showTodayPercent ? (
|
||||
<CountUp
|
||||
value={Math.abs(summary.todayReturnRate)}
|
||||
suffix="%"
|
||||
style={{ fontSize: metricSize }}
|
||||
/>
|
||||
) : (
|
||||
<CountUp
|
||||
value={Math.abs(summary.totalProfitToday)}
|
||||
style={{ fontSize: metricSize }}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<span style={{ fontSize: metricSize }}>--</span>
|
||||
|
||||
13
app/page.jsx
13
app/page.jsx
@@ -442,6 +442,7 @@ export default function HomePage() {
|
||||
const [historyModal, setHistoryModal] = useState({ open: false, fund: null });
|
||||
const [addHistoryModal, setAddHistoryModal] = useState({ open: false, fund: null });
|
||||
const [percentModes, setPercentModes] = useState({}); // { [code]: boolean }
|
||||
const [todayPercentModes, setTodayPercentModes] = useState({}); // { [code]: boolean }
|
||||
|
||||
const holdingsRef = useRef(holdings);
|
||||
const pendingTradesRef = useRef(pendingTrades);
|
||||
@@ -4334,7 +4335,9 @@ export default function HomePage() {
|
||||
favorites,
|
||||
dcaPlans,
|
||||
holdings,
|
||||
percentModes,
|
||||
percentModes,
|
||||
todayPercentModes,
|
||||
todayPercentModes,
|
||||
valuationSeries,
|
||||
collapsedCodes,
|
||||
collapsedTrends,
|
||||
@@ -4350,6 +4353,8 @@ export default function HomePage() {
|
||||
onActionClick: (f) => setActionModal({ open: true, fund: f }),
|
||||
onPercentModeToggle: (code) =>
|
||||
setPercentModes((prev) => ({ ...prev, [code]: !prev[code] })),
|
||||
onTodayPercentModeToggle: (code) =>
|
||||
setTodayPercentModes((prev) => ({ ...prev, [code]: !prev[code] })),
|
||||
onToggleCollapse: toggleCollapse,
|
||||
onToggleTrendCollapse: toggleTrendCollapse,
|
||||
masked: maskAmounts,
|
||||
@@ -4426,6 +4431,8 @@ export default function HomePage() {
|
||||
onActionClick: (f) => setActionModal({ open: true, fund: f }),
|
||||
onPercentModeToggle: (code) =>
|
||||
setPercentModes((prev) => ({ ...prev, [code]: !prev[code] })),
|
||||
onTodayPercentModeToggle: (code) =>
|
||||
setTodayPercentModes((prev) => ({ ...prev, [code]: !prev[code] })),
|
||||
onToggleCollapse: toggleCollapse,
|
||||
onToggleTrendCollapse: toggleTrendCollapse,
|
||||
masked: maskAmounts,
|
||||
@@ -4455,6 +4462,7 @@ export default function HomePage() {
|
||||
dcaPlans={dcaPlans}
|
||||
holdings={holdings}
|
||||
percentModes={percentModes}
|
||||
todayPercentModes={todayPercentModes}
|
||||
valuationSeries={valuationSeries}
|
||||
collapsedCodes={collapsedCodes}
|
||||
collapsedTrends={collapsedTrends}
|
||||
@@ -4471,6 +4479,9 @@ export default function HomePage() {
|
||||
onPercentModeToggle={(code) =>
|
||||
setPercentModes((prev) => ({ ...prev, [code]: !prev[code] }))
|
||||
}
|
||||
onTodayPercentModeToggle={(code) =>
|
||||
setTodayPercentModes((prev) => ({ ...prev, [code]: !prev[code] }))
|
||||
}
|
||||
onToggleCollapse={toggleCollapse}
|
||||
onToggleTrendCollapse={toggleTrendCollapse}
|
||||
masked={maskAmounts}
|
||||
|
||||
Reference in New Issue
Block a user