diff --git a/backend/src/VendingMachine.Api/Program.cs b/backend/src/VendingMachine.Api/Program.cs
index 14da4690..ce4cfa15 100644
--- a/backend/src/VendingMachine.Api/Program.cs
+++ b/backend/src/VendingMachine.Api/Program.cs
@@ -41,7 +41,13 @@ builder.Services.AddAuthentication(options =>
builder.Services.AddAuthorization();
// Controllers
-builder.Services.AddControllers();
+builder.Services.AddControllers()
+ .AddJsonOptions(options =>
+ {
+ // 支持枚举字符串序列化/反序列化
+ options.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
+ options.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
+ });
// CORS 配置(支持移动端和管理后台跨域请求)
builder.Services.AddCors(options =>
diff --git a/mobile/i18n/en.js b/mobile/i18n/en.js
index 0443dbc9..56b9330d 100644
--- a/mobile/i18n/en.js
+++ b/mobile/i18n/en.js
@@ -37,6 +37,7 @@ export default {
stamps: 'Stamps',
qrcode: 'QR Code',
guide: 'Guide',
+ redeemableCoupons: 'Redeemable Coupons',
redeemBtn: 'Redeem',
redeemSuccess: 'Redeemed successfully',
redeemFail: 'Insufficient points',
diff --git a/mobile/i18n/zh-CN.js b/mobile/i18n/zh-CN.js
index 90e0da4e..15d04495 100644
--- a/mobile/i18n/zh-CN.js
+++ b/mobile/i18n/zh-CN.js
@@ -37,6 +37,7 @@ export default {
stamps: '节日印花',
qrcode: '会员二维码',
guide: '使用说明',
+ redeemableCoupons: '可兑换优惠券',
redeemBtn: '兑换',
redeemSuccess: '兑换成功',
redeemFail: '积分不足,无法兑换',
diff --git a/mobile/i18n/zh-TW.js b/mobile/i18n/zh-TW.js
index e2859a27..76fa2573 100644
--- a/mobile/i18n/zh-TW.js
+++ b/mobile/i18n/zh-TW.js
@@ -37,6 +37,7 @@ export default {
stamps: '節日印花',
qrcode: '會員二維碼',
guide: '使用說明',
+ redeemableCoupons: '可兌換優惠券',
redeemBtn: '兌換',
redeemSuccess: '兌換成功',
redeemFail: '積分不足,無法兌換',
diff --git a/mobile/pages.json b/mobile/pages.json
index 4843f7b3..63936a87 100644
--- a/mobile/pages.json
+++ b/mobile/pages.json
@@ -76,14 +76,14 @@
{
"pagePath": "pages/index/index",
"text": "首页",
- "iconPath": "static/tab-home.png",
- "selectedIconPath": "static/tab-home-active.png"
+ "iconPath": "static/tab/ic_home.png",
+ "selectedIconPath": "static/tab/ic_home_s.png"
},
{
"pagePath": "pages/mine/mine",
"text": "我的",
- "iconPath": "static/tab-mine.png",
- "selectedIconPath": "static/tab-mine-active.png"
+ "iconPath": "static/tab/ic_me.png",
+ "selectedIconPath": "static/tab/ic_me_s.png"
}
]
}
diff --git a/mobile/pages/index/index.vue b/mobile/pages/index/index.vue
index 2e76de2d..c353788d 100644
--- a/mobile/pages/index/index.vue
+++ b/mobile/pages/index/index.vue
@@ -1,33 +1,70 @@
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
- {{ getEntryLabel(entry.key) }}
+
+
+
+
+
+
+
+ {{ t('home.membership') }}
+ Unlock VIP Benefits
+
+
+ ›
+
+
+
+
+
+
+ {{ t('home.stamps') }}
+
+
+
+ {{ t('home.qrcode') }}
-
-
-
+
+
+
+
+
+
+ {{ coupon.name }}
+
+ ●
+ 到期时间:
+ {{ formatExpire(coupon.expireAt) }}
+
+
+ ●
+ 兑换条件:
+ {{ coupon.requiredPoints }}积分
+
+
+
+
+ 兑换
+
+
+
@@ -44,9 +81,6 @@
@confirm="onRedeemConfirm"
@cancel="showRedeem = false"
/>
-
-
-
@@ -58,7 +92,6 @@ import { getRedeemableCoupons, redeemCoupon } from '../../api/coupon.js'
import { useUserStore } from '../../stores/user.js'
import { navigateBanner } from '../../utils/navigation.js'
import { resolveImageUrl } from '../../utils/image.js'
-import CouponCard from '../../components/CouponCard.vue'
import RedeemPopup from '../../components/RedeemPopup.vue'
import CouponGuidePopup from '../../components/CouponGuidePopup.vue'
@@ -77,17 +110,6 @@ const showRedeem = ref(false)
const selectedCoupon = ref(null)
const showQrcode = ref(false)
-// 入口标签映射
-function getEntryLabel(key) {
- const map = {
- membership: t('home.membership'),
- stamps: t('home.stamps'),
- qrcode: t('home.qrcode'),
- guide: t('home.guide')
- }
- return map[key] || key
-}
-
// Banner点击导航
function onBannerClick(banner) {
navigateBanner(banner)
@@ -124,9 +146,7 @@ async function handleQrcodeEntry() {
} else {
uni.navigateTo({ url: '/pages/membership/membership' })
}
- } catch (e) {
- // 错误已由请求模块统一处理
- }
+ } catch (e) {}
}
// 使用说明入口
@@ -135,9 +155,14 @@ async function handleGuideEntry() {
const res = await getCouponGuide()
guideContent.value = res.data?.content || res.data || ''
showGuide.value = true
- } catch (e) {
- // 错误已由请求模块统一处理
- }
+ } catch (e) {}
+}
+
+// 格式化到期时间
+function formatExpire(dateStr) {
+ if (!dateStr) return '无限制'
+ const d = new Date(dateStr)
+ return `${d.getFullYear()}年${d.getMonth() + 1}月${d.getDate()}日`
}
// 点击兑换按钮
@@ -154,11 +179,9 @@ async function onRedeemConfirm() {
showRedeem.value = false
selectedCoupon.value = null
uni.showToast({ title: t('home.redeemSuccess'), icon: 'none' })
- // 刷新优惠券列表
await loadCoupons()
} catch (e) {
showRedeem.value = false
- // 错误提示已由请求模块统一处理(积分不足、已下架等由后端message返回)
}
}
@@ -167,21 +190,21 @@ async function loadBanners() {
try {
const res = await getBanners()
banners.value = res.data || []
- } catch (e) { /* 错误已统一处理 */ }
+ } catch (e) {}
}
async function loadEntries() {
try {
const res = await getEntries()
entries.value = res.data || []
- } catch (e) { /* 错误已统一处理 */ }
+ } catch (e) {}
}
async function loadCoupons() {
try {
const res = await getRedeemableCoupons()
coupons.value = res.data || []
- } catch (e) { /* 错误已统一处理 */ }
+ } catch (e) {}
}
onMounted(() => {
@@ -194,47 +217,183 @@ onMounted(() => {
diff --git a/mobile/static/ic_qrcode.png b/mobile/static/ic_qrcode.png
new file mode 100644
index 00000000..a7e9bb94
Binary files /dev/null and b/mobile/static/ic_qrcode.png differ
diff --git a/mobile/static/ic_stamp.png b/mobile/static/ic_stamp.png
new file mode 100644
index 00000000..58b6bc29
Binary files /dev/null and b/mobile/static/ic_stamp.png differ
diff --git a/mobile/static/ic_vip.png b/mobile/static/ic_vip.png
new file mode 100644
index 00000000..6fbb5088
Binary files /dev/null and b/mobile/static/ic_vip.png differ
diff --git a/mobile/static/tab/ic_home.png b/mobile/static/tab/ic_home.png
new file mode 100644
index 00000000..4bd3b208
Binary files /dev/null and b/mobile/static/tab/ic_home.png differ
diff --git a/mobile/static/tab/ic_home_s.png b/mobile/static/tab/ic_home_s.png
new file mode 100644
index 00000000..a2212913
Binary files /dev/null and b/mobile/static/tab/ic_home_s.png differ
diff --git a/mobile/static/tab/ic_me.png b/mobile/static/tab/ic_me.png
new file mode 100644
index 00000000..c074e5bf
Binary files /dev/null and b/mobile/static/tab/ic_me.png differ
diff --git a/mobile/static/tab/ic_me_s.png b/mobile/static/tab/ic_me_s.png
new file mode 100644
index 00000000..c85a9895
Binary files /dev/null and b/mobile/static/tab/ic_me_s.png differ