197 lines
5.8 KiB
JavaScript
197 lines
5.8 KiB
JavaScript
import request from '../../../utils/request';
|
|
|
|
Page({
|
|
data: {
|
|
items: [],
|
|
currentSunlight: 0,
|
|
isLoading: true,
|
|
hasMore: true,
|
|
current: 1,
|
|
pageSize: 10,
|
|
activeType: 'PHYSICAL',
|
|
// Redeem popup
|
|
showRedeemPopup: false,
|
|
selectedItem: null,
|
|
redeemForm: {
|
|
recipientName: '',
|
|
phone: '',
|
|
address: ''
|
|
}
|
|
},
|
|
|
|
onLoad() {
|
|
this.fetchProfile();
|
|
this.fetchItems();
|
|
},
|
|
|
|
onShow() {
|
|
this.fetchProfile();
|
|
},
|
|
|
|
async fetchProfile() {
|
|
try {
|
|
const res = await request.get('/profile/detail');
|
|
if (res) {
|
|
this.setData({ currentSunlight: res.currentSunlight || 0 });
|
|
}
|
|
} catch (e) {
|
|
// Silent
|
|
}
|
|
},
|
|
|
|
async fetchItems(append = false) {
|
|
if (!append) {
|
|
this.setData({ isLoading: true, current: 1, items: [] });
|
|
}
|
|
try {
|
|
const res = await request.get('/exchange/list', {
|
|
current: this.data.current,
|
|
pageSize: this.data.pageSize,
|
|
type: this.data.activeType
|
|
});
|
|
const rawList = (res && res.list) ? res.list : [];
|
|
const total = (res && res.total) ? res.total : 0;
|
|
|
|
const now = Date.now();
|
|
const list = rawList.map(item => {
|
|
const hasStart = !!item.startTime;
|
|
const hasEnd = !!item.endTime;
|
|
const startTs = hasStart ? new Date(item.startTime).getTime() : 0;
|
|
const endTs = hasEnd ? new Date(item.endTime).getTime() : 0;
|
|
|
|
const notStarted = hasStart && now < startTs;
|
|
const hasEnded = hasEnd && now > endTs;
|
|
const isActive = !notStarted && !hasEnded;
|
|
|
|
let timeLabel = '';
|
|
if (hasStart && hasEnd) {
|
|
timeLabel = this.formatDate(item.startTime) + ' ~ ' + this.formatDate(item.endTime);
|
|
} else if (hasStart) {
|
|
timeLabel = this.formatDate(item.startTime) + ' 起';
|
|
} else if (hasEnd) {
|
|
timeLabel = '截止 ' + this.formatDate(item.endTime);
|
|
}
|
|
|
|
return {
|
|
...item,
|
|
hasTimeLimit: hasStart || hasEnd,
|
|
timeLabel,
|
|
notStarted,
|
|
hasEnded,
|
|
isActive
|
|
};
|
|
});
|
|
|
|
this.setData({
|
|
items: append ? [...this.data.items, ...list] : list,
|
|
hasMore: this.data.items.length + list.length < total
|
|
});
|
|
} catch (e) {
|
|
console.error('Fetch exchange items failed', e);
|
|
} finally {
|
|
this.setData({ isLoading: false });
|
|
wx.stopPullDownRefresh();
|
|
}
|
|
},
|
|
|
|
onReachBottom() {
|
|
if (!this.data.hasMore || this.data.isLoading) return;
|
|
this.setData({ current: this.data.current + 1 });
|
|
this.fetchItems(true);
|
|
},
|
|
|
|
onPullDownRefresh() {
|
|
this.fetchProfile();
|
|
this.fetchItems();
|
|
},
|
|
|
|
switchType(e) {
|
|
const key = e.currentTarget.dataset.key;
|
|
if (key === this.data.activeType) return;
|
|
this.setData({ activeType: key });
|
|
this.fetchItems();
|
|
},
|
|
|
|
// Redeem Flow
|
|
onItemTap(e) {
|
|
const item = e.currentTarget.dataset.item;
|
|
if (item.notStarted) {
|
|
wx.showToast({ title: '活动尚未开始', icon: 'none' });
|
|
return;
|
|
}
|
|
if (item.hasEnded) {
|
|
wx.showToast({ title: '活动已结束', icon: 'none' });
|
|
return;
|
|
}
|
|
if (item.stock === 0) {
|
|
wx.showToast({ title: '已兑完', icon: 'none' });
|
|
return;
|
|
}
|
|
this.setData({
|
|
selectedItem: item,
|
|
showRedeemPopup: true,
|
|
redeemForm: { recipientName: '', phone: '', address: '' }
|
|
});
|
|
},
|
|
|
|
onPopupClose() {
|
|
this.setData({ showRedeemPopup: false });
|
|
},
|
|
|
|
onFormInput(e) {
|
|
const field = e.currentTarget.dataset.field;
|
|
this.setData({ [`redeemForm.${field}`]: e.detail.value });
|
|
},
|
|
|
|
async confirmRedeem() {
|
|
const item = this.data.selectedItem;
|
|
if (!item) return;
|
|
|
|
// Check sunlight
|
|
if (this.data.currentSunlight < item.costSunlight) {
|
|
wx.showToast({ title: '阳光值不足', icon: 'none' });
|
|
return;
|
|
}
|
|
|
|
// Physical items require address
|
|
if (item.type === 'PHYSICAL') {
|
|
const { recipientName, phone, address } = this.data.redeemForm;
|
|
if (!recipientName || !phone || !address) {
|
|
wx.showToast({ title: '请填写完整收货信息', icon: 'none' });
|
|
return;
|
|
}
|
|
}
|
|
|
|
wx.showLoading({ title: '兑换中...', mask: true });
|
|
try {
|
|
await request.post('/exchange/redeem', {
|
|
itemId: item.id,
|
|
quantity: 1,
|
|
...this.data.redeemForm
|
|
});
|
|
wx.hideLoading();
|
|
wx.showToast({ title: '兑换成功!', icon: 'success' });
|
|
this.setData({ showRedeemPopup: false });
|
|
// Refresh data
|
|
this.fetchProfile();
|
|
this.fetchItems();
|
|
} catch (e) {
|
|
wx.hideLoading();
|
|
wx.showToast({ title: e.message || '兑换失败', icon: 'none' });
|
|
}
|
|
},
|
|
|
|
goToOrders() {
|
|
wx.navigateTo({ url: '/pages/profile/exchange/orders/index' });
|
|
},
|
|
|
|
formatDate(dateStr) {
|
|
if (!dateStr) return '';
|
|
const d = new Date(dateStr);
|
|
const m = (d.getMonth() + 1).toString().padStart(2, '0');
|
|
const day = d.getDate().toString().padStart(2, '0');
|
|
return m + '.' + day;
|
|
}
|
|
});
|
|
|