From 10025b49eedffa835c4e4c8703b7b5d912123522 Mon Sep 17 00:00:00 2001 From: "DESKTOP-I3JPKHK\\wy" <1111> Date: Tue, 23 Sep 2025 16:16:59 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../annotate_class/annotate_class_view.dart | 24 +- .../annotate_class/widget/annotate_item.dart | 17 +- .../fav_student/fav_student_view.dart | 15 +- .../widget/favorite_student_dialog.dart | 210 +++---- .../dropdown_switch_students_type.dart | 554 ++++++++++-------- 5 files changed, 435 insertions(+), 385 deletions(-) diff --git a/making_school_asignment_app/lib/page/home_page/children/annotate_class/annotate_class_view.dart b/making_school_asignment_app/lib/page/home_page/children/annotate_class/annotate_class_view.dart index 638eb68..d49b12e 100644 --- a/making_school_asignment_app/lib/page/home_page/children/annotate_class/annotate_class_view.dart +++ b/making_school_asignment_app/lib/page/home_page/children/annotate_class/annotate_class_view.dart @@ -8,6 +8,7 @@ import 'package:making_school_asignment_app/common/job/annotated_class.dart'; import 'package:making_school_asignment_app/common/utils/utils.dart'; import 'package:making_school_asignment_app/page/global_widget/ReturnToHomepage.dart'; import 'package:making_school_asignment_app/page/home_page/children/annotate_class/widget/annotate_item.dart'; + import 'annotate_class_logic.dart'; import 'widget/completed_annotate_item.dart'; @@ -27,23 +28,21 @@ class _AnnotateClassPageState extends State { String homeworkId = state.homeworkId.value; return AnnotatedRegion( value: const SystemUiOverlayStyle( - systemNavigationBarColor:Colors.transparent, + systemNavigationBarColor: Colors.transparent, systemNavigationBarDividerColor: null, statusBarColor: Colors.transparent, systemNavigationBarIconBrightness: Brightness.light, statusBarIconBrightness: Brightness.light, statusBarBrightness: Brightness.light, ), - child: OrientationBuilder( - builder: (BuildContext context, Orientation orientation) { + child: OrientationBuilder(builder: (BuildContext context, Orientation orientation) { return Scaffold( backgroundColor: const Color.fromRGBO(245, 245, 245, 1), appBar: AppBar( backgroundColor: Colors.white, + elevation: 0.3, title: Obx(() { - return Text(state.name.value, - style: - TextStyle(fontSize: 14.sp, color: const Color(0xFF333333))); + return Text(state.name.value, style: TextStyle(fontSize: 14.sp, color: const Color(0xFF333333))); }), centerTitle: true, leading: IconButton( @@ -71,13 +70,12 @@ class _AnnotateClassPageState extends State { child: state.completed.value ? Utils.isPad() ? GridView( - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, //横轴三个子widget - mainAxisSpacing: 10.h, - crossAxisSpacing: 6.w, - childAspectRatio: 1.48 //宽高比为1时,子widget - ), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, //横轴三个子widget + mainAxisSpacing: 10.h, + crossAxisSpacing: 6.w, + childAspectRatio: 1.48 //宽高比为1时,子widget + ), children: state.classList.map((taskItem) { return CompletedAnnotateItem( taskItem: taskItem, 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 bd49fe9..1b1eb7f 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 @@ -94,7 +94,7 @@ class _AnnotateItemState extends State { context: context, builder: (BuildContext context) { return ShowStudentList( - title: '${widget.item.className ?? ''} ${submitted ? '已提交' : '未提交'}作业学生', + title: '${widget.item.className} ${submitted ? '已提交' : '未提交'}作业学生', studentList: students, homeworkId: widget.homeworkId, subject: widget.logic.state.subject, @@ -133,7 +133,7 @@ class _AnnotateItemState extends State { }, child: Text( '已交:${widget.item.commitStudentCount}', - style: TextStyle(fontSize: widget.font - 2.sp, color: const Color(0xFF4CC793)), + style: TextStyle(fontSize: widget.font - 2.sp, color: Theme.of(context).primaryColor), ), ), SizedBox( @@ -256,12 +256,7 @@ class _AnnotateItemState extends State { linearGradient: LinearGradient( tileMode: TileMode.mirror, stops: const [0.0, 1.0], - 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), - ], + colors: [Theme.of(context).primaryColor.withOpacity(0.1), Theme.of(context).primaryColor], ), // linearStrokeCap: LinearStrokeCap.butt, // progressColor: Theme.of(context).primaryColor, @@ -271,21 +266,21 @@ class _AnnotateItemState extends State { ), ProgressBar( title: '客观题正确率:', - color: const Color(0xFFADDCA5), + color: Theme.of(context).primaryColor, 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), + color: Theme.of(context).primaryColor, 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), + color: Theme.of(context).primaryColor, percent: widget.item.correctRate / 100, padingEdg: EdgeInsets.symmetric(horizontal: 10.r), marginEdg: EdgeInsets.only(top: 8.h), diff --git a/making_school_asignment_app/lib/page/home_page/children/fav_student/fav_student_view.dart b/making_school_asignment_app/lib/page/home_page/children/fav_student/fav_student_view.dart index 27639e3..2ab019f 100644 --- a/making_school_asignment_app/lib/page/home_page/children/fav_student/fav_student_view.dart +++ b/making_school_asignment_app/lib/page/home_page/children/fav_student/fav_student_view.dart @@ -27,11 +27,16 @@ class _FavStudentPageState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - insetPadding: EdgeInsets.all(25.r), - content: FavoriteStudentDialog( - item: item, group: groups, deleteFav: logic.getDelete, confirmDialog: confirmDialog), - contentPadding: const EdgeInsets.all(0), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15.r)))); + insetPadding: EdgeInsets.all(25.r), + content: FavoriteStudentDialog( + item: item, + group: groups, + deleteFav: logic.getDelete, + confirmDialog: confirmDialog, + ), + contentPadding: const EdgeInsets.all(0), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15.r))), + ); }, ); } diff --git a/making_school_asignment_app/lib/page/home_page/children/fav_student/widget/favorite_student_dialog.dart b/making_school_asignment_app/lib/page/home_page/children/fav_student/widget/favorite_student_dialog.dart index 61cf1a8..d04b763 100644 --- a/making_school_asignment_app/lib/page/home_page/children/fav_student/widget/favorite_student_dialog.dart +++ b/making_school_asignment_app/lib/page/home_page/children/fav_student/widget/favorite_student_dialog.dart @@ -1,8 +1,6 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; -import 'package:get/get_rx/get_rx.dart'; import 'package:making_school_asignment_app/common/config/request_config.dart'; import 'package:making_school_asignment_app/common/job/annotated_class.dart'; import 'package:making_school_asignment_app/page/global_widget/MyEmptyWidget.dart'; @@ -15,12 +13,8 @@ class FavoriteStudentDialog extends StatefulWidget { final Function deleteFav; final Future Function() confirmDialog; - const FavoriteStudentDialog({Key? key, - required this.item, - required this.group, - required this.deleteFav, - required this.confirmDialog}) - : super(key: key); + const FavoriteStudentDialog( + {super.key, required this.item, required this.group, required this.deleteFav, required this.confirmDialog}); @override State createState() => _FavoriteStudentDialogState(); @@ -30,7 +24,7 @@ class _FavoriteStudentDialogState extends State { RxInt defaultIndex = 0.obs; RxList imageList = RxList(); late PageController pageController; - late Rx currentStudent = Rx(HomeworkFavs('','','',-1,-1,'','',-1,'',-1,'-1','','')); + late Rx currentStudent = Rx(HomeworkFavs('', '', '', -1, -1, '', '', -1, '', -1, '-1', '', '')); @override void initState() { @@ -43,8 +37,7 @@ class _FavoriteStudentDialogState extends State { } } imageList.value = list; - defaultIndex.value = - list.indexWhere((element) => element.id == widget.item.id); + defaultIndex.value = list.indexWhere((element) => element.id == widget.item.id); pageController = PageController(initialPage: defaultIndex.value); } @@ -58,14 +51,8 @@ class _FavoriteStudentDialogState extends State { @override Widget build(BuildContext context) { return Container( - width: MediaQuery - .of(context) - .size - .width, - height: MediaQuery - .of(context) - .size - .height, + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, padding: EdgeInsets.symmetric(vertical: 10.r, horizontal: 14.r), child: Column( children: [ @@ -74,16 +61,17 @@ class _FavoriteStudentDialogState extends State { children: [ Obx(() { return Text( - '${currentStudent.value.className} ${currentStudent.value - .studentName}', + '${currentStudent.value.className} ${currentStudent.value.studentName}', style: TextStyle(fontSize: 12.sp, color: Theme.of(context).primaryColor), ); }), Expanded(child: Container()), - Text( - '第${currentStudent.value.questionNo}页', - style: TextStyle(fontSize: 12.sp, color: Color(0xFF868686)), - ), + Obx(() { + return Text( + '第${currentStudent.value.questionNo}页', + style: TextStyle(fontSize: 12.sp, color: const Color(0xFF868686)), + ); + }), InkWell( onTap: () async { bool confim = await widget.confirmDialog(); @@ -94,8 +82,7 @@ class _FavoriteStudentDialogState extends State { if (defaultIndex.value < imageList.length) { currentStudent.value = imageList[defaultIndex.value]; } else { - currentStudent.value = - imageList[defaultIndex.value - 1]; + currentStudent.value = imageList[defaultIndex.value - 1]; defaultIndex = defaultIndex - 1; } } else { @@ -131,114 +118,93 @@ class _FavoriteStudentDialogState extends State { Obx(() { return imageList.isNotEmpty ? Expanded( - child: Container( - color: Colors.white, - width: MediaQuery - .of(context) - .size - .width, - child: PhotoViewGallery.builder( - scrollPhysics: const BouncingScrollPhysics(), - builder: (BuildContext context, int index) { - final HomeworkFavs item = imageList[index]; - return PhotoViewGalleryPageOptions( - imageProvider: NetworkImage(RequestConfig.imgUrl + item.zgtAnswer!), - heroAttributes: PhotoViewHeroAttributes(tag: item.id!), - ); - }, - itemCount: imageList.length, - pageController: pageController, - onPageChanged: (index) { - defaultIndex.value = index; - currentStudent.value = imageList[index]; - }, - scrollDirection: Axis.horizontal, - ), - ), - ) + child: Container( + color: Colors.white, + width: MediaQuery.of(context).size.width, + child: PhotoViewGallery.builder( + scrollPhysics: const BouncingScrollPhysics(), + builder: (BuildContext context, int index) { + final HomeworkFavs item = imageList[index]; + return PhotoViewGalleryPageOptions( + imageProvider: NetworkImage(RequestConfig.imgUrl + item.zgtAnswer!), + heroAttributes: PhotoViewHeroAttributes(tag: item.id!), + ); + }, + itemCount: imageList.length, + pageController: pageController, + onPageChanged: (index) { + defaultIndex.value = index; + currentStudent.value = imageList[index]; + }, + scrollDirection: Axis.horizontal, + ), + ), + ) : Padding( - padding: EdgeInsets.only( - top: MediaQuery - .of(context) - .size - .height / 2 - 200.r), - child: const MyEmptyWidget(), - ); + padding: EdgeInsets.only(top: MediaQuery.of(context).size.height / 2 - 200.r), + child: const MyEmptyWidget(), + ); }), - Obx(() { - return imageList.isNotEmpty?Padding( - padding: EdgeInsets.symmetric(vertical: 15.r), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - onTap: () { - if (defaultIndex.value > 0) { - defaultIndex.value = defaultIndex.value - 1; - pageController.jumpToPage(defaultIndex.value); - } - }, - child: Container( - width: - (MediaQuery - .of(context) - .size - .width - 78.r) / 2 - 10.r, - height: 28.r, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(6.r)), - border: Border.all( - width: 1.r, - color: Color(0xFFCACACA), - style: BorderStyle.solid), - ), - child: Center( - child: Text( + Obx(() { + return imageList.isNotEmpty + ? Padding( + padding: EdgeInsets.symmetric(vertical: 15.r), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + onTap: () { + if (defaultIndex.value > 0) { + defaultIndex.value = defaultIndex.value - 1; + pageController.jumpToPage(defaultIndex.value); + } + }, + child: Container( + width: (MediaQuery.of(context).size.width - 78.r) / 2 - 10.r, + height: 28.r, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(6.r)), + border: Border.all(width: 1.r, color: const Color(0xFFCACACA), style: BorderStyle.solid), + ), + child: Center( + child: Text( '上一页', style: TextStyle( fontSize: 10.r, - color: defaultIndex == 0 - ? Color(0xFFCACACA) - : Color(0xFF505E6E)), + color: defaultIndex == 0 ? const Color(0xFFCACACA) : const Color(0xFF505E6E)), )), - ), - ), - InkWell( - onTap: () { - if (defaultIndex.value < imageList.length - 1) { - defaultIndex.value = defaultIndex.value + 1; - pageController.jumpToPage(defaultIndex.value); - } - }, - child: Container( - width: - (MediaQuery - .of(context) - .size - .width - 78.r) / 2 - 10.r, - height: 28.r, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(6.r)), - border: Border.all( - width: 1.r, - color: Color(0xFFCACACA), - style: BorderStyle.solid), + ), ), - child: Center( - child: Text( + InkWell( + onTap: () { + if (defaultIndex.value < imageList.length - 1) { + defaultIndex.value = defaultIndex.value + 1; + pageController.jumpToPage(defaultIndex.value); + } + }, + child: Container( + width: (MediaQuery.of(context).size.width - 78.r) / 2 - 10.r, + height: 28.r, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(6.r)), + border: Border.all(width: 1.r, color: const Color(0xFFCACACA), style: BorderStyle.solid), + ), + child: Center( + child: Text( '下一页', style: TextStyle( fontSize: 10.r, color: defaultIndex == imageList.length - 1 - ? Color(0xFFCACACA) - : Color(0xFF505E6E)), + ? const Color(0xFFCACACA) + : const Color(0xFF505E6E)), )), - ), + ), + ), + ], ), - ], - ), - ):Container(); - }) + ) + : Container(); + }) ], ), ); 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 44aed12..a63f4be 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 @@ -15,8 +15,42 @@ import 'original_manuscript_handwriting/answer_handwriting_view.dart'; part 'dropdown_switch_students_type.g.dart'; -/// 学生和页码切换 +// 常量定义 +class _Constants { + static const double containerHeight = 30.0; + static const double borderRadius = 4.0; + static const double iconSize = 12.0; + static const double textSize = 14.0; + static const double smallTextSize = 12.0; + static const double tinyTextSize = 4.0; + + // 颜色常量 + static const Color shadowColor = Color.fromRGBO(46, 91, 255, 0.2); + static const Color backgroundColor = Color.fromRGBO(244, 244, 244, 1); + static const Color textColor = Color.fromRGBO(79, 79, 79, 1); + static const Color iconColor = Color.fromRGBO(104, 103, 103, 1); + static const Color priorityIconDisabledColor = Color.fromRGBO(164, 164, 164, 1); + + // 间距常量 + static const double paddingSmall = 2.0; + static const double paddingMedium = 8.0; + static const double paddingLarge = 12.0; + static const double paddingXL = 13.0; + + // 阴影参数 + static const double shadowBlurRadius = 14.0; + static const double shadowSpreadRadius = 0.5; + static const Offset shadowOffset = Offset(2.0, 2.0); +} + +/// 学生和页码切换组件 /// +/// 提供作业批阅时的页码选择和学生选择功能,包含: +/// - 页码下拉选择框 +/// - 学生下拉选择框 +/// - 继续批阅按钮 +/// - 学生历史作业按钮 +/// - 学生笔迹查看按钮 class DropdownSwitchStudentsType extends StatelessWidget { const DropdownSwitchStudentsType({super.key}); @@ -24,19 +58,20 @@ class DropdownSwitchStudentsType extends StatelessWidget { @override Widget build(BuildContext context) { final logic = Get.find(); - final sateData = logic.state.data; + final stateData = logic.state.data; return Container( - height: 30.h, - padding: EdgeInsets.only(bottom: 2.r, left: 12.r, right: 12.r), + height: _Constants.containerHeight.h, + padding: EdgeInsets.only( + bottom: _Constants.paddingSmall.r, left: _Constants.paddingLarge.r, right: _Constants.paddingLarge.r), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( - color: const Color.fromRGBO(46, 91, 255, 0.2), - offset: Offset(2.w, 2.h), //阴影y轴偏移量 - blurRadius: 14, //阴影模糊程度 - spreadRadius: 0.5, //阴影扩散程度 + color: _Constants.shadowColor, + offset: Offset(_Constants.shadowOffset.dx.w, _Constants.shadowOffset.dy.h), + blurRadius: _Constants.shadowBlurRadius, + spreadRadius: _Constants.shadowSpreadRadius, ) ], ), @@ -44,149 +79,14 @@ class DropdownSwitchStudentsType extends StatelessWidget { children: [ Expanded( flex: 2, - child: Container( - padding: EdgeInsets.only(left: 10.w), - decoration: BoxDecoration( - color: const Color.fromRGBO(244, 244, 244, 1), - borderRadius: BorderRadius.circular(4.r), - ), - child: Obx(() { - return DropdownButton( - isExpanded: true, - underline: Container(), - padding: EdgeInsets.only(right: 4.w), - icon: const Icon(Icons.keyboard_arrow_down_rounded), - value: sateData.value?.templateId, - hint: const Text('请选择作业页码'), // 锚点的显示文本 - items: sateData.value?.templateIdKeys?.map((e) { - return DropdownMenuItem( - value: e, - child: quickText('${sateData.value!.templateIdKeyMap![e]}页', - color: const Color.fromRGBO(79, 79, 79, 1), size: 14.sp), - ); - }).toList(), - onChanged: (value) { - if (logic.state.param.value.templateId == value) return; - var templateIds = logic.state.data.value?.templateIds; - - if (value != null && templateIds != null) { - final templateIdKeyMap = logic.state.data.value?.templateIdKeyMap; - - var answeredAlready = templateIds[value.toString()]; - if (answeredAlready != null && !answeredAlready) { - final currentStudentId = sateData.value?.studentId; - final students = sateData.value?.students ?? []; - - // 获取当前学生姓名 - PaperStudents? currentStudent; - if (currentStudentId != null) { - try { - currentStudent = students.firstWhere((e) => e.id == currentStudentId); - } catch (e) { - currentStudent = null; - } - } - - final studentName = currentStudent?.name ?? '当前学生'; - final questionNumber = templateIdKeyMap?[value] ?? '当前选择页'; - - ToastUtils.showInfo("$studentName第$questionNumber页,未作答 无需批阅"); - return; - } - } - - logic.state.param.value.templateId = value; - logic.state.param.value = DoPaperDetailsParam.fromJson(logic.state.param.value.toJson()); - // _useSwitchStudentAndType.currentTab.value = _useSwitchStudentAndType.tabs.value.firstWhere((element) => element.pageIndex == value); - }, - ); - }), - ), + child: _buildPageDropdown(logic, stateData), ), - SizedBox(width: 8.w), + SizedBox(width: _Constants.paddingMedium.w), Expanded( flex: 3, - child: Stack( - children: [ - Container( - padding: EdgeInsets.only(left: 13.w), - decoration: BoxDecoration( - color: const Color.fromRGBO(244, 244, 244, 1), - borderRadius: BorderRadius.circular(4.r), - ), - child: Obx(() { - return DropdownButton( - padding: EdgeInsets.only(right: 4.w), - icon: const Icon(Icons.keyboard_arrow_down_rounded), - value: sateData.value?.studentId, - underline: Container(), - isExpanded: true, - items: sateData.value?.students.map((e) { - return DropdownMenuItem( - value: e.id, - child: Stack( - alignment: const FractionalOffset(0, 0.62), - children: [ - Container( - padding: sateData.value?.studentId != e.id && e.isPriority - ? EdgeInsets.only(left: 14.w) - : null, - child: quickText( - e.name, - size: 14.sp, - color: const Color.fromRGBO(79, 79, 79, 1), - ), - ), - if (e.isPriority && sateData.value?.studentId != e.id) - Stack( - alignment: const FractionalOffset(0.52, 0.24), - children: [ - Icon( - const IconData(0xe63d, fontFamily: "AlibabaIcon"), - size: 12.sp, - color: e.isPriority - ? Theme.of(context).primaryColor - : const Color.fromRGBO(164, 164, 164, 1), - ), - quickText('优先', size: 4.sp, color: Colors.white), - ], - ), - ], - ), - ); - }).toList(), - hint: const Text('请选择学生'), // 锚点的显示文本 - onChanged: (value) { - if (logic.state.param.value.studentId == value) return; - logic.state.param.value.studentId = value; - logic.state.param.value = DoPaperDetailsParam.fromJson(logic.state.param.value.toJson()); - }, - ); - }), - ), - Positioned( - left: 2.w, - child: Stack( - alignment: const FractionalOffset(0.52, 0.24), - children: [ - Obx(() { - return Icon( - const IconData(0xe63d, fontFamily: "AlibabaIcon"), - size: 12.sp, - color: sateData.value?.priority ?? false - ? Theme.of(context).primaryColor - : const Color.fromRGBO(164, 164, 164, 1), - ); - }), - quickText('优先', size: 4.sp, color: Colors.white), - ], - ), - ), - ], - ), + child: _buildStudentDropdown(context, logic, stateData), ), - // const Expanded(flex: 1, child: SizedBox()), - SizedBox(width: 8.w), + SizedBox(width: _Constants.paddingMedium.w), const Expanded( flex: 5, child: Row( @@ -203,137 +103,323 @@ class DropdownSwitchStudentsType extends StatelessWidget { ), ); } + + /// 构建页码下拉框 + Widget _buildPageDropdown(HomeworkReviewLogic logic, Rx stateData) { + return Container( + padding: EdgeInsets.only(left: 10.w), + decoration: BoxDecoration( + color: _Constants.backgroundColor, + borderRadius: BorderRadius.circular(_Constants.borderRadius.r), + ), + child: Obx(() { + final data = stateData.value; + return DropdownButton( + isExpanded: true, + underline: Container(), + padding: EdgeInsets.only(right: 4.w), + icon: const Icon(Icons.keyboard_arrow_down_rounded), + value: data?.templateId, + hint: const Text('请选择作业页码'), + items: data?.templateIdKeys?.map((e) { + return DropdownMenuItem( + value: e, + child: quickText( + '${data.templateIdKeyMap![e]}页', + color: _Constants.textColor, + size: _Constants.textSize.sp, + ), + ); + }).toList(), + onChanged: (value) => _handlePageChange(logic, value), + ); + }), + ); + } + + /// 构建学生下拉框 + Widget _buildStudentDropdown(BuildContext context, HomeworkReviewLogic logic, Rx stateData) { + return Container( + padding: EdgeInsets.only(left: _Constants.paddingXL.w), + decoration: BoxDecoration( + color: _Constants.backgroundColor, + borderRadius: BorderRadius.circular(_Constants.borderRadius.r), + ), + child: Obx(() { + final data = stateData.value; + return DropdownButton( + padding: EdgeInsets.only(right: 4.w), + icon: const Icon(Icons.keyboard_arrow_down_rounded), + value: data?.studentId, + underline: Container(), + isExpanded: true, + items: data?.students.map((student) { + return DropdownMenuItem( + value: student.id, + child: _buildStudentItem(context, student), + ); + }).toList(), + hint: const Text('请选择学生'), + onChanged: (value) => _handleStudentChange(logic, value), + ); + }), + ); + } + + /// 构建学生项目 + Widget _buildStudentItem(BuildContext context, PaperStudents student) { + return Stack( + alignment: const FractionalOffset(0, 0.5), + children: [ + Container( + padding: EdgeInsets.only(left: 16.w), + child: quickText( + student.name, + size: _Constants.textSize.sp, + color: _Constants.textColor, + ), + ), + Stack( + alignment: const FractionalOffset(0.52, 0.26), + children: [ + Icon( + const IconData(0xe63d, fontFamily: "AlibabaIcon"), + size: _Constants.iconSize.sp, + color: student.isPriority ? Theme.of(context).primaryColor : _Constants.priorityIconDisabledColor, + ), + quickText('优先', size: _Constants.tinyTextSize.sp, color: Colors.white), + ], + ), + ], + ); + } + + /// 处理页码变更 + void _handlePageChange(HomeworkReviewLogic logic, dynamic value) { + if (logic.state.param.value.templateId == value) return; + + final templateIds = logic.state.data.value?.templateIds; + if (value == null || templateIds == null) return; + + final templateIdKeyMap = logic.state.data.value?.templateIdKeyMap; + final answeredAlready = templateIds[value.toString()]; + + if (answeredAlready != null && !answeredAlready) { + _showUnansweredPageToast(logic.state.data.value, value, templateIdKeyMap); + return; + } + + logic.state.param.value.templateId = value; + logic.state.param.value = DoPaperDetailsParam.fromJson(logic.state.param.value.toJson()); + } + + /// 处理学生变更 + void _handleStudentChange(HomeworkReviewLogic logic, dynamic value) { + if (logic.state.param.value.studentId == value) return; + + logic.state.param.value.studentId = value; + logic.state.param.value = DoPaperDetailsParam.fromJson(logic.state.param.value.toJson()); + } + + /// 显示未作答页面提示 + void _showUnansweredPageToast(DoPaperDetailsResult? data, dynamic value, Map? templateIdKeyMap) { + final currentStudentId = data?.studentId; + final students = data?.students ?? []; + + // 获取当前学生姓名 + PaperStudents? currentStudent; + if (currentStudentId != null) { + try { + currentStudent = students.firstWhere((e) => e.id == currentStudentId); + } catch (e) { + currentStudent = null; + } + } + + final studentName = currentStudent?.name ?? '当前学生'; + final questionNumber = templateIdKeyMap?[value] ?? '当前选择页'; + + ToastUtils.showInfo("$studentName第$questionNumber页,未作答 无需批阅"); + } } @swidget Widget $studentHandwriting(BuildContext context) { final logic = Get.find(); - final sateData = Get.find().state.data; + final stateData = logic.state.data; + return InkWell( - onTap: () => easyThrottle( - 'SHOW_ANSWER_HANDWRITING', - () async { - var homeworkId = logic.state.param.value.homeworkId; - var studentId = sateData.value?.studentId; - if (studentId == null) return; - var templateIdKeyMap = sateData.value?.templateIdKeyMap; - int? pageNum; - var templateId = sateData.value?.templateId; - if (templateIdKeyMap != null && templateId != null) { - pageNum = templateIdKeyMap[templateId]; - } - await showAnswerHandwriting(context, - homeworkId: homeworkId, studentId: studentId, templateId: templateId, pageNum: pageNum); - ToastUtils.dismiss(); - }, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.edit_outlined, size: 12.sp, color: Theme.of(context).primaryColor.withOpacity(0.8)), - SizedBox(width: 1.w), - quickText( - '学生笔迹', - size: 12.sp, - decoration: TextDecoration.underline, - color: Theme.of(context).primaryColor.withOpacity(0.9), - ), - ], - )); + onTap: () => easyThrottle( + 'SHOW_ANSWER_HANDWRITING', + () async { + final data = stateData.value; + final studentId = data?.studentId; + if (studentId == null) return; + + final homeworkId = logic.state.param.value.homeworkId; + final templateId = data?.templateId; + final templateIdKeyMap = data?.templateIdKeyMap; + + int? pageNum; + if (templateIdKeyMap != null && templateId != null) { + pageNum = templateIdKeyMap[templateId]; + } + + await showAnswerHandwriting( + context, + homeworkId: homeworkId, + studentId: studentId, + templateId: templateId, + pageNum: pageNum, + ); + ToastUtils.dismiss(); + }, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.edit_outlined, + size: _Constants.iconSize.sp, + color: Theme.of(context).primaryColor.withOpacity(0.8), + ), + SizedBox(width: 1.w), + quickText( + '学生笔迹', + size: _Constants.smallTextSize.sp, + decoration: TextDecoration.underline, + color: Theme.of(context).primaryColor.withOpacity(0.9), + ), + ], + ), + ); } @swidget Widget $continueToReview(BuildContext context, {bool isFloatingAction = false}) { final logic = Get.find(); - final sateData = Get.find().state.data; + final stateData = logic.state.data; + return Obx(() { - var data = sateData.value; - var param = logic.state.param.value; - int? submitCount = data?.submitCount; // 提交数量 - int? annotatedCount = data?.annotatedCount; // 批阅数量 - // || (submitCount == annotatedCount || (param.templateId == null && param.studentId == null)) - // if (data == null || (data.needAnnotate ? true : data.totalUnAnnotateCount <= 0) ) return const SizedBox(); - if (data == null || - (data.needAnnotate - ? (data.continuePage == null ? true : data.continuePage!.templateId == data.templateId) - : data.totalUnAnnotateCount <= 0)) return const SizedBox(); - callFun() => easyThrottle( + final data = stateData.value; + + // 检查是否需要显示继续批阅按钮 + if (!_shouldShowContinueReview(data)) { + return const SizedBox(); + } + + void onPressed() => easyThrottle( 'DO_PAPERS_JOB_CONTINUE_TO_REVIEW', () { - var param = logic.state.param.value; + final param = logic.state.param.value; param.templateId = null; param.studentId = null; logic.state.param.value = DoPaperDetailsParam.fromJson(param.toJson()); }, ); + if (isFloatingAction) { return FloatingActionButton( elevation: 8, tooltip: "继续批阅", backgroundColor: Colors.white, - onPressed: callFun, - child: Icon(Icons.flip_camera_android_outlined, size: 20.sp, color: Theme.of(context).primaryColor), + onPressed: onPressed, + child: Icon( + Icons.flip_camera_android_outlined, + size: 20.sp, + color: Theme.of(context).primaryColor, + ), ); } - return SizedBox( - child: InkWell( - onTap: callFun, + + return InkWell( + onTap: onPressed, child: Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(Icons.flip_camera_android_outlined, size: 12.sp, color: Theme.of(context).primaryColor.withOpacity(0.8)), + Icon( + Icons.flip_camera_android_outlined, + size: _Constants.iconSize.sp, + color: Theme.of(context).primaryColor.withOpacity(0.8), + ), SizedBox(width: 1.w), quickText( '继续批阅', - size: 12.sp, + size: _Constants.smallTextSize.sp, decoration: TextDecoration.underline, color: Theme.of(context).primaryColor.withOpacity(0.9), ), SizedBox(width: 2.w), ], ), - )); + ); }); } -// 学生历史作业 +/// 检查是否应该显示继续批阅按钮 +bool _shouldShowContinueReview(DoPaperDetailsResult? data) { + if (data == null) return false; + + if (data.needAnnotate) { + return data.continuePage == null || data.continuePage!.templateId != data.templateId; + } else { + return data.totalUnAnnotateCount > 0; + } +} + +/// 学生历史作业 @swidget Widget $historyHomework(BuildContext context) { - final sateData = Get.find().state.data; - return SizedBox( - child: InkWell( - onTap: () => easyThrottle('DO_PAPERS_JOB_HISTORICAL_HOMEWORK', () { - int? studentId = sateData.value?.studentId; - if (kDebugMode) print(studentId); - if (studentId == null || (sateData.value?.students.isEmpty ?? true)) return; - PaperStudents? currentStudent; - try { - currentStudent = sateData.value!.students.firstWhere((e) => e.id == studentId); - } catch (e) { - return; - } - 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, - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.location_history, size: 12.sp, color: const Color.fromRGBO(104, 103, 103, 1)), - SizedBox(width: 1.w), - quickText( - '历史作业', - size: 12.sp, - decoration: TextDecoration.underline, - color: Theme.of(context).primaryColor.withOpacity(0.8), - ), - ], - ), + final logic = Get.find(); + final stateData = logic.state.data; + + return InkWell( + onTap: () => easyThrottle( + 'DO_PAPERS_JOB_HISTORICAL_HOMEWORK', + () => _navigateToStudentHistory(logic, stateData.value), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.location_history, + size: _Constants.iconSize.sp, + color: _Constants.iconColor, + ), + SizedBox(width: 1.w), + quickText( + '历史作业', + size: _Constants.smallTextSize.sp, + decoration: TextDecoration.underline, + color: Theme.of(context).primaryColor.withOpacity(0.8), + ), + ], ), ); } + +/// 导航到学生历史作业页面 +void _navigateToStudentHistory(HomeworkReviewLogic logic, DoPaperDetailsResult? data) { + final studentId = data?.studentId; + final students = data?.students ?? []; + + if (kDebugMode) print('Student ID: $studentId'); + + if (studentId == null || students.isEmpty) return; + + PaperStudents? currentStudent; + try { + currentStudent = students.firstWhere((e) => e.id == studentId); + } catch (e) { + if (kDebugMode) print('Student not found: $e'); + return; + } + + Get.toNamed(Routes.studentWorkDetailPage, arguments: { + 'studentId': studentId, + 'studentName': currentStudent.name, + 'subject': logic.state.param.value.subject, + }); +}