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

171 lines
6.7 KiB
JavaScript
Raw 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 competition = require('../../../utils/competition');
Page({
data: {
loading: true,
context: null,
projects: [],
projectIndex: 0,
units: [],
pendingUnits: [],
checkedUnits: [],
lockedUnits: [],
checkedCount: 0,
pendingCount: 0,
progressPercent: 0,
updatingKey: '',
actionLoading: false
},
onLoad() { this.loadContext(); },
onPullDownRefresh() {
this.loadContext(this.currentProjectId()).finally(() => wx.stopPullDownRefresh());
},
currentProjectId() {
const item = this.data.projects[this.data.projectIndex];
return item && item.eventProjectId;
},
loadContext(eventProjectId) {
this.setData({ loading: true });
return competition.fetchCurrentCheckin({ eventProjectId })
.then((context) => this.applyContext(context))
.catch((err) => wx.showToast({ title: (err && err.message) || '检录信息加载失败', icon: 'none' }))
.finally(() => this.setData({ loading: false }));
},
applyContext(context) {
const projects = (context && context.projects) || [];
let projectIndex = projects.findIndex((item) => String(item.eventProjectId) === String(context.selectedEventProjectId));
if (projectIndex < 0) projectIndex = 0;
const units = (context && context.units) || [];
const pendingUnits = Array.isArray(context && context.pendingUnits) ? context.pendingUnits : units.filter((item) => item.canCheck && !item.checked);
const checkedUnits = Array.isArray(context && context.checkedUnits) ? context.checkedUnits : units.filter((item) => item.checked);
const lockedUnits = Array.isArray(context && context.lockedUnits) ? context.lockedUnits : units.filter((item) => !item.canCheck);
const totalRounds = Number(context && (context.totalCheckins || context.totalRounds)) || 0;
const currentRound = Number(context && (context.currentCheckinNo || context.currentRound)) || 0;
const rounds = Array.from({ length: totalRounds }, (_, index) => {
const number = index + 1;
return { number, state: number < currentRound ? 'done' : number === currentRound ? 'active' : '', label: number < currentRound ? '✓' : String(number) };
});
const checkedCount = units.filter((item) => item.checked).length;
this.setData({
context: context ? Object.assign({}, context, { rounds }) : null,
projects,
projectIndex,
units,
pendingUnits,
checkedUnits,
lockedUnits,
checkedCount,
pendingCount: pendingUnits.length,
progressPercent: units.length ? Math.round(checkedCount * 100 / units.length) : 0
});
},
onProjectTap(e) {
if (this.data.loading) return;
const projectIndex = Number(e.currentTarget.dataset.index) || 0;
if (projectIndex === this.data.projectIndex) return;
const project = this.data.projects[projectIndex];
if (project) this.loadContext(project.eventProjectId);
},
onStartCheckin() {
if (this.data.actionLoading) return;
const eventProjectId = this.currentProjectId();
wx.showModal({
title: '开始检录',
content: '开始后将通知当前项目的报名人员,确认继续吗?',
success: (res) => {
if (!res.confirm) return;
this.setData({ actionLoading: true });
competition.startCheckin({ eventProjectId })
.then((result) => {
if (result && result.context) this.applyContext(result.context);
wx.showToast({ title: (result && result.message) || '检录已开始', icon: 'none' });
if (!(result && result.context)) return this.loadContext(eventProjectId);
})
.catch((err) => wx.showToast({ title: (err && err.message) || '开始检录失败', icon: 'none' }))
.finally(() => this.setData({ actionLoading: false }));
}
});
},
onScanCheckin() {
if (this.data.actionLoading) return;
wx.scanCode({
scanType: ['qrCode', 'barCode'],
success: (scan) => {
this.setData({ actionLoading: true });
competition.scanCheckin({
code: scan.result,
eventProjectId: this.currentProjectId()
}).then((result) => {
// 后端在号码布不匹配时返回 success:false + message 且不带 context,
// 必须照样给出提示,否则检录员扫错码时收不到任何反馈。
const ok = !result || result.success !== false;
if (result && result.context) this.applyContext(result.context);
wx.showToast({
title: (result && result.message) || (ok ? '扫码检录成功' : '扫码检录失败'),
icon: ok ? 'success' : 'none'
});
if (!(result && result.context)) return this.loadContext(this.currentProjectId());
}).catch((err) => wx.showToast({ title: (err && err.message) || '扫码检录失败', icon: 'none' }))
.finally(() => this.setData({ actionLoading: false }));
}
});
},
onMarkOnStage(e) {
const unitKey = e.currentTarget.dataset.key;
if (!unitKey || this.data.updatingKey) return;
this.setData({ updatingKey: unitKey });
competition.markCheckinOnStage({
unitKey,
eventProjectId: this.currentProjectId()
}).then((context) => {
if (context) this.applyContext(context);
wx.showToast({ title: '已标记上场', icon: 'success' });
}).catch((err) => wx.showToast({ title: (err && err.message) || '标记上场失败', icon: 'none' }))
.finally(() => this.setData({ updatingKey: '' }));
},
onToggleUnit(e) {
const unitKey = e.currentTarget.dataset.key;
const current = this.data.units.find((item) => item.unitKey === unitKey)
|| this.data.checkedUnits.find((item) => item.unitKey === unitKey);
if (!current || !current.canCheck || this.data.updatingKey) return;
const checked = !current.checked;
if (current.checked) {
wx.showModal({
title: '取消检录',
content: `确认取消${current.teamName || current.athletes.map((item) => item.name).join('、')}的当前检录吗?`,
confirmText: '确认取消',
confirmColor: '#d94b4b',
success: (res) => {
if (res.confirm) this.updateUnitStatus(current, checked);
}
});
return;
}
this.updateUnitStatus(current, checked);
},
updateUnitStatus(current, checked) {
const unitKey = current.unitKey;
this.setData({ updatingKey: unitKey });
competition.updateCheckinStatus({
unitKey,
eventProjectId: this.currentProjectId(),
checked
}).then((res) => {
this.applyContext(res);
wx.showToast({ title: checked ? '该列已完成检录' : '已取消该列检录', icon: 'none' });
}).catch((err) => wx.showToast({ title: (err && err.message) || '操作失败', icon: 'none' }))
.finally(() => this.setData({ updatingKey: '' }));
}
});