From c4faf651879d17f5d1df29ca053ac71704694ff8 Mon Sep 17 00:00:00 2001
From: ltx <1006158920@qq.com>
Date: Tue, 7 Apr 2026 16:47:13 +0800
Subject: [PATCH] =?UTF-8?q?update:=E8=B5=9B=E4=BA=8B=E8=AF=A6=E6=83=85&?=
=?UTF-8?q?=E6=8A=A5=E5=90=8D=E9=99=90=E5=88=B6&openid?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/apply/apply.js | 339 +++++++++++++++++++++++++++++++++-
pages/apply/apply.wxml | 5 +-
pages/apply/apply.wxss | 23 +++
pages/detail/detail.js | 101 +++++++++-
pages/detail/detail.wxml | 7 +-
pages/detail/detail.wxss | 8 +
pages/home/home.js | 40 ++--
pages/home/home.wxml | 8 +-
pages/home/home.wxss | 6 +-
pages/mine/mine.js | 8 +
pages/mine/mine.wxml | 4 +
subpackages/mine/auth/auth.js | 2 +-
utils/constants.js | 2 +
utils/format.js | 43 ++++-
14 files changed, 557 insertions(+), 39 deletions(-)
diff --git a/pages/apply/apply.js b/pages/apply/apply.js
index b036950..624611c 100644
--- a/pages/apply/apply.js
+++ b/pages/apply/apply.js
@@ -1,6 +1,7 @@
const { API } = require('../../utils/constants');
const { request } = require('../../utils/http');
const { formatDateTime } = require('../../utils/format');
+const auth = require('../../utils/auth');
// 中文数字映射(项目一、二、三…)
const CN_NUM = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
@@ -9,6 +10,23 @@ const CN_NUM = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '
* 将 projects 数组转换为按项目分组的结构
* 每个项目下展开所有 groups,附带 selected 状态
*/
+function getEventStatus(detail) {
+ if (!detail || typeof detail !== 'object') return null;
+ const v = detail.eventStatus != null ? detail.eventStatus : detail.EventStatus;
+ if (v == null || v === '') return null;
+ const n = Number(v);
+ return Number.isNaN(n) ? null : n;
+}
+
+/** 仅 1=报名中 可进入报名页;与后端 EventStatus 枚举一致 */
+function toastForBlockedEventStatus(es) {
+ if (es === 0) return '赛事未开始';
+ if (es === 2) return '报名已结束';
+ if (es === 3) return '比赛进行中,暂不可报名';
+ if (es === 4) return '赛事已结束';
+ return '暂不可报名';
+}
+
function buildProjectGroups(projects) {
return projects.map((p, idx) => {
const groups = Array.isArray(p.groups) ? p.groups : [];
@@ -25,7 +43,8 @@ function buildProjectGroups(projects) {
fee: g.fee != null ? g.fee : (p.fee != null ? p.fee : 0),
selected: false,
ageRequirement: g.ageRequirement || g.AgeRequirement || '',
- genderRequirement: g.genderRequirement || g.GenderRequirement || '不限'
+ genderRequirement: g.genderRequirement != null ? g.genderRequirement : g.GenderRequirement != null ? g.GenderRequirement : '',
+ genderRequirementText: genderRequirementText(g.genderRequirement != null ? g.genderRequirement : g.GenderRequirement)
}))
};
});
@@ -42,6 +61,107 @@ function calcTotalPrice(projectGroups) {
return total;
}
+function toNonNegInt(v) {
+ const n = Number(v);
+ if (Number.isNaN(n)) return null;
+ const i = Math.floor(n);
+ return i >= 0 ? i : null;
+}
+
+function genderRequirementText(v) {
+ if (v === undefined || v === null || v === '') return '不限';
+ const s = String(v).trim();
+ if (s === '0' || s === '男' || s.toUpperCase() === 'M') return '男';
+ if (s === '1' || s === '女' || s.toUpperCase() === 'F') return '女';
+ if (s === '2' || s === '不限' || s === '全部') return '不限';
+ return s;
+}
+
+function normalizeGenderToNum(v) {
+ if (v === undefined || v === null || v === '') return null;
+ const s = String(v).trim();
+ if (s === '0' || s === '男' || s.toUpperCase() === 'M') return 0;
+ if (s === '1' || s === '女' || s.toUpperCase() === 'F') return 1;
+ if (s === '2' || s === '不限' || s === '全部') return 2;
+ const n = Number(s);
+ if (!Number.isNaN(n) && (n === 0 || n === 1 || n === 2)) return n;
+ return null;
+}
+
+function parseYmdDate(s) {
+ if (!s) return null;
+ const str = String(s).trim();
+ const m = str.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;
+ const at = parseYmdDate(atDateStr) || new Date();
+ let age = at.getFullYear() - b.getFullYear();
+ const m = at.getMonth() - b.getMonth();
+ if (m < 0 || (m === 0 && at.getDate() < b.getDate())) age -= 1;
+ return age >= 0 ? age : null;
+}
+
+function parseAgeRangeText(text) {
+ if (!text) return null;
+ const s = String(text);
+ const nums = s.match(/\d+/g);
+ if (!nums || nums.length === 0) return null;
+ const a = Number(nums[0]);
+ if (Number.isNaN(a)) return null;
+ if (nums.length === 1) return { min: a, max: a };
+ const b = Number(nums[1]);
+ if (Number.isNaN(b)) return { min: a, max: a };
+ return { min: Math.min(a, b), max: Math.max(a, b) };
+}
+
+function isIndividualProject(p) {
+ const t = (p && (p.typeName || p.TypeName)) || '';
+ const s = String(t);
+ // 只显示个人项目:个人速度、个人花样等
+ return s.includes('个人');
+}
+
+function projectTypeOf(rawProject) {
+ const t = (rawProject && (rawProject.typeName || rawProject.TypeName)) || '';
+ const s = String(t);
+ if (s.includes('团队')) return 'team';
+ if (s.includes('个人')) return 'individual';
+ return 'unknown';
+}
+
+function countSelectedByType(projectGroups, rawProjects) {
+ const map = new Map();
+ (rawProjects || []).forEach((p) => {
+ const pid = Number(p.id != null ? p.id : p.Id);
+ if (!Number.isNaN(pid)) map.set(pid, projectTypeOf(p));
+ });
+
+ let individual = 0;
+ let team = 0;
+ let unknown = 0;
+ projectGroups.forEach((pg) => {
+ const pid = Number(pg.projectId);
+ const type = map.get(pid) || 'unknown';
+ pg.groups.forEach((g) => {
+ if (!g.selected) return;
+ if (type === 'individual') individual += 1;
+ else if (type === 'team') team += 1;
+ else unknown += 1;
+ });
+ });
+ return { individual, team, unknown };
+}
+
Page({
data: {
eventId: null,
@@ -51,7 +171,9 @@ Page({
projectGroups: [], // 分组后的展示数据
couponCode: '',
totalPrice: 0,
- submitting: false
+ submitting: false,
+ openidLoading: false,
+ myAuth: null
},
onLoad(options) {
@@ -62,7 +184,9 @@ Page({
onShow() {
const accessToken = wx.getStorageSync('accessToken') || '';
- this.setData({ loggedIn: Boolean(accessToken) });
+ const loggedIn = Boolean(accessToken);
+ this.setData({ loggedIn });
+ if (loggedIn) this._ensureMyAuth();
},
onBack() {
@@ -81,7 +205,22 @@ Page({
needAuth: false
})
.then((detail) => {
- const projects = Array.isArray(detail.projects) ? detail.projects : [];
+ const es = getEventStatus(detail);
+ console.log( 'es', es);
+ if (es !== null && es !== 1) {
+ wx.showToast({ title: toastForBlockedEventStatus(es), icon: 'none' });
+ setTimeout(() => {
+ if (getCurrentPages().length > 1) {
+ wx.navigateBack();
+ } else {
+ wx.switchTab({ url: '/pages/home/home' });
+ }
+ }, 1600);
+ return;
+ }
+
+ const rawProjects = Array.isArray(detail.projects) ? detail.projects : [];
+ const projects = rawProjects.filter(isIndividualProject);
const projectGroups = buildProjectGroups(projects);
this.setData({
eventDetail: detail,
@@ -95,14 +234,167 @@ Page({
});
},
+ _ensureMyAuth() {
+ // 认证信息用于年龄/性别限制校验;没有认证则引导去个人中心
+ return auth
+ .fetchMyAuth()
+ .then((res) => {
+ const d = res && typeof res === 'object' ? res : null;
+ const birthDate = d ? (d.birthDate || d.birthday || '') : '';
+ if (!birthDate) {
+ wx.showModal({
+ title: '需先完成认证',
+ content: '报名个人项目需要先完成身份认证(用于校验年龄与性别限制)。',
+ confirmText: '去个人中心',
+ cancelText: '取消',
+ success: (r) => {
+ if (r.confirm) wx.switchTab({ url: '/pages/mine/mine' });
+ }
+ });
+ this.setData({ myAuth: null });
+ return null;
+ }
+ this.setData({ myAuth: d });
+ return d;
+ })
+ .catch(() => {
+ wx.showModal({
+ title: '获取认证信息失败',
+ content: '请稍后重试,或前往个人中心完成认证。',
+ confirmText: '去个人中心',
+ cancelText: '取消',
+ success: (r) => {
+ if (r.confirm) wx.switchTab({ url: '/pages/mine/mine' });
+ }
+ });
+ this.setData({ myAuth: null });
+ return null;
+ });
+ },
+
onGoMineLogin() {
wx.switchTab({ url: '/pages/mine/mine' });
},
+ _showOpenidResult(openid) {
+ wx.showModal({
+ title: 'openid',
+ content: String(openid),
+ confirmText: '复制',
+ success: (r) => {
+ if (r.confirm) {
+ wx.setClipboardData({ data: String(openid) });
+ }
+ }
+ });
+ },
+
+ /** 优先读本地登录缓存;没有则 wx.login + 后端换 openid */
+ onFetchOpenId() {
+ if (this.data.openidLoading) return;
+ const app = getApp();
+ const cached =
+ (app && app.globalData && app.globalData.openid) || wx.getStorageSync('openid') || '';
+ if (cached) {
+ this._showOpenidResult(cached);
+ return;
+ }
+
+ this.setData({ openidLoading: true });
+ wx.showLoading({ title: '获取中', mask: true });
+ wx.login({
+ success: (loginRes) => {
+ const code = loginRes.code;
+ if (!code) {
+ wx.hideLoading();
+ this.setData({ openidLoading: false });
+ wx.showToast({ title: '未获取到 code', icon: 'none' });
+ return;
+ }
+ request({
+ path: API.wechatOpenidByJsCode,
+ method: 'POST',
+ needAuth: false,
+ data: { code },
+ contentType: 'application/json'
+ })
+ .then((data) => {
+ const oid =
+ data && typeof data === 'object'
+ ? data.openid || data.OpenId || data.openId || ''
+ : '';
+ const openid = typeof oid === 'string' ? oid : '';
+ if (openid && app && typeof app.setAuth === 'function') {
+ app.setAuth({ openid });
+ }
+ wx.hideLoading();
+ this.setData({ openidLoading: false });
+ if (openid) {
+ this._showOpenidResult(openid);
+ } else {
+ wx.showToast({ title: '接口未返回 openid', icon: 'none' });
+ }
+ })
+ .catch(() => {
+ wx.hideLoading();
+ this.setData({ openidLoading: false });
+ wx.showModal({
+ title: '换取 openid 失败',
+ content: `请确认后端接口路径:${API.wechatOpenidByJsCode}\n\n可临时复制 code 给服务端调试:\n${code}`,
+ confirmText: '复制 code',
+ cancelText: '关闭',
+ success: (r) => {
+ if (r.confirm) wx.setClipboardData({ data: code });
+ }
+ });
+ });
+ },
+ fail: () => {
+ wx.hideLoading();
+ this.setData({ openidLoading: false });
+ wx.showToast({ title: 'wx.login 失败', icon: 'none' });
+ }
+ });
+ },
+
/** 点击组别标签切换选中状态 */
onGroupTap(e) {
const { projectId, groupId } = e.currentTarget.dataset;
- const projectGroups = this.data.projectGroups.map((p) => {
+ if (!this.data.myAuth) {
+ wx.showToast({ title: '请先完成身份认证', icon: 'none' });
+ wx.switchTab({ url: '/pages/mine/mine' });
+ return;
+ }
+
+ // 年龄/性别限制校验
+ const my = this.data.myAuth || {};
+ const birthDate = my.birthDate || my.birthday || '';
+ const myGender = normalizeGenderToNum(my.gender != null ? my.gender : my.sex);
+ const eventStart = (this.data.eventDetail && this.data.eventDetail.matchStartTime) || '';
+
+ const clickedProject = this.data.projectGroups.find((p) => p.projectId === projectId);
+ const clickedGroup = clickedProject ? clickedProject.groups.find((g) => g.groupId === groupId) : null;
+ if (clickedGroup) {
+ const reqGender = normalizeGenderToNum(clickedGroup.genderRequirement);
+ if (reqGender != null && reqGender !== 2 && myGender != null && reqGender !== myGender) {
+ wx.showToast({ title: `该组别仅限${genderRequirementText(reqGender)}报名`, icon: 'none' });
+ return;
+ }
+ const range = parseAgeRangeText(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;
+ }
+ }
+ }
+
+ const nextProjectGroups = this.data.projectGroups.map((p) => {
if (p.projectId !== projectId) return p;
return {
...p,
@@ -112,8 +404,23 @@ Page({
})
};
});
- const totalPrice = calcTotalPrice(projectGroups);
- this.setData({ projectGroups, totalPrice });
+
+ const detail = this.data.eventDetail || {};
+ const individualLimit = toNonNegInt(detail.individualProjectLimit);
+ const teamLimit = toNonNegInt(detail.teamProjectLimit);
+ const { individual, team } = countSelectedByType(nextProjectGroups, this.data.projects);
+
+ if (individualLimit != null && individual > individualLimit) {
+ wx.showToast({ title: `个人项目最多选择${individualLimit}个`, icon: 'none' });
+ return;
+ }
+ if (teamLimit != null && team > teamLimit) {
+ wx.showToast({ title: `团队项目最多选择${teamLimit}个`, icon: 'none' });
+ return;
+ }
+
+ const totalPrice = calcTotalPrice(nextProjectGroups);
+ this.setData({ projectGroups: nextProjectGroups, totalPrice });
},
onCouponInput(e) {
@@ -143,6 +450,24 @@ Page({
wx.showToast({ title: '请至少选择一个组别', icon: 'none' });
return null;
}
+
+ const detail = this.data.eventDetail || {};
+ const individualLimit = toNonNegInt(detail.individualProjectLimit);
+ const teamLimit = toNonNegInt(detail.teamProjectLimit);
+ const { individual, team, unknown } = countSelectedByType(this.data.projectGroups, this.data.projects);
+ if (unknown > 0 && (individualLimit != null || teamLimit != null)) {
+ // typeName 识别不出来时,不阻断提交,但提醒后端应补齐 typeName
+ console.warn('存在未识别项目类型的选项,无法严格执行个人/团队限报', { unknown });
+ }
+ if (individualLimit != null && individual > individualLimit) {
+ wx.showToast({ title: `个人项目最多选择${individualLimit}个`, icon: 'none' });
+ return null;
+ }
+ if (teamLimit != null && team > teamLimit) {
+ wx.showToast({ title: `团队项目最多选择${teamLimit}个`, icon: 'none' });
+ return null;
+ }
+
return {
eventId: Number(this.data.eventId),
registrationMode: 1,
diff --git a/pages/apply/apply.wxml b/pages/apply/apply.wxml
index 88c9b01..9a0dea0 100644
--- a/pages/apply/apply.wxml
+++ b/pages/apply/apply.wxml
@@ -1,5 +1,8 @@
+
+
+
登录后才能提交报名信息
@@ -21,7 +24,7 @@
{{group.groupName}}|
{{group.ageRequirement}}|
- {{group.genderRequirement}}
+ {{group.genderRequirementText}}
diff --git a/pages/apply/apply.wxss b/pages/apply/apply.wxss
index 5c2a63c..dcc962b 100644
--- a/pages/apply/apply.wxss
+++ b/pages/apply/apply.wxss
@@ -4,6 +4,29 @@
background: #f5f7fa;
}
+.openid-row {
+ display: flex;
+ justify-content: flex-end;
+ padding: 8rpx 32rpx 0;
+ box-sizing: border-box;
+}
+
+.openid-mini-btn {
+ margin: 0 !important;
+ padding: 0 20rpx !important;
+ height: 56rpx !important;
+ line-height: 56rpx !important;
+ font-size: 22rpx !important;
+ color: #1a56db !important;
+ background: rgba(26, 86, 219, 0.08) !important;
+ border: none !important;
+ border-radius: 28rpx !important;
+}
+
+.openid-mini-btn::after {
+ border: none;
+}
+
.scroll {
height: calc(100vh - 88rpx);
padding: 24rpx 32rpx 0;
diff --git a/pages/detail/detail.js b/pages/detail/detail.js
index 430646c..b35d4d4 100644
--- a/pages/detail/detail.js
+++ b/pages/detail/detail.js
@@ -48,6 +48,49 @@ function pick(obj, keys) {
return null;
}
+/**
+ * 赛事状态(与后端枚举一致)
+ * 0 NotStarted 未开始 | 1 Enrolling 报名中 | 2 RegistrationEnded 报名结束
+ * 3 Ongoing 比赛中 | 4 Ended 已结束
+ * 未返回字段时视为旧接口,不拦截报名
+ */
+function parseEventStatus(rawDetail) {
+ const v = pick(rawDetail, ['eventStatus', 'EventStatus']);
+ if (v == null || v === '') return null;
+ const n = Number(v);
+ return Number.isNaN(n) ? null : n;
+}
+
+function applyUiFromEventStatus(es) {
+ if (es == null) {
+ return { canApply: true, applyButtonText: '报名' };
+ }
+ if (es === 0) {
+ return { canApply: false, applyButtonText: '未开始' };
+ }
+ if (es === 1) {
+ return { canApply: true, applyButtonText: '报名' };
+ }
+ if (es === 2) {
+ return { canApply: false, applyButtonText: '报名结束' };
+ }
+ if (es === 3) {
+ return { canApply: false, applyButtonText: '比赛中' };
+ }
+ if (es === 4) {
+ return { canApply: false, applyButtonText: '已结束' };
+ }
+ return { canApply: false, applyButtonText: '暂不可报名' };
+}
+
+function toastForEventStatus(es) {
+ if (es === 0) return '赛事未开始';
+ if (es === 2) return '报名已结束';
+ if (es === 3) return '比赛进行中,暂不可报名';
+ if (es === 4) return '赛事已结束';
+ return '当前不可报名';
+}
+
function registrationModeText(mode) {
const m = mode === undefined || mode === null ? null : Number(mode);
if (m === 1) return '只允许个人报名';
@@ -73,6 +116,42 @@ function splitLines(text) {
.filter(Boolean);
}
+function toNonNegInt(v) {
+ const n = Number(v);
+ if (Number.isNaN(n)) return null;
+ const i = Math.floor(n);
+ return i >= 0 ? i : null;
+}
+
+function buildRegistrationLimitLines(detail, projects) {
+ const d = detail && typeof detail === 'object' ? detail : {};
+ const lines = [];
+
+ const individualLimit = toNonNegInt(pick(d, ['individualProjectLimit', 'IndividualProjectLimit']));
+ const teamLimit = toNonNegInt(pick(d, ['teamProjectLimit', 'TeamProjectLimit']));
+ if (individualLimit != null || teamLimit != null) {
+ const a = individualLimit != null ? `个人项目${individualLimit}个` : null;
+ const b = teamLimit != null ? `团队项目${teamLimit}个` : null;
+ const joined = [a, b].filter(Boolean).join(',');
+ if (joined) lines.push(`每人/单位限报:${joined}`);
+ }
+
+ if (Array.isArray(projects) && projects.length) {
+ const segs = [];
+ projects.forEach((p) => {
+ const name = p && (p.name || p.Name) ? (p.name || p.Name) : '';
+ const limit = toNonNegInt(pick(p, ['projectLimitCount', 'ProjectLimitCount']));
+ if (!name || limit == null) return;
+ segs.push(`${name}${limit}个`);
+ });
+ if (segs.length) {
+ lines.push(`项目组别单位报名上限(每组别):${segs.join(',')}`);
+ }
+ }
+
+ return lines;
+}
+
function flattenProjectTableRows(projects) {
if (!Array.isArray(projects)) return [];
const rows = [];
@@ -179,6 +258,10 @@ function normalizeEventDetail(raw) {
registrationLimitLines = [String(registrationLimitRaw)];
}
}
+ // 若接口未提供文本规则,则由结构化字段拼接
+ if (!registrationLimitLines.length) {
+ registrationLimitLines = buildRegistrationLimitLines(d, projects);
+ }
const participationPointsLabel =
pick(d, ['participationPointsText', 'ParticipationPointsText']) ||
@@ -236,7 +319,11 @@ Page({
hasNoticeBlock: false,
hasRegistrationLimit: false,
projectTableRows: [],
- unitGroups: []
+ unitGroups: [],
+ /** 0未开始 1报名中 2报名结束 3比赛中 4已结束;null 表示接口未返回 */
+ eventStatus: null,
+ canApply: true,
+ applyButtonText: '报名'
},
onLoad(options) {
@@ -353,6 +440,9 @@ Page({
.filter((t) => unitMap[t] && unitMap[t].length)
.map((t) => ({ label: UNIT_TYPE_LABELS[t], names: unitMap[t] }));
+ const eventStatus = parseEventStatus(detail);
+ const { canApply, applyButtonText } = applyUiFromEventStatus(eventStatus);
+
this.setData({
eventDetail: detail,
projects: normalizedProjects,
@@ -378,7 +468,10 @@ Page({
hasNoticeBlock,
hasRegistrationLimit,
projectTableRows,
- unitGroups
+ unitGroups,
+ eventStatus,
+ canApply,
+ applyButtonText
});
})
.catch(() => {
@@ -389,6 +482,10 @@ Page({
onApplyTap() {
const id = this.data.id;
if (!id) return;
+ if (!this.data.canApply) {
+ wx.showToast({ title: toastForEventStatus(this.data.eventStatus), icon: 'none' });
+ return;
+ }
wx.navigateTo({
url: `/pages/apply/apply?eventId=${id}`
});
diff --git a/pages/detail/detail.wxml b/pages/detail/detail.wxml
index 1b28b6a..dc84993 100644
--- a/pages/detail/detail.wxml
+++ b/pages/detail/detail.wxml
@@ -150,6 +150,11 @@
-
+
diff --git a/pages/detail/detail.wxss b/pages/detail/detail.wxss
index 20ccfaf..374c917 100644
--- a/pages/detail/detail.wxss
+++ b/pages/detail/detail.wxss
@@ -516,3 +516,11 @@ page {
.apply-btn::after {
border: none;
}
+
+.apply-btn.apply-btn--disabled,
+.apply-btn[disabled] {
+ background: #c4c4c4 !important;
+ color: #ffffff !important;
+ box-shadow: none;
+ opacity: 1;
+}
diff --git a/pages/home/home.js b/pages/home/home.js
index 3484a08..20ae2dc 100644
--- a/pages/home/home.js
+++ b/pages/home/home.js
@@ -1,6 +1,6 @@
const { API } = require('../../utils/constants');
const { request } = require('../../utils/http');
-const { formatDateTime, eventStatusText, eventFormatText } = require('../../utils/format');
+const { formatDateTime, eventStatusText, eventStatusForPill, eventFormatText } = require('../../utils/format');
/** 统一后台轮播字段(camelCase / PascalCase、枚举数字)供 wxml 绑定 */
function normalizeBannerItem(raw) {
@@ -54,6 +54,7 @@ Page({
pageSize: 10,
hasMore: true,
+ /** 列表筛选:-1=全部(不传 status),0~4 与后端 EventStatus 一致;默认报名中 */
status: 1,
keyword: '',
@@ -136,6 +137,7 @@ Page({
onStatusTap(e) {
const status = Number(e.currentTarget.dataset.status);
+ if (Number.isNaN(status)) return;
this.setData({
status,
pageNo: 1,
@@ -216,24 +218,36 @@ Page({
const status = this.data.status;
const keyword = this.data.keyword;
+ const query = {
+ page: pageNo,
+ pagesize: pageSize,
+ PageNo: pageNo,
+ PageSize: pageSize,
+ keyword,
+ Keyword: keyword
+ };
+ if (status >= 0) {
+ query.status = status;
+ query.Status = status;
+ }
+
return request({
path: API.eventList,
method: 'GET',
needAuth: false,
- data: {
- page: pageNo,
- pagesize: pageSize,
- PageNo: pageNo,
- PageSize: pageSize,
- status,
- Status: status,
- keyword,
- Keyword: keyword
- }
+ data: query
})
.then((res) => {
const rows = (res && Array.isArray(res.rows) ? res.rows : []).map((item) => {
const id = item.id;
+ const rawEventStatus =
+ item.eventStatus != null
+ ? item.eventStatus
+ : item.EventStatus != null
+ ? item.EventStatus
+ : item.status != null
+ ? item.status
+ : item.Status;
return {
...item,
rowKey: `e-${id}`,
@@ -241,7 +255,8 @@ Page({
registrationEndText: formatDateTime(item.registrationEndTime),
matchStartText: formatDateTime(item.matchStartTime),
matchEndText: formatDateTime(item.matchEndTime),
- eventStatusText: eventStatusText(item.eventStatus),
+ eventStatusText: eventStatusText(rawEventStatus),
+ eventStatusPill: eventStatusForPill(rawEventStatus),
eventFormatText: eventFormatText(item.eventType || item.eventFormat)
};
});
@@ -309,6 +324,7 @@ Page({
eventName: item.eventName,
coverImage: item.coverImage,
address: '',
+ eventStatusPill: 1,
eventStatusText: '已报名',
registrationTimeText: formatDateTime(item.registrationTime),
projectCount: item.projectCount,
diff --git a/pages/home/home.wxml b/pages/home/home.wxml
index baa6abe..c9f76a4 100644
--- a/pages/home/home.wxml
+++ b/pages/home/home.wxml
@@ -80,13 +80,13 @@
bindtap="onStatusTap"
>报名中
比赛中
已结束
diff --git a/pages/home/home.wxss b/pages/home/home.wxss
index 6bd9f29..4f4f372 100644
--- a/pages/home/home.wxss
+++ b/pages/home/home.wxss
@@ -281,13 +281,13 @@ page {
/* box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06); */
}
-.status-pill-top-0 {
+.status-pill-top-1 {
background: linear-gradient(135deg, rgba(0, 181, 109, 0) 20%, rgba(0, 96, 216, 1) 80% , rgba(0, 96, 216, 1) 100%) ;
}
-.status-pill-top-1 {
+.status-pill-top-3 {
background: linear-gradient(135deg, rgba(0, 181, 109, 0) 20%, rgba(0, 181, 109, 1) 80% , rgba(0, 181, 109, 1) 100%) ;
}
-.status-pill-top-2 {
+.status-pill-top-4 {
background: linear-gradient(135deg, rgba(0, 181, 109, 0) 20%, rgba(230, 6, 11, 1)80% , rgba(230, 6, 11, 1)100%) ;
}
diff --git a/pages/mine/mine.js b/pages/mine/mine.js
index a81cf29..ebdcebe 100644
--- a/pages/mine/mine.js
+++ b/pages/mine/mine.js
@@ -94,6 +94,14 @@ Page({
// TODO: 上传头像到服务器
}
});
+ },
+
+ onFetchOpenId() {
+ wx.login({
+ success: (res) => {
+ console.log('res', res);
+ }
+ });
}
});
diff --git a/pages/mine/mine.wxml b/pages/mine/mine.wxml
index 41ce1b2..8685399 100644
--- a/pages/mine/mine.wxml
+++ b/pages/mine/mine.wxml
@@ -73,4 +73,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/subpackages/mine/auth/auth.js b/subpackages/mine/auth/auth.js
index 1c3ac9a..23603b8 100644
--- a/subpackages/mine/auth/auth.js
+++ b/subpackages/mine/auth/auth.js
@@ -89,7 +89,7 @@ Page({
const passportImageUrl = d.passportImageUrl || '';
const birthDate = d.birthDate || d.birthday || '';
const gender = (d.gender || d.sex || '').toString().toUpperCase();
- const genderIndex = gender === 'F' || gender === '女' || gender === '2' ? 1 : 0;
+ const genderIndex = gender === 'F' || gender === '女' || gender === '1' ? 1 : 0;
// 有已提交信息时,按产品稿表现为“自动识别/灰色不可修改”
const readonlyName = Boolean(name);
diff --git a/utils/constants.js b/utils/constants.js
index fdf1654..61fa023 100644
--- a/utils/constants.js
+++ b/utils/constants.js
@@ -17,6 +17,8 @@ const API = {
oauthRegister: '/api/oauth/register',
oauthResetPassword: '/api/oauth/reset-password',
sendVerificationCode: '/api/sms/sendverificationcode',
+ /** 小程序 wx.login 的 code 换 openid(按后端实际路径修改) */
+ wechatOpenidByJsCode: '/api/wechat/jscode2session',
myProfile: '/api/my/profile',
myAuth: '/api/my/auth',
myRegistrations: '/api/my/registrations',
diff --git a/utils/format.js b/utils/format.js
index 68afe13..ba9f436 100644
--- a/utils/format.js
+++ b/utils/format.js
@@ -15,15 +15,41 @@ function formatTime(iso) {
}
function eventStatusText(status) {
- if (status === 'Enrolling') return '报名中';
- if (status === 'Ongoing') return '比赛中';
- if (status === 'Ended') return '已结束';
- const map = {
- 0: '报名中',
- 1: '比赛中',
- 2: '已结束'
+ // 与后端 EventStatus 枚举一致
+ const strMap = {
+ NotStarted: '未开始',
+ Enrolling: '报名中',
+ RegistrationEnded: '报名结束',
+ Ongoing: '比赛中',
+ Ended: '已结束'
};
- return map[status] !== undefined ? map[status] : `状态${status}`;
+ if (strMap[status] != null) return strMap[status];
+
+ const n = status === undefined || status === null || status === '' ? NaN : Number(status);
+ const numMap = {
+ 0: '未开始',
+ 1: '报名中',
+ 2: '报名结束',
+ 3: '比赛中',
+ 4: '已结束'
+ };
+ if (!Number.isNaN(n) && numMap[n] !== undefined) return numMap[n];
+ return status !== undefined && status !== null && status !== '' ? `状态${status}` : '';
+}
+
+/** 列表角标样式用:0~4,未知时回退 0 */
+function eventStatusForPill(status) {
+ const strToNum = {
+ NotStarted: 0,
+ Enrolling: 1,
+ RegistrationEnded: 2,
+ Ongoing: 3,
+ Ended: 4
+ };
+ if (strToNum[status] !== undefined) return strToNum[status];
+ const n = Number(status);
+ if (!Number.isNaN(n) && n >= 0 && n <= 4) return n;
+ return 0;
}
function eventFormatText(v) {
@@ -36,6 +62,7 @@ module.exports = {
formatDateTime,
formatTime,
eventStatusText,
+ eventStatusForPill,
eventFormatText
};