feat: 优化评分确认弹窗与表演赛表现布局

提交确认仅展示评分类别与录入说明,隐藏裁判总分和小项得分;表演赛表现裁判采用失误与表现左右双栏布局;补充提交确认弹窗组件测试。
This commit is contained in:
ltx 2026-09-24 10:06:45 +08:00
parent 8f95150f17
commit 116096aa51
3 changed files with 54 additions and 120 deletions

View File

@ -99,10 +99,7 @@ class _ScoringPageState extends State<ScoringPage> with WidgetsBindingObserver {
return;
}
final correctionSubmission = controller.isCorrectionMode.value;
final score = controller.currentJudgeScore;
final confirmed = await showSubmitConfirmation(
score: score,
scoreLabel: controller.currentJudgeScoreLabel,
details: _submissionScoreDetails(controller),
correctionMode: controller.isCorrectionMode.value,
);
@ -1134,7 +1131,8 @@ class _PerformancePanel extends StatelessWidget {
isPresentation &&
(controller.profile.competition == CompetitionKind.individual ||
controller.profile.competition == CompetitionKind.wheel ||
controller.profile.competition == CompetitionKind.doubleDutch);
controller.profile.competition == CompetitionKind.doubleDutch ||
controller.profile.competition == CompetitionKind.show);
final scoreRows = <Widget>[
...controller.performanceItems.entries.map((entry) {
if (isPresentation) {
@ -2410,8 +2408,6 @@ List<SubmissionScoreDetail> _submissionScoreDetails(
for (final category in controller.showDifficultyCategories)
SubmissionScoreDetail(
label: category,
value:
'${_formatScore(controller.showDifficultyCategorySubtotal(category))} 分',
description: _showDifficultyCountSummary(controller, category),
),
];
@ -2420,14 +2416,11 @@ List<SubmissionScoreDetail> _submissionScoreDetails(
for (final entry in controller.requiredElementCounts.entries)
SubmissionScoreDetail(
label: entry.key,
value: '${entry.value} 个',
description: '规定元素完成数量',
description: '规定元素完成数量:${entry.value} 个',
),
for (final entry in controller.difficultyCounts.entries)
SubmissionScoreDetail(
label: '${entry.key}级难度',
value:
'${_formatScore(controller.difficultySubtotal(entry.key, entry.value))} 分',
description: '记录数量:${entry.value}',
),
];
@ -2436,41 +2429,33 @@ List<SubmissionScoreDetail> _submissionScoreDetails(
for (final item in controller.performanceItems.keys)
SubmissionScoreDetail(
label: item,
value: '${controller.performanceCalculatedItemScore(item)} 分',
description:
'减 ${controller.performanceEffectiveMinusCount(item)} / 加 ${controller.performancePlusCount(item)}',
),
SubmissionScoreDetail(
label: '失误',
value: '${controller.performanceErrorCount.value} 次',
description: '计分时从五个表现类别各减去该次数',
description:
'已记录 ${controller.performanceErrorCount.value} 次,计分时从五个表现类别各减去该次数',
),
];
case ScoreRole.creative:
case ScoreRole.execution:
return [
for (final entry in controller.performanceItems.entries)
SubmissionScoreDetail(
label: entry.key,
value: '${_formatScore(entry.value)} 分',
description:
'本项满分 ${_formatScore(controller.performanceItemMaximum(entry.key))} 分',
),
SubmissionScoreDetail(label: entry.key, description: '评分项已完成录入'),
];
case ScoreRole.technical:
return [
for (final entry in controller.requiredElementCounts.entries)
SubmissionScoreDetail(
label: entry.key,
value: '${entry.value} 个',
description:
'规定元素 · Q=${controller.requiredElementFactor.value.toStringAsFixed(3)}',
description: '规定元素完成数量:${entry.value} 个',
),
for (final rule in controller.deductionRules)
SubmissionScoreDetail(
label: rule.key,
value: '${controller.deductionCounts[rule.key] ?? 0} 次',
description: rule.standard,
description:
'已记录 ${controller.deductionCounts[rule.key] ?? 0} 次 · ${rule.standard}',
),
];
}

View File

@ -7,14 +7,9 @@ import '../../../core/models/scoring_task.dart';
import '../../../core/network/api_models.dart';
class SubmissionScoreDetail {
const SubmissionScoreDetail({
required this.label,
required this.value,
required this.description,
});
const SubmissionScoreDetail({required this.label, required this.description});
final String label;
final String value;
final String description;
}
@ -241,24 +236,20 @@ class _PickerTitleLine extends StatelessWidget {
}
Future<bool?> showSubmitConfirmation({
required double score,
required String scoreLabel,
required List<SubmissionScoreDetail> details,
required bool correctionMode,
}) {
return Get.dialog<bool>(
_ScoringDialogFrame(
width: 960,
height: 720,
height: 620,
icon: correctionMode ? Icons.edit_document : Icons.task_alt_rounded,
title: correctionMode ? '确认提交修正' : '确认提交成绩',
subtitle: correctionMode
? '请核对当前裁判总分与全部评分类别,修正提交后将形成新的操作记录。'
: '请核对当前裁判总分与全部评分类别,确认后将锁定本场评分内容。',
? '请核对全部评分类别,修正提交后将形成新的操作记录。'
: '请核对全部评分类别,确认后将锁定本场评分内容。',
body: Column(
children: [
_SubmissionScoreSummary(score: score, scoreLabel: scoreLabel),
const SizedBox(height: 14),
Row(
children: [
const Icon(
@ -268,7 +259,7 @@ Future<bool?> showSubmitConfirmation({
),
const SizedBox(width: 8),
Text(
'评分明细(${details.length}项)',
'评分内容(${details.length}项)',
style: const TextStyle(
color: AppColors.textPrimary,
fontSize: 16,
@ -277,7 +268,7 @@ Future<bool?> showSubmitConfirmation({
),
const Spacer(),
const Text(
'请逐项确认后再提交',
'请逐项确认已完成录入',
style: TextStyle(color: AppColors.textSecondary, fontSize: 12),
),
],
@ -317,78 +308,6 @@ Future<bool?> showSubmitConfirmation({
);
}
class _SubmissionScoreSummary extends StatelessWidget {
const _SubmissionScoreSummary({
required this.score,
required this.scoreLabel,
});
final double score;
final String scoreLabel;
@override
Widget build(BuildContext context) => Container(
width: double.infinity,
height: 142,
padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 28),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [AppColors.primaryPale, Color(0xFFE7F1FF)],
),
border: Border.all(color: const Color(0xFFBCD1EE)),
borderRadius: BorderRadius.circular(14),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
scoreLabel,
style: const TextStyle(
color: AppColors.primaryDark,
fontSize: 14,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 2),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/images/score-left.png',
width: 34,
height: 50,
fit: BoxFit.contain,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
score.toStringAsFixed(2),
style: const TextStyle(
color: AppColors.primaryDark,
fontSize: 48,
height: 1,
fontWeight: FontWeight.w900,
),
),
),
Image.asset(
'assets/images/score-right.png',
width: 34,
height: 50,
fit: BoxFit.contain,
),
],
),
const SizedBox(height: 2),
const Text(
'评分数据与记录画板 PNG 将一并保存',
style: TextStyle(color: AppColors.textSecondary, fontSize: 12),
),
],
),
);
}
class _SubmissionDetailCard extends StatelessWidget {
const _SubmissionDetailCard({required this.detail});
@ -426,15 +345,6 @@ class _SubmissionDetailCard extends StatelessWidget {
),
),
),
const SizedBox(width: 8),
Text(
detail.value,
style: const TextStyle(
color: AppColors.primary,
fontSize: 16,
fontWeight: FontWeight.w900,
),
),
],
),
const SizedBox(height: 7),

View File

@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
import 'package:yd_pattern_scoring_system/modules/scoring/widgets/scoring_dialogs.dart';
void main() {
tearDown(Get.reset);
testWidgets('提交确认弹窗仅展示评分类别和录入说明,不展示裁判得分', (tester) async {
await tester.pumpWidget(
GetMaterialApp(
home: Scaffold(
body: Builder(
builder: (context) => TextButton(
onPressed: () => showSubmitConfirmation(
correctionMode: false,
details: const [
SubmissionScoreDetail(label: '音乐', description: '减 1 / 加 2'),
SubmissionScoreDetail(label: '完成质量', description: '评分项已完成录入'),
],
),
child: const Text('打开'),
),
),
),
),
);
await tester.tap(find.text('打开'));
await tester.pumpAndSettle();
expect(find.text('确认提交成绩'), findsOneWidget);
expect(find.text('评分内容(2项)'), findsOneWidget);
expect(find.text('音乐'), findsOneWidget);
expect(find.text('完成质量'), findsOneWidget);
expect(find.textContaining('裁判总分'), findsNothing);
expect(find.textContaining('本次裁判得分'), findsNothing);
});
}