Compare commits

...

3 Commits

Author SHA1 Message Date
machuanyu ffc9fdd9c1 历史详情 2024-03-28 16:08:53 +08:00
1147192855@qq.com bf3e2eb9e2 no message 2024-03-22 10:12:57 +08:00
1147192855@qq.com 2bf8ae88f6 no message 2024-03-22 09:57:00 +08:00
9 changed files with 1110 additions and 118 deletions

View File

@ -0,0 +1,144 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_student_history.g.dart';
@JsonSerializable()
class JobStudentHistory extends Object {
@JsonKey(name: 'correctRate')
int correctRate;
@JsonKey(name: 'objectiveCorrectRate')
int objectiveCorrectRate;
@JsonKey(name: 'subjectiveCorrectRate')
int subjectiveCorrectRate;
@JsonKey(name: 'pagedList')
PagedList pagedList;
JobStudentHistory(this.correctRate,this.objectiveCorrectRate,this.subjectiveCorrectRate,this.pagedList,);
factory JobStudentHistory.fromJson(Map<String, dynamic> srcJson) => _$JobStudentHistoryFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobStudentHistoryToJson(this);
}
@JsonSerializable()
class PagedList extends Object {
@JsonKey(name: 'page')
int page;
@JsonKey(name: 'pageSize')
int pageSize;
@JsonKey(name: 'total')
int total;
@JsonKey(name: 'totalPages')
int totalPages;
@JsonKey(name: 'items')
List<Items> items;
@JsonKey(name: 'hasPrevPage')
bool hasPrevPage;
@JsonKey(name: 'hasNextPage')
bool hasNextPage;
PagedList(this.page,this.pageSize,this.total,this.totalPages,this.items,this.hasPrevPage,this.hasNextPage,);
factory PagedList.fromJson(Map<String, dynamic> srcJson) => _$PagedListFromJson(srcJson);
Map<String, dynamic> toJson() => _$PagedListToJson(this);
}
@JsonSerializable()
class Items extends Object {
@JsonKey(name: 'id')
int id;
@JsonKey(name: 'name')
String name;
@JsonKey(name: 'subject')
int subject;
@JsonKey(name: 'subjectName')
String subjectName;
@JsonKey(name: 'publishTime')
String publishTime;
@JsonKey(name: 'isPaper')
bool isPaper;
@JsonKey(name: 'studentJobId')
int studentJobId;
@JsonKey(name: 'correctRate')
int correctRate;
@JsonKey(name: 'objectiveCorrectRate')
int objectiveCorrectRate;
@JsonKey(name: 'objectiveDtls')
List<SubjectiveDtls> objectiveDtls;
@JsonKey(name: 'subjectiveCorrectRate')
int subjectiveCorrectRate;
@JsonKey(name: 'subjectiveDtls')
List<SubjectiveDtls> subjectiveDtls;
Items(this.id,this.name,this.subject,this.subjectName,this.publishTime,this.isPaper,this.studentJobId,this.correctRate,this.objectiveCorrectRate,this.objectiveDtls,this.subjectiveCorrectRate,this.subjectiveDtls,);
factory Items.fromJson(Map<String, dynamic> srcJson) => _$ItemsFromJson(srcJson);
Map<String, dynamic> toJson() => _$ItemsToJson(this);
}
@JsonSerializable()
class SubjectiveDtls extends Object {
@JsonKey(name: 'studentJobId')
int studentJobId;
@JsonKey(name: 'questionId')
int questionId;
@JsonKey(name: 'questionNo')
String questionNo;
@JsonKey(name: 'questionType')
int questionType;
@JsonKey(name: 'useTime')
int useTime;
@JsonKey(name: 'score')
double score;
@JsonKey(name: 'annotateTime')
String? annotateTime;
@JsonKey(name: 'state')
int state;
SubjectiveDtls(this.studentJobId,this.questionId,this.questionNo,this.questionType,this.useTime,this.score,this.annotateTime,this.state,);
factory SubjectiveDtls.fromJson(Map<String, dynamic> srcJson) => _$SubjectiveDtlsFromJson(srcJson);
Map<String, dynamic> toJson() => _$SubjectiveDtlsToJson(this);
}

View File

