From 9517df9b0e880243459f2dd2414893f3f6e229a4 Mon Sep 17 00:00:00 2001 From: "1147192855@qq.com" <1147192855@qq.com> Date: Tue, 18 Jun 2024 10:17:04 +0800 Subject: [PATCH] no message --- .../lib/common/api/retrofit_client.dart | 11 + .../do_paper_details_result.dart | 23 +- .../review_submission_params.dart | 2 +- .../common/utils/upload_oss_img_utils.dart | 19 + .../components/question_paper_view.dart | 344 +++++++++++------- .../configuration_files/index.dart | 75 +++- .../children/homework_review/index.dart | 1 - making_school_asignment_app/pubspec.yaml | 2 + 8 files changed, 334 insertions(+), 143 deletions(-) create mode 100644 making_school_asignment_app/lib/common/utils/upload_oss_img_utils.dart diff --git a/making_school_asignment_app/lib/common/api/retrofit_client.dart b/making_school_asignment_app/lib/common/api/retrofit_client.dart index f8c0ad6..3d7e1f9 100644 --- a/making_school_asignment_app/lib/common/api/retrofit_client.dart +++ b/making_school_asignment_app/lib/common/api/retrofit_client.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:dio/dio.dart' hide Headers; import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_param.dart'; import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_result.dart'; @@ -123,4 +125,13 @@ abstract class RetrofitClient { // 批阅提交 @POST("/api/hms/Annotate/AnnotateSubmit") Future reviewSubmission(@Body() ReviewSubmissionParams param); + + // OSS 上传key + @GET("/api/infra/Oss/GetPresignedUri") + Future getOssPresignedUri(@Query('key') String key); + + // OSS 图片上传 + @PUT('{theUrl}') + @Headers({'Content-Type': ''}) + Future uploadImag(@Path() String theUrl, @Part() File file); } diff --git a/making_school_asignment_app/lib/common/job/marking_models/do_paper_details_result.dart b/making_school_asignment_app/lib/common/job/marking_models/do_paper_details_result.dart index 5403889..b5e18ff 100644 --- a/making_school_asignment_app/lib/common/job/marking_models/do_paper_details_result.dart +++ b/making_school_asignment_app/lib/common/job/marking_models/do_paper_details_result.dart @@ -1,6 +1,7 @@ import 'package:get/get.dart'; import 'package:get/get_connect/http/src/request/request.dart'; import 'package:json_annotation/json_annotation.dart'; +import 'package:making_school_asignment_app/common/config/request_config.dart'; part 'do_paper_details_result.g.dart'; @@ -39,12 +40,19 @@ class DoPaperDetailsResult extends Object { @JsonKey(name: 'zgtAnswer') // 主观题作答图片 String zgtAnswer; - @JsonKey(name: 'zgtAnnotate') // 主观题批注图片 + @JsonKey(name: 'showZgtAnnotate') // 主观题老师批注图片 + String? showZgtAnnotate; + + @JsonKey(name: 'zgtAnnotate') // 主观题老师批注图片 String? zgtAnnotate; - @JsonKey(name: 'lastAnswerTime') + @JsonKey(name: 'lastAnswerTime') // 学生提交作答试题时间 String lastAnswerTime; + // 批注时间 + @JsonKey(name: 'annotateTime') + String? annotateTime; + @JsonKey(name: 'isFav') bool isFav; @@ -78,6 +86,8 @@ class DoPaperDetailsResult extends Object { this.templateIdKeys, this.templateIdKeyMap, this.priority, + this.annotateTime, + this.showZgtAnnotate, ) { if (templateIds.keys.isNotEmpty) { templateIdKeys = templateIds.keys.map((e) => int.parse(e)).toList(); @@ -94,6 +104,15 @@ class DoPaperDetailsResult extends Object { var currentStudent = students.firstWhereOrNull((e) => e.id == studentId); if (currentStudent != null) priority = currentStudent.isPriority; } + zgtAnswer = '${RequestConfig.imgUrl}$zgtAnswer?$lastAnswerTime'; + + if (zgtAnnotate?.isNotEmpty ?? false) { + showZgtAnnotate = RequestConfig.imgUrl + zgtAnnotate!; // 批注图片地址赋值 + if (annotateTime != null) showZgtAnnotate = '${showZgtAnnotate!}?$annotateTime'; + } + + print('学生作答图片:${zgtAnswer}'); + print('老师批注图片:${showZgtAnnotate}'); } factory DoPaperDetailsResult.fromJson(Map srcJson) => _$DoPaperDetailsResultFromJson(srcJson); diff --git a/making_school_asignment_app/lib/common/job/marking_models/review_submission_params.dart b/making_school_asignment_app/lib/common/job/marking_models/review_submission_params.dart index 7f45794..33611a2 100644 --- a/making_school_asignment_app/lib/common/job/marking_models/review_submission_params.dart +++ b/making_school_asignment_app/lib/common/job/marking_models/review_submission_params.dart @@ -16,7 +16,7 @@ class ReviewSubmissionParams extends Object { @JsonKey(name: 'studentScores') List studentScores; - @JsonKey(name: 'pictureBytes') + @JsonKey(name: 'zgtAnnotate') String? zgtAnnotate; ReviewSubmissionParams({ diff --git a/making_school_asignment_app/lib/common/utils/upload_oss_img_utils.dart b/making_school_asignment_app/lib/common/utils/upload_oss_img_utils.dart new file mode 100644 index 0000000..415379f --- /dev/null +++ b/making_school_asignment_app/lib/common/utils/upload_oss_img_utils.dart @@ -0,0 +1,19 @@ +import '../mixins/request_tool_mixin.dart'; + +// OSS 图片上传 +class UploadOssImgUtils with RequestToolMixin { + static UploadOssImgUtils? _singleton; + static UploadOssImgUtils getInstance() => _singleton ??= UploadOssImgUtils._internal(); + + UploadOssImgUtils._internal(); + + Future getPresignedUri(String key) async { + var res = await getClient().getOssPresignedUri(key); + print(res); + } + + String setImgKey(String homeworkId, String studentId, String templateId) { + // $"hms-annotate/{input.HomeworkId}/{input.StudentId}/{input.TemplateId}.png"6月12日 13:54 + return 'hms-annotate/$homeworkId/$studentId/$templateId.png'; + } +} diff --git a/making_school_asignment_app/lib/page/home_page/children/homework_review/components/question_paper_view.dart b/making_school_asignment_app/lib/page/home_page/children/homework_review/components/question_paper_view.dart index 70e5bad..f37a0e9 100644 --- a/making_school_asignment_app/lib/page/home_page/children/homework_review/components/question_paper_view.dart +++ b/making_school_asignment_app/lib/page/home_page/children/homework_review/components/question_paper_view.dart @@ -47,7 +47,7 @@ class _QuestionPaperViewState extends State { return Stack( children: [ // 主图 - QuestionImageView(maxWidth, maxHeight, sateData, annotationState), + QuestionImageView(maxWidth, maxHeight, sateData, annotationState, logic), // 继续批阅按钮 Positioned(right: 3.w, bottom: 4.h, child: const $ContinueToReview(isFloatingAction: true)), // 上一题按钮 @@ -183,86 +183,85 @@ Widget $scoringQuestionsView(BuildContext context, StudentQuestions item, double }, []); var padinVal = item.correctRate > 0 ? EdgeInsets.only(top: 6.4.h) : EdgeInsets.symmetric(vertical: 2.h); return Container( - height: item.height * scaleRatio, - padding: EdgeInsets.zero, - child: Stack( - alignment: const FractionalOffset(0, 0), - children: [ - Container( - color: Colors.yellow, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // 对 - Expanded( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - padding: EdgeInsets.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - backgroundColor: const Color.fromRGBO(237, 237, 237, 1), // 设置背景色 - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), // 去除圆角 - ), - child: Padding( - padding: padinVal, - child: Icon( - size: 22.sp, - color: studentScore.value == 2 ? const Color.fromRGBO(255, 152, 0, 1) : const Color.fromRGBO(114, 114, 114, 1), - const IconData(0xe62b, fontFamily: "AlibabaIcon"), - ), - ), - onPressed: () => easyThrottle('scoring_homework_questions', () { - studentScore.value = studentScore.value == 2 ? null : 2; - }), + height: item.height * scaleRatio, + padding: EdgeInsets.zero, + child: Stack( + alignment: const FractionalOffset(0, 0), + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 对 + Expanded( + child: ElevatedButton( + style: ElevatedButton.styleFrom( + padding: EdgeInsets.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + backgroundColor: const Color.fromRGBO(237, 237, 237, 1), // 设置背景色 + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), // 去除圆角 + ), + child: Padding( + padding: padinVal, + child: Icon( + size: 22.sp, + color: studentScore.value == 2 ? const Color.fromRGBO(255, 152, 0, 1) : const Color.fromRGBO(114, 114, 114, 1), + const IconData(0xe62b, fontFamily: "AlibabaIcon"), ), ), - // 半 - Expanded( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - padding: EdgeInsets.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - backgroundColor: const Color.fromRGBO(237, 237, 237, 1), // 设置背景色 - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), // 去除圆角 - ), - child: Padding( - padding: padinVal, - child: Icon( - size: 22.sp, - color: studentScore.value == 1 ? const Color.fromRGBO(255, 152, 0, 1) : const Color.fromRGBO(114, 114, 114, 1), - const IconData(0xe62c, fontFamily: "AlibabaIcon"), - ), - ), - onPressed: () => easyThrottle('scoring_homework_questions', () { - studentScore.value = studentScore.value == 1 ? null : 1; - }), - ), - ), - // 错 - Expanded( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - padding: EdgeInsets.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - backgroundColor: const Color.fromRGBO(237, 237, 237, 1), // 设置背景色 - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), // 去除圆角 - ), - child: Padding( - padding: padinVal, - child: Icon( - size: 22.sp, - color: studentScore.value == 0 ? const Color.fromRGBO(255, 152, 0, 1) : const Color.fromRGBO(114, 114, 114, 1), - const IconData(0xe62a, fontFamily: "AlibabaIcon"), - ), - ), - onPressed: () => easyThrottle('scoring_homework_questions', () { - studentScore.value = studentScore.value == 0 ? null : 0; - }), - ), - ), - ], + onPressed: () => easyThrottle('scoring_homework_questions', () { + studentScore.value = studentScore.value == 2 ? null : 2; + }), + ), ), - ), - Row( + // 半 + Expanded( + child: ElevatedButton( + style: ElevatedButton.styleFrom( + padding: EdgeInsets.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + backgroundColor: const Color.fromRGBO(237, 237, 237, 1), // 设置背景色 + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), // 去除圆角 + ), + child: Padding( + padding: padinVal, + child: Icon( + size: 22.sp, + color: studentScore.value == 1 ? const Color.fromRGBO(255, 152, 0, 1) : const Color.fromRGBO(114, 114, 114, 1), + const IconData(0xe62c, fontFamily: "AlibabaIcon"), + ), + ), + onPressed: () => easyThrottle('scoring_homework_questions', () { + studentScore.value = studentScore.value == 1 ? null : 1; + }), + ), + ), + // 错 + Expanded( + child: ElevatedButton( + style: ElevatedButton.styleFrom( + padding: EdgeInsets.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + backgroundColor: const Color.fromRGBO(237, 237, 237, 1), // 设置背景色 + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), // 去除圆角 + ), + child: Padding( + padding: padinVal, + child: Icon( + size: 22.sp, + color: studentScore.value == 0 ? const Color.fromRGBO(255, 152, 0, 1) : const Color.fromRGBO(114, 114, 114, 1), + const IconData(0xe62a, fontFamily: "AlibabaIcon"), + ), + ), + onPressed: () => easyThrottle('scoring_homework_questions', () { + studentScore.value = studentScore.value == 0 ? null : 0; + }), + ), + ), + ], + ), + IgnorePointer( + // 事件穿透 + child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox(width: 1.1.w), @@ -281,18 +280,21 @@ Widget $scoringQuestionsView(BuildContext context, StudentQuestions item, double ), ) ], - ) - ], - )); + ), + ), + ], + ), + ); } // 试题图片视图 class QuestionImageView extends HookWidget with EventBusMixin { final double maxWidth; final double maxHeight; + final HomeworkReviewLogic logic; final HomeworkReviewState sateData; final HomeworkReviewAnnotationsControlState annotationState; - QuestionImageView(this.maxWidth, this.maxHeight, this.sateData, this.annotationState, {super.key}); + QuestionImageView(this.maxWidth, this.maxHeight, this.sateData, this.annotationState, this.logic, {super.key}); /// 获取数组指定倒数具体值的下标 int _findTargetIndex(List list, T target, [int reciprocal = 2]) { @@ -311,6 +313,15 @@ class QuestionImageView extends HookWidget with EventBusMixin>([]); + useEffect(() { + var listenStream = sateData.data.listen((e) { + // 数据清空 + sateData.handwritings = []; + vnHandWritings.value = sateData.handwritings; + }); + return () => listenStream.cancel(); + }, []); + ImageStream? imageStream; var imageStreamListener = useState(ImageStreamListener((ImageInfo info, bool _) { WidgetsBinding.instance.addPostFrameCallback((_) { @@ -335,24 +346,66 @@ class QuestionImageView extends HookWidget with EventBusMixin( context: context, builder: (context1) { - return AlertDialog(content: quickText("是否撤销上次批阅批注痕迹"), actions: [ + return AlertDialog(content: quickText("是否撤销全部批注痕迹?"), actions: [ TextButton(child: quickText("取消"), onPressed: () => Navigator.pop(context1, false)), TextButton(child: quickText("确定", color: Theme.of(context).primaryColor), onPressed: () => Navigator.pop(context1, true)) ]); }, ); if (res == true) vnHandWritings.value = []; + } else { + // 数据已经是空了 检查是否有上次批注图片 如果有就弹框询问清除 + if (sateData.data.value?.showZgtAnnotate != null) { + await showDialog( + context: context, + builder: (context1) { + return AlertDialog(content: quickText("是否撤销上次批阅批注痕迹?"), actions: [ + TextButton(child: quickText("取消"), onPressed: () => Navigator.pop(context1, false)), + TextButton( + child: quickText("确定", color: Theme.of(context).primaryColor), + onPressed: () { + Navigator.pop(context1, true); + sateData.data.value?.zgtAnnotate = null; + sateData.data.value?.showZgtAnnotate = null; + }, + ) + ]); + }, + ); + } } return; } // 返回上一步 - var index = _findTargetIndex(annotationsData, null); - if (index != -1) { - annotationsData = annotationsData.sublist(0, index + 1); - annotationsData = List.from(annotationsData); + if (annotationsData.isEmpty) { + // 数据已经是空了 检查是否有上次批注图片 如果有就弹框询问清除 + if (sateData.data.value?.showZgtAnnotate != null) { + await showDialog( + context: context, + builder: (context1) { + return AlertDialog(content: quickText("是否撤销上次批阅批注痕迹?"), actions: [ + TextButton(child: quickText("取消"), onPressed: () => Navigator.pop(context1, false)), + TextButton( + child: quickText("确定", color: Theme.of(context).primaryColor), + onPressed: () { + Navigator.pop(context1, true); + sateData.data.value?.zgtAnnotate = null; + sateData.data.value?.showZgtAnnotate = null; + }, + ) + ]); + }, + ); + } } else { - annotationsData = []; + var index = _findTargetIndex(annotationsData, null); + if (index != -1) { + annotationsData = annotationsData.sublist(0, index + 1); + annotationsData = List.from(annotationsData); + } else { + annotationsData = []; + } } vnHandWritings.value = annotationsData; }); @@ -373,63 +426,80 @@ class QuestionImageView extends HookWidget with EventBusMixin sateData.panQuestView = true, - child: SingleChildScrollView( - controller: scrollControllerQuestion, - physics: !annotationState.pen.value ? const BouncingScrollPhysics() : const NeverScrollableScrollPhysics(), - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, // 设置垂直滚动 - child: Container( - decoration: BoxDecoration( - boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.2), offset: Offset(-6.r, 1.r), blurRadius: 10.r, spreadRadius: 8.r)]), - child: Listener( - behavior: HitTestBehavior.opaque, - onPointerUp: (PointerUpEvent details) { - // 处理单个触摸点抬起的逻辑 - // activePointers--; - // globalPosition = null; - var imageScale = sateData.imageScale.value; - if (imageScale == null || !annotationState.pen.value) return; - vnHandWritings.value.add(null); // 增加空点以分隔不同的线段 - }, - onPointerMove: (PointerMoveEvent event) { - var imageScale = sateData.imageScale.value; - if (imageScale == null || !annotationState.pen.value) return; - Offset localPosition = event.localPosition; - var dy = localPosition.dy; - if (dy > imageScale.actualImgHeight || dy < 0) return; // 检查笔记是否超出图片范围 + return GestureDetector( + onPanDown: (_) => sateData.panQuestView = true, + child: SingleChildScrollView( + controller: scrollControllerQuestion, + physics: !annotationState.pen.value ? const BouncingScrollPhysics() : const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + scrollDirection: Axis.vertical, // 设置垂直滚动 + child: Container( + decoration: BoxDecoration( + boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.2), offset: Offset(-6.r, 1.r), blurRadius: 10.r, spreadRadius: 8.r)]), + child: Listener( + behavior: HitTestBehavior.opaque, + onPointerUp: (PointerUpEvent details) { + // 处理单个触摸点抬起的逻辑 + // activePointers--; + // globalPosition = null; + var imageScale = sateData.imageScale.value; + if (imageScale == null || !annotationState.pen.value) return; + vnHandWritings.value.add(null); // 增加空点以分隔不同的线段 + sateData.handwritings = vnHandWritings.value; // 添加笔迹数据 + }, + onPointerMove: (PointerMoveEvent event) { + var imageScale = sateData.imageScale.value; + if (imageScale == null || !annotationState.pen.value) return; + Offset localPosition = event.localPosition; + var dy = localPosition.dy; + if (dy > imageScale.actualImgHeight || dy < 0) return; // 检查笔记是否超出图片范围 - vnHandWritings.value = List.from(vnHandWritings.value)..add(localPosition); - }, - child: RepaintBoundary( - child: CustomPaint( - foregroundPainter: DrawingPainter(ctrl: vnHandWritings), - child: RepaintBoundary( - child: $TheCachedNetworkImage( - (context, imageProvider) { - Image imageWidget = Image(image: imageProvider, fit: BoxFit.fitWidth); - imageStream?.removeListener(imageStreamListener.value); - imageStream = imageWidget.image.resolve(const ImageConfiguration())..addListener(imageStreamListener.value); - return imageWidget; - }, - imageUrl: RequestConfig.imgUrl + imageUrl, + vnHandWritings.value = List.from(vnHandWritings.value)..add(localPosition); + sateData.handwritings = vnHandWritings.value; + }, + child: Stack( + children: [ + $TheCachedNetworkImage( + imageUrl: imageUrl, + (context, imageProvider) { + Image imageWidget = Image(image: imageProvider, fit: BoxFit.fitWidth); + imageStream?.removeListener(imageStreamListener.value); + imageStream = imageWidget.image.resolve(const ImageConfiguration())..addListener(imageStreamListener.value); + return imageWidget; + }, + ), + RepaintBoundary( + key: logic.pictureOverviewKey, + child: CustomPaint( + foregroundPainter: DrawingPainter(ctrl: vnHandWritings), + size: Size( + sateData.imageScale.value?.actualImgWidth ?? 0, + sateData.imageScale.value?.actualImgHeight ?? 0, ), + child: showZgtAnnotate != null + ? $TheCachedNetworkImage( + imageUrl: showZgtAnnotate, + (_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth), + ) + : null, ), ), - ), + ], ), ), ), - ); - })); + ), + ); + }), + ); } } diff --git a/making_school_asignment_app/lib/page/home_page/children/homework_review/configuration_files/index.dart b/making_school_asignment_app/lib/page/home_page/children/homework_review/configuration_files/index.dart index 17060db..f66fa0f 100644 --- a/making_school_asignment_app/lib/page/home_page/children/homework_review/configuration_files/index.dart +++ b/making_school_asignment_app/lib/page/home_page/children/homework_review/configuration_files/index.dart @@ -1,7 +1,12 @@ import 'dart:async'; -import 'dart:convert'; +import 'dart:io'; +import 'dart:ui' as ui; + +import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_param.dart'; import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_result.dart'; @@ -9,6 +14,7 @@ import 'package:making_school_asignment_app/common/job/marking_models/do_test_qu import 'package:making_school_asignment_app/common/job/marking_models/review_submission_params.dart'; import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart'; import 'package:making_school_asignment_app/common/utils/toast_utils.dart'; +import 'package:making_school_asignment_app/common/utils/upload_oss_img_utils.dart'; import 'package:making_school_asignment_app/page/global_widget/my_text.dart'; // 数据 @@ -23,6 +29,7 @@ class HomeworkReviewState { late Rx slide; // 滑动位置 late bool? panQuestView; late Rx imageScale; + List handwritings = []; // late String dateEnd = ''; // late int knowledgeId = 0; @@ -48,6 +55,7 @@ class HomeworkReviewBinding extends Bindings { } class HomeworkReviewLogic extends GetxController with RequestToolMixin { + final GlobalKey pictureOverviewKey = GlobalKey(); late StreamSubscription _paramListen; late StreamSubscription _dataListen; final HomeworkReviewState state = HomeworkReviewState(); @@ -92,6 +100,7 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin { // item.topHeight = itemPre.height; // } state.data.value = data; + state.handwritings = []; state.studentQuestions.value = data.studentQuestions; } finally { if (timerControl.isActive) timerControl.cancel(); @@ -140,11 +149,63 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin { await submit(context); } + // 上传图片 + Future saveImage(context) async { + if (state.handwritings.isEmpty) return null; + try { + var data = state.data.value; + var param = state.param.value; + if (data == null) return null; + + // 获取OSS 图片url + String imgKey = UploadOssImgUtils.getInstance().setImgKey(param.homeworkId, data.studentId.toString(), data.templateId.toString()); + var resUrl = await getClient().getOssPresignedUri(imgKey); + if (resUrl == null) return null; + + // 没有图片就上传图片 + RenderRepaintBoundary? boundary = pictureOverviewKey.currentContext!.findRenderObject() as RenderRepaintBoundary?; + if (boundary == null) return null; + // double dpr = MediaQuery.of(context).devicePixelRatio; + + double pixelRatio = MediaQuery.of(context).devicePixelRatio; + var imageScale = state.imageScale.value; + if (imageScale != null) { + // 还原图片原始比例 + pixelRatio = imageScale.imageWidth / imageScale.boxWidth; + } + + ui.Image image = await boundary.toImage(pixelRatio: pixelRatio); + ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png); + if (byteData == null) return null; + + Dio dio = Dio(); + dio.options.contentType = null; + List bytes = byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes); + await dio.put( + resUrl, + data: Stream.fromIterable(bytes.map((e) => [e])), + options: Options(contentType: null, headers: {Headers.contentLengthHeader: bytes.length}), + ); + + // var res = await getClient().uploadImag(resUrl, file); + + return imgKey; + } catch (e) { + print('图片上传失败'); + print(e.toString()); + ToastUtils.getFluttertoast(msg: '图片上传失败', context: context); + } finally { + // ToastUtils.dismiss(); + } + return null; + } + // 提交打分 /// allPairs Future submit(BuildContext context) async { var data = state.data.value; if (data == null) return; + if (state.data.value?.studentQuestions.isEmpty ?? true) return; var studentQuestions = state.data.value!.studentQuestions; var noRatingElement = studentQuestions.firstWhereOrNull((e) => e.studentScore == null); @@ -152,12 +213,19 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin { ToastUtils.showInfo('${noRatingElement.questionNo}题请评分'); return; } + + // 图片上传 + String? zgtAnnotate = state.data.value?.zgtAnnotate; + String? newzgtAnnotate = await saveImage(context); + if (newzgtAnnotate != null) zgtAnnotate = newzgtAnnotate; + // TODO 请求提交加载框是否需要 如何防止重复提交 await getClient() .reviewSubmission(ReviewSubmissionParams( homeworkId: state.param.value.homeworkId, templateId: data.templateId, studentId: data.studentId, + zgtAnnotate: zgtAnnotate, studentScores: studentQuestions.map((e) { var studentScore = e.studentScore!; return StudentScores( @@ -191,7 +259,10 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin { ); return; } - state.param.value = DoPaperDetailsParam.fromJson(state.param.value.toJson()); + var newParams = DoPaperDetailsParam.fromJson(state.param.value.toJson()); + newParams.templateId = null; + newParams.studentId = null; + state.param.value = newParams; }); } } diff --git a/making_school_asignment_app/lib/page/home_page/children/homework_review/index.dart b/making_school_asignment_app/lib/page/home_page/children/homework_review/index.dart index 1e9068c..9984046 100644 --- a/making_school_asignment_app/lib/page/home_page/children/homework_review/index.dart +++ b/making_school_asignment_app/lib/page/home_page/children/homework_review/index.dart @@ -26,7 +26,6 @@ class _HomeworkReviewState extends State { @override void initState() { WidgetsFlutterBinding.ensureInitialized(); - // SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown]); super.initState(); } diff --git a/making_school_asignment_app/pubspec.yaml b/making_school_asignment_app/pubspec.yaml index 8d38353..265d6dc 100644 --- a/making_school_asignment_app/pubspec.yaml +++ b/making_school_asignment_app/pubspec.yaml @@ -83,6 +83,8 @@ dependencies: flutter_hooks: ^0.20.5 flutter_spinkit: ^5.2.1 event_bus: ^2.0.0 + path_provider: ^2.1.3 + uuid: ^3.0.7 dev_dependencies: flutter_test: