数据快查

This commit is contained in:
machuanyu 2024-05-16 14:31:13 +08:00
parent 94977b5d96
commit 6285eeac5d
12 changed files with 893 additions and 0 deletions

View File

@ -0,0 +1,10 @@
import 'package:get/get.dart';
import 'annotate_class_logic.dart';
class AnnotateClassBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => AnnotateClassLogic());
}
}

View File

@ -0,0 +1,41 @@
import 'package:get/get.dart';
import 'package:school_asignment_app/common/job/annotated_class.dart';
import 'package:school_asignment_app/common/mixins/request_tool_mixin.dart';
import 'annotate_class_state.dart';
class AnnotateClassLogic extends GetxController with RequestToolMixin{
final AnnotateClassState state = AnnotateClassState();
@override
void onInit(){
super.onInit();
state.homeworkId.value = Get.arguments['id']??'';
state.name.value = Get.arguments['name']??'';
state.grade = Get.arguments['grade'];
getList();
}
void getList() async{
List<AnnotatedClass> data = await getClient(). getAnnotatedClassList(state.homeworkId.value);
state.classList.value = data;
for (var element in state.classList.value) {
int commitStudentCount = 0;
int noCommitStudentCount = 0;
for (var student in element.students) {
if(student.state == 0){
noCommitStudentCount ++;
}else{
commitStudentCount ++;
}
}
element.commitStudentCount = commitStudentCount;
element.noCommitStudentCount = noCommitStudentCount;
}
}
}

View File

@ -0,0 +1,13 @@
import 'package:get/get.dart';
import 'package:school_asignment_app/common/job/annotated_class.dart';
class AnnotateClassState {
AnnotateClassState() {
///Initialize variables
}
late RxString name = ''.obs;
late RxList<AnnotatedClass> classList = RxList();
late RxString homeworkId = ''.obs;
late int grade;
}

View File

