const app = getApp() Page({ data: { coupons: [], user: {} }, onLoad() { this.fetchCoupons(); }, onShow() { this.getUserInfo(); this.fetchCoupons(); }, getUserInfo() { const { request } = require('../../utils/request') const app = getApp() // Fetch latest user info from backend to check if phone exists in DB request({ url: '/user/' }).then(user => { app.globalData.userInfo = user; // Sync global data this.setData({ user: user }); }).catch(err => { console.error('Failed to fetch user info', err) // Fallback to global data if fetch fails if (app.globalData.userInfo) { this.setData({ user: app.globalData.userInfo }); } }) }, goToProfile() { const app = getApp(); app.globalData.profileAction = 'bind_phone'; wx.switchTab({ url: '/pages/profile/profile' }) }, fetchCoupons() { const { request } = require('../../utils/request') Promise.all([ request({ url: '/user-coupons/' }).catch(() => []), request({ url: '/available-coupons/' }).catch(() => []) ]).then(([userCoupons, availableCoupons]) => { // 1. Process User Coupons const userList = Array.isArray(userCoupons) ? userCoupons : (userCoupons && userCoupons.results) || []; const formattedUserList = userList.map(item => { if (item.coupon_detail) { let scopeText = item.coupon_detail.scope_text || '全场通用'; if (scopeText === '通用') scopeText = '全场通用'; return { ...item.coupon_detail, id: item.id, coupon_id: item.coupon_detail.id, status: item.status, expiry: item.coupon_detail.expiry, displayDesc: scopeText, is_time_limited: item.coupon_detail.is_time_limited } } return { ...item, displayDesc: item.desc } }); // 2. Process Available Coupons const userCouponIds = new Set(formattedUserList.map(item => item.coupon_id)); const availableList = Array.isArray(availableCoupons) ? availableCoupons : (availableCoupons && availableCoupons.results) || []; const formattedAvailableList = availableList .filter(c => !userCouponIds.has(c.id)) .map(c => { let scopeText = c.scope_text || '全场通用'; if (scopeText === '通用') scopeText = '全场通用'; return { ...c, id: 'avail_' + c.id, // Virtual ID coupon_id: c.id, status: 'can_claim', // Virtual Status displayDesc: scopeText } }); // 3. Merge and Sort const allCoupons = [...formattedAvailableList, ...formattedUserList]; // Sort: can_claim -> assigned -> used -> expired const statusOrder = { 'can_claim': 0, 'assigned': 1, 'used': 2, 'expired': 3, 'revoked': 4 }; allCoupons.sort((a, b) => { const orderA = statusOrder[a.status] !== undefined ? statusOrder[a.status] : 99; const orderB = statusOrder[b.status] !== undefined ? statusOrder[b.status] : 99; return orderA - orderB; }); this.setData({ coupons: allCoupons }); }) .catch((err) => { console.error(err); // Mock data fallback this.setData({ coupons: [ { id: 1, amount: '50', unit: '元', title: '新人见面礼', desc: '无门槛使用,适用于所有课程', displayDesc: '全场通用', expiry: '2023-12-31', status: 'available', color: 'from-blue-500 to-cyan-400', bgStart: 'from-blue-50', bgEnd: 'to-cyan-50', shadow: 'shadow-blue-100', is_time_limited: true }, // ... (existing mocks) ] }) }) }, handleCouponClick(e) { if (!this.data.user.phone) { wx.showModal({ title: '提示', content: '请先绑定手机号激活会员权益', confirmText: '去绑定', success: (res) => { if (res.confirm) { this.goToProfile(); } } }); return; } const status = e.currentTarget.dataset.status; if (status === 'can_claim') { this.handleClaim(e); return; } // If coupon is available/assigned, redirect to home page to use it if (status !== 'used') { wx.switchTab({ url: '/pages/index/index' }); return; } }, handleClaim(e) { const id = e.currentTarget.dataset.id; // This is 'avail_ID' const realId = id.toString().replace('avail_', ''); wx.showLoading({ title: '领取中...' }); const { request } = require('../../utils/request') request({ url: '/user-coupons/', method: 'POST', data: { coupon_id: realId } }).then(() => { wx.hideLoading(); wx.showToast({ title: '领取成功', icon: 'success' }); // Refresh list this.fetchCoupons(); }).catch(err => { wx.hideLoading(); console.error(err); // Handle specific error message from backend const msg = (err && err.error) || (err && err.detail) || '领取失败'; wx.showToast({ title: msg, icon: 'none' }); }); } })