fix(ledger): 修复币种符号映射逻辑,并扩充引擎下发流水明细支持 UI 下钻

This commit is contained in:
kennethcheng 2026-04-28 21:46:28 +08:00
parent e63f309a3a
commit cdea2ce608
3 changed files with 28 additions and 7 deletions

View File

@ -66,6 +66,10 @@
- 修復了 `avgCostFormatted` 的判空邏輯,將 `Big.eq(0)` 修正為 `Big.eq('0')`,確保當 `pos.avgCost` 存在且不為 0 時能正確格式化,不再顯示 `¥-`
- 在資產卡片中新增「累計分紅」行,展示 `accumulatedDividendsCny` 數據,保持與其它 CNY 數據一致的 `opacity-50` 樣式。
## 修復幣種符號映射 Bug 與引擎數據擴充 (Task 40)
- 修復了币种符号映射错乱 Bug`getCurrencySymbol()` 中 CNY 和 HKD 被错误地映射为 `HK$`,现修正为 USD→$、HKD→HK$、CNY→¥。
- 在 portfolio 引擎中新增了单资产的流水明细数组:`Position` 接口新增 `transactions` 字段,`getPortfolioPositions()` 按资产名下发排序后的原始交易流水,支持前端展开查看。
## 持倉引擎 Native 幣種算法重構 (Task 38)
- 重構底層盈虧引擎,全面轉向 Native 原生幣種計算,新增浮動/累計盈虧及百分比指標。
- 徹底分離 Native 與 CNY 計算:單隻股票的成本與盈虧全部改用 Native (原幣種) 進行計算。

View File

@ -6,13 +6,9 @@ import { SyncButton } from '@/components/assets/sync-button';
import Big from 'big.js';
function getCurrencySymbol(currency: string): string {
switch (currency) {
case 'USD': return '$';
case 'CNY':
case 'HKD': return 'HK$';
case 'JPY': return '¥';
default: return currency + ' ';
}
if (currency === 'USD') return '$';
if (currency === 'HKD') return 'HK$';
return '¥';
}
function formatNative(value: string, baseCurrency: string): string {

View File

@ -37,6 +37,15 @@ interface Position {
floatingPnlPercent: string;
cumulativePnlNative: string;
cumulativePnlPercent: string;
transactions: TransactionRecord[];
}
interface TransactionRecord {
txType: string;
quantity: string;
price: string;
txCurrency: string;
executedAt: Date | null;
}
interface RawRate {
@ -174,6 +183,8 @@ export async function getPortfolioPositions(): Promise<Position[]> {
accumulatedDividendsNative: Big;
// 首次买入日期
firstBuyDate: Date | null;
// 原始流水明细
transactions: TransactionRecord[];
}>();
for (const tx of allTransactions) {
@ -198,6 +209,7 @@ export async function getPortfolioPositions(): Promise<Position[]> {
accumulatedDividendsCny: new Big('0'),
accumulatedDividendsNative: new Big('0'),
firstBuyDate: null,
transactions: [],
});
}
@ -265,6 +277,14 @@ export async function getPortfolioPositions(): Promise<Position[]> {
if (tx.assetLatestPrice) {
holding.latestPrice = tx.assetLatestPrice;
}
holding.transactions.push({
txType: tx.txType,
quantity: tx.quantity,
price: tx.price,
txCurrency: tx.txCurrency,
executedAt: tx.executedAt,
});
}
const today = getTodayInShanghai();
@ -373,6 +393,7 @@ export async function getPortfolioPositions(): Promise<Position[]> {
floatingPnlPercent: floatingPnlPercent.toString(),
cumulativePnlNative: cumulativePnlNative.toString(),
cumulativePnlPercent: cumulativePnlPercent.toString(),
transactions: holding.transactions,
});
}