diff --git a/making_school_asignment_app/android/gradle/wrapper/gradle-wrapper.properties b/making_school_asignment_app/android/gradle/wrapper/gradle-wrapper.properties index c288d7a..a28a56b 100644 --- a/making_school_asignment_app/android/gradle/wrapper/gradle-wrapper.properties +++ b/making_school_asignment_app/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-7.6.3-all.zip +distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-7.6.3-all.zip \ No newline at end of file diff --git a/making_school_asignment_app/lib/common/utils/utils.dart b/making_school_asignment_app/lib/common/utils/utils.dart index 27bb5e6..21de0ed 100644 --- a/making_school_asignment_app/lib/common/utils/utils.dart +++ b/making_school_asignment_app/lib/common/utils/utils.dart @@ -181,9 +181,7 @@ class Utils { stu.noAnswerCount = data.dtls.where((w) => w.state == 0 && stu.studentId == w.studentId).length; List ques = data.questions; - stu.queDtls = data.dtls - .where((w) => w.studentId == stu.studentId && ques.indexWhere((q) => w.templateId == q.templateId && w.questionNo == q.questionNo) > -1) - .toList(); + stu.queDtls = data.dtls.where((w) => w.studentId == stu.studentId && ques.indexWhere((q) => w.templateId == q.templateId && w.questionNo == q.questionNo) > -1).toList(); int okCount = stu.queDtls!.where((w) => w.state == 3).length; int ttlCount = stu.queDtls!.length; stu.okRate = Utils.calcRate(okCount, ttlCount); @@ -291,23 +289,26 @@ class Utils { } static DateTime getWeekStartDate() { + // DateTime now = DateTime.now(); + // int dayOfWeek = now.weekday; // 获取今天是周几(1代表周一,7代表周日) + // int diff = dayOfWeek - 1; // 计算今天距离周一的天数差 + // if (diff < 0) { + // diff += 7; // 如果是周日,则需要加上一周的天数 + // } + // return now.subtract(Duration(days: diff)); // 减去天数差,得到本周一的时间 DateTime now = DateTime.now(); - int dayOfWeek = now.weekday; // 获取今天是周几(1代表周一,7代表周日) - int diff = dayOfWeek - 1; // 计算今天距离周一的天数差 - if (diff < 0) { - diff += 7; // 如果是周日,则需要加上一周的天数 - } - return now.subtract(Duration(days: diff)); // 减去天数差,得到本周一的时间 + return now.subtract(const Duration(days: 6)); } static DateTime getWeekEndDate() { - DateTime now = DateTime.now(); - int dayOfWeek = now.weekday; // 获取今天是周几 - int diff = 7 - dayOfWeek; // 计算今天距离周日的天数差 - if (diff == 0) { - diff = 7; // 如果是周日,则加上一周的天数 - } - return now.add(Duration(days: diff)); // 加上天数差减一,得到本周日的时间 + // DateTime now = DateTime.now(); + // int dayOfWeek = now.weekday; // 获取今天是周几 + // int diff = 7 - dayOfWeek; // 计算今天距离周日的天数差 + // if (diff == 0) { + // diff = 7; // 如果是周日,则加上一周的天数 + // } + // return now.add(Duration(days: diff)); // 加上天数差减一,得到本周日的时间 + return DateTime.now(); } } diff --git a/making_school_asignment_app/lib/main.dart b/making_school_asignment_app/lib/main.dart index f9443b9..b670e13 100644 --- a/making_school_asignment_app/lib/main.dart +++ b/making_school_asignment_app/lib/main.dart @@ -52,8 +52,10 @@ class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. + @override Widget build(BuildContext context) { + // String? oldRouter; return ScreenUtilInit( designSize: const Size(AppConfig.UI_WIDTH, AppConfig.UI_HEIGHT), /* minTextAdapt: true, @@ -87,6 +89,13 @@ class MyApp extends StatelessWidget { // systemStatusBarContrastEnforced: false, // )); // } + + // if (Routes.reviewHomework == currentRouter) { + // // SystemChrome.setEnabledSystemUIMode(SystemUiMode.leanBack, overlays: []); + // } else if (oldRouter == Routes.reviewHomework) { + // // SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]); // 屏幕刘海 + // } + // oldRouter = currentRouter; }, // 这里是国际化支持,确保添加flutter_localizations依赖 supportedLocales: const [ @@ -106,7 +115,7 @@ class MyApp extends StatelessWidget { return locale; }, //默认专场动画 - defaultTransition: Transition.fade, + defaultTransition: getTransition(), //初始化路由页面 initialRoute: Routes.startPage, diff --git a/making_school_asignment_app/lib/page/home_page/children/annotate_class/widget/annotate_item.dart b/making_school_asignment_app/lib/page/home_page/children/annotate_class/widget/annotate_item.dart index e3c7a66..4a96f36 100644 --- a/making_school_asignment_app/lib/page/home_page/children/annotate_class/widget/annotate_item.dart +++ b/making_school_asignment_app/lib/page/home_page/children/annotate_class/widget/annotate_item.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart'; import 'package:making_school_asignment_app/page/global_widget/show_student_list.dart'; import 'package:percent_indicator/percent_indicator.dart'; import 'package:making_school_asignment_app/common/job/annotated_class.dart'; @@ -81,6 +83,7 @@ class _AnnotateItemState extends State { ), ); } + void showStudentList(context, List students, [bool submitted = false]) async { showDialog( context: context, @@ -89,12 +92,13 @@ class _AnnotateItemState extends State { title: '${widget.item.className ?? ''} ${submitted ? '已提交' : '未提交'}作业学生', studentList: students, homeworkId: widget.homeworkId, - subject:widget.logic.state.subject, + subject: widget.logic.state.subject, ); }, ); EasyLoading.dismiss(); } + @override Widget build(BuildContext context) { AnnotatedClass itemData = widget.item; @@ -118,7 +122,7 @@ class _AnnotateItemState extends State { ), const Spacer(), InkWell( - onTap: (){ + onTap: () { EasyLoading.show(status: 'loading...'); showStudentList(context, widget.item.commitStudent!, true); }, @@ -131,7 +135,7 @@ class _AnnotateItemState extends State { width: 20.r, ), InkWell( - onTap: (){ + onTap: () { EasyLoading.show(status: 'loading...'); showStudentList(context, widget.item.noCommitStudent!, true); }, @@ -158,12 +162,7 @@ class _AnnotateItemState extends State { title: "收藏夹${widget.item.homeworkFavs.isNotEmpty ? '(${widget.item.homeworkFavs.length})' : ''}", font: widget.font - 2.sp, clickFunction: () { - Get.toNamed(Routes.favStudentPage, arguments: { - 'homeworkName': widget.name, - 'classId': widget.item.classId, - 'homeworkId': widget.logic.state.homeworkId.value, - 'grade': widget.item.grade - }); + Get.toNamed(Routes.favStudentPage, arguments: {'homeworkName': widget.name, 'classId': widget.item.classId, 'homeworkId': widget.logic.state.homeworkId.value, 'grade': widget.item.grade}); }, ), ), @@ -211,12 +210,7 @@ class _AnnotateItemState extends State { title: "收藏夹${widget.item.homeworkFavs.isNotEmpty ? '(${widget.item.homeworkFavs.length})' : ''}", font: widget.font - 2.sp, clickFunction: () { - Get.toNamed(Routes.favStudentPage, arguments: { - 'homeworkName': widget.name, - 'classId': widget.item.classId, - 'homeworkId': widget.logic.state.homeworkId.value, - 'grade': widget.item.grade - }); + Get.toNamed(Routes.favStudentPage, arguments: {'homeworkName': widget.name, 'classId': widget.item.classId, 'homeworkId': widget.logic.state.homeworkId.value, 'grade': widget.item.grade}); }, ), ), @@ -224,16 +218,14 @@ class _AnnotateItemState extends State { ), ), Padding( - padding: EdgeInsets.only(top: 10.r,left: 14.r,right: 14.r), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - quickText('批阅进度', size: widget.font - 2.sp, color: const Color(0xFF8E8E8E)), - quickText('${widget.item.annotateRate}%', size: widget.font + 10.sp, color: const Color(0xFF464646)) - ], - ),), + padding: EdgeInsets.only(top: 10.r, left: 14.r, right: 14.r), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [quickText('批阅进度', size: widget.font - 2.sp, color: const Color(0xFF8E8E8E)), quickText('${widget.item.annotateRate}%', size: widget.font + 10.sp, color: const Color(0xFF464646))], + ), + ), Padding( - padding: EdgeInsets.only(top: 0.r, left: 14.r,right: 14.r,bottom: 10.r), + padding: EdgeInsets.only(top: 0.r, left: 14.r, right: 14.r, bottom: 10.r), child: LinearPercentIndicator( padding: EdgeInsets.zero, animation: true, @@ -247,9 +239,9 @@ class _AnnotateItemState extends State { colors: widget.item.annotateRate / 100 != 1 ? [Theme.of(context).primaryColor.withOpacity(0.1), Theme.of(context).primaryColor] : [ - const Color.fromRGBO(144, 224, 190, 1).withOpacity(0.1), - const Color.fromRGBO(144, 224, 190, 1), - ], + const Color.fromRGBO(144, 224, 190, 1).withOpacity(0.1), + const Color.fromRGBO(144, 224, 190, 1), + ], ), // linearStrokeCap: LinearStrokeCap.butt, // progressColor: Theme.of(context).primaryColor, @@ -257,27 +249,9 @@ class _AnnotateItemState extends State { barRadius: Radius.circular(10.r), ), ), - ProgressBar( - title: '客观题正确率:', - color: const Color(0xFFADDCA5), - percent: widget.item.kgtCorrectRate / 100, - marginEdg: EdgeInsets.zero, - padingEdg: EdgeInsets.only(top: 8.h, left: 14.r, right: 14.r), - fontSize: widget.font - 2.sp), - ProgressBar( - title: '主观题正确率:', - color: const Color(0xFFADDCA5), - percent: widget.item.zgtCorrectRate / 100, - padingEdg: EdgeInsets.symmetric(horizontal: 10.r), - marginEdg: EdgeInsets.only(top: 8.h), - fontSize: widget.font - 2.sp), - ProgressBar( - title: '总正确率:', - color: const Color(0xFFADDCA5), - percent: widget.item.correctRate / 100, - padingEdg: EdgeInsets.symmetric(horizontal: 10.r), - marginEdg: EdgeInsets.only(top: 8.h), - fontSize: widget.font - 2.sp), + ProgressBar(title: '客观题正确率:', color: const Color(0xFFADDCA5), percent: widget.item.kgtCorrectRate / 100, marginEdg: EdgeInsets.zero, padingEdg: EdgeInsets.only(top: 8.h, left: 14.r, right: 14.r), fontSize: widget.font - 2.sp), + ProgressBar(title: '主观题正确率:', color: const Color(0xFFADDCA5), percent: widget.item.zgtCorrectRate / 100, padingEdg: EdgeInsets.symmetric(horizontal: 10.r), marginEdg: EdgeInsets.only(top: 8.h), fontSize: widget.font - 2.sp), + ProgressBar(title: '总正确率:', color: const Color(0xFFADDCA5), percent: widget.item.correctRate / 100, padingEdg: EdgeInsets.symmetric(horizontal: 10.r), marginEdg: EdgeInsets.only(top: 8.h), fontSize: widget.font - 2.sp), Container( margin: EdgeInsets.only(top: 10.r), decoration: BoxDecoration( @@ -302,10 +276,8 @@ class _AnnotateItemState extends State { widget.logic.goQuickDataCheck(widget.item); }, child: Container( - padding:EdgeInsets.symmetric(vertical:10.r), - decoration: BoxDecoration( - border: Border(right: BorderSide(width: 1.r,color:const Color.fromRGBO(221, 221, 221, 1) )) - ), + padding: EdgeInsets.symmetric(vertical: 10.r), + decoration: BoxDecoration(border: Border(right: BorderSide(width: 1.r, color: const Color.fromRGBO(221, 221, 221, 1)))), alignment: Alignment.center, child: quickText('数据快查', color: const Color.fromRGBO(118, 118, 118, 1), size: widget.font), ), @@ -326,20 +298,27 @@ class _AnnotateItemState extends State { : [ Expanded( child: InkWell( - onTap: () { - print('批阅..........'); - Get.toNamed(Routes.reviewHomework, arguments: { - 'homeworkId': widget.homeworkId, - 'homeworkName': widget.name, - 'classId': itemData.classId, - 'subject': widget.logic.state.subject, + onTap: () => easyThrottle('TO_GO_REVIEWHOMEWORK', () { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.leanBack, overlays: []).then((_) { + WidgetsBinding.instance.addPostFrameCallback((_) { + Get.toNamed(Routes.reviewHomework, arguments: { + 'homeworkId': widget.homeworkId, + 'homeworkName': widget.name, + 'classId': itemData.classId, + 'subject': widget.logic.state.subject, + }); + }); }); - }, + // Get.toNamed(Routes.reviewHomework, arguments: { + // 'homeworkId': widget.homeworkId, + // 'homeworkName': widget.name, + // 'classId': itemData.classId, + // 'subject': widget.logic.state.subject, + // }); + }), child: Container( - padding:EdgeInsets.symmetric(vertical:10.r), - decoration: BoxDecoration( - border: Border(right: BorderSide(width: 1.r,color:const Color.fromRGBO(221, 221, 221, 1) )) - ), + padding: EdgeInsets.symmetric(vertical: 10.r), + decoration: BoxDecoration(border: Border(right: BorderSide(width: 1.r, color: const Color.fromRGBO(221, 221, 221, 1)))), alignment: Alignment.center, child: quickText('批阅', color: const Color.fromRGBO(118, 118, 118, 1), size: widget.font), ), @@ -348,7 +327,7 @@ class _AnnotateItemState extends State { // Container(width: 1.w, height: 30.h, color: const Color.fromRGBO(221, 221, 221, 1)), Expanded( child: InkWell( - onTap: () async{ + onTap: () async { var confim = await confirmDialog('当前批阅任务未完成,请确认需要结束此任务?'); if (confim) { widget.logic.getOverAnnotate(widget.item.classId); diff --git a/making_school_asignment_app/lib/page/home_page/children/homework_review/components/dropdown_switch_students_type.dart b/making_school_asignment_app/lib/page/home_page/children/homework_review/components/dropdown_switch_students_type.dart index ac02830..9fb8651 100644 --- a/making_school_asignment_app/lib/page/home_page/children/homework_review/components/dropdown_switch_students_type.dart +++ b/making_school_asignment_app/lib/page/home_page/children/homework_review/components/dropdown_switch_students_type.dart @@ -269,7 +269,8 @@ Widget $historyHomework(BuildContext context) { if (studentId == null || (sateData.value?.students.isEmpty ?? true)) return; var currentStudent = sateData.value!.students.firstWhereOrNull((e) => e.id == studentId); if (currentStudent == null) return; - Get.toNamed(Routes.studentWorkDetailPage, arguments: {'studentId': studentId, 'studentName': currentStudent.name}); + var theState = Get.find().state; + Get.toNamed(Routes.studentWorkDetailPage, arguments: {'studentId': studentId, 'studentName': currentStudent.name,'subject':theState.param.value.subject}); }), child: Row( crossAxisAlignment: CrossAxisAlignment.center, diff --git a/making_school_asignment_app/lib/page/home_page/children/homework_review/components/question_number_view.dart b/making_school_asignment_app/lib/page/home_page/children/homework_review/components/question_number_view.dart new file mode 100644 index 0000000..ed7c1fc --- /dev/null +++ b/making_school_asignment_app/lib/page/home_page/children/homework_review/components/question_number_view.dart @@ -0,0 +1,270 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:functional_widget_annotation/functional_widget_annotation.dart'; +import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_result.dart'; +import 'package:making_school_asignment_app/common/job/marking_models/do_test_questions_image_info.dart'; +import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart'; +import 'package:making_school_asignment_app/page/global_widget/my_text.dart'; +import 'package:percent_indicator/linear_percent_indicator.dart'; + +import '../configuration_files/index.dart'; +import '../configuration_files/zoom_logic.dart'; + +part 'question_number_view.g.dart'; + +/// 试题题号 +class QuestionNumberView extends GetView { + const QuestionNumberView({super.key}); + + HomeworkReviewState get sateData => controller.state; + ZoomState get sateZoomData => controller.zoomLogic.zoomState; + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + height: double.infinity, + decoration: const BoxDecoration(color: Color.fromRGBO(159, 159, 159, 0.97)), + child: GestureDetector( + onPanDown: (_) => sateData.panQuestView = false, + child: Obx(() { + var zoomFile = sateZoomData.zoomFile.value; + if (zoomFile == null) return const SizedBox(); + + var studentQuestions = sateData.studentQuestions.value ?? []; + + return $QuestionNumberScrollView( + controller:controller, + sateData: sateData, + sateZoomData: sateZoomData, + studentQuestions: studentQuestions, + ); + }), + ), + ); + } +} + +// 试题题号视图 +@hwidget +Widget $questionNumberScrollView({ + required HomeworkReviewLogic controller, + required ZoomState sateZoomData, + required HomeworkReviewState sateData, + required List studentQuestions, +}) { + final scrollControllerNum = useScrollController(); // 试题题号区域 + var useZoom = useState(sateZoomData.initScale.value ?? 1); + var usePiddingTop = useState(sateZoomData.zoomFile.value?.imageHeightOffsetStart ?? 0); + useValueChanged(sateZoomData.zoomFile.value?.imageHeightOffsetStart, (_, __) { + usePiddingTop.value = sateZoomData.zoomFile.value?.imageHeightOffsetStart ?? 0; + }); + useEffect(() { + var stream = sateZoomData.initScale.listen((e) { + // print("initScale : $e"); + useZoom.value = e ?? 1; + var zoomFile = sateZoomData.zoomFile.value; + if (zoomFile?.actualHeight == null) return; + + // print(zoomFile?.toJson()); + // print("缩放基数:${useZoom.value}"); + // print("图片实际高度:${zoomFile!.actualHeight! * useZoom.value}"); + // print("视图剩余高度:${zoomFile.viewHeight - (zoomFile.actualHeight! * useZoom.value)}"); + // var topDistance = (zoomFile!.viewHeight - (zoomFile.actualHeight! * useZoom.value)) / 2; + var topDistance = zoomFile!.getZoomFileOffsetStart(useZoom.value); + // print("视图剩余高度/2:${max(0, topDistance)}"); + // 使用 max 函数确保 topDistance 不小于 0 + usePiddingTop.value = max(0, topDistance); + }); + + return () { + stream.cancel(); + }; + }, []); + + var actualImgHeight = useState(sateZoomData.zoomFile.value?.actualHeight); + useValueChanged(sateZoomData.zoomFile.value?.actualHeight, (_, __) { + actualImgHeight.value = sateZoomData.zoomFile.value?.actualHeight ?? 0; + }); + + useEffect(() { + scrollControllerNum.addListener(() { + if (sateData.panQuestView == false) sateData.slide.value = scrollControllerNum.offset; + }); + var listenVal = sateData.slide.listen((e) { + if (sateData.panQuestView != null && sateData.panQuestView == true && e != scrollControllerNum.offset) { + print("进来了试题题号视图"); + scrollControllerNum.jumpTo(e); + } + }); + + return () { + listenVal.cancel(); + }; + }, []); + + // var actualImgHeight = useImageInfo.value?.actualImgHeight ?? 0; // 实际图片高度 + + // print("图片高度:$actualImgHeight"); + + print("数据长度:${studentQuestions.length}"); + print("FFFFFFFFF ${usePiddingTop.value}"); + + return SingleChildScrollView( + controller: scrollControllerNum, + physics: const BouncingScrollPhysics(), + padding: EdgeInsets.only(top: usePiddingTop.value > 0 ? usePiddingTop.value : 0), + scrollDirection: Axis.vertical, // 设置垂直滚动 + child: SizedBox( + height: (actualImgHeight.value ?? 0) * useZoom.value, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: studentQuestions + .map((e) => $ScoringQuestionsView( + studentQuestions, + e, + controller, + sateZoomData.zoomFile.value!.scaleRatio, + useZoom.value, + )) + .toList(), + ), + ), + ); +} + +// 单道题得分框 +@hwidget +Widget $scoringQuestionsView(BuildContext context, List? studentQuestions,StudentQuestions item, HomeworkReviewLogic logic, double scaleRatio, double initScale) { + var studentScore = useState(item.studentScore); + + useValueChanged(studentScore.value, (_, __) { + item.studentScore = studentScore.value; + + // 校验是否自动提交 对于已经批阅过的试题 不重复自动提交 + var annotateTime = logic.state.data.value?.annotateTime; + if (annotateTime == null) { + var noRatingGiven = studentQuestions!.firstWhereOrNull((e) => e.studentScore == null); + if (noRatingGiven == null) logic.submit(context); + } + }); + + useValueChanged(item, (_, __) { + studentScore.value = item.studentScore; + }); + + useEffect(() { + return () {}; + }, []); + var padinVal = item.correctRate > 0 ? EdgeInsets.only(top: 6.4.h) : EdgeInsets.symmetric(vertical: 2.h); + return Container( + height: item.height! * scaleRatio * initScale, + padding: EdgeInsets.zero, + child: item.useTime == 0 + ? Container() + : 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 ? Colors.green : const Color.fromRGBO(114, 114, 114, 1), + const IconData(0xe62b, fontFamily: "AlibabaIcon"), + ), + ), + onPressed: () => easyThrottle('scoring_homework_questions', () { + studentScore.value = studentScore.value == 2 ? null : 2; + }, duration: const Duration(milliseconds: 222)), + ), + ), + // 半 + 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 ? Colors.green : const Color.fromRGBO(114, 114, 114, 1), + const IconData(0xe62c, fontFamily: "AlibabaIcon"), + ), + ), + onPressed: () => easyThrottle('scoring_homework_questions', () { + studentScore.value = studentScore.value == 1 ? null : 1; + }, duration: const Duration(milliseconds: 222)), + ), + ), + // 错 + 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 ? Colors.green : const Color.fromRGBO(114, 114, 114, 1), + const IconData(0xe62a, fontFamily: "AlibabaIcon"), + ), + ), + onPressed: () => easyThrottle('scoring_homework_questions', () { + studentScore.value = studentScore.value == 0 ? null : 0; + }, duration: const Duration(milliseconds: 222)), + ), + ), + ], + ), + IgnorePointer( + // 事件穿透 + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(width: 1.1.w), + quickText(item.questionNo, color: Theme.of(context).primaryColor.withOpacity(0.7), size: 8.sp), + if (item.correctRate > 0) quickText(' 正确率', color: Colors.grey, size: 5.sp), + if (item.correctRate > 0) + Expanded( + child: LinearPercentIndicator( + lineHeight: 6.h, + percent: item.correctRate / 100, + barRadius: Radius.circular(1.2.r), + alignment: MainAxisAlignment.center, + progressColor: Theme.of(context).primaryColor, + backgroundColor: const Color(0xFFB8C7CB).withOpacity(0.35), + center: quickText("${item.correctRate}%", size: 5.sp, align: TextAlign.center, color: Colors.white), + ), + ) + ], + ), + ), + ], + ), + ); +} 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 633dc68..ed29b06 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 @@ -13,26 +13,23 @@ import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.d import 'package:making_school_asignment_app/common/utils/cached_network_img.dart'; import 'package:making_school_asignment_app/page/global_widget/my_text.dart'; import 'package:making_school_asignment_app/page/home_page/children/homework_review/configuration_files/index.dart'; -import 'package:percent_indicator/linear_percent_indicator.dart'; import 'package:zoom_widget/zoom_widget.dart'; import '../configuration_files/zoom_logic.dart'; +import 'question_number_view.dart'; part 'question_paper_view.g.dart'; -// 试题详情 - -class QuestionPaperView extends StatelessWidget { +// 试题详情视图 +class QuestionPaperView extends GetView { const QuestionPaperView({super.key}); + HomeworkReviewState get sateData => controller.state; + ZoomState get zoomState => controller.zoomLogic.zoomState; + HomeworkReviewAnnotationsControlState get annotationState => controller.annotationState; + @override Widget build(BuildContext context) { - final zoomLogic = Get.find(); - final zoomState = zoomLogic.zoomState; - final logic = Get.find(); - final sateData = logic.state; - final annotationState = logic.annotationState; - return Stack( children: [ Row( @@ -46,34 +43,23 @@ class QuestionPaperView extends StatelessWidget { if (zoomFileModel == null) { /// 计算高度 return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { - var maxWidth = constraints.maxWidth; - var maxHeight = constraints.maxHeight; - // var maxHeight = ScreenUtil().screenHeight - 95.h - logic.appBarHeight; // 1187.2356785851596 - // print("原始 视图的高度:${maxHeight1} $maxHeight ${MediaQuery.of(context).padding.top}"); - WidgetsBinding.instance.addPostFrameCallback((_) { - zoomState.zoomFile.value = ZoomFileModel(viewWidth: maxWidth, viewHeight: maxHeight); - }); - return SizedBox(); + WidgetsBinding.instance.addPostFrameCallback((_) => zoomState.zoomFile.value = ZoomFileModel( + viewWidth: constraints.maxWidth, + viewHeight: constraints.maxHeight, + )); + return const SizedBox(); }); - } else if (zoomFileModel.fileHeight == null) { - /// 文件未计算实际高度 - return SizedBox(); } + /// 文件未计算实际高度 + if (zoomFileModel.fileHeight == null) return const SizedBox(); + var maxWidth = zoomFileModel.viewWidth; var maxHeight = zoomFileModel.viewHeight; - print("文件的高度:${zoomFileModel.actualHeight!}"); return Stack( children: [ // 主图 - QuestionImageView( - maxWidth, - maxHeight, - sateData, - annotationState, - logic, - actualHeight: zoomFileModel.actualHeight!, - ), + QuestionImageView(maxWidth, maxHeight, annotationState, controller, zoomState: zoomState, sateData: sateData, actualHeight: zoomFileModel.actualHeight!), // 继续批阅按钮 // Positioned(right: 3.w, bottom: 4.h, child: const $ContinueToReview(isFloatingAction: true)), // 上一题按钮 @@ -129,26 +115,41 @@ class QuestionPaperView extends StatelessWidget { }), ), // 试题题号视图 - Expanded(flex: 2, child: $QuestionNumberView(logic, sateData)), + const Expanded(flex: 2, child: QuestionNumberView()), ], ), - Obx(() { - if (!sateData.getDataError.value) return const SizedBox(); - return Center( - child: CupertinoButton( - color: Colors.grey[300], - onPressed: () => easyThrottle('home_work_reload_data', () { - sateData.param.value = DoPaperDetailsParam.fromJson(sateData.param.value.toJson()); - }), - child: quickText('再次请求', color: Colors.black38), - ), - ); - }), + + /// 数据出错再次请求按钮 + const DataErrorThenRequestAgainButton(), ], ); } } +/// 数据出错再次请求按钮 +class DataErrorThenRequestAgainButton extends StatelessWidget { + const DataErrorThenRequestAgainButton({super.key}); + + @override + Widget build(BuildContext context) { + return GetBuilder(builder: (logic) { + final sateData = logic.state; + + if (!sateData.getDataError.value) return const SizedBox(); + + return Center( + child: CupertinoButton( + color: Colors.grey[300], + onPressed: () => easyThrottle('home_work_reload_data', () { + sateData.param.value = DoPaperDetailsParam.fromJson(sateData.param.value.toJson()); + }), + child: quickText('再次请求', color: Colors.black38), + ), + ); + }); + } +} + // 底部已阅数量和待阅数量 @swidget Widget $totalSubmitCountView(BuildContext context, HomeworkReviewState sateData) { @@ -249,250 +250,16 @@ Widget $totalSubmitCountView(BuildContext context, HomeworkReviewState sateData) }); } -@swidget -Widget $questionNumberView(BuildContext context, HomeworkReviewLogic logic, HomeworkReviewState sateData) { - return Obx(() { - var imageVal = sateData.imageScale.value; - if (imageVal == null) return const SizedBox(); - - var studentQuestions = sateData.studentQuestions.value ?? []; - - return Container( - height: double.infinity, - decoration: BoxDecoration( - color: const Color.fromRGBO(159, 159, 159, 0.97), - boxShadow: [BoxShadow(color: const Color.fromRGBO(46, 91, 255, 0.2), offset: Offset(0, 8.w), blurRadius: 1, spreadRadius: 2)], - ), - child: GestureDetector( - onPanDown: (_) => sateData.panQuestView = false, - child: $QuestionNumberScrollView( - logic: logic, - sateData: sateData, - imageVal: imageVal, - studentQuestions: studentQuestions, - ), - ), - ); - }); -} - -// 试题题号视图 -@hwidget -Widget $questionNumberScrollView( - BuildContext context, { - required HomeworkReviewLogic logic, - required HomeworkReviewState sateData, - required TestQuestionsImageInfo imageVal, - required List studentQuestions, -}) { - var boxHeight = imageVal.boxHeight; - final scrollControllerNum = useScrollController(); // 试题题号区域 - var usePiddingTop = useState(logic.state.imageScaleZoom.value?.imageHeightOffsetStart ?? 0); - var useImageInfo = useState(imageVal); - - // var initScale = useState(logic.state.initScale.value ?? 1); - - // useValueChanged(logic.state.initScale.value, (_, __) { - // initScale.value = logic.state.initScale.value ?? 1; - // print("变化了.......... ${initScale.value}"); - // }); - - useEffect(() { - scrollControllerNum.addListener(() { - if (sateData.panQuestView == false) sateData.slide.value = scrollControllerNum.offset; - }); - var listenVal = sateData.slide.listen((e) { - if (sateData.panQuestView != null && sateData.panQuestView == true && e != scrollControllerNum.offset) { - print("进来了试题题号视图"); - scrollControllerNum.jumpTo(e); - } - }); - - var stream = logic.state.imageScaleZoom.listen((e) { - useImageInfo.value = e; - usePiddingTop.value = e?.imageHeightOffsetStart ?? 0; - }); - - return () { - stream.cancel(); - listenVal.cancel(); - }; - }, []); - - var actualImgHeight = useImageInfo.value?.actualImgHeight ?? 0; // 实际图片高度 - - print("容器高度:$boxHeight"); - print("图片高度:$actualImgHeight"); - - print("数据长度:${studentQuestions.length}"); - return SingleChildScrollView( - controller: scrollControllerNum, - physics: const BouncingScrollPhysics(), - padding: EdgeInsets.zero, - scrollDirection: Axis.vertical, // 设置垂直滚动 - child: Container( - height: actualImgHeight, - margin: EdgeInsets.only(top: usePiddingTop.value > 0 ? usePiddingTop.value : 0), - color: Colors.red, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: studentQuestions - .asMap() - .keys - .map((e) => $ScoringQuestionsView( - logic, - studentQuestions[e], - imageVal.scaleRatio, - studentQuestions, - useImageInfo.value?.zoom ?? 1, - )) - .toList(), - ), - ), - ); -} - -// 单道题得分框 -@hwidget -Widget $scoringQuestionsView(BuildContext context, HomeworkReviewLogic logic, StudentQuestions item, double scaleRatio, - List? studentQuestions, double initScale) { - var studentScore = useState(item.studentScore); - - useValueChanged(studentScore.value, (_, __) { - item.studentScore = studentScore.value; - - // 校验是否自动提交 对于已经批阅过的试题 不重复自动提交 - var annotateTime = logic.state.data.value?.annotateTime; - if (annotateTime == null) { - var noRatingGiven = studentQuestions!.firstWhereOrNull((e) => e.studentScore == null); - if (noRatingGiven == null) logic.submit(context); - } - }); - - useValueChanged(item, (_, __) { - studentScore.value = item.studentScore; - }); - - useEffect(() { - return () {}; - }, []); - var padinVal = item.correctRate > 0 ? EdgeInsets.only(top: 6.4.h) : EdgeInsets.symmetric(vertical: 2.h); - return Container( - height: item.height! * scaleRatio * initScale, - padding: EdgeInsets.zero, - child: item.useTime == 0 - ? Container() - : 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 ? Colors.green : const Color.fromRGBO(114, 114, 114, 1), - const IconData(0xe62b, fontFamily: "AlibabaIcon"), - ), - ), - onPressed: () => easyThrottle('scoring_homework_questions', () { - studentScore.value = studentScore.value == 2 ? null : 2; - }, duration: const Duration(milliseconds: 222)), - ), - ), - // 半 - 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 ? Colors.green : const Color.fromRGBO(114, 114, 114, 1), - const IconData(0xe62c, fontFamily: "AlibabaIcon"), - ), - ), - onPressed: () => easyThrottle('scoring_homework_questions', () { - studentScore.value = studentScore.value == 1 ? null : 1; - }, duration: const Duration(milliseconds: 222)), - ), - ), - // 错 - 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 ? Colors.green : const Color.fromRGBO(114, 114, 114, 1), - const IconData(0xe62a, fontFamily: "AlibabaIcon"), - ), - ), - onPressed: () => easyThrottle('scoring_homework_questions', () { - studentScore.value = studentScore.value == 0 ? null : 0; - }, duration: const Duration(milliseconds: 222)), - ), - ), - ], - ), - IgnorePointer( - // 事件穿透 - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox(width: 1.1.w), - quickText('${item.questionNo}', color: Theme.of(context).primaryColor.withOpacity(0.7), size: 8.sp), - if (item.correctRate > 0) quickText(' 正确率', color: Colors.grey, size: 5.sp), - if (item.correctRate > 0) - Expanded( - child: LinearPercentIndicator( - lineHeight: 6.h, - percent: item.correctRate / 100, - barRadius: Radius.circular(1.2.r), - alignment: MainAxisAlignment.center, - progressColor: Theme.of(context).primaryColor, - backgroundColor: const Color(0xFFB8C7CB).withOpacity(0.35), - center: quickText("${item.correctRate}%", size: 5.sp, align: TextAlign.center, color: Colors.white), - ), - ) - ], - ), - ), - ], - ), - ); -} - // 试题图片视图 class QuestionImageView extends HookWidget with EventBusMixin { final double maxWidth; final double maxHeight; final double actualHeight; final HomeworkReviewLogic logic; + final ZoomState zoomState; final HomeworkReviewState sateData; final HomeworkReviewAnnotationsControlState annotationState; - QuestionImageView(this.maxWidth, this.maxHeight, this.sateData, this.annotationState, this.logic, {required this.actualHeight, super.key}); + QuestionImageView(this.maxWidth, this.maxHeight, this.annotationState, this.logic, {required this.actualHeight, required this.zoomState, required this.sateData, super.key}); /// 获取数组指定倒数具体值的下标 int _findTargetIndex(List list, T target, [int reciprocal = 2]) { @@ -506,28 +273,24 @@ class QuestionImageView extends HookWidget with EventBusMixin(maxHeight); - useValueChanged(maxHeight, (oldValue, __) => theMaxHeight.value = maxHeight); - // final imgActualHeight = useState(sateData.imageScale.value?.actualImgHeight); - // final scrollControllerQuestion = useScrollController(); // 试题图片区域 + + var zoomKey = useState(GlobalKey()); + useValueChanged(zoomState.zoomFile.value?.templateId, (old, __) { + zoomKey.value = GlobalKey(); + }); + var vnHandWritings = useValueNotifier>([]); /// 滑动高度 var initPosition = useState(null); - var customPaintSize = useState(Size.zero); - - // useValueChanged(sateData.imageScale.value?.actualImgHeight, (_, __) { - // imgActualHeight.value = sateData.imageScale.value?.actualImgHeight; - // }); + // var customPaintSize = useState(Size.zero); useEffect(() { var listenStream = sateData.data.listen((e) { @@ -535,17 +298,9 @@ class QuestionImageView extends HookWidget with EventBusMixin(ImageStreamListener((ImageInfo info, bool _) { - WidgetsBinding.instance.addPostFrameCallback((_) { - sateData.imageScale.value = TestQuestionsImageInfo( - templateId: sateData.data.value?.templateId, - boxWidth: maxWidth, - boxHeight: theMaxHeight.value, - imageWidth: info.image.width.toDouble(), - imageHeight: info.image.height.toDouble(), - url: sateData.data.value!.zgtAnswer, - ); - // print("这里的高度 ${theMaxHeight.value} $actualHeight ${sateData.imageScale.value?.actualImgHeight}"); - }); - })); - // 可选:添加滚动监听 useEffect(() { eventOn(callback: (BottomOperationBar e) async { @@ -582,12 +322,9 @@ class QuestionImageView extends HookWidget with EventBusMixin( - context: context, + context: Get.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)) - ]); + return AlertDialog(content: quickText("是否撤销全部批注痕迹?"), actions: [TextButton(child: quickText("取消"), onPressed: () => Navigator.pop(context1, false)), TextButton(child: quickText("确定", color: Theme.of(context1).primaryColor), onPressed: () => Navigator.pop(context1, true))]); }, ); if (res == true) vnHandWritings.value = []; @@ -648,100 +385,82 @@ class QuestionImageView extends HookWidget with EventBusMixin zoomState.zoomFile.value!.imageHeightOffsetend!) return; // 检查笔记是否超出图片范围 - var dy = localPosition.dy; - if (dy > imageScale.actualImgHeight || dy < 0) return; // 检查笔记是否超出图片范围 + // 说明:“- imageHeightOffsetStart” 由于显示笔记的位置是以图片的位置开始,手势坐标是以左上角开始 所以需要减去上面空白位置 + print("向上距离:$imageHeightOffsetStart"); + localPosition = Offset(localPosition.dx, localPosition.dy - imageHeightOffsetStart); - var theScale = sateData.initScale.value ?? 1; + // var theScale = sateData.initScale.value ?? 1; - /// 缩放后的基数 - if (theScale != 1) { - localPosition = Offset(localPosition.dx / theScale, localPosition.dy / theScale); - var theZoomOffset = sateData.zoomOffset; - if (theZoomOffset != null) { - var dx = theZoomOffset.dx; - var dy = theZoomOffset.dy; - localPosition = Offset(localPosition.dx + dx, localPosition.dy + dy); - } - } + // print("}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} $theScale"); - vnHandWritings.value = List.from(vnHandWritings.value)..add(localPosition); - sateData.handwritings = vnHandWritings.value; - }, - child: Obx(() { - var isPen = annotationState.pen.value; - var showZgtAnnotate = sateData.data.value?.showZgtAnnotate; -// sateData.slide.value - // print("55555高度: ${actualHeight} ${initPosition.value}"); - return IgnorePointer( + // /// 缩放后的基数 + // if (theScale != 1) { + // print("PPPPPPPPPPPPPPPPPPPPPPPP"); + // localPosition = Offset(localPosition.dx / theScale, localPosition.dy / theScale); + // var theZoomOffset = sateData.zoomOffset; + // if (theZoomOffset != null) { + // var dx = theZoomOffset.dx; + // var dy = theZoomOffset.dy; + // localPosition = Offset(localPosition.dx + dx, localPosition.dy + dy); + // } + // } + + print("最终位置 : $localPosition"); + vnHandWritings.value = List.from(vnHandWritings.value)..add(localPosition); + sateData.handwritings = vnHandWritings.value; + print(sateData.handwritings); + }, + child: Obx(() { + var isPen = annotationState.pen.value; + var showZgtAnnotate = sateData.data.value?.showZgtAnnotate; + + return Container( + height: double.infinity, + width: double.infinity, + alignment: Alignment.center, + child: IgnorePointer( ignoring: isPen, child: Zoom( - key: zoomKey, + key: zoomKey.value, initTotalZoomOut: true, // 展示全部内容 初始化不产生滚动条 zoomSensibility: 0.05, scrollWeight: 4.r, @@ -749,53 +468,30 @@ class QuestionImageView extends HookWidget with EventBusMixin Image(image: imageProvider, fit: BoxFit.fitWidth)) - : null, - ), - ), - ], + onScaleUpdate: logic.zoomLogic.onScaleUpdate, + onPositionUpdate: logic.zoomLogic.onPanUpPosition, + child: RepaintBoundary( + key: logic.pictureOverviewKey, + child: CustomPaint( + // isComplex: true, + // size: customPaintSize.value, + foregroundPainter: DrawingPainter(ctrl: vnHandWritings), + child: $TheCachedNetworkImage( + imgWidth: maxWidth, + imageUrl: showZgtAnnotate ?? sateData.data.value!.zgtAnswer, + (_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth), + ), + // child: showZgtAnnotate != null ? $TheCachedNetworkImage(imgWidth: maxWidth, imageUrl: showZgtAnnotate, (_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth)) : null, ), ), ), - ); - }), - ), + ), + ); + }), ); - - // return Obx(() { - // var imageUrl = sateData.data.value?.zgtAnswer; - - // if (imageUrl == null) return const SizedBox(); - - // }); } } @@ -805,7 +501,7 @@ class DrawingPainter extends CustomPainter { final Paint paintBrush = Paint() ..color = Colors.red ..strokeCap = StrokeCap.round - ..strokeWidth = 0.6.r; + ..strokeWidth = 0.75.sp; DrawingPainter({required this.ctrl}) : super(repaint: ctrl); @override 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 9f338f6..ed4b5c8 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 @@ -14,7 +14,6 @@ import 'package:making_school_asignment_app/common/job/marking_models/do_test_qu import 'package:making_school_asignment_app/common/job/marking_models/favor_param.dart'; 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/anti_shake_throttling.dart' as anti_shake_throttling; import 'package:making_school_asignment_app/common/utils/permission_describe_util.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'; @@ -34,8 +33,8 @@ class HomeworkReviewState { late Rx?> studentQuestions; late Rx slide; // 滑动位置 bool? panQuestView = null; - late Rx imageScale; - late Rx imageScaleZoom = Rx(null); + // late Rx imageScale; + // late Rx imageScaleZoom = Rx(null); /// 图片放大后的操作存放数据 List handwritings = []; @@ -43,7 +42,6 @@ class HomeworkReviewState { bool lastQuestionPrompt = false; // 最后一题提示 Rx getDataError = false.obs; // 获取作业数据报错 - Rx initScale = Rx(null); Offset? zoomOffset; RxBool favorite = false.obs; // 初始化数据 // late String dateEnd = ''; @@ -68,22 +66,23 @@ class HomeworkReviewBinding extends Bindings { @override void dependencies() { Get.lazyPut(() => HomeworkReviewLogic()); - Get.lazyPut(() => ZoomLogic()); } } class HomeworkReviewLogic extends GetxController with RequestToolMixin { + final zoomLogic = Get.find(); final GlobalKey pictureOverviewKey = GlobalKey(); late StreamSubscription _paramListen; late StreamSubscription _dataListen; final HomeworkReviewState state = HomeworkReviewState(); final HomeworkReviewAnnotationsControlState annotationState = HomeworkReviewAnnotationsControlState(); double appBarHeight = 56; - StreamSubscription? initScaleStream; + StreamSubscription? imageScaleZoomStream; @override void onInit() { + appBarHeight = MediaQuery.of(Get.context!).padding.top; print("appBarHeight :$appBarHeight"); // WidgetsFlutterBinding.ensureInitialized(); @@ -98,7 +97,7 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin { ).obs; state.data = Rx(null); state.studentQuestions = Rx?>(null); - state.imageScale = Rx(null); + // state.imageScale = Rx(null); state.slide = 0.0.obs; // 参数变化更新作业详情 @@ -106,27 +105,26 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin { // 试题数据 _dataListen = state.data.listen((e) { if (e == null) return; - state.imageScale.value = null; + var zoomState = zoomLogic.zoomState; + + state.studentQuestions.value = e.studentQuestions; // 赋值试题集合 + + + final currentTemplateId = zoomState.zoomFile.value?.templateId; // 获取旧题号ID + if (currentTemplateId != null && currentTemplateId != e.templateId) { + // zoom 题号判断是否有变 有变就需要清空 zoom文件 + zoomState.initScale.value = null; + zoomState.zoomFile.value!.clearZoomFile(e.templateId); + zoomState.zoomFile.update((_) {}); // 更新的是对象 需要执行此回调 + } if (state.favorite.value != e.isFav) state.favorite.value = !state.favorite.value; }); - imageScaleZoomStream = state.imageScale.listen((e) { - // state.imageScaleZoom.value = theImageScale; - var theImageScaleZoom = state.imageScaleZoom.value; - if (theImageScaleZoom == null || theImageScaleZoom.url != e?.url) state.imageScaleZoom.value = e; - }); - - initScaleStream = state.initScale.listen((e) { - anti_shake_throttling.debounce(() { - var theImageScale = state.imageScale.value; - if (theImageScale != null) { - theImageScale = TestQuestionsImageInfo.fromJson(theImageScale.toJson()); - theImageScale.zoom = e ?? 1; - theImageScale = TestQuestionsImageInfo.fromJson(theImageScale.toJson()); - } - state.imageScaleZoom.value = theImageScale; - }, const Duration(milliseconds: 100))(); - }); + // imageScaleZoomStream = state.imageScale.listen((e) { + // // state.imageScaleZoom.value = theImageScale; + // var theImageScaleZoom = state.imageScaleZoom.value; + // if (theImageScaleZoom == null || theImageScaleZoom.url != e?.url) state.imageScaleZoom.value = e; + // }); WidgetsBinding.instance.addPostFrameCallback((_) => getData()); super.onInit(); @@ -154,7 +152,6 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin { SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]); // 屏幕刘海 _dataListen.cancel(); _paramListen.cancel(); - initScaleStream?.cancel(); imageScaleZoomStream?.cancel(); super.onClose(); } @@ -171,10 +168,8 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin { // item.topHeight = itemPre.height; // } state.getDataError.value = false; - state.data.value = data; state.handwritings = []; - state.studentQuestions.value = data.studentQuestions; - state.initScale.value = null; + state.data.value = data; } catch (e) { print('获取数据报错了:$e'); // ToastUtils.showError('未获取到试题数据,请重试'); @@ -243,12 +238,8 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin { 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; - } + /// 此图片在设备中的像素比例 + double? pixelRatio = zoomLogic.zoomState.zoomFile.value?.scaleRatio ?? MediaQuery.of(context).devicePixelRatio; ui.Image image = await boundary.toImage(pixelRatio: pixelRatio); ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png); @@ -351,24 +342,6 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin { }); } - void onPanUpPosition(Offset val) async { - // 手指在移动 非物体移动的位置 - - if (state.zoomOffset?.dy.toStringAsFixed(2) != val.dy.toStringAsFixed(2) || - state.zoomOffset?.dx.toStringAsFixed(2) != val.dx.toStringAsFixed(2)) { - print('**************** 正在移动位置 YYY:${val.dy}'); - print('**************** 正在移动位置 XXX:${val.dx}'); - state.zoomOffset = val; - state.slide.value = val.dy.abs().toInt().toDouble(); - } - } - - // 缩放组件 ==> 缩放监听 - void onScaleUpdate(double scale, double zoom) async { - print("$scale $zoom"); - state.initScale.value = zoom; - } - Future toFavorite() async { try { var data = state.data.value!; diff --git a/making_school_asignment_app/lib/page/home_page/children/homework_review/configuration_files/zoom_logic.dart b/making_school_asignment_app/lib/page/home_page/children/homework_review/configuration_files/zoom_logic.dart index 2b87d9f..76d6dcb 100644 --- a/making_school_asignment_app/lib/page/home_page/children/homework_review/configuration_files/zoom_logic.dart +++ b/making_school_asignment_app/lib/page/home_page/children/homework_review/configuration_files/zoom_logic.dart @@ -1,5 +1,6 @@ import 'dart:ui' show ImmutableBuffer, ImageDescriptor; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart' as anti_shake_throttling; import 'package:flutter/widgets.dart'; import 'dart:async'; @@ -13,24 +14,28 @@ import 'index.dart'; part 'zoom_logic.g.dart'; class ZoomLogic extends GetxController { - final logic = Get.find(); - HomeworkReviewState get homeworkState => logic.state; + ZoomState zoomState = ZoomState( + initScale: Rx(null), + zoomFile: Rx(null), + ); - ZoomState zoomState = ZoomState(zoomFile: Rx(null)); - - var oldTemplateId = null; + var oldTemplateId; late StreamSubscription _streamHomework; late StreamSubscription _streamZoomState; + StreamSubscription? initScaleStream; + @override void onInit() { oldTemplateId = zoomState.zoomFile.value?.templateId; + + /// 根据第一次加载的试题题号 分析试题图片所占的宽高 _streamZoomState = zoomState.zoomFile.listen((e) { var templateId = e?.templateId; print("ZOOMFILE 变化了 $templateId"); if (templateId == null) return; - var homeworkData = homeworkState.data.value; + var homeworkData = Get.find().state.data.value; var zgtAnswer = homeworkData?.zgtAnswer; print("333333"); if (zgtAnswer == null) return; @@ -51,13 +56,21 @@ class ZoomLogic extends GetxController { zoomState.zoomFile.value = ZoomFileModel.fromJson(oldVal.toJson()); }); }); - _streamHomework = homeworkState.data.listen((e) { - print("HOMEWORKSTATE 变化了"); - if (e == null || zoomState.zoomFile.value == null) return; - zoomState.zoomFile.value!.templateId = e.templateId; - print("666666 ${e.templateId}"); - zoomState.zoomFile.value = ZoomFileModel.fromJson(zoomState.zoomFile.value!.toJson()); + + WidgetsBinding.instance.addPostFrameCallback((e) { + /// 试题加载后更新尺寸对象(只要题号没有变就不更新尺寸对象) + _streamHomework = Get.find().state.data.listen((e) { + print("HOMEWORKSTATE 变化了"); + if (e == null || zoomState.zoomFile.value == null) return; + zoomState.zoomFile.value!.templateId = e.templateId; + print("666666 ${e.templateId}"); + zoomState.zoomFile.value = ZoomFileModel.fromJson(zoomState.zoomFile.value!.toJson()); + }); }); + + /// 监听缩放 + initScaleStream = zoomState.initScale.listen((e) {}); + super.onInit(); } @@ -67,12 +80,41 @@ class ZoomLogic extends GetxController { _streamZoomState.cancel(); super.onClose(); } + + // 缩放组件 ==> 缩放监听 + void onScaleUpdate(double scale, double zoom) async { + print("$scale $zoom"); + + /// 防抖 + zoomState.initScale.value = zoom; + // anti_shake_throttling.debounce(() => zoomState.initScale.value = zoom, const Duration(milliseconds: 100))(); + } + + // 缩放组件 ==> 位置更新 + void onPanUpPosition(Offset val) async { + // 手指在移动 非物体移动的位置 + var state = Get.find().state; + if (state.zoomOffset?.dy.toStringAsFixed(2) != val.dy.toStringAsFixed(2) || state.zoomOffset?.dx.toStringAsFixed(2) != val.dx.toStringAsFixed(2)) { + // print('**************** 正在移动位置 YYY:${val.dy}'); + // print('**************** 正在移动位置 XXX:${val.dx}'); + state.zoomOffset = val; + state.slide.value = val.dy.abs().toInt().toDouble(); + } + } +} + +class HomeworkReviewZoomBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => ZoomLogic()); + } } class ZoomState { + final Rx initScale; final Rx zoomFile; - const ZoomState({required this.zoomFile}); + const ZoomState({required this.zoomFile, required this.initScale}); } @JsonSerializable() @@ -80,38 +122,73 @@ class ZoomFileModel extends Object { double viewWidth; // 容器宽度 double viewHeight; // 容器高度 + double scaleRatio; // 基准 + int? templateId; // 页码 + double? pixelRatio; // 像素比率 + double? fileWidth; // 文件宽度 double? fileHeight; // 文件高度 double? actualWidth; // 实际展示宽度 double? actualHeight; // 实际展示高度 + double? remainingHeight; // 视图剩余高度 实际展示图片展示高度下 剩余高度.(若为负数就是超出视图的高度值) + double? imageHeightOffsetStart; // 顶部坐标Y + double? imageHeightOffsetend; // 底部坐标Y + ZoomFileModel({ required this.viewWidth, required this.viewHeight, + this.scaleRatio = 1, this.templateId, this.fileWidth, this.fileHeight, this.actualWidth, this.actualHeight, + this.remainingHeight, + this.imageHeightOffsetStart, + this.imageHeightOffsetend, + this.pixelRatio, }) { // 图片已视图宽为基准,高度自适应可滑动 图片的实际宽高都需要乘此基准值. if (fileHeight == null || fileWidth == null) return; - var scaleRatio = viewWidth / fileWidth!; + scaleRatio = viewWidth / fileWidth!; actualWidth = fileWidth! * scaleRatio; actualHeight = fileHeight! * scaleRatio; - // remainingHeight = boxHeight - actualImgHeight; - // imageHeightOffsetStart = remainingHeight / 2; - // imageHeightOffsetend = imageHeightOffsetStart + actualImgHeight; + pixelRatio = fileWidth! / viewWidth; // 图片在此设备的像素比例 + + remainingHeight = viewHeight - actualHeight!; + imageHeightOffsetStart = remainingHeight! / 2; + imageHeightOffsetend = imageHeightOffsetStart! + actualHeight!; } factory ZoomFileModel.fromJson(Map srcJson) => _$ZoomFileModelFromJson(srcJson); Map toJson() => _$ZoomFileModelToJson(this); + + // 清空zoom文件(templateId 页码变换清空试题图片信息) + ZoomFileModel clearZoomFile(int newTemplateId) { + templateId = newTemplateId; // 页码 + fileWidth = null; // 文件宽度 + fileHeight = null; // 文件高度 + actualWidth = null; // 实际展示宽度 + actualHeight = null; // 实际展示高度 + remainingHeight = null; // 视图剩余高度 实际展示图片展示高度下 剩余高度.(若为负数就是超出视图的高度值) + imageHeightOffsetStart = null; // 顶部坐标Y + imageHeightOffsetend = null; // 底部坐标Y + return this; + } + + /// 获取缩放比例后的空白距离 + /// zoom 缩放比例 + double getZoomFileOffsetStart(double zoom) { + if (zoom == 1 || actualHeight == null) return imageHeightOffsetStart ?? 0; + return (viewHeight - (actualHeight! * zoom)) / 2; + } } // 最终版 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 8531e1d..6f27907 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 @@ -20,47 +20,37 @@ class HomeworkReview extends StatelessWidget { Widget build(BuildContext context) { final logic = Get.find(); final sateData = logic.state; - final AnnotateClassLogic _controller = Get.find(); - final HomeLogic _homeLogicController = Get.find(); + final AnnotateClassLogic controller = Get.find(); + final HomeLogic homeLogicController = Get.find(); return PopScope( canPop: false, onPopInvoked: (e) { if (e && sateData.needRefresh) { - _controller.getList(); - _homeLogicController.getList(); + controller.getList(); + homeLogicController.getList(); } }, - child: SafeArea( - child: Scaffold( - appBar: AppBar( - // titleSpacing: 0, - leading: IconButton(icon: const Icon(Icons.arrow_back_ios), onPressed: () => Get.back()), - iconTheme: const IconThemeData(color: Colors.black), - title: quickText(sateData.param.value.homeworkName), - backgroundColor: Colors.white, - elevation: 0, - actions: [const FavoriteWidget(), SizedBox(width: 5.w), const ReturnToHomepage()], - ), - body: Column( - children: [ - // 下拉切换 30.h - const DropdownSwitchStudentsType(), - // +1 - SizedBox(height: 1.h), - const Expanded(child: QuestionPaperView()), - // +64.h - const BottomAnnotationSwitch() - ], - ), - // floatingActionButton: FloatingActionButton( - // elevation: 8, - // tooltip: "点击打开工具栏", - // backgroundColor: Colors.white, - // onPressed: () {}, - // child: Icon(Icons.edit, size: 20.sp, color: Theme.of(context).primaryColor), - // ), - // floatingActionButtonLocation: FloatingActionButtonLocation.startFloat, + child: Scaffold( + appBar: AppBar( + // titleSpacing: 0, + leading: IconButton(icon: const Icon(Icons.arrow_back_ios), onPressed: () => Get.back()), + iconTheme: const IconThemeData(color: Colors.black), + title: quickText(sateData.param.value.homeworkName), + backgroundColor: Colors.white, + elevation: 0, + actions: [const FavoriteWidget(), SizedBox(width: 5.w), const ReturnToHomepage()], + ), + body: const Column( + children: [ + // 下拉切换 + DropdownSwitchStudentsType(), + // SizedBox(height: 10), + // 试题展示区和打分区 + Expanded(child: QuestionPaperView()), + // 底部功能区 + BottomAnnotationSwitch() + ], ), ), ); diff --git a/making_school_asignment_app/lib/page/home_page/children/job_report/job_report_view.dart b/making_school_asignment_app/lib/page/home_page/children/job_report/job_report_view.dart index a2bc6ad..cdf4c0f 100644 --- a/making_school_asignment_app/lib/page/home_page/children/job_report/job_report_view.dart +++ b/making_school_asignment_app/lib/page/home_page/children/job_report/job_report_view.dart @@ -28,7 +28,7 @@ class _JobReportPageState extends State { Widget build(BuildContext context) { return OrientationBuilder(builder: (BuildContext context, Orientation orientation) { return Scaffold( - backgroundColor: Color.fromRGBO(245, 245, 245, 1), + backgroundColor: const Color.fromRGBO(245, 245, 245, 1), appBar: AppBar( backgroundColor: Colors.white, centerTitle: true, diff --git a/making_school_asignment_app/lib/page/home_page/children/job_report/widget/personnel_data_overview.dart b/making_school_asignment_app/lib/page/home_page/children/job_report/widget/personnel_data_overview.dart index e1874a6..5a8ca3e 100644 --- a/making_school_asignment_app/lib/page/home_page/children/job_report/widget/personnel_data_overview.dart +++ b/making_school_asignment_app/lib/page/home_page/children/job_report/widget/personnel_data_overview.dart @@ -5,7 +5,7 @@ import 'package:making_school_asignment_app/page/global_widget/my_text.dart'; class PersonnelDataOverview extends StatefulWidget { final List studentList; - const PersonnelDataOverview({Key? key, required this.studentList}) : super(key: key); + const PersonnelDataOverview({super.key, required this.studentList}); @override State createState() => _PersonnelDataOverviewState(); @@ -28,13 +28,13 @@ class _PersonnelDataOverviewState extends State { var student = widget.studentList[i]; TimeUnits timeUnits = convertMilliseconds(student.useTime!); String timeerStr = ''; - if (timeUnits.hours > 0) timeerStr = timeUnits.hours.toString() + ':'; - if (timeUnits.minutes > 0) timeerStr += timeUnits.minutes.toString() + ':'; + if (timeUnits.hours > 0) timeerStr = '${timeUnits.hours}:'; + if (timeUnits.minutes > 0) timeerStr += '${timeUnits.minutes}:'; timeerStr += timeUnits.seconds.toString(); names.add(student.studentName); useTimes.add(timeerStr); - correctRates.add(student.okRate!.toStringAsFixed(0) + '%'); + correctRates.add('${student.okRate!.toStringAsFixed(0)}%'); noAnswerCounts.add(student.noAnswerCount.toString()); rankings.add('${i + 1}名'); } @@ -60,7 +60,7 @@ class _PersonnelDataOverviewState extends State { children: [ Container( margin: EdgeInsets.only(bottom: 20.h), - child: quickText('人员数据概况', color: Color.fromRGBO(92, 92, 92, 1), size: 14.sp, fontWeight: FontWeight.bold), + child: quickText('人员数据概况', color: const Color.fromRGBO(92, 92, 92, 1), size: 14.sp, fontWeight: FontWeight.bold), ), Scrollbar( thickness: 8.w, @@ -88,7 +88,7 @@ class _PersonnelDataOverviewState extends State { color: const Color.fromRGBO(230, 230, 230, 1), margin: EdgeInsets.only(bottom: 1.h, right: 1.w), padding: EdgeInsets.symmetric(vertical: 10.h, horizontal: 8.w), - child: quickText(entrie.key, color: Color.fromRGBO(24, 35, 77, 1), size: 12.sp, maxLines: 2), + child: quickText(entrie.key, color: const Color.fromRGBO(24, 35, 77, 1), size: 12.sp, maxLines: 2), ), ...entrie.value.map((e) { bool isTransparentChineseNew = isTransparentChinese && (e?.length ?? 0) == 0; @@ -97,23 +97,23 @@ class _PersonnelDataOverviewState extends State { alignment: Alignment.center, margin: EdgeInsets.only(bottom: 1.h, right: 1.w), padding: EdgeInsets.symmetric(vertical: 10.h, horizontal: 8.w), - color: Color.fromRGBO(245, 245, 245, 1), + color: const Color.fromRGBO(245, 245, 245, 1), child: isTransparentChineseNew ? quickText('透明', color: Colors.transparent, size: 12.sp) : RegExp(r'^\d+$').hasMatch(e) || e.contains('%') ? Row( mainAxisSize: MainAxisSize.min, children: [ - quickText(e, color: Color.fromRGBO(82, 82, 82, 1), size: 12.sp, maxLines: 2), + quickText(e, color: const Color.fromRGBO(82, 82, 82, 1), size: 12.sp, maxLines: 2), quickText('透', color: Colors.transparent, size: 12.sp), ], ) - : quickText(e, color: Color.fromRGBO(82, 82, 82, 1), size: 12.sp, maxLines: 2), + : quickText(e, color: const Color.fromRGBO(82, 82, 82, 1), size: 12.sp, maxLines: 2), ); - }).toList(), + }), ], ); - }).toList(), + }), ], ), ), diff --git a/making_school_asignment_app/lib/page/home_page/children/read_over/widget/task_list_item.dart b/making_school_asignment_app/lib/page/home_page/children/read_over/widget/task_list_item.dart index 0e73dbb..db0a13d 100644 --- a/making_school_asignment_app/lib/page/home_page/children/read_over/widget/task_list_item.dart +++ b/making_school_asignment_app/lib/page/home_page/children/read_over/widget/task_list_item.dart @@ -19,7 +19,7 @@ class TaskListItem extends StatefulWidget { final int tabIndex; final Function(Items item) collectFun; - const TaskListItem({Key? key, required this.completed, required this.jobTaskItem, required this.type, required this.collectFun,required this.tabIndex}) : super(key: key); + const TaskListItem({Key? key, required this.completed, required this.jobTaskItem, required this.type, required this.collectFun, required this.tabIndex}) : super(key: key); @override State createState() => _TaskListItemState(); @@ -31,8 +31,7 @@ class _TaskListItemState extends State { return widget.completed ? InkWell( onTap: () { - Get.toNamed(Routes.annotateClassPage, - arguments: {'id': widget.jobTaskItem.id, 'name': widget.jobTaskItem.name, 'grade': widget.jobTaskItem.grade,'subject': widget.jobTaskItem.subject, 'completed': true,'tabIndex':widget.tabIndex}); + Get.toNamed(Routes.annotateClassPage, arguments: {'id': widget.jobTaskItem.id, 'name': widget.jobTaskItem.name, 'grade': widget.jobTaskItem.grade, 'subject': widget.jobTaskItem.subject, 'completed': true, 'tabIndex': widget.tabIndex}); }, child: Container( width: double.infinity, @@ -73,7 +72,7 @@ class _TaskListItemState extends State { ), ), margin: EdgeInsets.only(right: 4.w), - child: quickText( widget.jobTaskItem.assessType == 0?'作业':'考试', color: Colors.white, size: 10.sp), + child: quickText(widget.jobTaskItem.assessType == 0 ? '作业' : '考试', color: Colors.white, size: 10.sp), ), Expanded( child: quickText( @@ -143,7 +142,13 @@ class _TaskListItemState extends State { child: Row(children: [ Expanded( child: InkWell( - onTap: () {}, + onTap: () { + Get.toNamed(Routes.jobReportPage, arguments: { + 'title': widget.jobTaskItem.name, + 'homeworkId': widget.jobTaskItem.id, + 'grade': widget.jobTaskItem.grade, + }); + }, child: Container( alignment: Alignment.center, child: quickText('查看报告', color: const Color.fromRGBO(118, 118, 118, 1), size: 13.sp), @@ -156,11 +161,10 @@ class _TaskListItemState extends State { ), ) : Padding( - padding: EdgeInsets.only(top: 10.r), - child: InkWell( + padding: EdgeInsets.only(top: 10.r), + child: InkWell( onTap: () { - Get.toNamed(Routes.annotateClassPage, - arguments: {'id': widget.jobTaskItem.id, 'name': widget.jobTaskItem.name, 'grade': widget.jobTaskItem.grade,'subject':widget.jobTaskItem.subject,'tabIndex':widget.tabIndex}); + Get.toNamed(Routes.annotateClassPage, arguments: {'id': widget.jobTaskItem.id, 'name': widget.jobTaskItem.name, 'grade': widget.jobTaskItem.grade, 'subject': widget.jobTaskItem.subject, 'tabIndex': widget.tabIndex}); }, child: Container( margin: EdgeInsets.only(bottom: 16.h), @@ -202,8 +206,8 @@ class _TaskListItemState extends State { bottomRight: Radius.circular(12.r), ), ), - margin: EdgeInsets.only(top:0.h,right: 4.w), - child: quickText(widget.jobTaskItem.assessType == 0?'作业':'考试', color: Colors.white, size: 10.sp), + margin: EdgeInsets.only(top: 0.h, right: 4.w), + child: quickText(widget.jobTaskItem.assessType == 0 ? '作业' : '考试', color: Colors.white, size: 10.sp), ), Expanded( child: Padding( @@ -243,8 +247,7 @@ class _TaskListItemState extends State { ], ), quickText(' / ', color: const Color.fromRGBO(130, 130, 130, 1), size: 11.sp, fontWeight: FontWeight.w500), - quickText(DateTime.parse(widget.jobTaskItem.publishTime).toString().substring(0, 10), - color: const Color.fromRGBO(97, 97, 97, 1), size: 12.sp), + quickText(DateTime.parse(widget.jobTaskItem.publishTime).toString().substring(0, 10), color: const Color.fromRGBO(97, 97, 97, 1), size: 12.sp), ], ), ), @@ -266,7 +269,7 @@ class _TaskListItemState extends State { ), child: Text( widget.jobTaskItem.isFixed! ? '已订正' : '收集订正', - style: TextStyle(fontSize: 10.sp, color: widget.jobTaskItem.isFixed! ?const Color(0xFFF16262): const Color(0xFF8C68FF)), + style: TextStyle(fontSize: 10.sp, color: widget.jobTaskItem.isFixed! ? const Color(0xFFF16262) : const Color(0xFF8C68FF)), ), ), ), @@ -274,15 +277,17 @@ class _TaskListItemState extends State { ], ), ), - SizedBox(width: 10.r,), + SizedBox( + width: 10.r, + ), Container( - padding: EdgeInsets.symmetric(vertical: 10.r,horizontal: 9.r), + padding: EdgeInsets.symmetric(vertical: 10.r, horizontal: 9.r), decoration: const BoxDecoration(shape: BoxShape.circle, color: Colors.white), child: CircularPercentIndicator( radius: 50.r, lineWidth: 10.r, animation: true, - reverse:true, + reverse: true, percent: widget.jobTaskItem.annotateRate == null ? 0 : widget.jobTaskItem.annotateRate! / 100, center: Text.rich(TextSpan(children: [ TextSpan( @@ -317,6 +322,6 @@ class _TaskListItemState extends State { ), ), ), - ); + ); } } diff --git a/making_school_asignment_app/lib/page/home_page/children/student_work_detail/student_work_detail_view.dart b/making_school_asignment_app/lib/page/home_page/children/student_work_detail/student_work_detail_view.dart index dfd5863..09492cb 100644 --- a/making_school_asignment_app/lib/page/home_page/children/student_work_detail/student_work_detail_view.dart +++ b/making_school_asignment_app/lib/page/home_page/children/student_work_detail/student_work_detail_view.dart @@ -18,7 +18,7 @@ import 'package:syncfusion_flutter_datepicker/datepicker.dart'; import 'student_work_detail_logic.dart'; class StudentWorkDetailPage extends StatefulWidget { - const StudentWorkDetailPage({Key? key}) : super(key: key); + const StudentWorkDetailPage({super.key}); @override State createState() => _StudentWorkDetailPageState(); @@ -33,14 +33,14 @@ class _StudentWorkDetailPageState extends State { return OrientationBuilder( builder: (BuildContext context, Orientation orientation) { return Scaffold( - backgroundColor: Color.fromRGBO(245, 245, 245, 1), + backgroundColor: const Color.fromRGBO(245, 245, 245, 1), appBar: AppBar( backgroundColor: Colors.white, title: Text('${state.studentName}作业详情', - style: TextStyle(fontSize: 14.sp, color: Color(0xFF333333))), + style: TextStyle(fontSize: 14.sp, color: const Color(0xFF333333))), centerTitle: true, leading: IconButton( - icon: Icon(Icons.arrow_back_ios, color: Colors.black), + icon: const Icon(Icons.arrow_back_ios, color: Colors.black), onPressed: () => Get.back(), ), actions: const [ @@ -53,7 +53,7 @@ class _StudentWorkDetailPageState extends State { Container( height: 1.r, width: MediaQuery.of(context).size.width, - color: Color.fromRGBO(179, 179, 179, 0.3), + color: const Color.fromRGBO(179, 179, 179, 0.3), ), Container( color: Colors.white, @@ -79,7 +79,7 @@ class _StudentWorkDetailPageState extends State { fontSize: 14.sp, color: state.isJob.value ? Theme.of(context).primaryColor - : Color(0xFF505E6E)), + : const Color(0xFF505E6E)), )); }), ), @@ -87,7 +87,7 @@ class _StudentWorkDetailPageState extends State { Container( height: 40.r, width: 1.r, - color: Color.fromRGBO(179, 179, 179, 0.3), + color: const Color.fromRGBO(179, 179, 179, 0.3), ), InkWell( onTap: () { @@ -107,7 +107,7 @@ class _StudentWorkDetailPageState extends State { fontSize: 14.sp, color: !state.isJob.value ? Theme.of(context).primaryColor - : Color(0xFF505E6E)), + : const Color(0xFF505E6E)), ); })), ), @@ -223,7 +223,7 @@ class _StudentWorkDetailPageState extends State { children: [ Text( '注:', - style: TextStyle(fontSize: 8.sp, color: Color(0xFF8B8B8B)), + style: TextStyle(fontSize: 8.sp, color: const Color(0xFF8B8B8B)), ), Container( width: 10.r, @@ -239,7 +239,7 @@ class _StudentWorkDetailPageState extends State { ), Text( '正确', - style: TextStyle(fontSize: 8.sp, color: Color(0xFF8B8B8B)), + style: TextStyle(fontSize: 8.sp, color: const Color(0xFF8B8B8B)), ), SizedBox( width: 15.r, @@ -258,7 +258,7 @@ class _StudentWorkDetailPageState extends State { ), Text( '错误', - style: TextStyle(fontSize: 8.sp, color: Color(0xFF8B8B8B)), + style: TextStyle(fontSize: 8.sp, color: const Color(0xFF8B8B8B)), ), SizedBox( width: 15.r, @@ -269,7 +269,7 @@ class _StudentWorkDetailPageState extends State { decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(5.r)), // color: Color(0xFF666666), - border: Border.all(width: 1.r, color: Color(0xFF666666)), + border: Border.all(width: 1.r, color: const Color(0xFF666666)), // border: Border.all(width: 1.r,color: Colors.grey), /* boxShadow: [ BoxShadow( @@ -286,7 +286,7 @@ class _StudentWorkDetailPageState extends State { ), Text( '已作答未批阅', - style: TextStyle(fontSize: 8.sp, color: Color(0xFF8B8B8B)), + style: TextStyle(fontSize: 8.sp, color: const Color(0xFF8B8B8B)), ), SizedBox( width: 15.r, @@ -296,7 +296,7 @@ class _StudentWorkDetailPageState extends State { height: 10.r, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(5.r)), - border: Border.all(width: 1.r, color: Color(0xFFDDDDDD)), + border: Border.all(width: 1.r, color: const Color(0xFFDDDDDD)), // color: Color(0xFFDDDDDD), ), ), @@ -305,7 +305,7 @@ class _StudentWorkDetailPageState extends State { ), Text( '未做', - style: TextStyle(fontSize: 8.sp, color: Color(0xFF8B8B8B)), + style: TextStyle(fontSize: 8.sp, color: const Color(0xFF8B8B8B)), ), ], ), @@ -394,7 +394,7 @@ class _StudentWorkDetailPageState extends State { item.name, style: TextStyle( fontSize: 12.sp, - color: Color(0xFF464646)), + color: const Color(0xFF464646)), )), // SizedBox(width: 5.r,), // Text('2024.1',style: TextStyle(fontSize: 12.sp,color: Color(0xFF5B5B5B)),), diff --git a/making_school_asignment_app/lib/page/home_page/children/student_work_detail/widget/job_condition_filter.dart b/making_school_asignment_app/lib/page/home_page/children/student_work_detail/widget/job_condition_filter.dart index fa8de0f..2fb86dc 100644 --- a/making_school_asignment_app/lib/page/home_page/children/student_work_detail/widget/job_condition_filter.dart +++ b/making_school_asignment_app/lib/page/home_page/children/student_work_detail/widget/job_condition_filter.dart @@ -40,19 +40,21 @@ class _JobConditionFilterState extends State { } DateTime getMonthStartDate() { + // DateTime now = DateTime.now(); + // return DateTime(now.year, now.month, 1); // 获取当前月份的第一天 DateTime now = DateTime.now(); - return DateTime(now.year, now.month, 1); // 获取当前月份的第一天 + return now.subtract(const Duration(days: 29)); } DateTime getMonthEndDate() { DateTime now = DateTime.now(); - int nextMonth = now.month + 1; - if (nextMonth > 12) { - nextMonth = 1; - now = now.add(Duration(days: 31 - now.day)); // 跨年了,所以加到当前月的最后一天 - } else { - now = now.add(Duration(days: DateTime(now.year, nextMonth, 0).day - now.day)); // 加到下个月的第一天的前一天,即本月最后一天 - } + // int nextMonth = now.month + 1; + // if (nextMonth > 12) { + // nextMonth = 1; + // now = now.add(Duration(days: 31 - now.day)); // 跨年了,所以加到当前月的最后一天 + // } else { + // now = now.add(Duration(days: DateTime(now.year, nextMonth, 0).day - now.day)); // 加到下个月的第一天的前一天,即本月最后一天 + // } return now; } diff --git a/making_school_asignment_app/lib/routes/app_pages.dart b/making_school_asignment_app/lib/routes/app_pages.dart index 926141d..8606d36 100644 --- a/making_school_asignment_app/lib/routes/app_pages.dart +++ b/making_school_asignment_app/lib/routes/app_pages.dart @@ -14,6 +14,7 @@ import 'package:making_school_asignment_app/page/home_page/children/class_studen import 'package:making_school_asignment_app/page/home_page/children/fav_student/fav_student_binding.dart'; import 'package:making_school_asignment_app/page/home_page/children/fav_student/fav_student_view.dart'; import 'package:making_school_asignment_app/page/home_page/children/homework_review/configuration_files/index.dart'; +import 'package:making_school_asignment_app/page/home_page/children/homework_review/configuration_files/zoom_logic.dart'; import 'package:making_school_asignment_app/page/home_page/children/homework_review/index.dart'; import 'package:making_school_asignment_app/page/home_page/children/job_report/job_report_binding.dart'; import 'package:making_school_asignment_app/page/home_page/children/job_report/job_report_view.dart'; @@ -44,63 +45,30 @@ part 'app_routes.dart'; abstract class AppPages { static final pages = [ - GetPage(name: Routes.login, page: () => const LoginPage(), binding: LoginBinding(), transition: Transition.noTransition), + GetPage(name: Routes.login, page: () => const LoginPage(), binding: LoginBinding(), transition: getTransition()), GetPage(name: Routes.register, page: () => const Register(), transition: getTransition()), - GetPage(name: Routes.agreementPage, page: () => const AgreementPage(), binding: LoginBinding(), transition: Transition.noTransition), - GetPage(name: Routes.home, page: () => const HomePage(), binding: HomeBinding(), transition: Transition.noTransition), - GetPage(name: Routes.startPage, page: () => const StartPage(), binding: StartPageIndexBinding(), transition: Transition.noTransition), - GetPage(name: Routes.myInfo, page: () => const MyInfo(), transition: Transition.noTransition), - GetPage(name: Routes.work, page: () => const WorkPage(), binding: WorkBinding(), transition: Transition.noTransition), - GetPage(name: Routes.otherPage, page: () => const OhterPage(), transition: Transition.noTransition), - GetPage(name: Routes.readOverPage, page: () => const ReadOverPage(), binding: ReadOverBinding(), transition: Transition.noTransition), - GetPage( - name: Routes.studentHistoryWorkPage, - page: () => const StudentHistoryWorkPage(), - binding: StudentHistoryWorkBinding(), - transition: Transition.noTransition), - GetPage(name: Routes.classStudentPage, page: () => const ClassStudentPage(), binding: ClassStudentBinding(), transition: Transition.noTransition), - GetPage( - name: Routes.annotateClassPage, page: () => const AnnotateClassPage(), binding: AnnotateClassBinding(), transition: Transition.noTransition), - GetPage( - name: Routes.quickDataCheckPage, - page: () => const QuickDataCheckPage(), - binding: QuickDataCheckBinding(), - transition: Transition.noTransition), - GetPage(name: Routes.jobReportPage, page: () => const JobReportPage(), binding: JobReportBinding(), transition: Transition.noTransition), - GetPage( - name: Routes.studentPersonalPage, - page: () => const StudentPersonalPage(), - binding: StudentPersonalBinding(), - transition: Transition.noTransition), - GetPage( - name: Routes.studentWorkDetailPage, - page: () => const StudentWorkDetailPage(), - binding: StudentWorkDetailBinding(), - transition: Transition.noTransition), - GetPage( - name: Routes.knowledgePointsGraspPage, - page: () => const KnowledgePointsGraspPage(), - binding: KnowledgePointsGraspBinding(), - transition: Transition.noTransition), - GetPage( - name: Routes.knowledgePointsGraspDetailPage, - page: () => const KnowledgePointsGraspDetailPage(), - binding: KnowledgePointsGraspDetailBinding(), - transition: Transition.noTransition), - GetPage( - name: Routes.answerTrajectoryPage, - page: () => const AnswerTrajectoryPage(), - binding: AnswerTrajectoryBinding(), - transition: Transition.noTransition), - GetPage( - name: Routes.answerTrajectoryDetailPage, - page: () => const AnswerTrajectoryDetailPage(), - binding: AnswerTrajectoryDetailBinding(), - transition: Transition.noTransition), + GetPage(name: Routes.agreementPage, page: () => const AgreementPage(), binding: LoginBinding(), transition: getTransition()), + GetPage(name: Routes.home, page: () => const HomePage(), binding: HomeBinding(), transition: getTransition()), + GetPage(name: Routes.startPage, page: () => const StartPage(), binding: StartPageIndexBinding(), transition: getTransition()), + GetPage(name: Routes.myInfo, page: () => const MyInfo(), transition: getTransition()), + GetPage(name: Routes.work, page: () => const WorkPage(), binding: WorkBinding(), transition: getTransition()), + GetPage(name: Routes.otherPage, page: () => const OhterPage(), transition: getTransition()), + GetPage(name: Routes.readOverPage, page: () => const ReadOverPage(), binding: ReadOverBinding(), transition: getTransition()), + GetPage(name: Routes.studentHistoryWorkPage, page: () => const StudentHistoryWorkPage(), binding: StudentHistoryWorkBinding(), transition: getTransition()), + GetPage(name: Routes.classStudentPage, page: () => const ClassStudentPage(), binding: ClassStudentBinding(), transition: getTransition()), + GetPage(name: Routes.annotateClassPage, page: () => const AnnotateClassPage(), binding: AnnotateClassBinding(), transition: getTransition()), + GetPage(name: Routes.quickDataCheckPage, page: () => const QuickDataCheckPage(), binding: QuickDataCheckBinding(), transition: getTransition()), + GetPage(name: Routes.jobReportPage, page: () => const JobReportPage(), binding: JobReportBinding(), transition: getTransition()), + GetPage(name: Routes.studentPersonalPage, page: () => const StudentPersonalPage(), binding: StudentPersonalBinding(), transition: getTransition()), + GetPage(name: Routes.studentWorkDetailPage, page: () => const StudentWorkDetailPage(), binding: StudentWorkDetailBinding(), transition: getTransition()), + GetPage(name: Routes.knowledgePointsGraspPage, page: () => const KnowledgePointsGraspPage(), binding: KnowledgePointsGraspBinding(), transition: getTransition()), + GetPage(name: Routes.knowledgePointsGraspDetailPage, page: () => const KnowledgePointsGraspDetailPage(), binding: KnowledgePointsGraspDetailBinding(), transition: getTransition()), + GetPage(name: Routes.answerTrajectoryPage, page: () => const AnswerTrajectoryPage(), binding: AnswerTrajectoryBinding(), transition: getTransition()), + GetPage(name: Routes.answerTrajectoryDetailPage, page: () => const AnswerTrajectoryDetailPage(), binding: AnswerTrajectoryDetailBinding(), transition: getTransition()), // 批阅主页(作业、考试) - GetPage(name: Routes.reviewHomework, page: () => const HomeworkReview(), binding: HomeworkReviewBinding(), transition: getTransition()), - GetPage(name: Routes.reviewExam, page: () => const HomeworkReview(), binding: HomeworkReviewBinding(), transition: getTransition()), - GetPage(name: Routes.favStudentPage, page: () => const FavStudentPage(), binding: FavStudentBinding(), transition: Transition.noTransition), + GetPage(name: Routes.reviewHomework, page: () => const HomeworkReview(), bindings: [HomeworkReviewBinding(), HomeworkReviewZoomBinding()], transition: getTransition()), + // GetPage(name: Routes.reviewExam, page: () => const HomeworkReview(), bindings: [HomeworkReviewBinding(), HomeworkReviewZoomBinding()], transition: getTransition()), + GetPage(name: Routes.favStudentPage, page: () => const FavStudentPage(), binding: FavStudentBinding(), transition: getTransition()), ]; } diff --git a/making_school_asignment_app/pubspec.yaml b/making_school_asignment_app/pubspec.yaml index 2c2261d..7fb8c92 100644 --- a/making_school_asignment_app/pubspec.yaml +++ b/making_school_asignment_app/pubspec.yaml @@ -37,7 +37,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.6 # 路由、依赖、状态插件 - get: ^4.6.5 + get: ^4.7.2 # loading插件 flutter_easyloading: ^3.0.5 # 日志插件 @@ -65,6 +65,7 @@ dependencies: flutter_widget_from_html_core: ^0.14.12 # APP内存及本地存储插件 get_storage: ^2.0.3 + zoom_widget: ^2.0.1 # start retrofit请求封装 retrofit: ^4.1.0