@ -0,0 +1,705 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/job/job_student_history.dart';
import 'package:marking_app/pages/homework_correction/widget/personal_detail_topbar.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.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:syncfusion_flutter_datepicker/datepicker.dart';
class JobPersonalDetail extends StatefulWidget {
final String studentName;
final int studentId;
const JobPersonalDetail(
{Key? key, required this.studentName, required this.studentId})
: super(key: key);
@override
_JobPersonalDetailState createState() => _JobPersonalDetailState();
}
class _JobPersonalDetailState extends State<JobPersonalDetail>
with CommonMixin, TickerProviderStateMixin {
@override
int page = 1;
int pageSize = 10;
int totalPages = 0;
JobStudentHistory? studentData;
bool isJob = true;
late TabController tabController;
String startDataTime = '';
String endDataTime = '';
String customTimeStr = '自定义';
List<Items> dataList = [];
late final EasyRefreshController refreshController;
@override
void initState() {
super.initState();
refreshController = EasyRefreshController();
tabController = TabController(length: 4, vsync: this);
EasyLoading.show(status: 'loading...');
getList();
}
@override
void dispose() {
super.dispose();
tabController.dispose();
}
void getList() async {
RestClient _client = await getClient();
BaseStructureResult<JobStudentHistory> res =
await _client.getStudentJobHistory(widget.studentId, !isJob,
startDataTime, endDataTime, page, pageSize);
setState(() {
studentData = res.data!;
if (page == 1) {
dataList = studentData!.pagedList.items;
} else {
dataList = [...dataList, ...studentData!.pagedList.items];
}
totalPages = res.data!.pagedList.totalPages;
print('dataLists=${dataList.length}');
print('totalpages=$totalPages');
});
EasyLoading.dismiss();
}
@override
Widget build(BuildContext context) {
bool isPadFlag = isPad();
if (studentData == null) return Container();
return Scaffold(
backgroundColor: Color.fromRGBO(245, 245, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
title: Text('${widget.studentName}作业详情',
style: TextStyle(fontSize: 14.sp, color: Color(0xFF333333))),
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
elevation: 0,
),
body: Column(
children: [
Container(
height: 1.r,
width: MediaQuery.of(context).size.width,
color: Color.fromRGBO(179, 179, 179, 0.3),
),
Container(
color: Colors.white,
padding: EdgeInsets.symmetric(vertical: 2.r),
child: Row(
children: [
InkWell(
onTap: () {
EasyLoading.show(status: 'loading...');
setState(() {
isJob = true;
page = 1;
totalPages = 0;
});
getList();
},
child: Container(
width: (MediaQuery.of(context).size.width - 1.r) / 2,
height: 40.r,
child: Center(
child: Text(
'作业',
style: TextStyle(
fontSize: 14.sp,
color: isJob ? Color(0xFF7491FD) : Color(0xFF505E6E)),
)),
),
),
Container(
height: 40.r,
width: 1.r,
color: Color.fromRGBO(179, 179, 179, 0.3),
),
InkWell(
onTap: () {
EasyLoading.show(status: 'loading...');
setState(() {
isJob = false;
page = 1;
totalPages = 0;
});
getList();
},
child: Container(
width: (MediaQuery.of(context).size.width - 1.r) / 2,
height: 40.r,
child: Center(
child: Text(
'考试',
style: TextStyle(
fontSize: 14.sp,
color:
!isJob ? Color(0xFF7491FD) : Color(0xFF505E6E)),
)),
),
),
],
),
),
progressBar(context,
title: '客观题正确率:',
color: Color(0xFFB8C7FF),
percent: studentData!.objectiveCorrectRate / 100,
padingEdg: EdgeInsets.symmetric(horizontal: 14.r),
marginEdg: EdgeInsets.only(top: 8.h)),
progressBar(context,
title: '主观题正确率:',
color: Color(0xFFB8C7FF),
percent: studentData!.subjectiveCorrectRate / 100,
padingEdg: EdgeInsets.symmetric(horizontal: 14.r),
marginEdg: EdgeInsets.only(top: 8.h)),
progressBar(context,
title: '总正确率:',
color: Color(0xFFB8C7FF),
percent: studentData!.correctRate / 100,
padingEdg: EdgeInsets.symmetric(horizontal: 14.r),
marginEdg: EdgeInsets.only(top: 8.h)),
SizedBox(
height: 10.r,
),
jobConditionFilter(context,
controller: tabController,
jobType: isJob ? 1 : 2,
customTimeStr: customTimeStr,
customTime: tabController.index != 3 ||
((endDataTime == null || endDataTime == '') && (startDataTime == null || startDataTime == ''))
? null
: PickerDateRange(
startDataTime == null || startDataTime == ''
? null
: DateTime.parse(startDataTime!),endDataTime == null || endDataTime == '' ? null : DateTime.parse(endDataTime!),
), onTimeFilter: (String? startTime, String? endTime) {
EasyLoading.show(status: 'loading...');
if (startTime == null && endTime == null) {
if (tabController.index == 3) {
tabController.animateTo(0);
}
startDataTime = '';
endDataTime = '';
customTimeStr = '自定义';
} else {
print('startTime=$startTime');
print('endDataTime=$endTime');
startDataTime = startTime != null ? startTime : '';
endDataTime = endTime != null ? endTime : '';
}
page = 1;
setState(() {});
getList();
// _refreshController2.callRefresh();
}, refreshTime: (value) {
if (value != null && value.startDate != null) {
customTimeStr =
value.startDate?.toString().substring(0, 10) ?? '';
setState(() {});
if (value.endDate != null) {
if (!isPad() && value.startDate!.year == value.endDate!.year) {
customTimeStr = value.startDate.toString().substring(5, 10) +
'~${value.endDate.toString().substring(5, 10)}';
setState(() {});
} else {
customTimeStr =
'$customTimeStr~${value.endDate?.toString().substring(0, 10)}';
setState(() {});
}
}
}
}),
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 10.r),
child: EasyRefresh(
firstRefresh: false,
taskIndependence: true,
controller: refreshController,
header: MaterialHeader(),
footer: TaurusFooter(),
onRefresh: () async {
setState(() {
page = 1;
});
getList();
},
onLoad: () async {
if (page < totalPages) {
setState(() {
page += 1;
});
getList();
}
},
child: dataList.length > 0
? ListView.builder(
itemCount: dataList.length,
itemBuilder: (context, index) {
Items item = dataList[index];
return Container(
margin: EdgeInsets.symmetric(
vertical: 5.r, horizontal: 14.r),
padding: EdgeInsets.symmetric(
vertical: 14.r, horizontal: 10.r),
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(10.r)),
color: Colors.white),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
width: 32.w,
height: 18.h,
alignment: Alignment.center,
padding: EdgeInsets.only(left: 2.w),
decoration: BoxDecoration(
color: isJob
? const Color.fromRGBO(
104, 136, 253, 1)
: Color(0xFFFFA116),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(14.r),
topRight: Radius.circular(3.r),
bottomLeft: Radius.circular(4.r),
bottomRight: Radius.circular(4.r),
),
),
margin: EdgeInsets.only(right: 4.w),
child: Text(
isJob ? '作业' : '考试',
style: TextStyle(
fontSize: 10.sp,
color: Colors.white),
),
),
Expanded(
child: Text(
item.name,
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF464646)),
)),
// SizedBox(width: 5.r,),
// Text('2024.1',style: TextStyle(fontSize: 12.sp,color: Color(0xFF5B5B5B)),),
Container(
width: 40.r,
height: 20.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(4.r)),
border: Border.all(
width: 1.r,
color: Color(0xFF4CC793)),
),
child: Center(
child: Text(
item.subjectName,
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFF4CC793)),
)),
),
],
),
SizedBox(
height: 10.r,
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'客:',
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF5B5B5B)),
),
SizedBox(
width: 5.r,
),
item.objectiveDtls.length > 0
? Expanded(
child: Wrap(
direction: Axis.horizontal,
alignment: WrapAlignment.start,
spacing: 8,
runSpacing: 5,
children: List.generate(
item.objectiveDtls.length,
(i) {
SubjectiveDtls subjective =
item.objectiveDtls[i];
return Container(
width: 20.r,
height: 20.r,
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(
width: 1.r,
color: Color(
0xFF4CC793)),
borderRadius:
BorderRadius.all(
Radius.circular(
10.r))),
child: Center(
child: Text(
subjective.questionNo,
style: TextStyle(
fontSize: 10.r,
color:
Color(0xFF4CC793)),
)),
);
}),
),
)
: Text(
'',
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF5B5B5B)),
),
],
),
SizedBox(
height: 10.r,
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'主:',
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF5B5B5B)),
),
SizedBox(
width: 5.r,
),
item.subjectiveDtls.length > 0
? Expanded(
child: Wrap(
direction: Axis.horizontal,
alignment: WrapAlignment.start,
spacing: 8,
runSpacing: 5,
children: List.generate(
item.subjectiveDtls.length,
(i) {
SubjectiveDtls subjective =
item.subjectiveDtls[i];
return Container(
width: 20.r,
height: 20.r,
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(
width: 1.r,
color: subjective
.state ==
0
? Color(
0xFFDDDDDD)
: subjective.state ==
3
? Color(
0xFF666666)
: subjective.state ==
1
? Color(
0xFFFF7474)
: Color(
0xFF4CC793)),
borderRadius:
BorderRadius.all(
Radius.circular(
10.r))),
child: Center(
child: Text(
subjective.questionNo,
style: TextStyle(
fontSize: 10.r,
color: subjective
.state ==
0
? Color(0xFFDDDDDD)
: subjective.state ==
3
? Color(
0xFF666666)
: subjective.state ==
1
? Color(
0xFFFF7474)
: Color(
0xFF4CC793)),
)),
);
}),
),
)
: Text(
'',
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF5B5B5B)),
),
],
),
progressBar(context,
title: '客观题正确率:',
color: Color(0xFF90E0BE),
percent: item.objectiveCorrectRate / 100,
padingEdg: EdgeInsets.zero,
marginEdg: EdgeInsets.only(top: 8.h)),
progressBar(context,
title: '主观题正确率:',
color: Color(0xFF90E0BE),
percent: item.subjectiveCorrectRate / 100,
padingEdg: EdgeInsets.zero,
marginEdg: EdgeInsets.only(top: 8.h)),
progressBar(context,
title: '总正确率:',
color: Color(0xFF90E0BE),
percent: item.correctRate / 100,
padingEdg: EdgeInsets.zero,
marginEdg: EdgeInsets.only(top: 8.h)),
],
),
);
})
: MyEmptyWidget(),
),
),
),
],
),
);
}
}
@swidget
Widget progressBar(
BuildContext context, {
double? fontSize,
double? lineHeight,
required String title,
required Color color,
required double percent,
required EdgeInsets padingEdg,
required EdgeInsets marginEdg,
}) {
var percentStr = '${doubleToStringAsFixed(percent * 100)}%';
fontSize ??= 10.sp;
lineHeight ??= 8.h;
return Container(
margin: marginEdg,
padding: padingEdg,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (title == '总正确率:')
quickText('确率', color: Colors.transparent, size: fontSize),
quickText(title, color: Color(0xFF8B8B8B), size: fontSize),
Expanded(
flex: 1,
child: Container(
child: Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.r),
/* boxShadow: [
BoxShadow(
color: color,
spreadRadius: 0.6,
blurRadius: 3,
offset: Offset(0, 0),
),
],*/
),
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: lineHeight,
animationDuration: 2500,
percent: percent,
/* center: Text(
percentStr,
style: TextStyle(color: Colors.white, fontSize: 4.5.sp),
),*/
// linearStrokeCap: LinearStrokeCap.butt,
progressColor: color,
backgroundColor: Color(0xFFE8E8E8),
barRadius: Radius.circular(10.r),
// linearGradient: LinearGradient(
// tileMode: TileMode.mirror,
// stops: [0.0, 1.0],
// colors: [color.withOpacity(0.1), color],
// ),
),
),
),
SizedBox(width: 4.w),
quickText(percentStr, size: fontSize, color: Color(0xFF464646))
],
),
),
),
],
),
);
}
///
@hwidget
Widget jobConditionFilter(BuildContext context,
{required TabController controller,
required int jobType,
PickerDateRange? customTime,
required Function refreshTime,
required String customTimeStr,
required Function(String? startTime, String? endTime) onTimeFilter}) {
var customTimeState = PickerDateRange(null, null);
print('customTime=${customTime}');
if (customTime != null) {
customTimeState = PickerDateRange(
customTime!.startDate != null ? customTime!.startDate : null,
customTime!.endDate != null ? customTime!.endDate : null);
}
DateTime getWeekStartDate() {
DateTime now = DateTime.now();
int dayOfWeek = now.weekday; // 17
int diff = dayOfWeek - 1; //
if (diff < 0) {
diff += 7; //
}
return now.subtract(Duration(days: diff)); //
}
DateTime getWeekEndDate() {
DateTime now = DateTime.now();
int dayOfWeek = now.weekday; //
int diff = 7 - dayOfWeek; //
if (diff == 0) {
diff = 7; //
}
return now.add(Duration(days: diff)); //
}
DateTime getMonthStartDate() {
DateTime now = DateTime.now();
return DateTime(now.year, now.month, 1); //
}
DateTime getMonthEndDate() {
DateTime now = DateTime.now();
int nextMonth = now.month + 1;
if (nextMonth > 12) {
nextMonth = 1;
now = now.add(Duration(days: 31 - now.day)); //
} else {
now = now.add(Duration(
days: DateTime(now.year, nextMonth, 0).day -
now.day)); //
}
return now;
}
return Container(
// height: 39.h,
// padding: EdgeInsets.only(left: 4.w, right: 12.w),
decoration: BoxDecoration(
color: Color.fromRGBO(244, 244, 244, 1),
// border: Border(bottom: BorderSide(color: Color.fromRGBO(204, 204, 204, 1), width: 1)),
),
child: PersonalDetailTopBar(
controller: controller,
customTimeStr: customTimeStr,
onTap: (int val) async {
switch (val) {
case 0: //
onTimeFilter(null, null);
break;
case 1: //
onTimeFilter(
getWeekStartDate().toString().substring(0, 10),
getWeekEndDate().toString().substring(0, 10),
);
break;
case 2: //
onTimeFilter(
getMonthStartDate().toString().substring(0, 10),
getMonthEndDate().toString().substring(0, 10),
);
break;
default: //
var dialogData = await showDialog<PickerDateRange?>(
context: context,
builder: (BuildContext context1) {
return Center(
child: Container(
color: Colors.white,
width: isPad()
? ScreenUtil().screenWidth / 2
: ScreenUtil().screenWidth / 1.3,
height: ScreenUtil().screenHeight / 2,
child: SfDateRangePicker(
showActionButtons: true,
confirmText: '确定',
cancelText: '取消',
onSubmit: (p0) {
print(p0);
Navigator.of(context1).pop(p0);
refreshTime(p0);
},
onCancel: () {
Navigator.of(context1).pop();
},
selectionMode: DateRangePickerSelectionMode.range,
initialSelectedRange: customTimeState,
),
),
);
});
// startDate: 2024-03-04 18:47:00.117958, endDate: 2024-03-11 18:47:00.117986
// if (dialogData != null && (dialogData.startDate != null || dialogData.endDate != null)) {}
onTimeFilter(
dialogData?.startDate?.toString().substring(0, 10),
dialogData?.endDate?.toString().substring(0, 10),
);
customTimeState = dialogData!;
}
},
),
);
}

