裁判打分页面编辑按钮调整

This commit is contained in:
马梓彭 2026-10-12 17:29:19 +08:00
parent 5480427d65
commit 0be9c0d3c1
3 changed files with 80 additions and 59 deletions

View File

@ -66,6 +66,19 @@ abstract final class RemoteScoringAdapter {
sheet.header.judgeRole.trim().toUpperCase() ==
session.judgeRole.trim().toUpperCase();
/// Returns the business session number shown on the judge task card.
///
/// [JudgeEntry.playOrder] is the entry order inside an EventSession. The
/// arrangement order identifies the first business session represented by
/// that EventSession, so both values are needed for a stable display number.
static int sessionDisplayOrder(JudgeSession session, JudgeEntry entry) {
final playOrder = entry.playOrder > 0 ? entry.playOrder : 1;
final arrangementOrder = session.arrangementOrder;
return arrangementOrder > 0 && arrangementOrder < 0x7fffffff
? arrangementOrder + playOrder - 1
: playOrder;
}
static JudgeAccount accountForSession(
JudgeSession session, {
required String userId,

View File

@ -44,7 +44,6 @@ class _HomePageState extends State<HomePage> {
late final Worker _syncStatusWorker;
Timer? _messageTimer;
int _unreadMessages = 0;
int _correctionTaskCount = 0;
@override
void initState() {
@ -56,9 +55,6 @@ class _HomePageState extends State<HomePage> {
_loadUnreadMessages();
_messageTimer = Timer.periodic(const Duration(seconds: 30), (_) {
_loadUnreadMessages();
if (_allSessions.isNotEmpty) {
_loadCorrectionTaskCount(_allSessions);
}
});
}
@ -122,7 +118,6 @@ class _HomePageState extends State<HomePage> {
sessionsResult.fromCache || batches.any((item) => item.fromCache);
_loading = false;
});
unawaited(_loadCorrectionTaskCount(sessionsResult.data));
} on ApiException catch (error) {
if (!mounted) return;
setState(() {
@ -172,9 +167,7 @@ class _HomePageState extends State<HomePage> {
userName: userName,
roleSummary: roleSummary,
unreadMessages: _unreadMessages,
correctionTaskCount: _correctionTaskCount,
onMessages: _openMessages,
onCorrections: _openCorrections,
onResults: chiefSessions.isNotEmpty ? _openResults : null,
onLogout: _logout,
),
@ -209,6 +202,11 @@ class _HomePageState extends State<HomePage> {
padding: const EdgeInsets.only(bottom: 16),
child: _TaskCard(
task: entry.$2,
sessionDisplayOrder: RemoteScoringAdapter
.sessionDisplayOrder(
_remoteTasks[entry.$1].session,
_remoteTasks[entry.$1].entry,
),
roleLabel:
RemoteScoringAdapter.roleLabelForSession(
_remoteTasks[entry.$1].session,
@ -332,41 +330,6 @@ class _HomePageState extends State<HomePage> {
if (mounted) setState(() {});
}
Future<void> _openCorrections() async {
final entryId = await Get.toNamed(
AppRoutes.corrections,
arguments: _sessions,
);
if (!mounted) return;
await _loadTasks();
if (!mounted || entryId is! String) return;
final index = _remoteTasks.indexWhere(
(item) => item.entry.sessionEntryId == entryId,
);
if (index >= 0) {
await _openTask(index, _remoteTasks[index], correction: true);
} else {
await _openCorrectionTask(entryId);
}
}
Future<void> _loadCorrectionTaskCount(List<JudgeSession> sessions) async {
try {
final batches = await Future.wait(
sessions.map(
(session) => _api.loadCorrectionCandidates(session.sessionId),
),
);
final count = batches
.expand((items) => items)
.where((item) => item.isAssignedTask)
.length;
if (mounted) setState(() => _correctionTaskCount = count);
} on ApiException {
// Badge refresh failure must not block the scoring task list.
}
}
Future<void> _openResults() async {
await Get.toNamed(AppRoutes.results, arguments: _chiefSessions);
}
@ -696,9 +659,7 @@ class _TopBar extends StatelessWidget {
required this.userName,
required this.roleSummary,
required this.unreadMessages,
required this.correctionTaskCount,
required this.onMessages,
required this.onCorrections,
required this.onResults,
required this.onLogout,
});
@ -707,9 +668,7 @@ class _TopBar extends StatelessWidget {
final String userName;
final String roleSummary;
final int unreadMessages;
final int correctionTaskCount;
final VoidCallback onMessages;
final VoidCallback onCorrections;
final VoidCallback? onResults;
final VoidCallback onLogout;
@ -762,19 +721,7 @@ class _TopBar extends StatelessWidget {
),
),
const SizedBox(width: 18),
Badge(
isLabelVisible: correctionTaskCount > 0,
label: Text(
correctionTaskCount > 99 ? '99+' : '$correctionTaskCount',
),
child: IconButton.outlined(
onPressed: onCorrections,
tooltip: '成绩修正任务',
icon: const Icon(Icons.edit_note_rounded, size: 21),
),
),
if (onResults != null) ...[
const SizedBox(width: 8),
IconButton.outlined(
onPressed: onResults,
tooltip: '场次成绩',
@ -944,6 +891,7 @@ class _PageHeading extends StatelessWidget {
class _TaskCard extends StatelessWidget {
const _TaskCard({
required this.task,
required this.sessionDisplayOrder,
required this.roleLabel,
required this.status,
required this.isCurrent,
@ -951,6 +899,7 @@ class _TaskCard extends StatelessWidget {
required this.onTap,
});
final ScoringTask task;
final int sessionDisplayOrder;
final String roleLabel;
final String status;
final bool isCurrent;
@ -1050,7 +999,7 @@ class _TaskCard extends StatelessWidget {
),
const SizedBox(height: 3),
Text(
'#${task.displayOrder}',
'#${sessionDisplayOrder.toString().padLeft(2, '0')}',
style: TextStyle(
color: color,
fontSize: 14,

View File

@ -220,6 +220,63 @@ void main() {
expect(task.session, isNot(contains(task.project)));
expect(task.session, isNot(contains(task.groupName)));
});
test('任务卡场次号由编排起始场次和出场顺序计算', () {
final firstSession = _session(
id: 'session-1',
role: 'DJ1',
roleType: 'DJ',
arrangementOrder: 1,
);
final secondSession = _session(
id: 'session-2',
role: 'DJ1',
roleType: 'DJ',
arrangementOrder: 2,
);
const firstEntry = JudgeEntry(
sessionEntryId: 'entry-1',
entryNo: '01',
playOrder: 1,
participantName: '测试队',
groupName: '青年组',
entryStatus: 0,
isRematch: false,
scoreStatus: 0,
scoreStatusName: '待评分',
isDisqualified: false,
scoreSheetId: '',
);
const secondEntryInSameSession = JudgeEntry(
sessionEntryId: 'entry-2',
entryNo: '02',
playOrder: 2,
participantName: '测试队',
groupName: '青年组',
entryStatus: 0,
isRematch: false,
scoreStatus: 0,
scoreStatusName: '待评分',
isDisqualified: false,
scoreSheetId: '',
);
expect(
RemoteScoringAdapter.sessionDisplayOrder(firstSession, firstEntry),
1,
);
expect(
RemoteScoringAdapter.sessionDisplayOrder(secondSession, firstEntry),
2,
);
expect(
RemoteScoringAdapter.sessionDisplayOrder(
firstSession,
secondEntryInSameSession,
),
2,
);
});
}
JudgeSession _session({
@ -227,6 +284,7 @@ JudgeSession _session({
required String role,
required String roleType,
String roleName = '',
int arrangementOrder = 0,
}) => JudgeSession(
sessionId: id,
eventId: 'event-1',
@ -244,6 +302,7 @@ JudgeSession _session({
judgeRoleName: roleName,
entryCount: 2,
scoredCount: 0,
arrangementOrder: arrangementOrder,
);
JudgeScoreSheet _sheet({