import 'package:achievement_view/achievement_view.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:functional_widget_annotation/functional_widget_annotation.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:marking_app/common/mixin/common.dart'; import 'package:marking_app/common/model/common/base_page_data_report.dart'; import 'package:marking_app/common/model/common/base_structure_result_report.dart'; import 'package:marking_app/common/model/enum/reportUserIdentity.dart'; import 'package:marking_app/common/model/report/exam_records.dart'; import 'package:marking_app/common/model/report/exam_records_all.dart'; import 'package:marking_app/common/model/report/exam_records_params.dart'; import 'package:marking_app/common/model/report/report_histogram_model.dart'; import 'package:marking_app/common/model/report/report_home_model.dart'; import 'package:marking_app/common/model/user/user_info.dart'; import 'package:marking_app/common/model/user/user_info_report.dart'; import 'package:marking_app/pages/report_detail/widgets/no_data.dart'; import 'package:marking_app/pages/reports/bar_chart_histogram.dart'; import 'package:marking_app/pages/reports/services/report_home_services.dart'; import 'package:marking_app/provider/user_provider.dart'; import 'package:marking_app/routes/RouterManager.dart'; import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart'; import 'package:marking_app/utils/index.dart'; import 'package:marking_app/utils/my_text.dart'; import 'package:marking_app/utils/request/rest_client_report.dart'; import 'package:percent_indicator/linear_percent_indicator.dart'; import 'widgets/myDrawer.dart'; import 'widgets/userInfo.dart'; part 'index.g.dart'; class TheReport extends StatefulHookConsumerWidget { const TheReport({Key? key}) : super(key: key); @override _TheReportState createState() => _TheReportState(); } class _TheReportState extends ConsumerState with CommonMixin, AutomaticKeepAliveClientMixin { late RemoveListener _userReportListener; late RestClientReport ClientReport; late UserInfo _user; late UserInfoReport _userReport; late Future _future; int? theExamId; List gradeList = []; List testTypeList = []; List selectList = []; bool isGrade = false; ComboData currentGrade = ComboData('', ''); ComboData currentTestType = ComboData('', ''); List reportList = []; bool showGrade = false; @override bool get wantKeepAlive => true; @override void initState() { getHomeComboExam(); // getExamTypeList(); // getGradeEnumList(); // _future = initData(); Future.delayed(Duration.zero, () { _user = ref.read(userProvider); _userReportListener = ref.read(userReportProvider.notifier).addListener( (state) { _userReport = state; if (_userReport.normal) { // _future = initData(); toUpState(setState, () {}, mounted); } }, ); }); super.initState(); } @override void dispose() { _userReportListener(); super.dispose(); } //获取考试类别、年级 void getHomeComboExam() async { RestClientReport clientReport = await getClientReport(); BaseStructureResultReport res = await clientReport.getHomeCombo(); testTypeList = res.data!.type.comboData; gradeList = res.data!.grade.comboData; testTypeList[0].isCheck = true; gradeList[0].isCheck = true; setState(() { currentTestType = testTypeList[0]; currentGrade = gradeList[0]; }); // getExamRecordsList(); getLevel(); } //获取考试类别 /* void getExamTypeList() async { RestClientReport clientReport = await getClientReport(); BaseStructureResultReport res = await clientReport.getExamType(); testTypeList = res.data!.comboData; testTypeList[0].isCheck = true; setState(() { currentTestType = testTypeList[0]; }); }*/ /* //获取年级 void getGradeEnumList() async { RestClientReport clientReport = await getClientReport(); BaseStructureResultReport> result = await clientReport.getGradeEnum(); gradeList = result.data!; print(gradeList); gradeList[0].isCheck = true; setState(() { currentGrade = gradeList[0]; }); }*/ //获取列表数据 void getExamRecordsList() async { RestClientReport clientReport = await getClientReport(); ExamRecordsParams params = ExamRecordsParams( reportType: currentTestType.value, grade: currentGrade.value, page: 1, limit: 10); BaseStructureResultReport> result = await clientReport.getExamrecords(params); setState(() { reportList = result.data!.items; }); } void checkHandle(item) { setState(() { if (isGrade) { gradeList.forEach((element) { element.isCheck = false; }); item.isCheck = true; currentGrade = item; } else { testTypeList.forEach((element) { element.isCheck = false; }); item.isCheck = true; currentTestType = item; } }); } void getLevel() async { getExamRecordsList(); RestClientReport clientReport = await getClientReport(); BaseStructureResultReport res = await clientReport.getPositionlevel(currentGrade.text); if (res.data <= 3) { showGrade = true; }else{ showGrade = false; } } /// 初始化数据 Future initData({int? examId}) async { try { RestClientReport clientReport = await getClientReport(); UserInfoReport _userReport = ref.read(userReportProvider); if (!_userReport.normal) { if(ref.read(userProvider).id == '540117143121989') return null; // 用户职位数据是否已经请求,在主页已经请求一次 为正常使用 备用 bool theFlag = await ref.read(userReportProvider.notifier).initUserReport(); if (!theFlag) { return ToastUtils.showError('请求失败请重试'); } } BaseStructureResultReport res = await clientReport.getReportHomeData(examId); if (res.success) { return res.data; } else { ToastUtils.showError(res.message ?? '请求错误,请重试'); } } catch (e) { if (e is CheckedFromJsonException) { // JSON 解析失败,处理异常 toPrint(val: 'JSON 解析失败: ${e.message}'); toPrint(val: 'JSON 解析失败,出错字段: ${e.key}'); } else { // 其他异常,处理其他错误 toPrint(val: '发生了其他错误: $e'); } return null; } return null; } var _scaffoldkey = new GlobalKey(); //将Scaffold设置为全局变量 @override Widget build(BuildContext context) { super.build(context); //调用super.build(返回值始终返回null,应将其忽略) final userState = ref.watch(userProvider); return AnnotatedRegion( value: const SystemUiOverlayStyle( systemNavigationBarColor: Color(0xFF000000), systemNavigationBarDividerColor: null, statusBarColor: Colors.transparent, systemNavigationBarIconBrightness: Brightness.light, statusBarIconBrightness: Brightness.dark, statusBarBrightness: Brightness.light, ), child: Scaffold( key: _scaffoldkey, drawer: MyDrawer( list: selectList, isGrade: isGrade, onChanged: checkHandle, refresh: getLevel), body: Column( children: [ Container( color: Colors.white, padding: EdgeInsets.only( top: MediaQuery.of(context).padding.top + 4.h, left: 14.w, right: 14.w, bottom: 19.h), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: TopUserInfo(), ), /* InkWell( onTap: () {}, child: Text( '历史报告', style: TextStyle( fontSize: 14.sp, color: Color.fromRGBO(128, 128, 128, 1)), ), ),*/ ], ), ), Expanded( child: Padding( padding: EdgeInsets.only(left: 14.w, right: 14.w), child: Column( children: [ SizedBox( height: 50.r, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset( 'assets/images/school_icon.png', width: 22.w, height: 22.w, ), Text( userState.schoolName, style: TextStyle( fontSize: 14.sp, color: Color.fromRGBO(62, 86, 173, 1)), ) ], ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ InkWell( onTap: () { setState(() { selectList = gradeList; isGrade = true; _scaffoldkey.currentState?.openDrawer(); }); }, child: Container( padding: EdgeInsets.symmetric( vertical: 8.h, horizontal: 20.r), width: (MediaQuery.of(context).size.width - 80.r) / 2, child: Row( children: [ Text( '年级:', style: TextStyle( fontSize: 12.sp, color: Color(0xFF585858)), ), Text( currentGrade.text, style: TextStyle( fontSize: 12.sp, color: Color(0xFF6686FD)), ), ], ), decoration: BoxDecoration( color: Color.fromRGBO(197, 220, 255, 0.3), borderRadius: BorderRadius.circular(20.r), border: Border.all( color: Color(0xFFC0DCFF), width: 1.r), ), ), ), InkWell( onTap: () { setState(() { selectList = testTypeList; isGrade = false; _scaffoldkey.currentState?.openDrawer(); }); }, child: Container( padding: EdgeInsets.symmetric( vertical: 8.h, horizontal: 20.r), width: (MediaQuery.of(context).size.width - 80.r) / 2, child: Row( children: [ Text( '考试类别:', style: TextStyle( fontSize: 12.sp, color: Color(0xFF585858)), ), Text( currentTestType.text, style: TextStyle( fontSize: 12.sp, color: Color(0xFF6686FD)), ), ], ), decoration: BoxDecoration( color: Color.fromRGBO(197, 220, 255, 0.3), borderRadius: BorderRadius.circular(20.r), border: Border.all( color: Color(0xFFC0DCFF), width: 1.r), ), ), ) ], ), SizedBox( height: 20.r, ), Expanded( child: reportList.length>0?ListView.builder( itemBuilder: (BuildContext context, int index) { var item = reportList[index]; return Container( // padding: EdgeInsets.all(6.r), margin: EdgeInsets.only(bottom: 20.r), width: double.infinity, decoration: BoxDecoration( image: DecorationImage( image: AssetImage( 'assets/images/reports_bg.png'), fit: BoxFit.fill, ), border: Border.all( width: 1.r, color: Color.fromRGBO(46, 91, 255, 0.2)), borderRadius: BorderRadius.circular(5.r), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(top: 5.r,bottom: 5.r,right: 2.r), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( padding: EdgeInsets.symmetric( vertical: 20.r, horizontal: 25.r), decoration: BoxDecoration( image: DecorationImage( image: AssetImage( 'assets/images/report_group_bg.png'), fit: BoxFit.fill, )), child: Text( item.typeName, style: TextStyle( fontSize: 12.sp, color: Colors.white), ), ), Flexible( child: Text( item.name, style: TextStyle( fontSize: 14.sp, color: Colors.black), ), ) ], ), ), Container( padding: EdgeInsets.symmetric(horizontal: 10.r), decoration: BoxDecoration( borderRadius: BorderRadius.circular(5.r), ), child: Table( defaultVerticalAlignment: TableCellVerticalAlignment.middle, border: TableBorder.symmetric( inside: BorderSide( width: 1, color: Color(0xFFD7DBF0)), outside: BorderSide.none, ), // borderRadius: BorderRadius.circular(5.r), children: [ TableRow( decoration: BoxDecoration( color: Color(0xFFECECEC), ), children: [ Center( child: Container( padding: EdgeInsets.symmetric( vertical: 6.r), child: Text( '年级', style: TextStyle( fontSize: 14.sp, color: Color(0xFF8A8A8A)), ), ), ), Center( child: Text( '科目', style: TextStyle( fontSize: 14.sp, color: Color(0xFF8A8A8A)), ), ), Center( child: Text( '考试日期', style: TextStyle( fontSize: 14.sp, color: Color(0xFF8A8A8A)), ), ), ], ), TableRow( decoration: BoxDecoration( color: Colors.white, ), children: [ Center( child: Container( padding: EdgeInsets.symmetric( vertical: 6.r), child: Text( item.grade, style: TextStyle( fontSize: 14.sp, color: Color(0xFF4A4A4A)), ), ), ), Center( child: Text( item.subjectStr, style: TextStyle( fontSize: 14.sp, color: Color(0xFF4A4A4A)), ), ), Center( child: Text( item.startTimeStr, style: TextStyle( fontSize: 14.sp, color: Color(0xFF4A4A4A)), ), ), ]) ], ), ), InkWell( onTap: () { RouterManager.router.navigateTo( context, RouterManager.reportDetailPath + '?examId=${item.id}&showGrade=${showGrade}', transition: getTransition(), ); }, child: Container( margin: EdgeInsets.symmetric( horizontal: 60.r, vertical: 20.r), padding: EdgeInsets.symmetric(vertical: 5.r), width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20.r), gradient: LinearGradient( begin: Alignment(0.95, -0.30), end: Alignment(-0.95, 0.3), colors: [ Color(0xFF3561FE), Color(0xFF6A89FC) ])), child: Center( child: Text( '查看报告', style: TextStyle( fontSize: 16.sp, color: Colors.white), )), ), ) ], ), ); }, itemCount: reportList.length, ):MyEmptyWidget(), ), ], ), ), ) ], )), ); } } // 报告body class _TheReportBody extends HookWidget { final UserInfo user; final UserInfoReport userReport; final ReportHomeModel? data; final Function(int? examId, int positionIndex) switchCall; final Function() refreshReport; _TheReportBody( {required this.user, required this.userReport, required this.switchCall, required this.refreshReport, required this.data, Key? key}) : super(key: key); @override Widget build(BuildContext context) { ExamData? examData = data?.examData; List? tagComparisonList = examData?.tagComparisonList .map((e) => ReportHistogramModel(name: e.name, val: e.count)) .toList(); List? examSubjectDatas = data?.examSubjectDatas; List _positions = userReport.positions; SwitchIdentityExamsController potnAndExamCotl = SwitchIdentityExamsController.use( position: userReport.positionIndex, exam: -1, initExamId: examData?.examId, positons: userReport.positions); Positions? theCurrentPosition = _positions.isEmpty ? null : _positions[potnAndExamCotl.positionIndex.value]; if (examData == null || theCurrentPosition == null) { return Padding( padding: EdgeInsets.only( left: 16.w, right: 16.w, top: MediaQuery.of(context).padding.top), child: Column( children: [ $ReportTitle( titleName: '', switchCall: () => easyThrottle('reportHomeExamSwitchCall', () async { // switchCall(examId, potnAndExamCotl.positionIndex.value); List positions = userReport.positions; if (positions.isEmpty) { return ToastUtils.showInfo('没有数据,请刷新'); } int? examId = await potnAndExamCotl.openSwitch( context: context, currentExamId: examData?.examId ?? -1, currentPositionIndex: userReport.positionIndex); switchCall(examId, potnAndExamCotl.positionIndex.value); }), ), Expanded( child: Center( child: Container( child: CupertinoButton( padding: const EdgeInsets.only(left: 10, right: 10), color: Theme.of(context).primaryColor, //按钮被按下时的不透明度程度,0~1之间 pressedOpacity: 1, //这也可以自己定义Container然后固定大小进行设置等等 child: quickText('没有数据,请重试', color: Colors.white, size: 14.sp), onPressed: () => easyThrottle( 'reportHomeNoDataAgain', () => refreshReport()), ), ), ), ) ], ), ); } // 内容区域 return Padding( padding: EdgeInsets.only( left: 16.w, right: 16.w, top: MediaQuery.of(context).padding.top), child: Column( children: [ SizedBox(height: 6.h), // 考试报告TITLE $ReportTitle( titleName: examData.examName, switchCall: () => easyThrottle('reportHomeExamSwitchCall', () async { List positions = userReport.positions; if (positions.isEmpty) { return ToastUtils.showInfo('没有数据,请刷新'); } int? examId = await potnAndExamCotl.openSwitch( context: context, currentExamId: examData.examId, currentPositionIndex: userReport.positionIndex); switchCall(examId, potnAndExamCotl.positionIndex.value); }), ), Expanded( child: ScrollConfiguration( behavior: EUMNoScrollBehavior(), child: ListView( padding: EdgeInsets.only(top: 20.h, bottom: 20.h), children: [ // 顶部平均分模块 $TopAverageContainer( averageVal: examData.averageScore, totalVal: examData.totalScore, context: context), // 详细报告入口区域 $DetailedReportEntry( context: context, examId: examData.examId, subjectId: theCurrentPosition.subjectId, classId: theCurrentPosition.classId, grade: examData.grade, subject: examData.subjects, examDate: examData.startTime, identity: theCurrentPosition.identityEnum, subjectName: theCurrentPosition.subjectName ?? '', ), // 分段情况 $GraphicDataArea( title: '分段概况', titleImg: 'assets/images/report_home_icon_burst.png', graphicContainer: Padding( padding: EdgeInsets.only(top: 60.h, bottom: 20.h), child: BarChartSample3(tagComparisonList!), )), // 单科概况 $GraphicDataArea( title: '单科概况', titleImg: 'assets/images/report_home_icon_subject.png', graphicContainer: $TheProgressChart(context, examSubjectDatas!)), ], ), ), ), ], ), ); } } /// 底部渐变色 @swidget Widget $scaffoldBgc() { return Container( height: ScreenUtil().screenHeight, width: ScreenUtil().screenWidth, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color.fromRGBO(226, 232, 255, 1), Colors.white, Colors.white], ), ), ); } // 页面TITLE @swidget Widget $reportTitle({required String titleName, required switchCall}) { return Stack( alignment: const FractionalOffset(0.98, 0.5), children: [ Container( padding: EdgeInsets.only(right: titleName.length > 14 ? 50 : 0).w, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded( child: Center( child: quickText( titleName, size: 16.sp, color: Color.fromRGBO(45, 56, 76, 1), fontWeight: FontWeight.w600, maxLines: 2, ), ), ), ], ), ), InkWell( onTap: () => easyThrottle('switchRoleExamSheetCall', () => switchCall()), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.swap_vert_rounded, color: Color.fromRGBO(80, 87, 103, 0.8), size: 16.sp), quickText('切换', color: Color.fromRGBO(80, 87, 103, 1), size: 12.sp), ], ), ) ], ); } /// 顶部平均分模块 @swidget Widget $topAverageContainer( {required double averageVal, required double totalVal, required BuildContext context}) { return Stack( alignment: const FractionalOffset(0.99, 0), children: [ Container( padding: EdgeInsets.only(left: 12.w), child: Row( children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.circular(3).r, child: Container( alignment: Alignment.centerLeft, padding: EdgeInsets.only(left: 4, right: 4, top: 4, bottom: 7).r, child: quickText('平均分', size: 6.sp, color: Colors.white), decoration: ShapeDecoration( shape: BeveledRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(2).r, topRight: Radius.circular(2).r, bottomLeft: Radius.circular(15).r, bottomRight: Radius.circular(15).r, ), ), gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Theme.of(context).primaryColor, Theme.of(context).primaryColor.withOpacity(0.3) ], ), ), ), ), SizedBox(height: 1.h), quickText(averageVal.toString(), size: 38.sp, color: Color.fromRGBO(45, 56, 76, 1), fontWeight: FontWeight.bold), SizedBox(height: 1.h), quickText('满分' + totalVal.toString(), size: 12.sp, color: Color.fromRGBO(80, 87, 103, 0.7)), ], ), ], ), ), Image.asset("assets/images/report_home_top_img.png", width: 100.r, height: 100.r) ], ); } /// 详细报告入口模块 @swidget Widget $detailedReportEntry({ required String grade, required String subject, required String examDate, required int examId, required int? classId, required int? subjectId, required ReportUserIdentity identity, required String subjectName, required BuildContext context, }) { return Container( width: double.infinity, margin: EdgeInsets.only(top: 6.h, bottom: 28.h), // constraints: BoxConstraints( // minHeight: 140.h, // minWidth: double.infinity, // maxHeight: 160.h, // maxWidth: double.infinity, // ), padding: EdgeInsets.symmetric(horizontal: 18.w, vertical: 16.h), decoration: BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/detailed_report_entry_bgm.png'), fit: BoxFit.fill, ), ), child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ quickText('年级', size: 12.sp, color: Color.fromRGBO(80, 87, 103, 1)), SizedBox(height: 5.h), quickText(grade, size: 16.sp, fontWeight: FontWeight.bold, color: Color.fromRGBO(45, 56, 76, 1)), ], ), SizedBox(width: 23.w), Expanded( child: Column( mainAxisSize: MainAxisSize.min, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ quickText('学科', size: 12.sp, color: Color.fromRGBO(80, 87, 103, 1)), SizedBox(height: 5.h), quickText(subject, size: 16.sp, fontWeight: FontWeight.bold, color: Color.fromRGBO(45, 56, 76, 1), maxLines: 2), ], ) ], ), ), SizedBox(width: 23.w), Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ quickText('考试日期', size: 12.sp, color: Color.fromRGBO(80, 87, 103, 1)), SizedBox(height: 5.h), quickText(examDate, size: 16.sp, fontWeight: FontWeight.bold, color: Color.fromRGBO(45, 56, 76, 1)), ], ), ], ), SizedBox(height: 30.h), InkWell( onTap: () => easyThrottle('reportToUserPositionDetails', () { String rootPath; switch (identity) { case ReportUserIdentity.TEACHER: // 单科老师 rootPath = RouterManager.reportSubjectTeacherPath + '?examId=$examId&classId=$classId&subject=$subjectId&subjectName=${Uri.encodeComponent(subjectName)}'; break; case ReportUserIdentity.CLASS: // 班主任 rootPath = RouterManager.reportClassTeacherPath + '?examId=$examId'; break; case ReportUserIdentity.GRADE: // 年级 case ReportUserIdentity.SCHOOL_LEVEL: // 校级 case ReportUserIdentity.STATE_EDUCATION_COMMISSION: // 国家教育委员会 default: rootPath = ''; return AchievementView( elevation: 0.5, duration: Duration(seconds: 1), title: "提示", subTitle: "当前职位详情还未开放,请稍后", color: Theme.of(context).primaryColor, ).show(context); } RouterManager.router .navigateTo(context, rootPath, transition: getTransition()); }), child: Container( width: double.infinity, margin: EdgeInsets.symmetric(horizontal: 25.w), padding: EdgeInsets.symmetric(vertical: 9.h), alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.circular(80).r, gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color.fromRGBO(54, 86, 255, 1), Color.fromRGBO(93, 128, 255, 1) ], ), boxShadow: [ BoxShadow( color: Color.fromRGBO(46, 91, 255, 0.4), offset: Offset(2.0, 2.0), //阴影xy轴偏移量 blurRadius: 15.0, //阴影模糊程度 spreadRadius: 1.0, //阴影扩散程度 ) ], ), child: quickText('查看详细报告', color: Colors.white, size: 14.sp, fontWeight: FontWeight.w400), ), ), ], ), ); } /// 图形数据模块 @swidget Widget $graphicDataArea( {required String title, required String titleImg, required Widget graphicContainer}) { return Container( margin: EdgeInsets.only(bottom: 28.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset(titleImg, width: 22.w, height: 22.h), SizedBox(width: 2.w), quickText(title, size: 16.sp, color: Color.fromRGBO(45, 56, 76, 1)), ], ), SizedBox(height: 6.h), Card( elevation: 11.h, shadowColor: Color.fromRGBO(46, 91, 255, 0.10), borderOnForeground: true, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(6).r, side: BorderSide(color: Colors.white, width: 1.4.r), ), child: graphicContainer, ), ], ), ); } /// 进度图 @swidget Widget $theProgressChart(context, List datas) { bool isMultiple = datas.length > 1; // 是不是多个数据 return Container( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 19.h), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(6).r, gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color.fromRGBO(249, 250, 255, 1), Colors.white], ), ), child: Column( children: [ /// 平均分 ...datas.map((e) { return $theProgressWidget( context: context, isMultiple: isMultiple, linearGradient: LinearGradient( colors: [Colors.white, Theme.of(context).primaryColor]), subjectName: e.subjectName + '平均分', suffixTitle: e.totalScoreStr + '分', contentVal: e.averageScoreStr + '分', percent: e.averagePercent, contentColor: Theme.of(context).primaryColor, ); }), SizedBox(height: 20.h), /// 通过率 ...datas.map((e) { return $theProgressWidget( context: context, isMultiple: isMultiple, linearGradient: LinearGradient( colors: [Colors.white, Color.fromRGBO(0, 131, 253, 1)]), subjectName: e.subjectName + '及格率', suffixTitle: '100%', contentVal: e.passRateStr + '%', percent: e.passPercent, contentColor: Color.fromRGBO(0, 131, 253, 1), ); }) ], ), ); } /// 进度条图 @swidget Widget $theProgressWidget({ required bool isMultiple, required BuildContext context, required LinearGradient linearGradient, required String subjectName, required String suffixTitle, required String contentVal, required Color contentColor, required double percent, }) { return Padding( padding: EdgeInsets.only(top: isMultiple ? 4.h : 0), child: Stack( alignment: const FractionalOffset(0.5, 0.45), children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ quickText(subjectName, size: 14.sp, color: Color.fromRGBO(45, 56, 76, 1), fontWeight: FontWeight.w400), SizedBox(height: 6.h), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: LinearPercentIndicator( padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0), // width: MediaQuery.of(context).size.width - 50, animation: true, lineHeight: 9.h, animationDuration: 2500, percent: percent, linearGradient: linearGradient, // center: Text( // '${markingItem.completionRateStr}%', // style: TextStyle(color: Colors.white, fontSize: 10.sp), // ), // linearStrokeCap: LinearStrokeCap.butt, // progressColor: Theme.of(context).primaryColor, backgroundColor: const Color.fromRGBO(219, 224, 243, 1) .withOpacity(0.45), barRadius: Radius.circular(10.h), ), ), Container( width: 42.w, alignment: Alignment.centerRight, // padding: EdgeInsets.only(left: 20.w),suffixTitle child: quickText(suffixTitle, size: 12.sp, color: Color.fromRGBO(148, 163, 182, 1), fontWeight: FontWeight.w400), ), ], ), ], ), quickText(contentVal, size: 12.sp, fontWeight: FontWeight.w700, color: contentColor), ], ), ); }