feat: 汇率换算功能完整实现
- 首页双向换算:30种主流货币,实时计算,一键互换 - 汇率总览页:一对多查看所有货币换算结果 - 数据源 open.er-api.com,4小时本地缓存 + 失败兜底 - UI 美化:渐变背景、分色货币块、紫色互换按钮 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,106 @@
|
||||
const { CURRENCIES, getPickerData } = require('../../utils/currencies');
|
||||
const { getRates, convert, formatAmount, formatRate } = require('../../utils/rate');
|
||||
|
||||
const pickerData = getPickerData();
|
||||
const DEFAULT_FROM = 0; // CNY
|
||||
const DEFAULT_TO = 1; // USD
|
||||
|
||||
Page({
|
||||
data: {},
|
||||
data: {
|
||||
pickerData,
|
||||
fromIndex: DEFAULT_FROM,
|
||||
toIndex: DEFAULT_TO,
|
||||
amount: '100',
|
||||
result: '',
|
||||
unitRate: '',
|
||||
reverseRate: '',
|
||||
updatedAt: '',
|
||||
loading: true,
|
||||
error: '',
|
||||
rates: null,
|
||||
baseCurrency: 'CNY',
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
console.log('Index page loaded');
|
||||
this.loadRates();
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.loadRates().then(() => {
|
||||
wx.stopPullDownRefresh();
|
||||
});
|
||||
},
|
||||
|
||||
async loadRates() {
|
||||
this.setData({ loading: true, error: '' });
|
||||
try {
|
||||
const { rates, updatedAt } = await getRates('CNY');
|
||||
this.setData({
|
||||
rates,
|
||||
baseCurrency: 'CNY',
|
||||
updatedAt,
|
||||
loading: false,
|
||||
});
|
||||
this.calculate();
|
||||
} catch (e) {
|
||||
this.setData({
|
||||
loading: false,
|
||||
error: '汇率获取失败,请检查网络后下拉刷新',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
calculate() {
|
||||
const { rates, fromIndex, toIndex, amount, baseCurrency } = this.data;
|
||||
if (!rates) return;
|
||||
|
||||
const num = parseFloat(amount);
|
||||
if (isNaN(num) || num <= 0) {
|
||||
this.setData({ result: '', unitRate: '', reverseRate: '' });
|
||||
return;
|
||||
}
|
||||
|
||||
const fromCode = CURRENCIES[fromIndex].code;
|
||||
const toCode = CURRENCIES[toIndex].code;
|
||||
const converted = convert(num, fromCode, toCode, rates);
|
||||
const unitForward = convert(1, fromCode, toCode, rates);
|
||||
const unitReverse = convert(1, toCode, fromCode, rates);
|
||||
|
||||
this.setData({
|
||||
result: formatAmount(converted, toCode),
|
||||
unitRate: `1 ${fromCode} = ${formatRate(unitForward)} ${toCode}`,
|
||||
reverseRate: `1 ${toCode} = ${formatRate(unitReverse)} ${fromCode}`,
|
||||
});
|
||||
},
|
||||
|
||||
handleAmountInput(e) {
|
||||
const value = e.detail.value;
|
||||
this.setData({ amount: value });
|
||||
this.calculate();
|
||||
},
|
||||
|
||||
handleFromChange(e) {
|
||||
this.setData({ fromIndex: Number(e.detail.value) });
|
||||
this.calculate();
|
||||
},
|
||||
|
||||
handleToChange(e) {
|
||||
this.setData({ toIndex: Number(e.detail.value) });
|
||||
this.calculate();
|
||||
},
|
||||
|
||||
handleSwap() {
|
||||
const { fromIndex, toIndex } = this.data;
|
||||
this.setData({
|
||||
fromIndex: toIndex,
|
||||
toIndex: fromIndex,
|
||||
});
|
||||
this.calculate();
|
||||
},
|
||||
|
||||
goOverview() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/overview/overview',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user