YD_Event.miniApp/utils/competition.js
马梓彭 341449efe9 报时间冲突的比赛弹窗提醒
检录工作台选择项目后不用再细化到组别,按照场次顺序排列
2026-09-21 14:15:59 +08:00

167 lines
5.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { API } = require('./constants');
const { request } = require('./http');
const { normalizeCheckinProgress } = require('./checkin-progress');
function fetchScoreEvents() {
return request({ path: API.scoreEvents, method: 'GET', needAuth: false });
}
function fetchScoreFilters(eventId) {
return request({ path: API.scoreFilters, method: 'GET', data: { eventId }, needAuth: false });
}
function queryScores({ eventId, projectId, groupName, keyword } = {}) {
return request({ path: API.scoreQuery, method: 'GET', data: { eventId, projectId, groupName, keyword }, needAuth: false });
}
function isEmptyValue(value) {
return value === undefined || value === null || value === '';
}
// 参数校验一律以 reject 返回,不能同步 throw:
// 调用方普遍写成 fn().then().catch().finally(),同步抛出会绕过 catch/finally,
// 造成 loading 遮罩不消失、按钮 loading 锁死。
function rejectWith(message) {
return Promise.reject(new Error(message));
}
function withProjectScope(data, eventProjectId) {
if (!isEmptyValue(eventProjectId)) data.eventProjectId = eventProjectId;
return data;
}
function fetchCurrentCheckin({ eventProjectId } = {}) {
return request({ path: API.checkinContext, method: 'GET', data: withProjectScope({}, eventProjectId), needAuth: true });
}
function updateCheckinStatus({ unitKey, eventProjectId, checked }) {
return request({ path: API.checkinStatus, method: 'POST', data: withProjectScope({ unitKey, checked }, eventProjectId), needAuth: true });
}
function startCheckin({ eventProjectId } = {}) {
if (isEmptyValue(eventProjectId)) return rejectWith('请选择检录项目');
return request({
path: API.checkinStart,
method: 'POST',
data: { eventProjectId },
needAuth: true
});
}
function scanCheckin({ code, eventProjectId } = {}) {
if (isEmptyValue(code)) return rejectWith('未识别到有效检录码');
const normalizedCode = String(code).trim();
if (!normalizedCode) return rejectWith('未识别到有效检录码');
return request({
path: API.checkinScan,
method: 'POST',
data: withProjectScope({ code: normalizedCode }, eventProjectId),
needAuth: true
});
}
function markCheckinOnStage({ unitKey, eventProjectId } = {}) {
if (isEmptyValue(unitKey)) return rejectWith('缺少参赛单位标识');
return request({
path: API.checkinOnStage,
method: 'POST',
data: withProjectScope({ unitKey }, eventProjectId),
needAuth: true
});
}
function fetchCheckinProgress(eventId) {
if (isEmptyValue(eventId)) return rejectWith('缺少赛事ID');
return request({ path: API.checkinProgress, method: 'GET', data: { eventId }, needAuth: true })
.then(normalizeCheckinProgress);
}
function fetchRefereeProfileOptions() {
return request({ path: API.refereeProfileOptions, method: 'GET', needAuth: true })
.then((res) => (res && typeof res === 'object' ? res : {}));
}
function fetchRefereeProfile() {
// 裁判未提交资料时后端返回 data:null,统一归一为空对象,避免调用方读字段时抛错
return request({ path: API.refereeProfile, method: 'GET', needAuth: true })
.then((res) => (res && typeof res === 'object' ? res : {}));
}
function resolveRefereeRegistrationCode(code) {
if (isEmptyValue(code)) return rejectWith('裁判报名码无效');
return request({ path: API.refereeRegistrationCode(String(code).trim()), method: 'GET', needAuth: false });
}
// 裁判角色是 [Flags] 位枚举(1-主裁 2-表现 4-难度 8-创意编排 16-完成质量)。
// 接口文档在 RefereeProfileSubmitInput/RefereeProfileDto 两处误写为 int 数组,
// 后端实际按单个 RefereeRole 反序列化,因此提交前合并为位标志,回显时再拆开。
function combineRefereeRoles(roles) {
const list = Array.isArray(roles) ? roles : [roles];
return list.reduce((mask, item) => {
const value = Number(item);
return Number.isFinite(value) && value > 0 ? mask | value : mask;
}, 0);
}
function splitRefereeRoles(value) {
if (Array.isArray(value)) return value.map(Number).filter((item) => Number.isFinite(item) && item > 0);
const mask = Number(value);
if (!Number.isFinite(mask) || mask <= 0) return [];
const result = [];
for (let bit = 1; bit <= mask; bit *= 2) {
if (mask & bit) result.push(bit);
}
return result;
}
function submitRefereeProfile(payload) {
const data = Object.assign({}, payload || {});
data.roles = combineRefereeRoles(data.roles);
return request({
path: API.refereeProfileSubmit,
method: 'POST',
data,
needAuth: true
});
}
function fetchRefereeQuota(eventId) {
if (isEmptyValue(eventId)) return rejectWith('缺少赛事ID');
return request({ path: API.refereeApplicationQuota, method: 'GET', data: { eventId }, needAuth: true });
}
function fetchRefereeApplications() {
return request({ path: API.refereeApplications, method: 'GET', needAuth: true });
}
function applyForReferee(event) {
const payload = event && typeof event === 'object' ? event : {};
if (isEmptyValue(payload.eventId)) return rejectWith('缺少赛事ID');
return request({
path: API.refereeApply,
method: 'POST',
data: { eventId: payload.eventId },
needAuth: true
});
}
module.exports = {
fetchScoreEvents,
fetchScoreFilters,
queryScores,
fetchCurrentCheckin,
updateCheckinStatus,
startCheckin,
scanCheckin,
markCheckinOnStage,
fetchCheckinProgress,
fetchRefereeProfileOptions,
fetchRefereeProfile,
resolveRefereeRegistrationCode,
submitRefereeProfile,
splitRefereeRoles,
fetchRefereeQuota,
fetchRefereeApplications,
applyForReferee
};