update:报名
This commit is contained in:
parent
c4faf65187
commit
c21de31c69
@ -101,6 +101,19 @@ function parseYmdDate(s) {
|
||||
return Number.isNaN(dt.getTime()) ? null : dt;
|
||||
}
|
||||
|
||||
function parseYmdDateAny(text) {
|
||||
if (!text) return null;
|
||||
const s = String(text);
|
||||
const m = s.match(/(\d{4})-(\d{2})-(\d{2})/);
|
||||
if (!m) return null;
|
||||
const y = Number(m[1]);
|
||||
const mo = Number(m[2]);
|
||||
const d = Number(m[3]);
|
||||
if ([y, mo, d].some((x) => Number.isNaN(x))) return null;
|
||||
const dt = new Date(y, mo - 1, d);
|
||||
return Number.isNaN(dt.getTime()) ? null : dt;
|
||||
}
|
||||
|
||||
function calcAgeYears(birthDateStr, atDateStr) {
|
||||
const b = parseYmdDate(birthDateStr);
|
||||
if (!b) return null;
|
||||
@ -111,7 +124,22 @@ function calcAgeYears(birthDateStr, atDateStr) {
|
||||
return age >= 0 ? age : null;
|
||||
}
|
||||
|
||||
function parseAgeRangeText(text) {
|
||||
function parseBirthDateRangeText(text) {
|
||||
// e.g. "2021-03-31 至 2026-04-29" / "2021-03-31~2026-04-29"
|
||||
if (!text) return null;
|
||||
const s = String(text);
|
||||
const ms = s.match(/(\d{4}-\d{2}-\d{2})/g);
|
||||
if (!ms || ms.length < 2) return null;
|
||||
const a = parseYmdDate(ms[0]);
|
||||
const b = parseYmdDate(ms[1]);
|
||||
if (!a || !b) return null;
|
||||
const start = a <= b ? a : b;
|
||||
const end = a <= b ? b : a;
|
||||
return { start, end, startText: ms[0], endText: ms[1] };
|
||||
}
|
||||
|
||||
function parseAgeYearsRangeText(text) {
|
||||
// 兼容旧格式:如 "6-12岁" / "6~12"
|
||||
if (!text) return null;
|
||||
const s = String(text);
|
||||
const nums = s.match(/\d+/g);
|
||||
@ -162,6 +190,23 @@ function countSelectedByType(projectGroups, rawProjects) {
|
||||
return { individual, team, unknown };
|
||||
}
|
||||
|
||||
function buildCalculateAmountItems(projectGroups) {
|
||||
const map = new Map(); // projectId -> personCount
|
||||
projectGroups.forEach((p) => {
|
||||
const pid = Number(p.projectId);
|
||||
if (Number.isNaN(pid)) return;
|
||||
let cnt = 0;
|
||||
p.groups.forEach((g) => {
|
||||
if (g.selected) cnt += 1;
|
||||
});
|
||||
if (cnt > 0) map.set(pid, (map.get(pid) || 0) + cnt);
|
||||
});
|
||||
return Array.from(map.entries()).map(([projectId, personCount]) => ({
|
||||
projectId,
|
||||
personCount
|
||||
}));
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
eventId: null,
|
||||
@ -176,6 +221,9 @@ Page({
|
||||
myAuth: null
|
||||
},
|
||||
|
||||
_calcTimer: null,
|
||||
_calcSeq: 0,
|
||||
|
||||
onLoad(options) {
|
||||
const eventId = Number(options.eventId);
|
||||
this.setData({ eventId });
|
||||
@ -380,17 +428,34 @@ Page({
|
||||
wx.showToast({ title: `该组别仅限${genderRequirementText(reqGender)}报名`, icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const range = parseAgeRangeText(clickedGroup.ageRequirement);
|
||||
if (range) {
|
||||
const age = calcAgeYears(birthDate, eventStart);
|
||||
if (age == null) {
|
||||
// 年龄限制:优先支持“出生日期范围”,兼容旧“岁数范围”
|
||||
const birthRange = parseBirthDateRangeText(clickedGroup.ageRequirement);
|
||||
if (birthRange) {
|
||||
const bd = parseYmdDateAny(birthDate);
|
||||
if (!bd) {
|
||||
wx.showToast({ title: '无法解析出生日期,请先完善认证信息', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (age < range.min || age > range.max) {
|
||||
wx.showToast({ title: `年龄需在${range.min}-${range.max}岁`, icon: 'none' });
|
||||
if (bd < birthRange.start || bd > birthRange.end) {
|
||||
wx.showToast({
|
||||
title: `出生日期需在${birthRange.startText}至${birthRange.endText}`,
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const range = parseAgeYearsRangeText(clickedGroup.ageRequirement);
|
||||
if (range) {
|
||||
const age = calcAgeYears(birthDate, eventStart);
|
||||
if (age == null) {
|
||||
wx.showToast({ title: '无法解析出生日期,请先完善认证信息', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (age < range.min || age > range.max) {
|
||||
wx.showToast({ title: `年龄需在${range.min}-${range.max}岁`, icon: 'none' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,8 +484,65 @@ Page({
|
||||
return;
|
||||
}
|
||||
|
||||
const totalPrice = calcTotalPrice(nextProjectGroups);
|
||||
this.setData({ projectGroups: nextProjectGroups, totalPrice });
|
||||
this.setData({ projectGroups: nextProjectGroups }, () => {
|
||||
this._scheduleRecalcAmount();
|
||||
});
|
||||
},
|
||||
|
||||
_scheduleRecalcAmount() {
|
||||
if (this._calcTimer) {
|
||||
clearTimeout(this._calcTimer);
|
||||
this._calcTimer = null;
|
||||
}
|
||||
this._calcTimer = setTimeout(() => {
|
||||
this._calcTimer = null;
|
||||
this._recalcAmountNow();
|
||||
}, 250);
|
||||
},
|
||||
|
||||
_recalcAmountNow() {
|
||||
const items = buildCalculateAmountItems(this.data.projectGroups);
|
||||
if (!items.length) {
|
||||
this.setData({ totalPrice: 0 });
|
||||
return;
|
||||
}
|
||||
|
||||
const seq = (this._calcSeq += 1);
|
||||
request({
|
||||
path: API.calculateAmount,
|
||||
method: 'POST',
|
||||
needAuth: true,
|
||||
data: {
|
||||
eventId: Number(this.data.eventId),
|
||||
registrationMode: 2,
|
||||
items
|
||||
},
|
||||
contentType: 'application/json'
|
||||
})
|
||||
.then((res) => {
|
||||
// 兼容:后端可能返回 number / string / {amount}
|
||||
if (seq !== this._calcSeq) return;
|
||||
let amount = null;
|
||||
if (typeof res === 'number') amount = res;
|
||||
else if (typeof res === 'string') {
|
||||
const n = Number(res);
|
||||
amount = Number.isNaN(n) ? null : n;
|
||||
} else if (res && typeof res === 'object') {
|
||||
const v = res.amount != null ? res.amount : res.payAmount != null ? res.payAmount : res.totalAmount;
|
||||
const n = Number(v);
|
||||
amount = Number.isNaN(n) ? null : n;
|
||||
}
|
||||
if (amount == null) {
|
||||
// fallback:仍然展示前端计算的费用,避免空白
|
||||
this.setData({ totalPrice: calcTotalPrice(this.data.projectGroups) });
|
||||
} else {
|
||||
this.setData({ totalPrice: amount });
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (seq !== this._calcSeq) return;
|
||||
this.setData({ totalPrice: calcTotalPrice(this.data.projectGroups) });
|
||||
});
|
||||
},
|
||||
|
||||
onCouponInput(e) {
|
||||
|
||||
@ -9,6 +9,7 @@ const API = {
|
||||
eventMyList: '/api/eventclient/my-events',
|
||||
eventDetail: (id) => `/api/eventclient/${id}`,
|
||||
apply: '/api/eventclient/apply',
|
||||
calculateAmount: '/api/eventclient/calculate-amount',
|
||||
|
||||
wechatLogin: '/api/oauth/login',
|
||||
loginByCode: '/api/oauth/login',
|
||||
|
||||
@ -37,6 +37,7 @@ function getHeaderValue(headers, headerName) {
|
||||
|
||||
function tryUpdateAccessTokenFromResponseHeaders(res) {
|
||||
// wx.request 的返回头在 res.header(部分环境也可能是 res.headers)
|
||||
console.log( 'res', res);
|
||||
const headers = (res && res.header) || (res && res.headers) || null;
|
||||
const newAccessToken = getHeaderValue(headers, 'x-access-token');
|
||||
if (!newAccessToken) return;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user