View File

@ -7,6 +7,7 @@ import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/job/job_level_set_params.dart';
import 'package:marking_app/common/model/job/job_review_submission.dart';
import 'package:marking_app/common/model/job/job_student_level.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/request/rest_client.dart';
@ -153,7 +154,7 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
),children: List.generate(levelList.length, (index) {
JobStudentLevel item = levelList[index];
return Container(
padding: EdgeInsets.symmetric(horizontal: 15.r),
padding: EdgeInsets.symmetric(horizontal: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
@ -161,7 +162,8 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(item.studentName,style: TextStyle(fontSize: 12.sp,color: Color(0xFF6888FD)),),
Expanded(child: Text(item.studentName,style: TextStyle(fontSize: 12.sp,color: Color(0xFF6888FD)),)),
tabIndex == 0?InkWell(
onTap: (){
setState(() {
@ -201,6 +203,24 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
child:Text('设为优先',style: TextStyle(fontSize: 10.sp,color: isClicking?Color(0xFFFFFFFF):Color(0xFF6888FD)),),
),
),
),
SizedBox(width: 5.r,),
InkWell(
onTap: (){
RouterManager.router.navigateTo(context, '${RouterManager.jobPersonalDetailPath}?studentId=${item.studentId}&studentName=${Uri.encodeComponent(item.studentName)}');
},
child: Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.r)),
color: Colors.white,
border: Border.all(width: 1.r,color: Color(0xFFFCA017))
),
child: Center(
child: Text('详情',style: TextStyle(fontSize: 10.sp,color: Color(0xFFFCA017)),),
),
),
)
],
),
@ -217,7 +237,7 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(item.studentName,style: TextStyle(fontSize: 12.sp,color: Color(0xFF6888FD)),),
Expanded(child: Text(item.studentName,style: TextStyle(fontSize: 12.sp,color: Color(0xFF6888FD)),)),
tabIndex == 0?InkWell(
onTap: (){
setState(() {
@ -254,6 +274,24 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
child:Text('设为优先',style: TextStyle(fontSize: 10.sp,color: Color(0xFF6888FD)),),
),
),
),
SizedBox(width: 5.r,),
InkWell(
onTap: (){
RouterManager.router.navigateTo(context, '${RouterManager.jobPersonalDetailPath}?studentId=${item.studentId}&studentName=${Uri.encodeComponent(item.studentName)}');
},
child: Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.r)),
color: Colors.white,
border: Border.all(width: 1.r,color: Color(0xFFFCA017))
),
child: Center(
child: Text('详情',style: TextStyle(fontSize: 10.sp,color: Color(0xFFFCA017)),),
),
),
)
],
),

