import 'dart:convert'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:collection/collection.dart'; 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:hooks_riverpod/hooks_riverpod.dart'; import 'package:marking_app/common/mixin/common.dart'; import 'package:marking_app/common/model/common/base_structure_result_report.dart'; import 'package:marking_app/common/model/report/detail_base_info.dart'; import 'package:marking_app/common/model/report/exam_records_all.dart'; import 'package:marking_app/common/model/report/question_know_point.dart'; import 'package:marking_app/common/model/report/report_card.dart'; import 'package:marking_app/common/model/report/report_card_params.dart'; import 'package:marking_app/common/model/report/small_question.dart'; import 'package:marking_app/pages/report_detail/widgets/basic_table.dart'; import 'package:marking_app/pages/report_detail/widgets/card_table.dart'; import 'package:marking_app/pages/report_detail/widgets/know_point_list.dart'; import 'package:marking_app/pages/report_detail/widgets/lab_title.dart'; import 'package:marking_app/pages/report_detail/widgets/no_data.dart'; import 'package:marking_app/pages/report_detail/widgets/overall_level_table.dart'; import 'package:marking_app/pages/report_detail/widgets/report_card_dialog.dart'; import 'package:marking_app/pages/report_detail/widgets/question_table.dart'; import 'package:marking_app/utils/request/rest_client_report.dart'; import 'package:marking_app/utils/toast_utils.dart'; class ReportDetail extends StatefulHookConsumerWidget { final int examId; final bool showGrade; const ReportDetail({Key? key, required this.examId, required this.showGrade}) : super(key: key); @override _ReportDetailState createState() => _ReportDetailState(); } class _ReportDetailState extends ConsumerState with CommonMixin { bool isGrade = true; bool isHasData = false; BaseInfo? baseInfo; BaseStructureResultReport? overallLevelRes; BaseStructureResultReport? knowPointRes; BaseStructureResultReport? smallQuestionRes; List subjectList = []; //科目 List classList = []; //班级 ComboData currentSubject = ComboData('', ''); ComboData currentClass = ComboData('', ''); // List questionClassList = []; //小题得分班级 ComboData questionCurrentClass = ComboData('', ''); bool isClass = false; // List cardHeadList = ['序号', '考号', '姓名', '班级', '分数', '班次', '校次']; List cardHeadList = []; //成绩单表头 List cardBodyList = []; //成绩单表格 int currentPage = 1; //成绩单当前页 int pageSize = 10; //成绩单当前页面请求数量 int totalPage = 1; //成绩单总页数 bool isRefresh = true; //防止请求未返回多次点击 List initialList = []; int questionCurrentPage = 1; //成绩单当前页 int questionTotalPage = 1; //成绩单总页数 bool questionIsRefresh = true; //防止请求未返回多次点击 void initState() { super.initState(); EasyLoading.show(status: 'loading...'); getClass(); } void getClass() async { RestClientReport clientReport = await getClientReport(); BaseStructureResultReport> res = await clientReport.getClassList(widget.examId); BaseStructureResultReport> subjecData = await clientReport.getExamsubject(widget.examId); setState(() { classList = List.from(res.data!); questionCurrentClass = ComboData(0, '全部', isCheck: true); classList.insert(0, questionCurrentClass); // classList[1].isCheck = true; currentClass = classList[1]; /* questionClassList = List.from(res.data!); questionCurrentClass =ComboData(0, '全部',isCheck: true); questionClassList.insert(0,questionCurrentClass);*/ subjectList = subjecData.data!; subjectList[0].isCheck = true; currentSubject = subjectList[0]; }); getBaseInfo(); } //基础信息,总体水平,重点关注 void getBaseInfo() async { RestClientReport clientReport = await getClientReport(); BaseStructureResultReport result = await clientReport.getReportDetail(widget.examId, widget.showGrade && isGrade ? -1 : currentClass.value); // print('*************result=${result.message}'); if (result.code == 200) { setState(() { currentPage = 1; questionCurrentPage = 1; overallLevelRes = result; if (result!.data != null) { baseInfo = result!.data!.baseInfo; } }); getQuestionTable(); getKnowPointTable(); getCard(); } else { Navigator.pop(context); EasyLoading.dismiss(); ToastUtils.showError(result.message.toString()); } } //小题得分 void getQuestionTable() async { RestClientReport clientReport = await getClientReport(); print( "%%%%%%%%%%%%%%%%%%%widget.examId=${widget.examId}&questionCurrentClass.value=${questionCurrentClass.value}¤tSubject.value=${currentSubject.value}"); ReportCardParams params = ReportCardParams( examId: widget.examId, classId: isGrade ? questionCurrentClass.value : currentClass.value, // classId: 494760774623317, subject: currentSubject.value, page: questionCurrentPage, limit: pageSize); BaseStructureResultReport res = await clientReport.getQuestion(params); print( 'res.data!.total=${res.code == 200 ? res.data!.bodyExcelData.sheets[0].bodyData.length : ''}'); if (res.code != 200 || res.data == null) { setState(() { smallQuestionRes = null; questionTotalPage = 0; }); } else { setState(() { smallQuestionRes = res; questionTotalPage = (res.data!.total / pageSize).ceil(); questionIsRefresh = true; }); } EasyLoading.dismiss(); } //知识点 void getKnowPointTable() async { RestClientReport clientReport = await getClientReport(); BaseStructureResultReport res = await clientReport.getKnowPoint( //494760774623317 widget.examId, isGrade ? questionCurrentClass.value : currentClass.value, currentSubject.value); setState(() { knowPointRes = res; }); EasyLoading.dismiss(); } void getCard() async { RestClientReport clientReport = await getClientReport(); ReportCardParams params = ReportCardParams( examId: widget.examId, classId: widget.showGrade && isGrade ? -1 : currentClass.value, page: currentPage, limit: pageSize); BaseStructureResultReport result = await clientReport.getReportCard(params); List head = result.data!.head; head.removeAt(0); List beforeList = ['序号', '考号', '姓名', '班级', '分数', '班次', '校次']; beforeList.addAll(head); cardHeadList = beforeList; List bodylist = []; initialList = result.data!.data; result.data!.data.forEach((item) { List arr = [ item.examNo, item.examStudentId, item.name, item.className, item.totalScore.toString(), item.totalClassRanking.toString(), item.totalRanking.toString() ]; item.subjectDetails.forEach((subject) { arr.add(subject.score); }); bodylist.add(arr); }); totalPage = (result.data!.totalCount / pageSize).ceil(); setState(() { cardBodyList = []; cardBodyList = bodylist; isRefresh = true; }); EasyLoading.dismiss(); } //成绩单详情 void showAlertDialog(BuildContext context, int index) { List detailHead = []; detailHead.addAll(cardHeadList.slice(5)); detailHead.insert(0, '总分'); showDialog( context: context, builder: (BuildContext context) { return AlertDialog( insetPadding: EdgeInsets.all(25.r), content: ReportCardDialog(initialList[index], detailHead), contentPadding: EdgeInsets.all(0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(15.r)))); }, ); } void refreshData(item, type, index) { setState(() { if (type == 'classList') { currentClass = item; currentPage = 1; } else if (type == 'questionClassList') { questionCurrentClass = item; questionCurrentPage = 1; } else if (type == 'subjectList') { currentSubject = item; questionCurrentPage = 1; } }); if (type == 'classList') { getBaseInfo(); } if (type == 'questionClassList' || type == 'subjectList' || !isGrade) { getQuestionTable(); getKnowPointTable(); } } void showSubjectDialog(BuildContext context, List list, String type, ComboData currentSelect) { showModalBottomSheet( context: context, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(10.r))), builder: (BuildContext context) { return StatefulBuilder(builder: (context, setDialogState) { return Container( padding: EdgeInsets.only(top: 20.r), height: list.length * 100.r, constraints: BoxConstraints(maxHeight: 300.r), child: ListView.builder( itemBuilder: (BuildContext context, int index) { var item = list?[index]; return InkWell( onTap: () { setDialogState(() { list.forEach((element) { element.isCheck = false; }); // item!.isCheck = true; if (item!.value == currentSelect.value) { item!.isCheck = true; } }); EasyLoading.show(status: 'loading...'); refreshData(item, type, index); Navigator.pop(context); }, child: type == 'classList' && index == 0 ? Container() : Padding( padding: EdgeInsets.symmetric(vertical: 10.r), child: Center( child: Text( item!.text, style: TextStyle( fontSize: 14.r, color: item.value == currentSelect.value // item.isCheck ? Color(0xFF5F81FD) : Color(0xFF2E2E2E)), ))), ); }, itemCount: list.length, ), ); }); }); } @override Widget build(BuildContext context) { if (baseInfo == null || overallLevelRes == null) { return Container(); } return AnnotatedRegion( value: SystemUiOverlayStyle( statusBarColor: Colors.transparent, systemNavigationBarIconBrightness: Brightness.light, statusBarBrightness: Brightness.dark, statusBarIconBrightness: Brightness.light, ), child: Container( color: Color(0xFFF8F9FF), child: Column( children: [ Padding( padding: EdgeInsets.only( top: MediaQuery.of(context).padding.top + 20.h, bottom: 20.r), child: Stack( alignment: const FractionalOffset(0.04, 0.1), children: [ Container( width: MediaQuery.of(context).size.width - 50.r, margin: EdgeInsets.only(left: 50.r), alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Center( child: Text( // '2023-2024学年度(上)高一年级期末考试高一年级期末考试高一年级期末考试高一年级期末考试高一年级期末考试级期末考试高一年级期末考试级期末考试高一年级期末考试级期末考试高一年级期末考试级期末考试高一年级期末考试级期末考试高一年级期末考试', baseInfo!.examName, style: TextStyle( fontSize: 16.sp, color: Color(0xFF2D384C)), ), ), ], ), ), InkWell( onTap: () => Navigator.pop(context), child: Icon(Icons.arrow_back_ios_new_rounded, color: Color(0xFF505767), size: 24.sp), ), ], ), ), if (widget.showGrade) Container( margin: EdgeInsets.only(left: 20.r, right: 20.r, bottom: 10.r), width: MediaQuery.of(context).size.width - 40.r, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20.r), color: Colors.white, boxShadow: [ BoxShadow( color: Color(0x566787FD), offset: Offset(1.0, 1.0), //阴影xy轴偏移量 blurRadius: 10.0, //阴影模糊程度 spreadRadius: 0.1, //阴影扩散程度 ) ]), child: Flex( direction: Axis.horizontal, children: [ Expanded( flex: 1, child: InkWell( onTap: () { setState(() { isGrade = true; }); EasyLoading.show(status: 'loading...'); getBaseInfo(); }, child: Container( padding: EdgeInsets.symmetric(vertical: 10.r), decoration: BoxDecoration( color: isGrade ? Color(0xFF6787FD) : Colors.white, borderRadius: BorderRadius.circular(20.r), ), child: Center( child: Text( '年级', style: TextStyle( fontSize: 14.sp, color: isGrade ? Colors.white : Colors.black), )), ), ), ), Expanded( flex: 1, child: InkWell( onTap: () { setState(() { isGrade = false; }); EasyLoading.show(status: 'loading...'); getBaseInfo(); }, child: Container( padding: EdgeInsets.symmetric(vertical: 10.r), decoration: BoxDecoration( color: !isGrade ? Color(0xFF6787FD) : Colors.white, borderRadius: BorderRadius.circular(20.r), ), child: Center( child: Text( '班级', style: TextStyle( fontSize: 14.sp, color: !isGrade ? Colors.white : Colors.black), ), ), ), ), ), // Text('99'), ], ), ), //基本信息 Expanded( child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (!widget.showGrade || !isGrade) Padding( padding: EdgeInsets.only(left: 16.r), child: Row( children: [ Text( '班级:', style: TextStyle( fontSize: 14.sp, color: Color(0xFF474747)), ), InkWell( onTap: () { showSubjectDialog(context, classList, 'classList', currentClass); }, child: Container( padding: EdgeInsets.symmetric( vertical: 3.r, horizontal: 30.r), decoration: BoxDecoration( color: Color.fromRGBO(197, 223, 255, 0.31), border: Border.all( width: 1.r, color: Color(0xFFC0DCFF)), borderRadius: BorderRadius.all(Radius.circular(20.r)), ), child: Text( currentClass.text, style: TextStyle( fontSize: 14.r, color: Color(0xFF6787FD), fontWeight: FontWeight.w500), ), ), ) ], ), ), LabTitle('基本信息', 'assets/images/basic_info.png'), BasicTable(baseInfo, !widget.showGrade || !isGrade), LabTitle('总体水平', 'assets/images/overall_level.png'), overallLevelRes!.data!.module1CJZL != null && overallLevelRes! .data!.module1CJZL.sheets[0].bodyData.length > 0 ? Container( height: overallLevelRes! .data!.module1CJZL.sheets[0].bodyData.length>5? 300.r : overallLevelRes! .data!.module1CJZL.sheets[0].bodyData.length * 50.r + 40.r, padding: EdgeInsets.symmetric(horizontal: 14.r), child: CardList( headList: overallLevelRes! .data!.module1CJZL.sheets[0].headData, bodyList: overallLevelRes! .data!.module1CJZL.sheets[0].bodyData, isScore: true, fixedRows: 1, fixedCols: 1, ), ):NoData(), // OverallLevelTable(overallLevelRes!.data!.module1CJZL.sheets[0]), LabTitle('重点关注学生', 'assets/images/reports_focus.png'), overallLevelRes!.data!.module2ZDGZ.topExcelData != null ? /*OverallLevelTable(overallLevelRes! .data!.module2ZDGZ.topExcelData?.sheets[0])*/ Container( height: 300.r, padding: EdgeInsets.symmetric(horizontal: 14.r), child: CardList( headList: overallLevelRes! .data!.module2ZDGZ.topExcelData!.sheets[0].headData, bodyList: overallLevelRes! .data!.module2ZDGZ.topExcelData!.sheets[0].bodyData, isScore: true, isHtml:true, fixedRows: 1, fixedCols: 1, ), ) : NoData(), SizedBox( height: 20.r, ), if (overallLevelRes!.data!.module2ZDGZ.topExcelData != null) /* OverallLevelTable(overallLevelRes! .data!.module2ZDGZ.bottomExcelData?.sheets[0]),*/ Container( height: 300.r, padding: EdgeInsets.symmetric(horizontal: 14.r), child: CardList( headList: overallLevelRes! .data!.module2ZDGZ.bottomExcelData!.sheets[0].headData, bodyList: overallLevelRes! .data!.module2ZDGZ.bottomExcelData!.sheets[0].bodyData, isScore: true, isHtml:true, fixedRows: 1, fixedCols: 1, ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ LabTitle('小题得分', 'assets/images/reports_score.png'), Expanded( child: Text(''), ), if (isGrade) Container( padding: EdgeInsets.symmetric( vertical: 2.r, horizontal: 10.r), margin: EdgeInsets.only(right: 14.r), decoration: BoxDecoration( color: Color(0xFF6787FD), borderRadius: BorderRadius.all(Radius.circular(15.r)), ), child: InkWell( onTap: () { showSubjectDialog( context, classList, 'questionClassList', questionCurrentClass); }, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( questionCurrentClass.text, style: TextStyle( fontSize: 14.sp, color: Colors.white, fontWeight: FontWeight.w500), ), Padding( padding: EdgeInsets.only(left: 8.r), child: Image.asset( 'assets/images/right_icon.png', width: 6.r, height: 10.r, ), ) ], ), ), ), Container( padding: EdgeInsets.symmetric( vertical: 2.r, horizontal: 10.r), margin: EdgeInsets.only(right: 14.r), decoration: BoxDecoration( color: Color(0xFF6787FD), borderRadius: BorderRadius.all(Radius.circular(15.r)), ), child: InkWell( onTap: () { showSubjectDialog(context, subjectList, 'subjectList', currentSubject); }, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( currentSubject.text, style: TextStyle( fontSize: 14.sp, color: Colors.white, fontWeight: FontWeight.w500), ), Padding( padding: EdgeInsets.only(left: 8.r), child: Image.asset( 'assets/images/right_icon.png', width: 6.r, height: 10.r, ), ) ], ), ), ), ], ), if (knowPointRes != null) Container( // color: Colors.white, margin: EdgeInsets.symmetric(horizontal: 14.r), padding: EdgeInsets.only(bottom: 10.r, top: 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ (smallQuestionRes != null && smallQuestionRes!.data!.bodyExcelData .sheets[0].headData.length > 0 && smallQuestionRes!.data!.bodyExcelData .sheets[0].bodyData.length > 0) ? SizedBox( height: smallQuestionRes! .data! .bodyExcelData .sheets[0] .bodyData .length > 9 ? 300.r : smallQuestionRes! .data! .bodyExcelData .sheets[0] .bodyData .length * 50.r + 40.r, // width: MediaQuery.of(context).size.width, child: CardList( headList: smallQuestionRes!.data! .bodyExcelData.sheets[0].headData, bodyList: smallQuestionRes!.data! .bodyExcelData.sheets[0].bodyData, isScore: true, fixedRows: 1, fixedCols: 3, ), ) : NoData(), if (smallQuestionRes != null && smallQuestionRes!.data!.bodyExcelData .sheets[0].bodyData.length > 0) Padding( padding: EdgeInsets.only(right: 14.r, top: 6.r), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ InkWell( onTap: () { setState(() { if (questionCurrentPage > 1 && questionIsRefresh) { questionIsRefresh = false; questionCurrentPage = questionCurrentPage - 1; getQuestionTable(); EasyLoading.show( status: 'loading...'); } }); }, child: Container( padding: EdgeInsets.symmetric( vertical: 2.r, horizontal: 5.r), decoration: BoxDecoration( border: Border.all( color: questionCurrentPage == 1 ? Color(0xFFB3B9B9) : Color(0xFF6787FD), width: 1.r), borderRadius: BorderRadius.all( Radius.circular(2.r)), ), child: Text( '上一页', style: TextStyle( color: questionCurrentPage == 1 ? Color(0xFFB3B9B9) : Color(0xFF6787FD)), ), )), SizedBox( width: 15.r, ), InkWell( onTap: () { setState(() { if (questionCurrentPage < totalPage && questionIsRefresh) { questionIsRefresh = false; questionCurrentPage = questionCurrentPage + 1; getQuestionTable(); EasyLoading.show( status: 'loading...'); } }); }, child: Container( padding: EdgeInsets.symmetric( vertical: 2.r, horizontal: 5.r), decoration: BoxDecoration( border: Border.all( color: questionTotalPage - questionCurrentPage > 0 ? Color(0xFF6787FD) : Color(0xFFB3B9B9), width: 1.r), borderRadius: BorderRadius.all( Radius.circular(2.r)), ), child: Text( '下一页', style: TextStyle( color: questionTotalPage - questionCurrentPage > 0 ? Color(0xFF6787FD) : Color(0xFFB3B9B9)), ), )) ], ), ), Padding( padding: EdgeInsets.symmetric( vertical: 10.r, horizontal: 10.r), child: Text( '知识点分析', style: TextStyle( fontSize: 16.sp, color: Color(0xFF2D384C), fontWeight: FontWeight.w500), ), ), knowPointRes!.data!.knowPointList.length > 0 ? SizedBox( height: 300.r, child: KnowPointTable( knowPointRes!.data!.knowPointList), ) : NoData(), /* knowPointRes!.data!.knowPointList.length > 0 ? KnowPointTable( knowPointRes!.data!.knowPointList) : NoData(),*/ ], ), ), LabTitle('成绩单', 'assets/images/reports_card.png'), if (cardBodyList.length > 0) Container( // width: MediaQuery.of(context).size.width, height: 330.r, margin: EdgeInsets.symmetric(horizontal: 14.r), child: CardList( headList: cardHeadList, bodyList: cardBodyList, showCardDetail: showAlertDialog, fixedRows: 1, fixedCols: 3, ), ), if (cardBodyList.length > 0) Padding( padding: EdgeInsets.only(right: 14.r, top: 6.r), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ InkWell( onTap: () { setState(() { if (currentPage > 1 && isRefresh) { isRefresh = false; currentPage = currentPage - 1; getCard(); EasyLoading.show(status: 'loading...'); } }); }, child: Container( padding: EdgeInsets.symmetric( vertical: 2.r, horizontal: 5.r), decoration: BoxDecoration( border: Border.all( color: currentPage == 1 ? Color(0xFFB3B9B9) : Color(0xFF6787FD), width: 1.r), borderRadius: BorderRadius.all( Radius.circular(2.r)), ), child: Text( '上一页', style: TextStyle( color: currentPage == 1 ? Color(0xFFB3B9B9) : Color(0xFF6787FD)), ), ) /*Icon(Icons.keyboard_arrow_left, color: currentPage == 1 ? Color(0xFFB3B9B9) : Color(0xFF505767), size: 24.sp),*/ ), SizedBox( width: 15.r, ), InkWell( onTap: () { setState(() { if (currentPage < totalPage && isRefresh) { isRefresh = false; currentPage = currentPage + 1; getCard(); EasyLoading.show(status: 'loading...'); } }); }, child: Container( padding: EdgeInsets.symmetric( vertical: 2.r, horizontal: 5.r), decoration: BoxDecoration( border: Border.all( color: totalPage - currentPage > 0 ? Color(0xFF6787FD) : Color(0xFFB3B9B9), width: 1.r), borderRadius: BorderRadius.all( Radius.circular(2.r)), ), child: Text( '下一页', style: TextStyle( color: totalPage - currentPage > 0 ? Color(0xFF6787FD) : Color(0xFFB3B9B9)), ), ) /*Icon(Icons.keyboard_arrow_right, color: totalPage - currentPage > 0 ? Color(0xFF505767) : Color(0xFFB3B9B9), size: 24.sp),*/ ) ], ), ), if (cardBodyList.length == 0) NoData(), SizedBox( height: 20.r, ), ], ), ), ), ], ), )); } }