From 993c7d819a24c2acede92d1c5af1b14ffd7023c4 Mon Sep 17 00:00:00 2001 From: kennethcheng Date: Sat, 2 May 2026 15:35:09 +0800 Subject: [PATCH] =?UTF-8?q?feat(portfolio):=20CSV=20=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=B8=82=E5=9C=BA=E5=88=86=E7=B1=BB=E7=BB=B4?= =?UTF-8?q?=E5=BA=A6=EF=BC=8C=E6=94=AF=E6=8C=81=20A=E8=82=A1/=E7=BE=8E?= =?UTF-8?q?=E8=82=A1/=E6=B8=AF=E8=82=A1/=E8=99=9A=E6=8B=9F=E5=B8=81?= =?UTF-8?q?=E7=B2=BE=E5=87=86=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Memory.md | 6 ++++++ app/dashboard/page.tsx | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Memory.md b/Memory.md index 15b3767..53428b1 100644 --- a/Memory.md +++ b/Memory.md @@ -1,5 +1,11 @@ # Omniledger 架构与开发记忆 (Memory) +## 优化 exportToCSV 功能,基于 type 和 baseCurrency 的交叉判定注入了'市场'属性分类列,便于在外部进行资产敞口分析 (Task 70) +- 在 `app/dashboard/page.tsx` 的 `exportToCSV()` 函数中新增 `getMarketName(item)` 纯函数,实现市场维度的智能推导。 +- 判定优先级:`type === 'CRYPTO'` → `baseCurrency` 硬核锚定 (USD→美股, HKD→港股, CNY/RMB→A股) → 正则兜底 (5位数字→港股, 60/00/30开头→A股) → 默认"其他市场"。 +- CSV 表头在"代码"之后插入"市场"列,`rows` 映射严格对齐,确保 BTC 显示"虚拟币"、谷歌显示"美股"、小米显示"港股"、上海机场显示"A股"。 +- 文件仍带 `\uFEFF` BOM 头,Excel 打开中文不乱码。 + ## 优化 exportToCSV 数据净洗逻辑,利用防科学计数法的纯正则处理去除现价/成本价末尾的无意义零 (Task 69) - 在 `app/dashboard/page.tsx` 的 `exportToCSV()` 函数顶部注入 `stripTrailingZeros` 纯字符串去零工具函数。 - 该函数内置防御性设计:对 null/undefined/空值返回 `"0"`;仅对包含小数点的字符串执行正则处理(`/0+$/` 剥离尾随零 → `/\.$/` 剥离末尾小数点),彻底杜绝极小数值(如 `0.00000001`)被 `String()` 转换后触发科学计数法(`1e-8`)。 diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index 13cfc94..60ed2ef 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -66,11 +66,24 @@ function exportToCSV(positions: any[]) { return str; }; - const headers = ["资产名称", "代码", "持仓量", "成本价", "现价", "总市值", "浮动盈亏", "累计盈亏"]; + const getMarketName = (item: any): string => { + if (item.type === 'CRYPTO' || item.assetType === 'CRYPTO') return '虚拟币'; + const currency = (item.baseCurrency || '').toUpperCase(); + if (currency === 'USD') return '美股'; + if (currency === 'HKD') return '港股'; + if (currency === 'CNY' || currency === 'RMB') return 'A股'; + const symbol = (item.symbol || '').toLowerCase(); + if (/^\d{5}$/.test(symbol)) return '港股'; + if (/^(60|00|30)\d{4}$/.test(symbol) || symbol.startsWith('sh') || symbol.startsWith('sz')) return 'A股'; + return '其他市场'; + }; + + const headers = ["资产名称", "代码", "市场", "持仓量", "成本价", "现价", "总市值", "浮动盈亏", "累计盈亏"]; const rows = positions.map(item => [ item.name || item.symbol, item.symbol, + getMarketName(item), item.quantity || '0', stripTrailingZeros(new Big(item.avgCostNative || '0').toFixed(2)), stripTrailingZeros(item.latestPrice || '0'),