feat: 调整小程序为项目级检录

This commit is contained in:
ltx 2026-09-20 17:40:38 +08:00
parent adfc7a66fb
commit 02527ad5b2
3 changed files with 19 additions and 65 deletions

View File

@ -7,9 +7,7 @@ Page({
projects: [],
projectNames: [],
projectIndex: 0,
groups: [],
groupNames: [],
groupIndex: 0,
currentProjectName: '',
units: [],
pendingUnits: [],
checkedUnits: [],
@ -25,7 +23,7 @@ Page({
onLoad() { this.loadContext(); },
onPullDownRefresh() {
this.loadContext(this.currentProjectId(), this.currentGroupId()).finally(() => wx.stopPullDownRefresh());
this.loadContext(this.currentProjectId()).finally(() => wx.stopPullDownRefresh());
},
currentProjectId() {
@ -33,14 +31,9 @@ Page({
return item && item.eventProjectId;
},
currentGroupId() {
const item = this.data.groups[this.data.groupIndex];
return item && item.id;
},
loadContext(eventProjectId, groupId) {
loadContext(eventProjectId) {
this.setData({ loading: true });
return competition.fetchCurrentCheckin({ eventProjectId, groupId })
return competition.fetchCurrentCheckin({ eventProjectId })
.then((context) => this.applyContext(context))
.catch((err) => wx.showToast({ title: (err && err.message) || '检录信息加载失败', icon: 'none' }))
.finally(() => this.setData({ loading: false }));
@ -50,9 +43,6 @@ Page({
const projects = (context && context.projects) || [];
let projectIndex = projects.findIndex((item) => String(item.eventProjectId) === String(context.selectedEventProjectId));
if (projectIndex < 0) projectIndex = 0;
const groups = (projects[projectIndex] && projects[projectIndex].groups) || [];
let groupIndex = groups.findIndex((item) => String(item.id) === String(context.selectedGroupId));
if (groupIndex < 0) groupIndex = 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);
@ -84,9 +74,7 @@ Page({
projects,
projectNames: projects.map((item) => item.projectName),
projectIndex,
groups,
groupNames: groups.map((item) => item.groupName),
groupIndex,
currentProjectName: (projects[projectIndex] && projects[projectIndex].projectName) || '',
units,
pendingUnits,
checkedUnits,
@ -103,33 +91,23 @@ Page({
const projectIndex = Number(e.currentTarget.dataset.index) || 0;
if (projectIndex === this.data.projectIndex) return;
const project = this.data.projects[projectIndex];
const group = project && project.groups && project.groups[0];
if (project && group) this.loadContext(project.eventProjectId, group.id);
},
onGroupTap(e) {
if (this.data.loading) return;
const groupIndex = Number(e.currentTarget.dataset.index) || 0;
if (groupIndex === this.data.groupIndex) return;
const group = this.data.groups[groupIndex];
if (group) this.loadContext(this.currentProjectId(), group.id);
if (project) this.loadContext(project.eventProjectId);
},
onStartCheckin() {
if (this.data.actionLoading) return;
const eventProjectId = this.currentProjectId();
const groupId = this.currentGroupId();
wx.showModal({
title: '开始检录',
content: '开始后将通知本组报名人员,确认继续吗?',
content: '开始后将按秩序册顺序检录该项目全部组别,并通知报名人员,确认继续吗?',
success: (res) => {
if (!res.confirm) return;
this.setData({ actionLoading: true });
competition.startCheckin({ eventProjectId, groupId })
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, groupId);
if (!(result && result.context)) return this.loadContext(eventProjectId);
})
.catch((err) => wx.showToast({ title: (err && err.message) || '开始检录失败', icon: 'none' }))
.finally(() => this.setData({ actionLoading: false }));
@ -145,8 +123,7 @@ Page({
this.setData({ actionLoading: true });
competition.scanCheckin({
code: scan.result,
eventProjectId: this.currentProjectId(),
groupId: this.currentGroupId()
eventProjectId: this.currentProjectId()
}).then((result) => {
// 后端在号码布不匹配时返回 success:false + message 且不带 context,
// 必须照样给出提示,否则检录员扫错码时收不到任何反馈。
@ -156,7 +133,7 @@ Page({
title: (result && result.message) || (ok ? '扫码检录成功' : '扫码检录失败'),
icon: ok ? 'success' : 'none'
});
if (!(result && result.context)) return this.loadContext(this.currentProjectId(), this.currentGroupId());
if (!(result && result.context)) return this.loadContext(this.currentProjectId());
}).catch((err) => wx.showToast({ title: (err && err.message) || '扫码检录失败', icon: 'none' }))
.finally(() => this.setData({ actionLoading: false }));
}
@ -169,8 +146,7 @@ Page({
this.setData({ updatingKey: unitKey });
competition.markCheckinOnStage({
unitKey,
eventProjectId: this.currentProjectId(),
groupId: this.currentGroupId()
eventProjectId: this.currentProjectId()
}).then((context) => {
if (context) this.applyContext(context);
wx.showToast({ title: '已标记上场', icon: 'success' });
@ -205,7 +181,6 @@ Page({
competition.updateCheckinStatus({
unitKey,
eventProjectId: this.currentProjectId(),
groupId: this.currentGroupId(),
checked
}).then((res) => {
this.applyContext(res);

View File

@ -12,8 +12,8 @@
</view>
<view class="compact-divider"></view>
<view class="compact-status-item group-status-item">
<text class="compact-label">当前组别</text>
<text class="compact-value">{{context.currentGroupName || '请选择组别'}}</text>
<text class="compact-label">当前项目</text>
<text class="compact-value">{{currentProjectName || '请选择项目'}}</text>
</view>
</view>
</view>
@ -40,30 +40,10 @@
</view>
</scroll-view>
<view class="selector-separator"></view>
<view class="selector-heading group-heading">
<view class="selector-step">2</view>
<view class="selector-heading-text"><text class="selector-title">选择参赛组别</text><text class="selector-hint">点击后立即切换检录名单</text></view>
</view>
<scroll-view class="group-scroll" scroll-x enhanced show-scrollbar="{{false}}" scroll-with-animation>
<view class="group-options">
<view
wx:for="{{groups}}"
wx:key="id"
class="group-option {{index === groupIndex ? 'active' : ''}} {{item.isCompleted ? 'completed' : ''}}"
data-index="{{index}}"
bindtap="onGroupTap"
>
<view class="group-active-dot"></view>
<view class="group-option-content"><text class="group-option-name">{{item.groupName}}</text><text class="group-option-progress">{{item.checkedUnits}}/{{item.totalUnits}} · {{item.isCompleted ? '已完成' : item.progressPercent + '%'}}</text></view>
</view>
</view>
</scroll-view>
</view>
<view class="checkin-toolbar" wx:if="{{context}}">
<button class="toolbar-btn toolbar-btn--primary" loading="{{actionLoading}}" disabled="{{actionLoading}}" bindtap="onStartCheckin">开始当前组检录</button>
<button class="toolbar-btn toolbar-btn--primary" loading="{{actionLoading}}" disabled="{{actionLoading}}" bindtap="onStartCheckin">开始当前项目检录</button>
<button class="toolbar-btn" disabled="{{actionLoading}}" bindtap="onScanCheckin">扫码检录</button>
</view>
@ -71,7 +51,7 @@
<block wx:if="{{context}}">
<view class="progress-card">
<view class="progress-top"><text class="section-title">当前组别进度</text><text class="progress-count"><text class="progress-count-main">{{checkedCount}}</text> / {{units.length}} 项</text></view>
<view class="progress-top"><text class="section-title">当前项目进度</text><text class="progress-count"><text class="progress-count-main">{{checkedCount}}</text> / {{units.length}} 项</text></view>
<view class="progress-track"><view class="progress-fill" style="width: {{progressPercent}}%;"></view></view>
<view class="progress-bottom"><text>已检录 {{checkedCount}} 项</text><text>待检录 {{pendingCount}} 项</text></view>
</view>
@ -83,7 +63,7 @@
<view class="unit-athletes"><text class="athlete-chip" wx:for="{{item.athletes}}" wx:for-item="athlete" wx:key="id">{{athlete.name}}</text></view>
<view class="unit-action {{updatingKey === item.unitKey ? 'disabled' : ''}}" data-key="{{item.unitKey}}" bindtap="onToggleUnit">确认检录</view>
</view>
<view wx:if="{{!pendingUnits.length}}" class="empty-tip">当前组别暂无待检录项</view>
<view wx:if="{{!pendingUnits.length}}" class="empty-tip">当前项目暂无待检录项</view>
<view class="list-heading" wx:if="{{lockedUnits.length}}"><text class="section-title">等待前序检录</text><text class="list-tip">前一检通过后可操作</text></view>
<view class="unit-card locked" wx:for="{{lockedUnits}}" wx:key="unitKey">
@ -95,7 +75,7 @@
<view class="checked-section-head">
<view class="checked-section-title"><text class="section-title">已检录</text><text class="checked-count">{{checkedUnits.length}} 项</text></view>
<text class="scope-tip">仅展示当前选中项目和组别的已检录结果</text>
<text class="scope-tip">展示当前项目全部组别的已检录结果</text>
</view>
<block wx:for="{{checkedGroups}}" wx:for-item="checkedGroup" wx:key="key">
<view class="checked-group-head">

View File

@ -41,11 +41,10 @@ function updateCheckinStatus({ unitKey, eventProjectId, groupId, checked }) {
function startCheckin({ eventProjectId, groupId } = {}) {
if (isEmptyValue(eventProjectId)) return rejectWith('请选择检录项目');
if (isEmptyValue(groupId)) return rejectWith('请选择检录组别');
return request({
path: API.checkinStart,
method: 'POST',
data: { eventProjectId, groupId },
data: withScope({ eventProjectId }, eventProjectId, groupId),
needAuth: true
});
}