- 新增参赛者、裁判、检录员角色识别及角色化首页与个人中心 - 新增裁判注册、身份认证提示、赛事执裁报名及报名记录查询 - 新增检录工作台,支持检录任务、轮次状态与运动员检录操作 - 新增赛事成绩查询页面及成绩详情展示 - 封装成绩、检录和裁判报名接口,补充请求参数清理逻辑 - 新增检录 Tab 图标、页面路由及本地开发配置 - 新增 Git 忽略规则,排除依赖、构建缓存、日志和本地工具文件
162 lines
7.0 KiB
JavaScript
162 lines
7.0 KiB
JavaScript
const { API } = require('./constants');
|
||
const { request } = require('./http');
|
||
|
||
// 已对接 YD_Event.Admin;如需离线演示可临时改回 true。
|
||
const USE_LOCAL_MOCK = false;
|
||
const CHECKIN_STORAGE_KEY = 'mockCheckinAthletes';
|
||
const REFEREE_APPLICATIONS_KEY = 'mockRefereeApplications';
|
||
|
||
const MOCK_SCORE_EVENTS = [
|
||
{ id: 'event-2026-summer', name: '2026 跃享跳花样跳绳公开赛' },
|
||
{ id: 'event-2026-city', name: '跃享跳城市挑战赛' }
|
||
];
|
||
|
||
const MOCK_SCORES = [
|
||
{
|
||
id: 'score-001', eventId: 'event-2026-summer', eventName: '2026 跃享跳花样跳绳公开赛',
|
||
athleteName: '陈跃', athleteNo: 'A018', category: '个人花样', groupName: 'U12 男子组',
|
||
roundName: '决赛', rank: 1, totalScore: '86.50', difficultyScore: '28.50',
|
||
executionScore: '30.00', creativityScore: '28.00', status: '成绩有效',
|
||
judgeScores: [
|
||
{ label: '难度裁判', score: '28.50' }, { label: '完成裁判', score: '30.00' },
|
||
{ label: '创意裁判', score: '28.00' }
|
||
]
|
||
},
|
||
{
|
||
id: 'score-002', eventId: 'event-2026-summer', eventName: '2026 跃享跳花样跳绳公开赛',
|
||
athleteName: '林晓', athleteNo: 'A026', category: '个人花样', groupName: 'U12 女子组',
|
||
roundName: '决赛', rank: 2, totalScore: '84.20', difficultyScore: '27.70',
|
||
executionScore: '29.00', creativityScore: '27.50', status: '成绩有效',
|
||
judgeScores: [
|
||
{ label: '难度裁判', score: '27.70' }, { label: '完成裁判', score: '29.00' },
|
||
{ label: '创意裁判', score: '27.50' }
|
||
]
|
||
},
|
||
{
|
||
id: 'score-003', eventId: 'event-2026-city', eventName: '跃享跳城市挑战赛',
|
||
athleteName: '跃动少年队', athleteNo: 'T009', category: '团体花样', groupName: '公开组',
|
||
roundName: '预赛', rank: 3, totalScore: '81.80', difficultyScore: '26.80',
|
||
executionScore: '28.00', creativityScore: '27.00', status: '成绩有效',
|
||
judgeScores: [
|
||
{ label: '难度裁判', score: '26.80' }, { label: '完成裁判', score: '28.00' },
|
||
{ label: '创意裁判', score: '27.00' }
|
||
]
|
||
}
|
||
];
|
||
|
||
const DEFAULT_CHECKIN_ATHLETES = [
|
||
{ id: 'athlete-01', userId: 'user-01', bibNo: 'A018', name: '陈跃', teamName: '跃动俱乐部', checked: true, canCheck: true, orderBookSessionName: '第1场 · 30秒单摇' },
|
||
{ id: 'athlete-02', userId: 'user-02', bibNo: 'A021', name: '周航', teamName: '星火跳绳队', checked: true, canCheck: true, orderBookSessionName: '第1场 · 30秒单摇' },
|
||
{ id: 'athlete-03', userId: 'user-03', bibNo: 'A024', name: '许嘉', teamName: '青苗体育', checked: false, canCheck: true, orderBookSessionName: '第2场 · 花样跳绳' },
|
||
{ id: 'athlete-04', userId: 'user-04', bibNo: 'A027', name: '江晨', teamName: '跃动俱乐部', checked: false, canCheck: true, orderBookSessionName: '第2场 · 花样跳绳' }
|
||
];
|
||
|
||
function clone(data) {
|
||
return JSON.parse(JSON.stringify(data));
|
||
}
|
||
|
||
function mockResolve(data) {
|
||
return new Promise((resolve) => setTimeout(() => resolve(clone(data)), 180));
|
||
}
|
||
|
||
function fetchScoreEvents() {
|
||
if (USE_LOCAL_MOCK) return mockResolve(MOCK_SCORE_EVENTS);
|
||
return request({ path: API.scoreEvents, method: 'GET', needAuth: false });
|
||
}
|
||
|
||
function queryScores({ eventId, keyword } = {}) {
|
||
if (!USE_LOCAL_MOCK) {
|
||
return request({ path: API.scoreQuery, method: 'GET', data: { eventId, keyword }, needAuth: false });
|
||
}
|
||
const search = String(keyword || '').trim().toLowerCase();
|
||
const rows = MOCK_SCORES.filter((item) => {
|
||
const eventMatched = !eventId || item.eventId === eventId;
|
||
const keywordMatched = !search || [item.athleteName, item.athleteNo, item.groupName]
|
||
.some((value) => String(value || '').toLowerCase().includes(search));
|
||
return eventMatched && keywordMatched;
|
||
});
|
||
return mockResolve({ rows, total: rows.length });
|
||
}
|
||
|
||
function fetchCurrentCheckin({ eventProjectId, groupId } = {}) {
|
||
if (!USE_LOCAL_MOCK) {
|
||
const data = {};
|
||
if (eventProjectId !== undefined && eventProjectId !== null && eventProjectId !== '') {
|
||
data.eventProjectId = eventProjectId;
|
||
}
|
||
if (groupId !== undefined && groupId !== null && groupId !== '') {
|
||
data.groupId = groupId;
|
||
}
|
||
return request({ path: API.checkinContext, method: 'GET', data, needAuth: true });
|
||
}
|
||
const stored = wx.getStorageSync(CHECKIN_STORAGE_KEY);
|
||
const athletes = Array.isArray(stored) ? stored : clone(DEFAULT_CHECKIN_ATHLETES);
|
||
const rounds = [{ round: 1, order: 1 }, { round: 2, order: 2 }];
|
||
const pendingAthletes = athletes.filter((item) => !item.checked && item.canCheck);
|
||
const checkedAthletes = athletes.filter((item) => item.checked);
|
||
const lockedAthletes = athletes.filter((item) => !item.checked && !item.canCheck);
|
||
return mockResolve({
|
||
eventId: 'event-2026-summer', eventName: '2026 跃享跳花样跳绳公开赛', venue: '一号检录区',
|
||
totalCheckins: 2, currentCheckinNo: 1, currentCheckinName: '一检',
|
||
totalRounds: 2, currentRound: 1, roundName: '一检', currentSessionVenue: '一号检录区',
|
||
rounds, athletes, pendingAthletes, checkedAthletes, lockedAthletes
|
||
});
|
||
}
|
||
|
||
function updateCheckinStatus({ unitKey, eventProjectId, groupId, checked }) {
|
||
if (!USE_LOCAL_MOCK) {
|
||
const data = { unitKey, checked };
|
||
if (eventProjectId !== undefined && eventProjectId !== null && eventProjectId !== '') {
|
||
data.eventProjectId = eventProjectId;
|
||
}
|
||
if (groupId !== undefined && groupId !== null && groupId !== '') {
|
||
data.groupId = groupId;
|
||
}
|
||
return request({ path: API.checkinStatus, method: 'POST', data, needAuth: true });
|
||
}
|
||
return fetchCurrentCheckin().then((context) => {
|
||
const units = (context.units || []).map((item) => item.unitKey === unitKey ? Object.assign({}, item, { checked: !!checked }) : item);
|
||
return Object.assign({}, context, { units });
|
||
});
|
||
}
|
||
|
||
function fetchRefereeApplications() {
|
||
if (!USE_LOCAL_MOCK) {
|
||
return request({ path: API.refereeApplications, method: 'GET', needAuth: true });
|
||
}
|
||
const stored = wx.getStorageSync(REFEREE_APPLICATIONS_KEY);
|
||
return mockResolve({ rows: Array.isArray(stored) ? stored : [], total: Array.isArray(stored) ? stored.length : 0 });
|
||
}
|
||
|
||
function applyForReferee(event) {
|
||
const payload = event && typeof event === 'object' ? event : {};
|
||
if (!USE_LOCAL_MOCK) {
|
||
return request({ path: API.refereeApply, method: 'POST', data: { eventId: payload.eventId }, needAuth: true });
|
||
}
|
||
return fetchRefereeApplications().then((res) => {
|
||
const rows = (res && res.rows) || [];
|
||
const exists = rows.some((item) => String(item.eventId) === String(payload.eventId));
|
||
if (!exists) {
|
||
rows.unshift(Object.assign({}, payload, {
|
||
id: `referee-${payload.eventId}`,
|
||
applicationId: `mock-${Date.now()}`,
|
||
applicationStatus: 1,
|
||
applicationStatusText: '已报名执裁',
|
||
appliedAt: new Date().toISOString()
|
||
}));
|
||
wx.setStorageSync(REFEREE_APPLICATIONS_KEY, rows);
|
||
}
|
||
return { success: true, alreadyApplied: exists, rows };
|
||
});
|
||
}
|
||
|
||
module.exports = {
|
||
USE_LOCAL_MOCK,
|
||
fetchScoreEvents,
|
||
queryScores,
|
||
fetchCurrentCheckin,
|
||
updateCheckinStatus,
|
||
fetchRefereeApplications,
|
||
applyForReferee
|
||
};
|