diff --git a/.gitignore b/.gitignore index 3d52dec..8a33ba6 100644 --- a/.gitignore +++ b/.gitignore @@ -230,3 +230,4 @@ marking_app/lib/pages/homework_correction/widget/answer_handwriting.g.dart marking_app/lib/pages/report_detail/report_history.g.dart marking_app/lib/common/model/report/report_student_history_record.g.dart marking_app/lib/common/model/report/report_student_info.g.dart +marking_app/lib/common/model/marking/marking_exam_status_flag.g.dart diff --git a/marking_app/lib/common/model/marking/marking_exam_status_flag.dart b/marking_app/lib/common/model/marking/marking_exam_status_flag.dart new file mode 100644 index 0000000..916a67b --- /dev/null +++ b/marking_app/lib/common/model/marking/marking_exam_status_flag.dart @@ -0,0 +1,18 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'marking_exam_status_flag.g.dart'; + +@JsonSerializable() +class MarkingExamStatusFlag extends Object { + @JsonKey(name: 'markingUserDetailId') + int markingUserDetailId; + + @JsonKey(name: 'markingFlag') + int? markingFlag; + + MarkingExamStatusFlag({required this.markingUserDetailId, this.markingFlag}); + + factory MarkingExamStatusFlag.fromJson(Map srcJson) => _$MarkingExamStatusFlagFromJson(srcJson); + + Map toJson() => _$MarkingExamStatusFlagToJson(this); +} diff --git a/marking_app/lib/common/model/marking/marking_text_question.dart b/marking_app/lib/common/model/marking/marking_text_question.dart index a0c9d4a..150381e 100644 --- a/marking_app/lib/common/model/marking/marking_text_question.dart +++ b/marking_app/lib/common/model/marking/marking_text_question.dart @@ -6,8 +6,6 @@ * @FilePath: \marking_app\lib\common\model\marking\marking_text_question.dart * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ -import 'dart:convert'; - import 'package:json_annotation/json_annotation.dart'; import 'package:marking_app/common/model/marking/progress_of_marking.dart'; import 'package:marking_app/utils/image/gallery_example_item_model.dart'; @@ -57,6 +55,9 @@ class MarkingTextQuestion extends Object { // @JsonKey(name: 'currentIndex') // int currentIndex; + @JsonKey(name: 'markingFlag') // 试题状态 默认null 1:优秀 2:错误卷 + int? markingFlag; + @JsonKey(name: 'lastOne') bool lastOne; @@ -159,7 +160,6 @@ class MarkingTextQuestion extends Object { // return HistoricalScoring.fromJson(e as Map); // }).toList(); // } - // TODO 删除 // this.historicalScorings = [ // HistoricalScoring.fromJson({'scorel': 1.5, 'name': 'wy', 'markingUserld': 121321231313}), // HistoricalScoring.fromJson({'scorel': 5, 'name': '汪杨', 'markingUserld': 121321231313}) diff --git a/marking_app/lib/pages/marking/components/do_paper_bottom_review_marks.dart b/marking_app/lib/pages/marking/components/do_paper_bottom_review_marks.dart index 6e78354..070752d 100644 --- a/marking_app/lib/pages/marking/components/do_paper_bottom_review_marks.dart +++ b/marking_app/lib/pages/marking/components/do_paper_bottom_review_marks.dart @@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:marking_app/common/model/enum/review_marks_bottom_btns_enum.dart'; import 'package:marking_app/common/model/event_bus/bottom_annotation_switch_cleanall.dart'; +import 'package:marking_app/common/model/marking/marking_text_question.dart'; import 'package:marking_app/pages/common/event_bus_mixin.dart'; import 'package:marking_app/utils/anti_shake_throttling.dart'; import 'package:marking_app/utils/my_text.dart'; @@ -12,7 +13,9 @@ import '../provider/do_paper_bottom_review_marks_provider.dart'; // 底部批阅动作切换区域 class DoPaperBottomReviewMarks extends StatefulHookConsumerWidget { - const DoPaperBottomReviewMarks({super.key}); + final MarkingTextQuestion data; + final Function(int) examStatusCall; + const DoPaperBottomReviewMarks(this.data, this.examStatusCall, {super.key}); @override ConsumerState createState() => _DoPaperBottomReviewMarksState(); @@ -35,6 +38,9 @@ class _DoPaperBottomReviewMarksState extends ConsumerState 清空 - IconButton( - onPressed: () => easyThrottle( + // IconButton( + // onPressed: () => easyThrottle( + // 'REVIEW_MARKS_BOTTOM_BTNS', + // duration: const Duration(milliseconds: 100), + // () async { + // var resFlag = await showDialog( + // context: context, + // builder: (BuildContext context) { + // return CupertinoAlertDialog( + // title: quickText('撤销批阅痕迹', size: 14.sp, color: Color.fromARGB(255, 53, 52, 52)), + // content: SingleChildScrollView( + // padding: EdgeInsets.only(top: 4.h), + // child: RichText(text: TextSpan(text: '请确认需要撤销所有批阅痕迹?', style: TextStyle(color: Color.fromARGB(255, 58, 58, 58)))), + // ), + // actions: [ + // CupertinoDialogAction( + // child: Text("取消", style: TextStyle(color: Color.fromARGB(255, 58, 58, 58))), + // onPressed: () => Navigator.of(context).pop(false), + // ), + // CupertinoDialogAction( + // child: Text("确定"), + // onPressed: () => Navigator.of(context).pop(true), + // ), + // ], + // ); + // }, + // ); + // if (resFlag == true) eventFire(model: BottomAnnotationSwitchCleanallOfMarking(cleanAll: true)); + // }, + // ), + // padding: EdgeInsets.zero, + // icon: Icon(Icons.reply_all_outlined, color: btnEnum == ReviewMarksBottomBtnsEnum.CLEAR_ALL ? actionColor : Colors.white, size: 34.r), + // ), + GestureDetector( + onTap: () => easyThrottle( 'REVIEW_MARKS_BOTTOM_BTNS', duration: const Duration(milliseconds: 100), - () async { - var resFlag = await showDialog( - context: context, - builder: (BuildContext context) { - return CupertinoAlertDialog( - title: quickText('撤销批阅痕迹', size: 14.sp, color: Color.fromARGB(255, 53, 52, 52)), - content: SingleChildScrollView( - padding: EdgeInsets.only(top: 4.h), - child: RichText(text: TextSpan(text: '请确认需要撤销所有批阅痕迹?', style: TextStyle(color: Color.fromARGB(255, 58, 58, 58)))), - ), - actions: [ - CupertinoDialogAction( - child: Text("取消", style: TextStyle(color: Color.fromARGB(255, 58, 58, 58))), - onPressed: () => Navigator.of(context).pop(false), - ), - CupertinoDialogAction( - child: Text("确定"), - onPressed: () => Navigator.of(context).pop(true), - ), - ], - ); - }, - ); - if (resFlag == true) eventFire(model: BottomAnnotationSwitchCleanallOfMarking(cleanAll: true)); - }, + () async => widget.examStatusCall(1), + ), + child: quickText( + '优', + size: 23.sp, + fontWeight: FontWeight.bold, + color: markingFlag == 1 ? Theme.of(context).primaryColor : Colors.white, ), - padding: EdgeInsets.zero, - icon: Icon(Icons.reply_all_outlined, color: btnEnum == ReviewMarksBottomBtnsEnum.CLEAR_ALL ? actionColor : Colors.white, size: 34.r), ), + SizedBox(width: 5.w), + GestureDetector( + onTap: () => easyThrottle( + 'REVIEW_MARKS_BOTTOM_BTNS', + duration: const Duration(milliseconds: 100), + () async => widget.examStatusCall(2), + ), + child: quickText( + '错', + size: 23.sp, + fontWeight: FontWeight.bold, + color: markingFlag == 2 ? Theme.of(context).primaryColor : Colors.white, + ), + ), + // IconButton( + // onPressed: () => easyThrottle( + // 'REVIEW_MARKS_BOTTOM_BTNS', + // duration: const Duration(milliseconds: 100), + // () async {}, + // ), + // padding: EdgeInsets.zero, + // icon: Icon(Icons.reply_all_outlined, color: btnEnum == ReviewMarksBottomBtnsEnum.CLEAR_ALL ? actionColor : Colors.white, size: 34.r), + // ), ], ), ), diff --git a/marking_app/lib/pages/marking/do_papers.dart b/marking_app/lib/pages/marking/do_papers.dart index 7990c7f..1b114a2 100644 --- a/marking_app/lib/pages/marking/do_papers.dart +++ b/marking_app/lib/pages/marking/do_papers.dart @@ -31,9 +31,11 @@ import 'package:marking_app/common/model/enum/KeyboardType.dart'; import 'package:marking_app/common/model/enum/marking_list_type.dart'; import 'package:marking_app/common/model/enum/review_marks_bottom_btns_enum.dart'; import 'package:marking_app/common/model/event_bus/bottom_annotation_switch_cleanall.dart'; +import 'package:marking_app/common/model/job/upload_file_interface_config_params.dart'; import 'package:marking_app/common/model/marking/current_review_task.dart'; import 'package:marking_app/common/model/marking/do_marking_keyboard_model.dart'; import 'package:marking_app/common/model/marking/keyboard_assist_event.dart'; +import 'package:marking_app/common/model/marking/marking_exam_status_flag.dart'; import 'package:marking_app/common/model/marking/marking_tag_single_params.dart'; import 'package:marking_app/common/model/marking/marking_text_question.dart'; import 'package:marking_app/common/model/marking/marking_text_question_params.dart'; @@ -312,6 +314,13 @@ class _MarkingPapersState extends ConsumerState ); } + Future toMarkingFlag(int markingUserDetailId, int? markingFlag) async { + // toMarkingFlag + var _client = await getClient(); + var res = await _client.toMarkingFlag(MarkingExamStatusFlag(markingUserDetailId: markingUserDetailId, markingFlag: markingFlag)); + if (res.success) toUpState(setState, () => currentQuestion?.markingFlag = markingFlag, mounted); + } + // 查看答案 void viewAnswer() async { String? questionNum = currentQuestion?.questionNum; @@ -1933,7 +1942,7 @@ class _MarkingPapersState extends ConsumerState }, ), ), - + $ExamStatusBox(data), // 试卷状态 // 大题评分展示框 if (!hasSubtopic) Positioned( @@ -1953,10 +1962,7 @@ class _MarkingPapersState extends ConsumerState data.completeRating ? getDoubleRemoveZero(data.score) : '请评分,满分${getDoubleRemoveZero(currentQuestion?.totalScore)}', - style: TextStyle( - fontSize: 18.sp, - color: const Color.fromRGBO(46, 91, 255, 1), - ), + style: TextStyle(fontSize: 18.sp, color: const Color.fromRGBO(46, 91, 255, 1)), ), ), ), @@ -2002,7 +2008,10 @@ class _MarkingPapersState extends ConsumerState ), ), // 底部批阅痕迹按钮 - DoPaperBottomReviewMarks(), + DoPaperBottomReviewMarks(data, (e) async { + // 试卷状态切换 + await toMarkingFlag(data.id, data.markingFlag == e ? null : e); + }), // 下一题 按钮 if (!_theOldAnnotationGraffiti && pressedNextTest != null && isNormal) Positioned( @@ -2756,3 +2765,74 @@ Widget $arbitrationQuestionInfo({required bool show, required bool isBroadwise, ), ); } + +// 试卷状态 优秀卷 错误卷 默认卷 +@hwidget +Widget $examStatusBox(MarkingTextQuestion? data) { + ValueNotifier markingFlag = useState(data?.markingFlag ?? 0); + + useValueChanged(data?.markingFlag, (oldValue, oldResult) { + markingFlag.value = data?.markingFlag ?? 0; + }); + + if (data == null || data.markingFlag == null || markingFlag.value == 0) return Container(); + + var _strVal = markingFlag.value == 1 ? '优' : '错'; + return Positioned( + top: 60.h, + left: 4.w, + child: CustomPaint( + painter: CircleWithText(_strVal), + size: Size(90.r, 90.r), // 设置你需要的尺寸 + ), + // Container( + // padding: EdgeInsets.symmetric(horizontal: 6.w, vertical: 10.h), + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(100.r), + // border: Border.all(width: 10.r, color: Colors.red), + // ), + // child: quickText(markingFlag.value == 1 ? '优秀' : '错误'), + // ), + ); +} + +class CircleWithText extends CustomPainter { + final String textVal; + const CircleWithText(this.textVal); + @override + void paint(Canvas canvas, Size size) { + final paint = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = 5.r + ..color = Colors.red.withOpacity(0.8); + + // 绘制红色圆圈边框 + final radius = size.width / 2; // 假设宽高相等,取宽度的一半作为半径 + canvas.drawCircle(Offset(size.width / 2, size.height / 2), radius, paint); + + // 绘制“优”字 + final textSpan = TextSpan(text: textVal, style: TextStyle(color: Colors.red.withOpacity(0.8), fontWeight: FontWeight.bold, fontSize: 44.sp)); + + final textPainter = + TextPainter(text: TextSpan(children: [textSpan]), textDirection: TextDirection.ltr, textAlign: TextAlign.center, textScaleFactor: 1.0); + + // 只设置maxWidth,因为TextPainter.layout不需要maxHeight + textPainter.layout(maxWidth: size.width); + + // 计算文本绘制的偏移量,使其居中 + final offset = Offset( + (size.width - textPainter.width) / 2, + (size.height - textPainter.height) / 2, + ); + + // 注意:这里textPainter.height可能不准确,因为TextPainter默认不会自动换行 + // 如果需要精确控制文本在圆中的位置,可能需要手动调整偏移量 + + textPainter.paint(canvas, offset); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return oldDelegate != this; + } +} diff --git a/marking_app/lib/utils/request/rest_client.dart b/marking_app/lib/utils/request/rest_client.dart index a6a81d8..b7362dc 100644 --- a/marking_app/lib/utils/request/rest_client.dart +++ b/marking_app/lib/utils/request/rest_client.dart @@ -41,6 +41,7 @@ import 'package:marking_app/common/model/job/review_again_list_params.dart'; import 'package:marking_app/common/model/job/upload_file_interface_config.dart'; import 'package:marking_app/common/model/job/upload_file_interface_config_params.dart'; import 'package:marking_app/common/model/marking/marking_abnormal_res.dart'; +import 'package:marking_app/common/model/marking/marking_exam_status_flag.dart'; import 'package:marking_app/common/model/marking/marking_item.dart'; import 'package:marking_app/common/model/marking/marking_list_params.dart'; import 'package:marking_app/common/model/marking/marking_statistics.dart'; @@ -194,6 +195,9 @@ abstract class RestClient { @the_retrofit.GET("/api/Upload") Future> getMarkingUploadFile(@the_retrofit.Queries() UploadFileInterfaceConfigParams params); + // 阅卷 => 上传图片请求参数 + @the_retrofit.PUT("/api/marking/flag") + Future toMarkingFlag(@the_retrofit.Body() MarkingExamStatusFlag params); // ------------------------------------------ 作业 ------------------------------------------ // 作业 => 作业列表