@ -0,0 +1,336 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:school_asignment_app/common/job/annotated_class.dart';
import 'package:school_asignment_app/page/global_widget/ReturnToHomepage.dart';
import 'package:school_asignment_app/page/global_widget/my_text.dart';
import 'package:school_asignment_app/page/home_page/widget/progress_bar.dart';
import 'package:school_asignment_app/routes/app_pages.dart';
import 'annotate_class_logic.dart';
class AnnotateClassPage extends StatefulWidget {
const AnnotateClassPage({Key? key}) : super(key: key);
@override
State<AnnotateClassPage> createState() => _AnnotateClassPageState();
}
class _AnnotateClassPageState extends State<AnnotateClassPage> {
final logic = Get.find<AnnotateClassLogic>();
final state = Get.find<AnnotateClassLogic>().state;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromRGBO(245, 245, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
title: Obx(() {
return Text(state.name.value,
style:
TextStyle(fontSize: 14.sp, color: const Color(0xFF333333)));
}),
centerTitle: true,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
actions: const [
ReturnToHomepage(),
],
),
body: Padding(
padding: EdgeInsets.symmetric(vertical: 14.r, horizontal: 14.r),
child: Obx(() {
return ListView.builder(
itemCount: state.classList.length,
itemBuilder: (context, index) {
AnnotatedClass item = state.classList[index];
return Container(
padding: EdgeInsets.only(top: 10.r),
margin: EdgeInsets.only(bottom: 10.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadiusDirectional.circular(4.r),
boxShadow: const [BoxShadow(color: Color.fromRGBO(0, 0, 0, 0.15), blurRadius: 10)],
),
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.r),
child: Row(
children: [
Text(
item.className,
style: TextStyle(
fontSize: 14.sp,
color: const Color(0xFF000000)),
),
const Spacer(),
Text(
'已交:${item.commitStudentCount}',
style: TextStyle(
fontSize: 12.sp,
color: const Color(0xFF6888FD)),
),
SizedBox(
width: 20.r,
),
Text(
'未交:${item.noCommitStudentCount}',
style: TextStyle(
fontSize: 12.sp,
color: const Color(0xFFFF5656)),
),
],
),
),
SizedBox(
height: 10.r,
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 10.r),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children:
item.finishTime != null ?
[
Expanded(
flex:4,
child: InkWell(
splashColor: Theme.of(context).primaryColor,
child: ElevatedButton(
style: ButtonStyle(
overlayColor:MaterialStateProperty.all(
const Color(0xFF6888FD)),
backgroundColor:
MaterialStateProperty.all(
const Color(0xFFF4F4F4)),
// foregroundColor: MaterialStateProperty.all(Colors.red.shade200),//
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(22), //
))),
onPressed: () {},
child: Text(
"收藏夹",
style: TextStyle(
fontSize: 10.sp,
color: const Color(0xFF666666)),
)),
),
),
const Expanded(flex: 1, child: SizedBox()),
const Expanded(flex: 4, child: SizedBox()),
const Expanded(flex: 1, child: SizedBox()),
const Expanded(flex: 4, child: SizedBox()),
]:[
Expanded(
flex: 4,
child: ElevatedButton(
style: ButtonStyle(
overlayColor:MaterialStateProperty.all(
const Color(0xFF6888FD)),
backgroundColor:
MaterialStateProperty.all(
const Color(0xFFF4F4F4)),
// foregroundColor: MaterialStateProperty.all(Colors.red.shade200),//
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(22), //
))),
onPressed: () {},
child: Text(
"一键批阅",
style: TextStyle(
fontSize: 10.sp, color: const Color(0xFF666666)),
)),
),
const Expanded(flex: 1,child: Text(''),),
Expanded(
flex:4,
child: ElevatedButton(
style: ButtonStyle(
overlayColor:MaterialStateProperty.all(
const Color(0xFF6888FD)),
backgroundColor:
MaterialStateProperty.all(
const Color(0xFFF4F4F4)),
// foregroundColor: MaterialStateProperty.all(Colors.red.shade200),//
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(22), //
))),
onPressed: () {
Get.toNamed(Routes.quickDataCheckPage,arguments: {'homeworkId':state.homeworkId.value,'classId':item.classId,'grade':state.grade,'className':item.className
});
},
child: Text(
"数据快查",
style: TextStyle(
fontSize: 10.sp,
color: const Color(0xFF666666)),
)),
),
const Expanded(flex: 1,child: Text(''),),
Expanded(
flex:4,
child: ElevatedButton(
style: ButtonStyle(
overlayColor:MaterialStateProperty.all(
const Color(0xFF6888FD)),
backgroundColor:
MaterialStateProperty.all(
const Color(0xFFF4F4F4)),
// foregroundColor: MaterialStateProperty.all(Colors.red.shade200),//
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(22), //
))),
onPressed: () {},
child: Text(
"收藏夹",
style: TextStyle(
fontSize: 10.sp,
color: const Color(0xFF666666)),
)),
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 10.r,horizontal: 14.r),
child: Row(
children: [
Expanded(
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: 8.h,
animationDuration: 2500,
percent: item.annotateRate / 100,
linearGradient: LinearGradient(
tileMode: TileMode.mirror,
stops: const [0.0, 1.0],
colors: 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),
],
),
// linearStrokeCap: LinearStrokeCap.butt,
// progressColor: Theme.of(context).primaryColor,
backgroundColor: const Color.fromRGBO(232, 232, 232, 1),
barRadius: Radius.circular(10.r),
),
),
SizedBox(width: 7.w),
quickText('${item.annotateRate}%',
size: 10.sp, color: const Color.fromRGBO(70, 70, 70, 1))
],
),
),
ProgressBar(
title: '客观题正确率:',
color: const Color(0xFFB8C7FF),
percent: item.kgtCorrectRate / 100,
marginEdg: EdgeInsets.zero,
padingEdg: EdgeInsets.only(top: 8.h,left: 14.r,right: 14.r)),
ProgressBar(
title: '主观题正确率:',
color: const Color(0xFFB8C7FF),
percent: item.zgtCorrectRate / 100,
padingEdg: EdgeInsets.symmetric(horizontal: 10.r),
marginEdg: EdgeInsets.only(top: 8.h)),
ProgressBar(
title: '总正确率:',
color: const Color(0xFFB8C7FF),
percent: item.correctRate / 100,
padingEdg: EdgeInsets.symmetric(horizontal: 10.r),
marginEdg: EdgeInsets.only(top: 8.h)),
Container(
margin: EdgeInsets.only(top: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(4.r), bottomRight: Radius.circular(4.r)),
color: Colors.white,
boxShadow: const [
BoxShadow(
color: Color.fromRGBO(0, 0, 0, 0.15),
offset: Offset(0, -0.0001), //y轴偏移量
blurRadius: 4, //
spreadRadius: 0, //
)
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children:
item.finishTime != null ?
[
Expanded(
child: InkWell(
onTap: () {},
child: Container(
alignment: Alignment.center,
child: quickText('数据快查', color: Color.fromRGBO(118, 118, 118, 1), size: 12.sp),
),
),
),
Container(width: 1.w, height: 30.h, color: const Color.fromRGBO(221, 221, 221, 1)),
Expanded(
child: InkWell(
onTap: () {},
child: Container(
alignment: Alignment.center,
child: quickText('查看报告', color: Color.fromRGBO(118, 118, 118, 1), size: 12.sp),
),
)),
]
:
[
Expanded(
child: InkWell(
onTap: () {},
child: Container(
alignment: Alignment.center,
child: quickText('批阅', color: const Color.fromRGBO(118, 118, 118, 1), size: 12.sp),
),
),
),
Container(width: 1.w, height: 30.h, color: const Color.fromRGBO(221, 221, 221, 1)),
Expanded(
child: InkWell(
onTap: () {},
child: Container(
alignment: Alignment.center,
child: quickText('结束批阅', color: const Color.fromRGBO(118, 118, 118, 1), size: 12.sp),
),
)),
],
),
)
],
),
);
});
}),
),
);
}
@override
void dispose() {
Get.delete<AnnotateClassLogic>();
super.dispose();
}
}

