190 lines
5.0 KiB
JavaScript
190 lines
5.0 KiB
JavaScript
const { API } = require('../../utils/constants');
|
||
const { request } = require('../../utils/http');
|
||
const { formatDateTime } = require('../../utils/format');
|
||
|
||
// 中文数字映射(项目一、二、三…)
|
||
const CN_NUM = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
|
||
|
||
/**
|
||
* 将 projects 数组转换为按项目分组的结构
|
||
* 每个项目下展开所有 groups,附带 selected 状态
|
||
*/
|
||
function buildProjectGroups(projects) {
|
||
return projects.map((p, idx) => {
|
||
const groups = Array.isArray(p.groups) ? p.groups : [];
|
||
return {
|
||
projectId: p.id || p.Id || idx,
|
||
projectName: p.name || p.Name || '-',
|
||
index: CN_NUM[idx] || String(idx + 1),
|
||
fee: p.fee != null ? p.fee : 0,
|
||
groups: groups.map((g) => ({
|
||
groupId: g.groupId || g.GroupId || g.id,
|
||
groupName: g.groupName || g.GroupName || '-',
|
||
ageRange: g.ageRange || g.AgeRange || '',
|
||
gender: g.gender || g.Gender || '',
|
||
fee: g.fee != null ? g.fee : (p.fee != null ? p.fee : 0),
|
||
selected: false,
|
||
ageRequirement: g.ageRequirement || g.AgeRequirement || '',
|
||
genderRequirement: g.genderRequirement || g.GenderRequirement || '不限'
|
||
}))
|
||
};
|
||
});
|
||
}
|
||
|
||
/** 计算已选组别的总价 */
|
||
function calcTotalPrice(projectGroups) {
|
||
let total = 0;
|
||
projectGroups.forEach((p) => {
|
||
p.groups.forEach((g) => {
|
||
if (g.selected) total += Number(g.fee) || 0;
|
||
});
|
||
});
|
||
return total;
|
||
}
|
||
|
||
Page({
|
||
data: {
|
||
eventId: null,
|
||
loggedIn: false,
|
||
eventDetail: null,
|
||
projects: [],
|
||
projectGroups: [], // 分组后的展示数据
|
||
couponCode: '',
|
||
totalPrice: 0,
|
||
submitting: false
|
||
},
|
||
|
||
onLoad(options) {
|
||
const eventId = Number(options.eventId);
|
||
this.setData({ eventId });
|
||
this.fetchDetail(eventId);
|
||
},
|
||
|
||
onShow() {
|
||
const accessToken = wx.getStorageSync('accessToken') || '';
|
||
this.setData({ loggedIn: Boolean(accessToken) });
|
||
},
|
||
|
||
onBack() {
|
||
if (getCurrentPages().length > 1) {
|
||
wx.navigateBack();
|
||
} else {
|
||
wx.switchTab({ url: '/pages/home/home' });
|
||
}
|
||
},
|
||
|
||
fetchDetail(eventId) {
|
||
if (!eventId) return;
|
||
request({
|
||
path: API.eventDetail(eventId),
|
||
method: 'GET',
|
||
needAuth: false
|
||
})
|
||
.then((detail) => {
|
||
const projects = Array.isArray(detail.projects) ? detail.projects : [];
|
||
const projectGroups = buildProjectGroups(projects);
|
||
this.setData({
|
||
eventDetail: detail,
|
||
projects,
|
||
projectGroups,
|
||
totalPrice: 0
|
||
});
|
||
})
|
||
.catch(() => {
|
||
wx.showToast({ title: '加载失败', icon: 'none' });
|
||
});
|
||
},
|
||
|
||
onGoMineLogin() {
|
||
wx.switchTab({ url: '/pages/mine/mine' });
|
||
},
|
||
|
||
/** 点击组别标签切换选中状态 */
|
||
onGroupTap(e) {
|
||
const { projectId, groupId } = e.currentTarget.dataset;
|
||
const projectGroups = this.data.projectGroups.map((p) => {
|
||
if (p.projectId !== projectId) return p;
|
||
return {
|
||
...p,
|
||
groups: p.groups.map((g) => {
|
||
if (g.groupId !== groupId) return g;
|
||
return { ...g, selected: !g.selected };
|
||
})
|
||
};
|
||
});
|
||
const totalPrice = calcTotalPrice(projectGroups);
|
||
this.setData({ projectGroups, totalPrice });
|
||
},
|
||
|
||
onCouponInput(e) {
|
||
this.setData({ couponCode: (e.detail.value || '').trim() });
|
||
},
|
||
|
||
/** 收集已选的 projectId + groupId */
|
||
_getSelectedItems() {
|
||
const items = [];
|
||
this.data.projectGroups.forEach((p) => {
|
||
p.groups.forEach((g) => {
|
||
if (g.selected) {
|
||
items.push({ projectId: Number(p.projectId), groupId: Number(g.groupId) });
|
||
}
|
||
});
|
||
});
|
||
return items;
|
||
},
|
||
|
||
_validateAndGetPayload(paymentMethod) {
|
||
if (!this.data.loggedIn) {
|
||
wx.showToast({ title: '请先登录', icon: 'none' });
|
||
return null;
|
||
}
|
||
const items = this._getSelectedItems();
|
||
if (items.length === 0) {
|
||
wx.showToast({ title: '请至少选择一个组别', icon: 'none' });
|
||
return null;
|
||
}
|
||
return {
|
||
eventId: Number(this.data.eventId),
|
||
registrationMode: 1,
|
||
paymentMethod, // 1=线下 2=线上
|
||
couponCode: this.data.couponCode || null,
|
||
items
|
||
};
|
||
},
|
||
|
||
/** 线下支付 */
|
||
onPayOffline() {
|
||
const payload = this._validateAndGetPayload(1);
|
||
if (!payload) return;
|
||
this._submitApply(payload);
|
||
},
|
||
|
||
/** 线上支付 */
|
||
onPayOnline() {
|
||
const payload = this._validateAndGetPayload(2);
|
||
if (!payload) return;
|
||
this._submitApply(payload);
|
||
},
|
||
|
||
_submitApply(payload) {
|
||
this.setData({ submitting: true });
|
||
request({
|
||
path: API.apply,
|
||
method: 'POST',
|
||
needAuth: true,
|
||
data: payload,
|
||
contentType: 'application/json'
|
||
})
|
||
.then(() => {
|
||
wx.showToast({ title: '报名成功', icon: 'success' });
|
||
setTimeout(() => wx.switchTab({ url: '/pages/mine/mine' }), 800);
|
||
})
|
||
.catch((err) => {
|
||
wx.showToast({ title: err && err.message ? err.message : '提交失败', icon: 'none' });
|
||
})
|
||
.finally(() => this.setData({ submitting: false }));
|
||
}
|
||
});
|
||
|
||
|