diff --git a/.gitignore b/.gitignore
index 1230299..724d3b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
node_modules/
miniprogram_npm/
.DS_Store
+project.private.config.json
+project.miniapp.json
+miniprogram/app.miniapp.json
+i18n/
diff --git a/logo.html b/logo.html
new file mode 100644
index 0000000..daa9fc4
--- /dev/null
+++ b/logo.html
@@ -0,0 +1,31 @@
+
+
+
+
+Logo
+
+
+
+
+
+
diff --git a/miniprogram/app.js b/miniprogram/app.js
index dc45afe..3d3020d 100644
--- a/miniprogram/app.js
+++ b/miniprogram/app.js
@@ -1,7 +1,3 @@
App({
globalData: {},
-
- onLaunch() {
- console.log('App launched');
- },
});
diff --git a/miniprogram/app.wxss b/miniprogram/app.wxss
index 64a56de..e1b7f2a 100644
--- a/miniprogram/app.wxss
+++ b/miniprogram/app.wxss
@@ -1,6 +1,6 @@
page {
- background-color: #F5F5F5;
- color: #333333;
+ background: linear-gradient(180deg, #EEF2FF 0%, #F5F5F5 320rpx);
+ color: #1E293B;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 28rpx;
line-height: 1.6;
@@ -8,24 +8,12 @@ page {
.container {
padding: 32rpx;
+ padding-top: 24rpx;
}
.card {
background-color: #FFFFFF;
- border-radius: 16rpx;
- padding: 32rpx;
+ border-radius: 24rpx;
margin-bottom: 24rpx;
- box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
-}
-
-.page-title {
- font-size: 40rpx;
- font-weight: 700;
- margin-bottom: 16rpx;
-}
-
-.page-subtitle {
- font-size: 26rpx;
- color: #999999;
- margin-bottom: 32rpx;
+ box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
}
diff --git a/miniprogram/pages/index/index.js b/miniprogram/pages/index/index.js
index c925faf..397d820 100644
--- a/miniprogram/pages/index/index.js
+++ b/miniprogram/pages/index/index.js
@@ -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',
+ });
},
});
diff --git a/miniprogram/pages/index/index.json b/miniprogram/pages/index/index.json
index a97367d..9fa0b64 100644
--- a/miniprogram/pages/index/index.json
+++ b/miniprogram/pages/index/index.json
@@ -1,3 +1,5 @@
{
+ "navigationBarTitleText": "汇率换算",
+ "enablePullDownRefresh": true,
"usingComponents": {}
}
diff --git a/miniprogram/pages/index/index.wxml b/miniprogram/pages/index/index.wxml
index 9b5df6e..a20aec9 100644
--- a/miniprogram/pages/index/index.wxml
+++ b/miniprogram/pages/index/index.wxml
@@ -1,8 +1,76 @@
- 汇率换算
- 实时汇率,主流货币换算
+
+
+ 💱 汇率换算
+ {{updatedAt}} 更新
+ 正在获取最新汇率...
+
-
- 功能开发中
+
+
+
+
+
+
+ {{pickerData[fromIndex]}}
+ ▼
+
+
+
+
+
+
+
+
+
+ ⇅
+
+
+
+
+
+
+
+
+ {{pickerData[toIndex]}}
+ ▼
+
+
+ {{result || '—'}}
+
+
+
+
+
+
+
+ {{unitRate}}
+
+
+
+ {{reverseRate}}
+
+
+
+
+
+ ⚠
+ {{error}}
+
+
+
+
+
+ 📊
+ 查看汇率总览
+
+ ›
diff --git a/miniprogram/pages/index/index.wxss b/miniprogram/pages/index/index.wxss
index d2e7505..36ee0cf 100644
--- a/miniprogram/pages/index/index.wxss
+++ b/miniprogram/pages/index/index.wxss
@@ -1,6 +1,192 @@
-.placeholder-text {
- color: #999999;
- font-size: 28rpx;
- text-align: center;
- padding: 48rpx 0;
+/* ===== 顶部标题 ===== */
+.hero {
+ padding: 16rpx 8rpx 24rpx;
+}
+
+.hero-title {
+ font-size: 48rpx;
+ font-weight: 800;
+ color: #1E293B;
+ letter-spacing: 2rpx;
+}
+
+.hero-desc {
+ font-size: 24rpx;
+ color: #94A3B8;
+ margin-top: 8rpx;
+}
+
+/* ===== 换算主卡片 ===== */
+.converter-card {
+ padding: 40rpx 36rpx;
+}
+
+.currency-block {
+ border-radius: 20rpx;
+ padding: 28rpx;
+}
+
+.from-block {
+ background: #F8FAFC;
+ border: 2rpx solid #E2E8F0;
+}
+
+.to-block {
+ background: linear-gradient(135deg, #EEF2FF 0%, #E0E7FF 100%);
+ border: 2rpx solid #C7D2FE;
+}
+
+.currency-tag {
+ display: inline-flex;
+ align-items: center;
+ background: #FFFFFF;
+ border-radius: 12rpx;
+ padding: 10rpx 20rpx;
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
+}
+
+.currency-tag-text {
+ font-size: 26rpx;
+ font-weight: 500;
+ color: #334155;
+}
+
+.tag-arrow {
+ font-size: 18rpx;
+ color: #94A3B8;
+ margin-left: 10rpx;
+}
+
+.amount-input {
+ width: 100%;
+ margin-top: 20rpx;
+ font-size: 56rpx;
+ font-weight: 800;
+ color: #1E293B;
+ text-align: right;
+}
+
+.amount-placeholder {
+ color: #CBD5E1;
+ font-weight: 400;
+}
+
+.result-display {
+ margin-top: 20rpx;
+ font-size: 56rpx;
+ font-weight: 800;
+ color: #4F46E5;
+ text-align: right;
+}
+
+/* ===== 互换按钮 ===== */
+.swap-wrapper {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 12rpx 0;
+}
+
+.swap-line {
+ flex: 1;
+ height: 2rpx;
+ background: #E2E8F0;
+}
+
+.swap-btn {
+ width: 80rpx;
+ height: 80rpx;
+ border-radius: 50%;
+ background: #4F46E5;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin: 0 24rpx;
+ box-shadow: 0 6rpx 20rpx rgba(79, 70, 229, 0.3);
+}
+
+.swap-icon {
+ font-size: 36rpx;
+ color: #FFFFFF;
+}
+
+/* ===== 单位汇率 ===== */
+.rate-card {
+ padding: 28rpx 36rpx;
+}
+
+.rate-row {
+ display: flex;
+ align-items: center;
+ padding: 8rpx 0;
+}
+
+.rate-dot {
+ width: 14rpx;
+ height: 14rpx;
+ border-radius: 50%;
+ margin-right: 16rpx;
+ flex-shrink: 0;
+}
+
+.from-dot {
+ background: #64748B;
+}
+
+.to-dot {
+ background: #4F46E5;
+}
+
+.rate-text {
+ font-size: 26rpx;
+ color: #64748B;
+ font-weight: 500;
+}
+
+/* ===== 错误提示 ===== */
+.error-card {
+ display: flex;
+ align-items: center;
+ padding: 28rpx 36rpx;
+ background: #FEF2F2;
+}
+
+.error-icon {
+ font-size: 32rpx;
+ margin-right: 16rpx;
+}
+
+.error-text {
+ font-size: 26rpx;
+ color: #DC2626;
+}
+
+/* ===== 汇率总览入口 ===== */
+.overview-entry {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 36rpx;
+}
+
+.overview-left {
+ display: flex;
+ align-items: center;
+}
+
+.overview-icon {
+ font-size: 36rpx;
+ margin-right: 16rpx;
+}
+
+.overview-label {
+ font-size: 30rpx;
+ font-weight: 500;
+ color: #334155;
+}
+
+.overview-arrow {
+ font-size: 40rpx;
+ color: #CBD5E1;
+ font-weight: 300;
}
diff --git a/miniprogram/pages/overview/overview.js b/miniprogram/pages/overview/overview.js
index 43d9a28..eed7de0 100644
--- a/miniprogram/pages/overview/overview.js
+++ b/miniprogram/pages/overview/overview.js
@@ -1,7 +1,84 @@
+const { CURRENCIES, getPickerData } = require('../../utils/currencies');
+const { getRates, convert, formatAmount, formatRate } = require('../../utils/rate');
+
+const pickerData = getPickerData();
+
Page({
- data: {},
+ data: {
+ pickerData,
+ baseIndex: 0, // CNY
+ amount: '100',
+ list: [],
+ updatedAt: '',
+ loading: true,
+ error: '',
+ rates: null,
+ },
onLoad() {
- console.log('Overview page loaded');
+ this.loadRates();
+ },
+
+ onPullDownRefresh() {
+ this.loadRates().then(() => {
+ wx.stopPullDownRefresh();
+ });
+ },
+
+ async loadRates() {
+ this.setData({ loading: true, error: '' });
+ try {
+ const baseCode = CURRENCIES[this.data.baseIndex].code;
+ const { rates, updatedAt } = await getRates(baseCode);
+ this.setData({
+ rates,
+ updatedAt,
+ loading: false,
+ });
+ this.buildList();
+ } catch (e) {
+ this.setData({
+ loading: false,
+ error: '汇率获取失败,请检查网络后下拉刷新',
+ });
+ }
+ },
+
+ buildList() {
+ const { rates, baseIndex, amount } = this.data;
+ if (!rates) return;
+
+ const num = parseFloat(amount);
+ if (isNaN(num) || num <= 0) {
+ this.setData({ list: [] });
+ return;
+ }
+
+ const baseCode = CURRENCIES[baseIndex].code;
+ const list = CURRENCIES
+ .filter((c) => c.code !== baseCode)
+ .map((c) => {
+ const converted = convert(num, baseCode, c.code, rates);
+ const unitRate = convert(1, baseCode, c.code, rates);
+ return {
+ flag: c.flag,
+ code: c.code,
+ name: c.name,
+ converted: formatAmount(converted, c.code),
+ unitRate: formatRate(unitRate),
+ };
+ });
+
+ this.setData({ list });
+ },
+
+ handleBaseChange(e) {
+ this.setData({ baseIndex: Number(e.detail.value) });
+ this.loadRates();
+ },
+
+ handleAmountInput(e) {
+ this.setData({ amount: e.detail.value });
+ this.buildList();
},
});
diff --git a/miniprogram/pages/overview/overview.json b/miniprogram/pages/overview/overview.json
index 7d9fbbc..4100ccf 100644
--- a/miniprogram/pages/overview/overview.json
+++ b/miniprogram/pages/overview/overview.json
@@ -1,4 +1,5 @@
{
"navigationBarTitleText": "汇率总览",
+ "enablePullDownRefresh": true,
"usingComponents": {}
}
diff --git a/miniprogram/pages/overview/overview.wxml b/miniprogram/pages/overview/overview.wxml
index 5f55da3..1c6c274 100644
--- a/miniprogram/pages/overview/overview.wxml
+++ b/miniprogram/pages/overview/overview.wxml
@@ -1,8 +1,64 @@
- 汇率总览
- 一个基准货币对所有主流货币
+
+
diff --git a/miniprogram/pages/overview/overview.wxss b/miniprogram/pages/overview/overview.wxss
index d2e7505..07f72f5 100644
--- a/miniprogram/pages/overview/overview.wxss
+++ b/miniprogram/pages/overview/overview.wxss
@@ -1,6 +1,157 @@
-.placeholder-text {
- color: #999999;
- font-size: 28rpx;
- text-align: center;
- padding: 48rpx 0;
+/* ===== 顶部控制区 ===== */
+.header-card {
+ padding: 36rpx;
+}
+
+.header-top {
+ margin-bottom: 28rpx;
+}
+
+.header-title {
+ font-size: 40rpx;
+ font-weight: 800;
+ color: #1E293B;
+}
+
+.control-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 20rpx 0;
+ border-top: 2rpx solid #F1F5F9;
+}
+
+.control-label {
+ font-size: 28rpx;
+ color: #64748B;
+ font-weight: 500;
+}
+
+.base-tag {
+ display: inline-flex;
+ align-items: center;
+ background: #F8FAFC;
+ border: 2rpx solid #E2E8F0;
+ border-radius: 12rpx;
+ padding: 10rpx 20rpx;
+}
+
+.base-tag-text {
+ font-size: 26rpx;
+ font-weight: 500;
+ color: #334155;
+}
+
+.tag-arrow {
+ font-size: 18rpx;
+ color: #94A3B8;
+ margin-left: 10rpx;
+}
+
+.amount-input {
+ flex: 1;
+ text-align: right;
+ font-size: 40rpx;
+ font-weight: 800;
+ color: #1E293B;
+ margin-left: 24rpx;
+}
+
+.amount-placeholder {
+ color: #CBD5E1;
+ font-weight: 400;
+}
+
+.updated-at {
+ font-size: 22rpx;
+ color: #94A3B8;
+ margin-top: 16rpx;
+}
+
+/* ===== 错误 & 加载 ===== */
+.error-card {
+ display: flex;
+ align-items: center;
+ padding: 28rpx 36rpx;
+ background: #FEF2F2;
+}
+
+.error-icon {
+ font-size: 32rpx;
+ margin-right: 16rpx;
+}
+
+.error-text {
+ font-size: 26rpx;
+ color: #DC2626;
+}
+
+.loading-card {
+ padding: 40rpx;
+ text-align: center;
+ color: #94A3B8;
+ font-size: 26rpx;
+}
+
+/* ===== 汇率列表 ===== */
+.list-card {
+ padding: 8rpx 0;
+}
+
+.rate-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 28rpx 36rpx;
+ border-bottom: 2rpx solid #F8FAFC;
+ transition: background 0.15s;
+}
+
+.rate-item:last-child {
+ border-bottom: none;
+}
+
+.rate-left {
+ display: flex;
+ align-items: center;
+}
+
+.rate-flag {
+ font-size: 44rpx;
+ margin-right: 20rpx;
+}
+
+.rate-info {
+ display: flex;
+ flex-direction: column;
+}
+
+.rate-code {
+ font-size: 30rpx;
+ font-weight: 700;
+ color: #1E293B;
+}
+
+.rate-name {
+ font-size: 22rpx;
+ color: #94A3B8;
+ margin-top: 4rpx;
+}
+
+.rate-right {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+}
+
+.rate-value {
+ font-size: 32rpx;
+ font-weight: 800;
+ color: #1E293B;
+}
+
+.rate-unit {
+ font-size: 22rpx;
+ color: #94A3B8;
+ margin-top: 4rpx;
}
diff --git a/miniprogram/utils/currencies.js b/miniprogram/utils/currencies.js
new file mode 100644
index 0000000..6dd93c2
--- /dev/null
+++ b/miniprogram/utils/currencies.js
@@ -0,0 +1,65 @@
+/**
+ * 主流货币配置(约 30 种)
+ * flag: emoji 国旗
+ * code: ISO 4217 货币代码
+ * name: 中文名
+ */
+const CURRENCIES = [
+ { flag: '🇨🇳', code: 'CNY', name: '人民币' },
+ { flag: '🇺🇸', code: 'USD', name: '美元' },
+ { flag: '🇪🇺', code: 'EUR', name: '欧元' },
+ { flag: '🇬🇧', code: 'GBP', name: '英镑' },
+ { flag: '🇯🇵', code: 'JPY', name: '日元' },
+ { flag: '🇰🇷', code: 'KRW', name: '韩元' },
+ { flag: '🇭🇰', code: 'HKD', name: '港币' },
+ { flag: '🇹🇼', code: 'TWD', name: '新台币' },
+ { flag: '🇲🇴', code: 'MOP', name: '澳门元' },
+ { flag: '🇸🇬', code: 'SGD', name: '新加坡元' },
+ { flag: '🇦🇺', code: 'AUD', name: '澳元' },
+ { flag: '🇨🇦', code: 'CAD', name: '加元' },
+ { flag: '🇳🇿', code: 'NZD', name: '新西兰元' },
+ { flag: '🇹🇭', code: 'THB', name: '泰铢' },
+ { flag: '🇲🇾', code: 'MYR', name: '马来西亚林吉特' },
+ { flag: '🇵🇭', code: 'PHP', name: '菲律宾比索' },
+ { flag: '🇮🇩', code: 'IDR', name: '印尼盾' },
+ { flag: '🇻🇳', code: 'VND', name: '越南盾' },
+ { flag: '🇮🇳', code: 'INR', name: '印度卢比' },
+ { flag: '🇷🇺', code: 'RUB', name: '俄罗斯卢布' },
+ { flag: '🇧🇷', code: 'BRL', name: '巴西雷亚尔' },
+ { flag: '🇲🇽', code: 'MXN', name: '墨西哥比索' },
+ { flag: '🇿🇦', code: 'ZAR', name: '南非兰特' },
+ { flag: '🇹🇷', code: 'TRY', name: '土耳其里拉' },
+ { flag: '🇸🇦', code: 'SAR', name: '沙特里亚尔' },
+ { flag: '🇦🇪', code: 'AED', name: '阿联酋迪拉姆' },
+ { flag: '🇨🇭', code: 'CHF', name: '瑞士法郎' },
+ { flag: '🇸🇪', code: 'SEK', name: '瑞典克朗' },
+ { flag: '🇩🇰', code: 'DKK', name: '丹麦克朗' },
+ { flag: '🇳🇴', code: 'NOK', name: '挪威克朗' },
+];
+
+const CURRENCY_MAP = {};
+CURRENCIES.forEach((c) => {
+ CURRENCY_MAP[c.code] = c;
+});
+
+function getCurrency(code) {
+ return CURRENCY_MAP[code] || null;
+}
+
+function getCurrencyLabel(code) {
+ const c = CURRENCY_MAP[code];
+ if (!c) return code;
+ return `${c.flag} ${c.code} ${c.name}`;
+}
+
+function getPickerData() {
+ return CURRENCIES.map((c) => `${c.flag} ${c.code} ${c.name}`);
+}
+
+module.exports = {
+ CURRENCIES,
+ CURRENCY_MAP,
+ getCurrency,
+ getCurrencyLabel,
+ getPickerData,
+};
diff --git a/miniprogram/utils/rate.js b/miniprogram/utils/rate.js
new file mode 100644
index 0000000..d2449d2
--- /dev/null
+++ b/miniprogram/utils/rate.js
@@ -0,0 +1,130 @@
+/**
+ * 汇率 API 调用 + 本地缓存
+ * 数据源:https://open.er-api.com/v6/latest/{base}
+ * 免费,无需 key,每日更新,1500 次/月
+ */
+
+const CACHE_KEY = 'exchange_rates';
+const CACHE_TTL = 4 * 60 * 60 * 1000; // 4 小时
+
+function getCache() {
+ try {
+ const data = wx.getStorageSync(CACHE_KEY);
+ if (!data) return null;
+ return data;
+ } catch (e) {
+ return null;
+ }
+}
+
+function setCache(data) {
+ try {
+ wx.setStorageSync(CACHE_KEY, data);
+ } catch (e) {
+ console.warn('cache write failed', e);
+ }
+}
+
+function isCacheValid(cache, base) {
+ if (!cache || !cache.rates || !cache.timestamp) return false;
+ if (cache.base !== base) return false;
+ return Date.now() - cache.timestamp < CACHE_TTL;
+}
+
+function fetchRates(base) {
+ return new Promise((resolve, reject) => {
+ wx.request({
+ url: `https://open.er-api.com/v6/latest/${base}`,
+ method: 'GET',
+ success(res) {
+ if (res.statusCode === 200 && res.data && res.data.result === 'success') {
+ resolve(res.data.rates);
+ } else {
+ reject(new Error('API 返回异常'));
+ }
+ },
+ fail(err) {
+ reject(err);
+ },
+ });
+ });
+}
+
+async function getRates(base) {
+ const cache = getCache();
+
+ if (isCacheValid(cache, base)) {
+ return {
+ rates: cache.rates,
+ updatedAt: cache.updatedAt,
+ fromCache: true,
+ };
+ }
+
+ try {
+ const rates = await fetchRates(base);
+ const now = new Date();
+ const cacheData = {
+ base,
+ rates,
+ timestamp: now.getTime(),
+ updatedAt: formatTime(now),
+ };
+ setCache(cacheData);
+ return {
+ rates,
+ updatedAt: cacheData.updatedAt,
+ fromCache: false,
+ };
+ } catch (e) {
+ // API 失败时用过期缓存兜底
+ if (cache && cache.rates) {
+ return {
+ rates: cache.rates,
+ updatedAt: cache.updatedAt + '(缓存)',
+ fromCache: true,
+ };
+ }
+ throw e;
+ }
+}
+
+function convert(amount, fromCode, toCode, rates) {
+ if (!rates || !rates[fromCode] || !rates[toCode]) return 0;
+ if (fromCode === toCode) return amount;
+ return (amount / rates[fromCode]) * rates[toCode];
+}
+
+function formatAmount(value, code) {
+ // 日元、韩元、越南盾、印尼盾等无小数货币
+ const noDecimal = ['JPY', 'KRW', 'VND', 'IDR'];
+ if (noDecimal.includes(code)) {
+ return Math.round(value).toLocaleString('en-US');
+ }
+ return Number(value.toFixed(2)).toLocaleString('en-US', {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ });
+}
+
+function formatRate(value) {
+ if (value >= 100) return value.toFixed(2);
+ if (value >= 1) return value.toFixed(4);
+ return value.toFixed(6);
+}
+
+function formatTime(date) {
+ const y = date.getFullYear();
+ const m = String(date.getMonth() + 1).padStart(2, '0');
+ const d = String(date.getDate()).padStart(2, '0');
+ const h = String(date.getHours()).padStart(2, '0');
+ const min = String(date.getMinutes()).padStart(2, '0');
+ return `${y}-${m}-${d} ${h}:${min}`;
+}
+
+module.exports = {
+ getRates,
+ convert,
+ formatAmount,
+ formatRate,
+};
diff --git a/project.config.json b/project.config.json
index 43d68f4..114e78c 100644
--- a/project.config.json
+++ b/project.config.json
@@ -1,6 +1,6 @@
{
"miniprogramRoot": "miniprogram/",
- "appid": "",
+ "appid": "wx7401eb1b9415ae4d",
"projectname": "currency-converter",
"description": "汇率换算工具",
"setting": {
@@ -26,8 +26,29 @@
"ignore": [],
"disablePlugins": [],
"outputPath": ""
- }
+ },
+ "compileWorklet": false,
+ "uglifyFileName": false,
+ "packNpmManually": false,
+ "packNpmRelationList": [],
+ "minifyWXSS": true,
+ "minifyWXML": true,
+ "localPlugins": false,
+ "disableUseStrict": false,
+ "useCompilerPlugins": false,
+ "condition": true,
+ "swc": false,
+ "disableSWC": true
},
"compileType": "miniprogram",
- "condition": {}
-}
+ "condition": {},
+ "simulatorPluginLibVersion": {
+ "wxext14566970e7e9f62": "2.27.3"
+ },
+ "packOptions": {
+ "ignore": [],
+ "include": []
+ },
+ "editorSetting": {},
+ "projectArchitecture": "multiPlatform"
+}
\ No newline at end of file