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