Compare commits

..

2 Commits

2 changed files with 19 additions and 4 deletions

View File

@ -70,6 +70,14 @@
- 修復了币种符号映射错乱 Bug`getCurrencySymbol()` 中 CNY 和 HKD 被错误地映射为 `HK$`,现修正为 USD→$、HKD→HK$、CNY→¥。 - 修復了币种符号映射错乱 Bug`getCurrencySymbol()` 中 CNY 和 HKD 被错误地映射为 `HK$`,现修正为 USD→$、HKD→HK$、CNY→¥。
- 在 portfolio 引擎中新增了单资产的流水明细数组:`Position` 接口新增 `transactions` 字段,`getPortfolioPositions()` 按资产名下发排序后的原始交易流水,支持前端展开查看。 - 在 portfolio 引擎中新增了单资产的流水明细数组:`Position` 接口新增 `transactions` 字段,`getPortfolioPositions()` 按资产名下发排序后的原始交易流水,支持前端展开查看。
## 流水交易類型中文化映射 (Task 42a)
- 在 `app/dashboard/page.tsx` 中新增 `txTypeMap` 字典,將 `BUY`/`SELL`/`DIVIDEND`/`AIRDROP` 映射為對應中文(買入/賣出/分紅/空投)。
- 流水明細子表格中渲染 `tx.txType` 的邏輯替換為 `{txTypeMap[tx.txType] || tx.txType}`,保留原始值兜底。
## 利用 Big.js 剥离流水明细无意义尾随零 (Task 42b)
- 利用 `Big.js` 剥离了流水明细中无意义的尾随零,提升了高精度数据的可读性。
- 在 `app/dashboard/page.tsx` 的流水明細子表格中,将 `tx.quantity`、`tx.price`、`tx.fee` 的渲染逻辑改为 `new Big(value).toString()`,安全剥离因数据库 `numeric(36,18)` 配置导致的如 `0.041000000000000000` 这类冗余尾随零。
## 持倉引擎 Native 幣種算法重構 (Task 38) ## 持倉引擎 Native 幣種算法重構 (Task 38)
- 重構底層盈虧引擎,全面轉向 Native 原生幣種計算,新增浮動/累計盈虧及百分比指標。 - 重構底層盈虧引擎,全面轉向 Native 原生幣種計算,新增浮動/累計盈虧及百分比指標。
- 徹底分離 Native 與 CNY 計算:單隻股票的成本與盈虧全部改用 Native (原幣種) 進行計算。 - 徹底分離 Native 與 CNY 計算:單隻股票的成本與盈虧全部改用 Native (原幣種) 進行計算。

View File

@ -31,6 +31,13 @@ import { deleteTransaction } from '@/actions/transaction';
import { ChevronDown, ChevronUp, Plus, Edit3, Trash2 } from 'lucide-react'; import { ChevronDown, ChevronUp, Plus, Edit3, Trash2 } from 'lucide-react';
import Big from 'big.js'; import Big from 'big.js';
const txTypeMap: Record<string, string> = {
BUY: '买入',
SELL: '卖出',
DIVIDEND: '分红',
AIRDROP: '空投',
};
function getCurrencySymbol(currency: string): string { function getCurrencySymbol(currency: string): string {
if (currency === 'USD') return '$'; if (currency === 'USD') return '$';
if (currency === 'HKD') return 'HK$'; if (currency === 'HKD') return 'HK$';
@ -303,16 +310,16 @@ export default function DashboardPage() {
tx.txType === 'AIRDROP' ? 'bg-purple-100 text-purple-700' : tx.txType === 'AIRDROP' ? 'bg-purple-100 text-purple-700' :
'bg-gray-100 text-gray-700' 'bg-gray-100 text-gray-700'
}`}> }`}>
{tx.txType} {txTypeMap[tx.txType] || tx.txType}
</span> </span>
</TableCell> </TableCell>
<TableCell className="text-right text-xs"> <TableCell className="text-right text-xs">
<div className="flex flex-col items-end"> <div className="flex flex-col items-end">
<span>: {tx.quantity}</span> <span>: {new Big(tx.quantity).toString()}</span>
<span>: {tx.price}</span> <span>: {new Big(tx.price).toString()}</span>
</div> </div>
</TableCell> </TableCell>
<TableCell className="text-right text-xs">{tx.fee || '0'}</TableCell> <TableCell className="text-right text-xs">{new Big(tx.fee || 0).toString()}</TableCell>
<TableCell className="text-xs text-muted-foreground">-</TableCell> <TableCell className="text-xs text-muted-foreground">-</TableCell>
<TableCell className="text-right"> <TableCell className="text-right">
<div className="flex items-center justify-end gap-1"> <div className="flex items-center justify-end gap-1">