View File

@ -0,0 +1,10 @@
import 'package:get/get.dart';
import 'job_report_logic.dart';
class JobReportBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => JobReportLogic());
}
}

View File

@ -0,0 +1,7 @@
import 'package:get/get.dart';
import 'job_report_state.dart';
class JobReportLogic extends GetxController {
final JobReportState state = JobReportState();
}

View File

@ -0,0 +1,5 @@
class JobReportState {
JobReportState() {
///Initialize variables
}
}

View File

@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'job_report_logic.dart';
class JobReportPage extends StatefulWidget {
const JobReportPage({Key? key}) : super(key: key);
@override
State<JobReportPage> createState() => _JobReportPageState();
}
class _JobReportPageState extends State<JobReportPage> {
final logic = Get.find<JobReportLogic>();
final state = Get.find<JobReportLogic>().state;
@override
Widget build(BuildContext context) {
return Container();
}
@override
void dispose() {
Get.delete<JobReportLogic>();
super.dispose();
}
}

View File

@ -0,0 +1,10 @@
import 'package:get/get.dart';
import 'quick_data_check_logic.dart';
class QuickDataCheckBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => QuickDataCheckLogic());
}
}

View File

@ -0,0 +1,34 @@
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:school_asignment_app/common/job/homework_details.dart';
import 'package:school_asignment_app/common/mixins/request_tool_mixin.dart';
import 'package:school_asignment_app/common/utils/utils.dart';
import 'quick_data_check_state.dart';
class QuickDataCheckLogic extends GetxController with RequestToolMixin{
final QuickDataCheckState state = QuickDataCheckState();
@override
void onInit(){
super.onInit();
state.homeworkId.value = Get.arguments['homeworkId']??'';
state.classId.value = Get.arguments['classId']??'';
state.className.value = Get.arguments['className']??'';
state.grade = Get.arguments['grade'];
EasyLoading.show(status: 'loading...');
getWorkData();
}
void getWorkData() async{
HomeworkDetails data = await getClient(). getHomeworkDetails(state.homeworkId.value,state.classId.value);
state.homeData = data;
state.dataCount = Utils.getHomeworkData(data);
state.kgReport.value = data.questions.where((w)=>w.questionType == 1).toList();
state.zgReport.value = data.questions.where((w)=>w.questionType == 2).toList();
state.studentList.value = data.students;
state.hasData.value = true;
EasyLoading.dismiss();
}
}

View File

