返回 AiToEarn
currency.ts
根目录 / project / aitoearn-web / src / utils / currency.ts
1 /** 当前环境对应的货币代码 */
2 export const appCurrency: 'USD' = 'USD'
3
4 /** 当前环境对应的货币符号 */
5 export const appCurrencySymbol: '$' = '$'
6
7 /** 货币代码到符号的映射(优先查找,覆盖常见货币) */
8 const currencySymbolMap: Record<string, string> = {
9 CNY: '¥',
10 USD: '$',
11 EUR: '€',
12 GBP: '£',
13 JPY: '¥',
14 PHP: '₱',
15 THB: '฿',
16 KRW: '₩',
17 VND: '₫',
18 INR: '₹',
19 IDR: 'Rp',
20 MYR: 'RM',
21 SGD: 'S$',
22 HKD: 'HK$',
23 TWD: 'NT$',
24 AUD: 'A$',
25 CAD: 'C$',
26 NZD: 'NZ$',
27 BRL: 'R$',
28 MXN: 'MX$',
29 RUB: '₽',
30 TRY: '₺',
31 ZAR: 'R',
32 AED: 'د.إ',
33 SAR: '﷼',
34 NGN: '₦',
35 EGP: 'E£',
36 PKR: '₨',
37 BDT: '৳',
38 ARS: 'AR$',
39 }
40
41 /** Intl.NumberFormat 兜底缓存(处理 Map 中未覆盖的货币) */
42 const intlSymbolCache = new Map<string, string>()
43
44 /** 根据货币代码获取对应符号,优先硬编码 Map,未命中走 Intl.NumberFormat 兜底 */
45 export function getCurrencySymbol(currency?: string): string {
46 if (!currency)
47 return appCurrencySymbol
48 if (currencySymbolMap[currency])
49 return currencySymbolMap[currency]
50 const cached = intlSymbolCache.get(currency)
51 if (cached)
52 return cached
53 try {
54 const symbol = new Intl.NumberFormat('en', {
55 style: 'currency',
56 currency,
57 currencyDisplay: 'narrowSymbol',
58 })
59 .formatToParts(0)
60 .find(p => p.type === 'currency')
61 ?.value ?? currency
62 intlSymbolCache.set(currency, symbol)
63 return symbol
64 }
65 catch {
66 return currency
67 }
68 }
69
70 /** 分转元,格式化为两位小数 */
71 export function formatCents(cents: number | null | undefined): string {
72 if (cents == null || Number.isNaN(cents))
73 return '0.00'
74 return (cents / 100).toFixed(2)
75 }
76
77 /** 货币展示结构化数据 */
78 export interface CurrencyDisplay {
79 /** 货币符号,如 '₱' */
80 symbol: string
81 /** 格式化后的金额,如 '100.00' */
82 amount: string
83 /** 货币代码,如 'PHP' */
84 code: string
85 /** 完整文本,如 '₱100.00 PHP'(纯文本场景用) */
86 text: string
87 }
88
89 /**
90 * 生成货币展示结构化数据
91 * @param value 金额值
92 * @param currencyCode 货币代码,默认 appCurrency
93 * @param isCents 是否为分(默认 true,会除以 100;false 则直接使用原值)
94 */
95 export function formatCurrencyDisplay(
96 value: number | string | null | undefined,
97 currencyCode?: string,
98 isCents: boolean = true,
99 ): CurrencyDisplay {
100 const code = currencyCode || appCurrency
101 const symbol = getCurrencySymbol(code)
102 const amount = isCents
103 ? formatCents(typeof value === 'string' ? Number(value) : value)
104 : String(value ?? '0.00')
105 return {
106 symbol,
107 amount,
108 code,
109 text: `${symbol}${amount} ${code}`,
110 }
111 }
112
112 lines TYPESCRIPT