Files
currency-converter/miniprogram/pages/index/index.js
manpengan 92304d4fa2 feat: 汇率换算功能完整实现
- 首页双向换算:30种主流货币,实时计算,一键互换
- 汇率总览页:一对多查看所有货币换算结果
- 数据源 open.er-api.com,4小时本地缓存 + 失败兜底
- UI 美化:渐变背景、分色货币块、紫色互换按钮

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 17:26:53 +08:00

107 lines
2.4 KiB
JavaScript

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: {
pickerData,
fromIndex: DEFAULT_FROM,
toIndex: DEFAULT_TO,
amount: '100',
result: '',
unitRate: '',
reverseRate: '',
updatedAt: '',
loading: true,
error: '',
rates: null,
baseCurrency: 'CNY',
},
onLoad() {
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',
});
},
});