@ -0,0 +1,40 @@
import 'package:get/get.dart';
import 'package:school_asignment_app/common/job/homework_details.dart';
class QuickDataCheckState {
QuickDataCheckState() {
///Initialize variables
}
late RxString homeworkId = ''.obs;
late RxString classId = ''.obs;
late RxString className = ''.obs;
late int grade;
late CountData dataCount = CountData();
late RxBool hasData = false.obs;
late RxList<Questions> kgReport = RxList();
late RxList<Questions> zgReport = RxList();
late RxList<Students> studentList = RxList();
late final HomeworkDetails homeData;
}
class CountData extends Object {
int? kgtOkCount = 0;
int? kgtDtlCount = 0;
double? kgtAnswerRate = 0;
double? kgtOkRate = 0;
int? kgtAnswerCount = 0;
int? kgtCount = 0;
int? zgtDtlCount = 0;
int? zgtOkCount = 0;
int? zgtAnswerCount = 0;
double? zgtAnswerRate = 0;
double? zgtOkRate = 0;
int? zgtCount = 0;
int? studentCount = 0;
List<Students>? priorityStudents = [];
int? studentSubmitCount = 0;
CountData({this.kgtOkCount, this.kgtDtlCount,this.kgtAnswerRate,this.kgtAnswerCount,this.kgtOkRate,this.studentCount,
this.kgtCount,this.zgtAnswerCount,this.zgtOkCount,this.zgtDtlCount,this.zgtAnswerRate,this.zgtOkRate,this.zgtCount,this.priorityStudents,
this.studentSubmitCount,});
}

View File

