diff --git a/lib/modules/scoring/views/scoring_page.dart b/lib/modules/scoring/views/scoring_page.dart index 440840a..c8d40ba 100644 --- a/lib/modules/scoring/views/scoring_page.dart +++ b/lib/modules/scoring/views/scoring_page.dart @@ -1295,6 +1295,8 @@ class _PerformancePanel extends StatelessWidget { final value = await showScorePicker( current: entry.value, maximum: itemMaximum, + // 规定赛创意与完成质量评分允许为 0,需支持清零后正常提交。 + includeZero: true, ); if (value != null) { controller.setPerformance(entry.key, value); diff --git a/lib/modules/scoring/widgets/scoring_dialogs.dart b/lib/modules/scoring/widgets/scoring_dialogs.dart index be6e028..4c6e059 100644 --- a/lib/modules/scoring/widgets/scoring_dialogs.dart +++ b/lib/modules/scoring/widgets/scoring_dialogs.dart @@ -21,9 +21,12 @@ class SubmissionScoreDetail { Future showScorePicker({ required double current, required int maximum, + bool includeZero = false, }) { - var selected = current.round().clamp(1, maximum); - final rowCount = (maximum / 5).ceil(); + final minimum = includeZero ? 0 : 1; + var selected = current.round().clamp(minimum, maximum); + final itemCount = maximum - minimum + 1; + final rowCount = (itemCount / 5).ceil(); final dialogHeight = (285 + rowCount * 58).clamp(420, 650).toDouble(); return Get.dialog( StatefulBuilder( @@ -101,9 +104,9 @@ Future showScorePicker({ crossAxisSpacing: 20, mainAxisExtent: itemExtent, ), - itemCount: maximum, + itemCount: itemCount, itemBuilder: (context, index) { - final value = index + 1; + final value = index + minimum; final active = value == selected; return InkWell( onTap: () => diff --git a/test/api_models_test.dart b/test/api_models_test.dart index 783e2c8..9ef3ce2 100644 --- a/test/api_models_test.dart +++ b/test/api_models_test.dart @@ -142,9 +142,14 @@ void main() { itemCode: 'CQ_ACCURACY', inputValue: 18.5, ); + const zeroScore = JudgeScoreItemInput( + itemCode: 'CQ_ACCURACY', + inputValue: 0, + ); const count = JudgeScoreItemInput(itemCode: 'T_FAILURE', countValue: 2); expect(score.toJson(), {'itemCode': 'CQ_ACCURACY', 'inputValue': 18.5}); + expect(zeroScore.toJson(), {'itemCode': 'CQ_ACCURACY', 'inputValue': 0.0}); expect(count.toJson(), {'itemCode': 'T_FAILURE', 'countValue': 2.0}); expect(score.toJson(), isNot(contains('totalScore'))); }); diff --git a/test/scoring_dialogs_test.dart b/test/scoring_dialogs_test.dart new file mode 100644 index 0000000..bca2048 --- /dev/null +++ b/test/scoring_dialogs_test.dart @@ -0,0 +1,21 @@ +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() { + testWidgets('规定赛评分选择器可以选择并返回 0 分', (tester) async { + Get.testMode = true; + await tester.pumpWidget(const GetMaterialApp(home: Scaffold())); + + final result = showScorePicker(current: 0, maximum: 20, includeZero: true); + await tester.pumpAndSettle(); + + expect(find.text('0'), findsOneWidget); + await tester.tap(find.text('0')); + await tester.tap(find.text('确定')); + await tester.pumpAndSettle(); + + expect(await result, 0); + }); +}