feat(ui): 首页挂载重构历史触发按钮,打通历史净值回溯全链路
This commit is contained in:
parent
fd0ef345dd
commit
c38d3fe30f
@ -147,3 +147,10 @@
|
||||
- 循环体内调用 `getHistoricalPositions(currentDate)` 获取当天所有有持仓的资产(含持仓数量与累计本金),再调用 `getEffectivePrice(assetId, currentDate)` 获取各资产的有效价格(断点结转)。
|
||||
- 引入汇率转换逻辑:预先加载 `assets` 表获取各资产的基础币种,加载 `exchangeRates` 表构建汇率映射,支持直接汇率与 USD 交叉换算,将各资产市值统一换算为 CNY。
|
||||
- 使用 `Big.js` 确保所有金额计算的高精度,按天计算 `totalValueCny`(总市值)与 `totalCostCny`(总本金),并通过 Upsert 逻辑写入 `portfolioSnapshots` 表,确保每天仅存一条记录。
|
||||
|
||||
## Dashboard 首页实装"重构历史走势"功能按钮 (Task 50c)
|
||||
- 在 `app/dashboard/page.tsx` 的"总资产概览"卡片右上角挂载"重构历史走势"按钮 (Button variant="outline")。
|
||||
- 点击按钮后调用 `reconstructPortfolioHistory()` Server Action,启动 Day-by-Day 历史净值回溯引擎。
|
||||
- 集成 Sonner Toast 通知:点击时显示 `toast.loading('正在重构历史走势...')`,完成后显示 `toast.success('重构成功,已填充 N 天历史数据')`,并自动刷新 `snapshots` 状态以更新 AreaChart 走势图。
|
||||
- 按钮启用 `isPending` 防重复点击,重构期间显示"重构中..."并禁用按钮。
|
||||
- 打通历史净值回溯全链路:用户从 Dashboard 首页一键触发,底层引擎自动从最早交易日起逐天计算持仓与价格,填充 `portfolio_snapshots` 表,前端图表实时渲染历史波动曲线。
|
||||
@ -22,7 +22,7 @@ import {
|
||||
import { toast } from 'sonner';
|
||||
import { getPortfolioSummary } from '@/actions/portfolio';
|
||||
import { getAssets } from '@/actions/asset';
|
||||
import { recordDailySnapshot, getSnapshots } from '@/actions/snapshots';
|
||||
import { recordDailySnapshot, getSnapshots, reconstructPortfolioHistory } from '@/actions/snapshots';
|
||||
import { formatQuantity, formatAmount } from '@/lib/formatters';
|
||||
import AllocationChart from '@/components/dashboard/allocation-chart';
|
||||
import NetWorthChart from '@/components/dashboard/net-worth-chart';
|
||||
@ -201,7 +201,29 @@ export default function DashboardPage() {
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">总资产概览</CardTitle>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
startTransition(async () => {
|
||||
toast.loading('正在重构历史走势...');
|
||||
const result = await reconstructPortfolioHistory();
|
||||
toast.dismiss();
|
||||
if (result.success) {
|
||||
toast.success(`重构成功,已填充 ${result.daysReconstructed} 天历史数据`);
|
||||
setSnapshots(await getSnapshots({ limit: 30 }));
|
||||
} else if (result.message) {
|
||||
toast.info(result.message);
|
||||
}
|
||||
});
|
||||
}}
|
||||
disabled={isPending}
|
||||
>
|
||||
{isPending ? '重构中...' : '重构历史走势'}
|
||||
</Button>
|
||||
<SyncButton />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-6 pb-6">
|
||||
<div className="flex items-center gap-3">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user