@ -0,0 +1,360 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:school_asignment_app/common/utils/enum_untils.dart';
import 'package:school_asignment_app/common/utils/utils.dart';
import 'package:school_asignment_app/page/global_widget/MyEmptyWidget.dart';
import 'package:school_asignment_app/page/global_widget/ReturnToHomepage.dart';
import 'package:school_asignment_app/page/home_page/children/quick_data_check/widget/kgt_zgt_table.dart';
import 'package:school_asignment_app/page/home_page/children/quick_data_check/widget/quick_data_check_bottom.dart';
import 'package:school_asignment_app/page/home_page/children/quick_data_check/widget/report_table.dart';
import 'quick_data_check_logic.dart';
class QuickDataCheckPage extends StatefulWidget {
const QuickDataCheckPage({Key? key}) : super(key: key);
@override
State<QuickDataCheckPage> createState() => _QuickDataCheckPageState();
}
class _QuickDataCheckPageState extends State<QuickDataCheckPage> {
final logic = Get.find<QuickDataCheckLogic>();
final state = Get
.find<QuickDataCheckLogic>()
.state;
@override
Widget build(BuildContext context) {
return AnnotatedRegion(
value: const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
systemNavigationBarIconBrightness: Brightness.light,
statusBarIconBrightness: Brightness.light,
statusBarBrightness: Brightness.dark,
),
child: Container(
padding: EdgeInsets.only(top: MediaQuery
.of(context)
.padding
.top),
height: MediaQuery
.of(context)
.size
.height,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF6889FD),
Color(0xFFF5F5F5),
],
stops: [
0.09,
0.3
])),
child:
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
IconButton(
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
onPressed: () => Navigator.of(context).pop(),
),
Expanded(
child: Padding(
padding: EdgeInsets.only(right: 8.r),
child: Center(
child: Text(
'数据快查',
style: TextStyle(
fontSize: 14.sp, color: Colors.white),
)),
)),
const ReturnToHomepage(bgColor: Colors.white,),
],
),
SizedBox(height: 10.r),
Obx(() {
if (state.hasData.value) {
return Expanded(
child: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: EdgeInsets.only(left: 14.r, top: 2.r),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset(
'assets/images/job_report_class_icon.png',
width: 22.r,
height: 22.r,
),
SizedBox(
width: 6.r,
),
Obx(() {
return Text(
'${EnumUtils.formatGrade(
state.grade)}${state.className.value}',
style: TextStyle(
fontSize: 14.r, color: Colors.white),
);
})
],
),
),
Container(
padding: EdgeInsets.symmetric(
vertical: 15.r, horizontal: 15.r),
margin: EdgeInsets.symmetric(
vertical: 10.r, horizontal: 14.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.all(Radius.circular(6.r))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 2.r,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 12.r,
height: 12.r,
decoration: BoxDecoration(
color: const Color(0xFF4CC793),
borderRadius: BorderRadius.all(
Radius.circular(7.r))),
),
SizedBox(
width: 6.r,
),
Text(
'已提交',
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF333333)),
),
SizedBox(
width: 35.r,
),
Container(
width: 12.r,
height: 12.r,
decoration: BoxDecoration(
color: const Color(0xFF6888FD),
borderRadius: BorderRadius.all(
Radius.circular(7.r))),
),
SizedBox(
width: 6.r,
),
Text(
'未提交',
style: TextStyle(
fontSize: 12.sp,
color: const Color(0xFF333333)),
)
],
),
SizedBox(
height: 2.r,
),
//
SizedBox(
height: MediaQuery
.of(context)
.size
.width * 0.3,
child: PieChart(
PieChartData(
borderData: FlBorderData(show: false),
sectionsSpace: 0,
centerSpaceRadius:
MediaQuery
.of(context)
.size
.width * 0.06,
sections: [
PieChartSectionData(
color: const Color(0xFF4CC793),
value: state.dataCount
.studentSubmitCount! /
state.dataCount.studentCount! *
100,
radius:
MediaQuery
.of(context)
.size
.width *
0.07 +
5,
title: '${state.dataCount
.studentSubmitCount}',
titleStyle: TextStyle(
fontSize: 14.sp,
color: Colors.white,
),
),
PieChartSectionData(
color: const Color(0xFF6888FD),
value: (state.dataCount
.studentCount! - state.dataCount
.studentSubmitCount!) /
state.dataCount.studentCount! *
100,
radius:
MediaQuery
.of(context)
.size
.width *
0.07,
title: '${state.dataCount
.studentCount! - state.dataCount
.studentSubmitCount!}',
titleStyle: TextStyle(
fontSize: 14.sp,
color: Colors.white,
),
),
],
),
),
),
//
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'客观题答题进度',
style: TextStyle(
fontSize: 10.sp,
color: const Color(0xFF8B8B8B)),
),
Text(
'${state.dataCount.kgtAnswerRate!
.toStringAsFixed(0)}%',
style: TextStyle(
fontSize: 10.sp,
color: const Color(0xFF333333)),
),
],
),
SizedBox(height: 6.r),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 10,
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: 9.h,
animationDuration: 2500,
percent: state.dataCount
.kgtAnswerRate! / 100,
progressColor: const Color(
0xFFFF7F22),
backgroundColor: const Color(
0xFFEAEAEA),
barRadius: Radius.circular(10.r),
)),
],
),
SizedBox(height: 20.r),
//
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'主观题答题进度',
style: TextStyle(
fontSize: 10.sp,
color: const Color(0xFF8B8B8B)),
),
Text(
'${state.dataCount.zgtAnswerRate!
.toStringAsFixed(0)}%',
style: TextStyle(
fontSize: 10.sp,
color: const Color(0xFF333333)),
),
],
),
SizedBox(height: 6.r),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 10,
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: 9.h,
animationDuration: 2500,
percent: state.dataCount
.zgtAnswerRate! / 100,
progressColor: const Color(
0xFFFF7F22),
backgroundColor: const Color(
0xFFEAEAEA),
barRadius: Radius.circular(10.r),
)),
],
),
],
),
),
QuickDataCheckBottom(jobData: state.studentList.value,
jobId: state.homeworkId.value,
kgCount: state.dataCount.kgtDtlCount!,
zgCount: state.dataCount.zgtDtlCount!,),
//
KgtZgtTable(studentCount:state.dataCount.studentCount!,homeworkId:state.homeworkId.value,kgReport: state.kgReport,zgReport: state.zgReport,kgtOkRate:state.dataCount.kgtOkRate!
.toStringAsFixed(0),zgtOkRate:state.dataCount.zgtOkRate!
.toStringAsFixed(0)),
],
),
));
} else {
return Padding(
padding: EdgeInsets.only(
top: MediaQuery
.of(context)
.size
.height / 2 - 200.r),
child: const MyEmptyWidget()
);
}
})
],
),
),
);
}
@override
void dispose() {
Get.delete<QuickDataCheckLogic>();
super.dispose();
}
}