View File

@ -293,7 +293,8 @@ class _JobListParticipateInClassState extends State<JobListParticipateInClass> w
void quickDataCheck(MarkingTasks task) {
RouterManager.router.navigateTo(
context,
RouterManager.quickDataCheckPath + '?className=${Uri.encodeComponent(task.className)}&jobId=${widget.jobId}',
RouterManager.quickDataCheckPath +
'?gradeName=${Uri.encodeComponent(widget.genderName)}&className=${Uri.encodeComponent(task.className)}&jobId=${widget.jobId}',
transition: getTransition(),
);
}
@ -408,16 +409,33 @@ class _JobListParticipateInClassState extends State<JobListParticipateInClass> w
),
backgroundColor: Colors.white,
),
body: MyFutureBuilder.buildFutureBuilderOfSingleInstance<List<MarkingTasks>?>(context, _future, (value) {
if (value == null) return Container();
value.forEach((e) {
e.collectNumber = favoriteMap['${e.dpcSchoolId}+${e.dpcGradeId}+${e.className}'] ?? 0;
});
bool thePadTerminal = isPad();
if (widget.completed) {
//
if (thePadTerminal)
return TabletEndCompleted(
body: RefreshIndicator(
onRefresh: () async {
getListOfJobFavoritesData().then((value) {
_future = getData();
toUpState(setState, () {}, mounted);
});
},
child: MyFutureBuilder.buildFutureBuilderOfSingleInstance<List<MarkingTasks>?>(context, _future, (value) {
if (value == null) return Container();
value.forEach((e) {
e.collectNumber = favoriteMap['${e.dpcSchoolId}+${e.dpcGradeId}+${e.className}'] ?? 0;
});
bool thePadTerminal = isPad();
if (widget.completed) {
//
if (thePadTerminal)
return TabletEndCompleted(
data: value,
genderName: widget.genderName,
bookmarks: bookmarks,
jobViewReport: jobViewReport,
quickDataCheck: quickDataCheck,
showStudentList: showStudentList,
);
//
return MobileEndCompleted(
data: value,
genderName: widget.genderName,
bookmarks: bookmarks,
@ -425,21 +443,23 @@ class _JobListParticipateInClassState extends State<JobListParticipateInClass> w
quickDataCheck: quickDataCheck,
showStudentList: showStudentList,
);
}
//
return MobileEndCompleted(
data: value,
genderName: widget.genderName,
bookmarks: bookmarks,
jobViewReport: jobViewReport,
quickDataCheck: quickDataCheck,
showStudentList: showStudentList,
);
}
//
if (thePadTerminal)
return TabletEnd(
data: value,
genderName: widget.genderName,
bookmarks: bookmarks,
endReview: endReview,
goToReview: goToReview,
jobViewReport: jobViewReport,
quickDataCheck: quickDataCheck,
oneClickReview: oneClickReview,
showStudentList: showStudentList,
);
//
if (thePadTerminal)
return TabletEnd(
return MobileEnd(
data: value,
genderName: widget.genderName,
bookmarks: bookmarks,
@ -450,19 +470,8 @@ class _JobListParticipateInClassState extends State<JobListParticipateInClass> w
oneClickReview: oneClickReview,
showStudentList: showStudentList,
);
return MobileEnd(
data: value,
genderName: widget.genderName,
bookmarks: bookmarks,
endReview: endReview,
goToReview: goToReview,
jobViewReport: jobViewReport,
quickDataCheck: quickDataCheck,
oneClickReview: oneClickReview,
showStudentList: showStudentList,
);
}),
}),
),
),
);
}
@ -602,7 +611,7 @@ class TabletEndCompleted extends StatelessWidget {
marginEdg: EdgeInsets.only(top: 5.h),
),
$CompletedHomeworkProgressBar(
color: Color.fromRGBO(255, 190, 91, 1),
color: Color.fromRGBO(76, 199, 147, 1),
percent: taskItem.subjectivePrecision,
title: '主观题正确率:',
fontSize: 8.sp,
@ -611,7 +620,7 @@ class TabletEndCompleted extends StatelessWidget {
marginEdg: EdgeInsets.only(top: 5.h),
),
$CompletedHomeworkProgressBar(
color: Color.fromRGBO(166, 139, 242, 1),
color: Color.fromRGBO(76, 199, 147, 1),
percent: taskItem.precision,
title: '总正确率:',
fontSize: 8.sp,
@ -715,7 +724,7 @@ class TabletEndCompleted extends StatelessWidget {
onTap: () => easyThrottle('go_to_review_homework', () => quickDataCheck(taskItem)),
child: Container(
alignment: Alignment.center,
child: quickText('数据快查', color: Color.fromRGBO(79, 79, 79, 1), size: 11.sp),
child: quickText('数据快查', color: Color.fromRGBO(118, 118, 118, 1), size: 11.sp),
),
),
),
@ -798,7 +807,7 @@ class MobileEndCompleted extends StatelessWidget {
),
if (task.isFinish)
$CompletedHomeworkProgressBar(
color: Color.fromRGBO(255, 190, 91, 1),
color: Color.fromRGBO(76, 199, 147, 1),
percent: task.subjectivePrecision,
title: '主观题正确率:',
padingEdg: padingEdg,
@ -806,7 +815,7 @@ class MobileEndCompleted extends StatelessWidget {
),
if (task.isFinish)
$CompletedHomeworkProgressBar(
color: Color.fromRGBO(166, 139, 242, 1),
color: Color.fromRGBO(76, 199, 147, 1),
percent: task.precision,
title: '总正确率:',
padingEdg: padingEdg,
@ -904,7 +913,7 @@ class MobileEndCompleted extends StatelessWidget {
onTap: () => easyThrottle('go_to_review_homework', () => quickDataCheck(task)),
child: Container(
alignment: Alignment.center,
child: quickText('数据快查', color: Color.fromRGBO(79, 79, 79, 1), size: 13.sp),
child: quickText('数据快查', color: Color.fromRGBO(118, 118, 118, 1), size: 12.sp),
),
),
),
@ -1123,37 +1132,38 @@ Widget $itemDataViewOfPad(
),
),
SizedBox(height: 8.h),
Padding(
padding: EdgeInsets.only(left: 10.w, right: 10.w),
child: Row(
children: [
Expanded(
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: 5.h,
animationDuration: 2500,
percent: task.progressPercentage / 100,
linearGradient: LinearGradient(
tileMode: TileMode.mirror,
stops: [0.0, 1.0],
colors: task.progressPercentage / 100 != 1
? [Theme.of(context).primaryColor.withOpacity(0.1), Theme.of(context).primaryColor]
: [
Color.fromRGBO(144, 224, 190, 1).withOpacity(0.1),
Color.fromRGBO(144, 224, 190, 1),
],
if (!task.isFinish)
Padding(
padding: EdgeInsets.only(left: 10.w, right: 10.w),
child: Row(
children: [
Expanded(
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: 5.h,
animationDuration: 2500,
percent: task.progressPercentage / 100,
linearGradient: LinearGradient(
tileMode: TileMode.mirror,
stops: [0.0, 1.0],
colors: task.progressPercentage / 100 != 1
? [Theme.of(context).primaryColor.withOpacity(0.1), Theme.of(context).primaryColor]
: [
Color.fromRGBO(144, 224, 190, 1).withOpacity(0.1),
Color.fromRGBO(144, 224, 190, 1),
],
),
backgroundColor: Color.fromRGBO(232, 232, 232, 1),
barRadius: Radius.circular(10.r),
),
backgroundColor: Color.fromRGBO(232, 232, 232, 1),
barRadius: Radius.circular(10.r),
),
),
SizedBox(width: 7.w),
quickText('${getDoubleRemoveZero(task.progressPercentage)}%',
size: 8.sp, color: Color.fromRGBO(70, 70, 70, 1))
],
SizedBox(width: 7.w),
quickText('${getDoubleRemoveZero(task.progressPercentage)}%',
size: 8.sp, color: Color.fromRGBO(70, 70, 70, 1))
],
),
),
),
if (task.isFinish)
$CompletedHomeworkProgressBar(
fontSize: 8.sp,
@ -1168,7 +1178,7 @@ Widget $itemDataViewOfPad(
$CompletedHomeworkProgressBar(
fontSize: 8.sp,
lineHeight: 6.h,
color: Color.fromRGBO(255, 190, 91, 1),
color: Color.fromRGBO(76, 199, 147, 1),
percent: task.subjectivePrecision,
title: '主观题正确率:',
padingEdg: edgins,
@ -1178,7 +1188,7 @@ Widget $itemDataViewOfPad(
$CompletedHomeworkProgressBar(
fontSize: 8.sp,
lineHeight: 6.h,
color: Color.fromRGBO(166, 139, 242, 1),
color: Color.fromRGBO(76, 199, 147, 1),
percent: task.precision,
title: '总正确率:',
padingEdg: edgins,
@ -1206,7 +1216,7 @@ Widget $itemDataViewOfPad(
onTap: () => easyThrottle('go_to_review_homework', () => quickDataCheck(task)),
child: Container(
alignment: Alignment.center,
child: quickText('数据快查', color: Color.fromRGBO(79, 79, 79, 1), size: 13.sp),
child: quickText('数据快查', color: Color.fromRGBO(118, 118, 118, 1), size: 12.sp),
),
),
),
@ -1397,45 +1407,46 @@ Widget $itemDataView(
],
),
),
SizedBox(height: 13.h),
Padding(
padding: padingEdg,
child: Row(
children: [
Expanded(
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: 8.h,
animationDuration: 2500,
SizedBox(height: 10.h),
if (!task.isFinish)
Padding(
padding: padingEdg,
child: Row(
children: [
Expanded(
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: 8.h,
animationDuration: 2500,
percent: task.progressPercentage / 100,
// center: Text(
// '${getDoubleRemoveZero(jobTaskClassItem.progressPercentage)}%',
// style: TextStyle(color: Colors.white, fontSize: 8.sp),
// ),
linearGradient: LinearGradient(
tileMode: TileMode.mirror,
stops: [0.0, 1.0],
colors: task.progressPercentage / 100 != 1
? [Theme.of(context).primaryColor.withOpacity(0.1), Theme.of(context).primaryColor]
: [
Color.fromRGBO(144, 224, 190, 1).withOpacity(0.1),
Color.fromRGBO(144, 224, 190, 1),
],
percent: task.progressPercentage / 100,
// center: Text(
// '${getDoubleRemoveZero(jobTaskClassItem.progressPercentage)}%',
// style: TextStyle(color: Colors.white, fontSize: 8.sp),
// ),
linearGradient: LinearGradient(
tileMode: TileMode.mirror,
stops: [0.0, 1.0],
colors: task.progressPercentage / 100 != 1
? [Theme.of(context).primaryColor.withOpacity(0.1), Theme.of(context).primaryColor]
: [
Color.fromRGBO(144, 224, 190, 1).withOpacity(0.1),
Color.fromRGBO(144, 224, 190, 1),
],
),
// linearStrokeCap: LinearStrokeCap.butt,
// progressColor: Theme.of(context).primaryColor,
backgroundColor: Color.fromRGBO(232, 232, 232, 1),
barRadius: Radius.circular(10.r),
),
// linearStrokeCap: LinearStrokeCap.butt,
// progressColor: Theme.of(context).primaryColor,
backgroundColor: Color.fromRGBO(232, 232, 232, 1),
barRadius: Radius.circular(10.r),
),
),
SizedBox(width: 7.w),
quickText('${getDoubleRemoveZero(task.progressPercentage)}%',
size: 10.sp, color: Color.fromRGBO(70, 70, 70, 1))
],
SizedBox(width: 7.w),
quickText('${getDoubleRemoveZero(task.progressPercentage)}%',
size: 10.sp, color: Color.fromRGBO(70, 70, 70, 1))
],
),
),
),
if (task.isFinish)
$CompletedHomeworkProgressBar(
color: Color.fromRGBO(76, 199, 147, 1),
@ -1446,7 +1457,7 @@ Widget $itemDataView(
),
if (task.isFinish)
$CompletedHomeworkProgressBar(
color: Color.fromRGBO(255, 190, 91, 1),
color: Color.fromRGBO(76, 199, 147, 1),
percent: task.subjectivePrecision,
title: '主观题正确率:',
padingEdg: padingEdg,
@ -1454,7 +1465,7 @@ Widget $itemDataView(
),
if (task.isFinish)
$CompletedHomeworkProgressBar(
color: Color.fromRGBO(166, 139, 242, 1),
color: Color.fromRGBO(76, 199, 147, 1),
percent: task.precision,
title: '总正确率:',
padingEdg: padingEdg,
@ -1485,7 +1496,7 @@ Widget $itemDataView(
onTap: () => easyThrottle('go_to_review_homework', () => quickDataCheck(task)),
child: Container(
alignment: Alignment.center,
child: quickText('数据快查', color: Color.fromRGBO(79, 79, 79, 1), size: 13.sp),
child: quickText('数据快查', color: Color.fromRGBO(118, 118, 118, 1), size: 12.sp),
),
),
),
@ -1505,7 +1516,7 @@ Widget $itemDataView(
onTap: () => easyThrottle('go_to_review_homework', () => goToReview(task)),
child: Container(
alignment: Alignment.center,
child: quickText('批阅', color: Color.fromRGBO(79, 79, 79, 1), size: 13.sp),
child: quickText('批阅', color: Color.fromRGBO(79, 79, 79, 1), size: 12.sp),
),
),
),
@ -1537,7 +1548,6 @@ Widget $completedHomeworkProgressBar(
required EdgeInsets marginEdg,
}) {
var percentStr = '${doubleToStringAsFixed(percent * 100)}%';
print(fontSize);
fontSize ??= 10.sp;
lineHeight ??= 8.h;
return Container(

View File

@ -6,6 +6,7 @@ import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/job/job_data_report.dart';
import 'package:marking_app/pages/homework_correction/widget/student_kg_table.dart';
import 'package:marking_app/pages/homework_correction/widget/student_zg_table.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/request/rest_client.dart';
import 'package:marking_app/utils/toast_utils.dart';
@ -69,6 +70,25 @@ class _QuickCheckPersonalState extends State<QuickCheckPersonal>
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
actions: [
Title(
color: Color(0xFF6888FD),
child: Container(
child: InkWell(
onTap: (){
RouterManager.router.navigateTo(context, '${RouterManager.jobPersonalDetailPath}?studentId=${widget.studentId}&studentName=${Uri.encodeComponent(studentInfo!.studentName!)}');
},
child: Padding(
padding: EdgeInsets.only(right: 16.r),
child: Text('历史作业',style: TextStyle(fontSize: 12.sp,color: Color(0xFF6888FD)),),
),
),
alignment: Alignment.center,
),
),
],
),
body: SingleChildScrollView(

View File

@ -0,0 +1,50 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class PersonalDetailTopBar extends StatefulWidget {
final TabController controller;
final ValueChanged<int>? onTap;
final String customTimeStr;
const PersonalDetailTopBar({Key? key,required this.controller, this.onTap, required this.customTimeStr}) : super(key: key);
@override
State<PersonalDetailTopBar> createState() => _PersonalDetailTopBarState();
}
class _PersonalDetailTopBarState extends State<PersonalDetailTopBar> {
@override
void initState(){
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
border: Border(bottom: BorderSide(width: 1.r,color: Color(0xFFCCCCCC)))
),
child: TabBar(
controller: widget.controller,
unselectedLabelStyle: TextStyle(fontSize: 12.sp, color: const Color.fromRGBO(102, 102, 102, 1)),
labelStyle: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(116, 145, 253, 1),
),
isScrollable: true,
labelColor: Color(0xFF6888FD),
unselectedLabelColor: Color(0xFF666666),
padding: EdgeInsets.symmetric(horizontal: 14.r),
// indicatorSize: TabBarIndicatorSize.label, //
onTap: widget.onTap,
tabs: <Widget>[
const Tab(text: '全部'),
const Tab(text: '近一周'),
const Tab(text: '近一月'),
Tab(text: widget.customTimeStr),
],
),
);
}
}

View File

@ -14,6 +14,7 @@ import 'package:flutter/material.dart';
import 'package:marking_app/common/model/enum/marking_list_type.dart';
import 'package:marking_app/pages/common/startUpPage.dart';
import 'package:marking_app/pages/homework_correction/do_papers_job_exam.dart';
import 'package:marking_app/pages/homework_correction/job_personal_detail.dart';
import 'package:marking_app/pages/homework_correction/job_priority_review_set.dart';
import 'package:marking_app/pages/homework_correction/job_report.dart';
import 'package:marking_app/pages/homework_correction/job_student_group.dart';
@ -72,6 +73,7 @@ class RouterManager {
static const String quickCheckPersonalPath = '/homework_correction/quick_check_personal';
static const String jobPriorityReviewSetPath = '/homework_correction/job_priority_review_set';
static const String jobStudentGroupPath = '/homework_correction/job_student_group';
static const String jobPersonalDetailPath = '/homework_correction/job_personal_detail';
// TheMine
@ -332,6 +334,14 @@ class RouterManager {
},
);
//
static final _jobPersonalDetailPathHandler = Handler(
handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
String studentName = params['studentName']![0];
int studentId = int.parse(params['studentId']![0]);
return JobPersonalDetail(studentId: studentId,studentName:studentName);
},
);
//
// static final _doMarkingPapers = Handler(handlerFunc: (BuildContext? context, Map<String, List<String>> params) => MarkingPapers());
@ -375,6 +385,7 @@ class RouterManager {
handler: _jobPriorityReviewSetPageHandler, transitionType: TransitionType.material);
router.define(jobStudentGroupPath, handler: _jobStudentGroupPageHandler, transitionType: TransitionType.material);
router.define(jobFavoritePagePath, handler: _jobFavoritePagePathHandler, transitionType: TransitionType.material);
router.define(jobPersonalDetailPath, handler: _jobPersonalDetailPathHandler, transitionType: TransitionType.material);
// getTransition()

View File

@ -29,6 +29,7 @@ import 'package:marking_app/common/model/job/job_report_model.dart';
import 'package:marking_app/common/model/job/job_report_question_deatil_model.dart';
import 'package:marking_app/common/model/job/job_review_submission.dart';
import 'package:marking_app/common/model/job/job_student_goups.dart';
import 'package:marking_app/common/model/job/job_student_history.dart';
import 'package:marking_app/common/model/job/job_student_level.dart';
import 'package:marking_app/common/model/job/job_task_item.dart';
import 'package:marking_app/common/model/job/marking_text_question_job.dart';
@ -344,4 +345,17 @@ abstract class RestClient {
@the_retrofit.POST("/api/jobs/de-fav-student-job")
Future<BaseStructureResult> getJobDeFavorites(@the_retrofit.Field("jobId") int jobId,
@the_retrofit.Field("studentId") int studentId, @the_retrofit.Field("questionPage") int questionPage);
// =>
@the_retrofit.GET("/api/read/student-job-history")
Future<BaseStructureResult<JobStudentHistory>> getStudentJobHistory(
@the_retrofit.Query("StudentId") int studentId,
@the_retrofit.Query("IsPaper") bool isPaper,
@the_retrofit.Query("DateStart") String? dateStart,
@the_retrofit.Query("DateEnd") String? dateEnd,
@the_retrofit.Query("Page") int page,
@the_retrofit.Query("PageSize") int pageSize,
);
}

View File

@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.98
version: 1.0.101
environment:
sdk: ">=2.17.1 <3.0.0"