Compare commits

..

31 Commits

Author SHA1 Message Date
wangyang 5d3d4b17a2 Merge pull request 'job_report_revision' (#2) from job_report_revision into main
Reviewed-on: #2
2024-03-13 15:11:28 +08:00
wangyang e84eca79d2 Merge branch 'main' into job_report_revision 2024-03-13 15:11:13 +08:00
1147192855@qq.com cea53d3544 no message 2024-03-13 15:10:15 +08:00
machuanyu c653b10515 收藏夹 2024-03-13 15:00:33 +08:00
machuanyu 001ac3a21b Merge branch 'mcy_revision' into job_report_revision 2024-03-12 14:09:31 +08:00
machuanyu c22e4f95bf 暂无数据显示 2024-03-12 14:08:59 +08:00
1147192855@qq.com 57642af805 no message 2024-03-12 14:08:07 +08:00
1147192855@qq.com 8130e8250a no message 2024-03-12 13:51:46 +08:00
1147192855@qq.com e4c889fc6d no message 2024-03-12 13:48:45 +08:00
machuanyu 314638a3ae 页面入参修改 2024-03-11 18:14:15 +08:00
machuanyu 72a04ceb10 Merge branch 'mcy_revision' into job_report_revision 2024-03-11 18:03:57 +08:00
1147192855@qq.com 3293de1814 no message 2024-03-11 18:03:46 +08:00
machuanyu 8ef26ca793 页面入参修改 2024-03-11 18:03:31 +08:00
machuanyu ea5a73d9a1 页面入参修改 2024-03-11 17:46:25 +08:00
machuanyu 199397ac3b Merge remote-tracking branch 'origin/job_report_revision' into job_report_revision 2024-03-11 17:19:55 +08:00
1147192855@qq.com 0143dc0da7 no message 2024-03-11 17:19:39 +08:00
machuanyu 68e3ed45f8 Merge branch 'mcy_revision' into job_report_revision
# Conflicts:
#	marking_app/lib/pages/homework_correction/index.dart
#	marking_app/lib/utils/request/rest_client.dart
2024-03-11 17:19:31 +08:00
1147192855@qq.com 195b6ba2b5 调整数据 2024-03-11 17:16:42 +08:00
machuanyu 9878d22822 学生分组,优先批阅人配置 2024-03-11 16:46:10 +08:00
machuanyu 0fad2da7f6 合并代码 2024-03-11 10:35:03 +08:00
machuanyu b8eceb80bb Merge branch 'mcy_revision' into job_report_revision
# Conflicts:
#	marking_app/lib/routes/RouterManager.dart
2024-03-11 10:30:00 +08:00
machuanyu 7e1ce0ef72 页面入参修改 2024-03-11 10:25:12 +08:00
1147192855@qq.com 02a7b748e1 处理列表 2024-03-09 21:56:32 +08:00
machuanyu 046f8cda4d Merge remote-tracking branch 'origin/job_report_revision' into job_report_revision 2024-03-08 11:06:05 +08:00
machuanyu 1de02f27e2 合并代码 2024-03-08 11:04:46 +08:00
1147192855@qq.com 35eaa570d1 no message 2024-03-08 10:55:12 +08:00
machuanyu cf76e6aa44 Merge branch 'mcy_revision' into job_report_revision
# Conflicts:
#	marking_app/lib/routes/RouterManager.dart
#	marking_app/lib/utils/request/rest_client.dart
2024-03-08 10:52:26 +08:00
machuanyu 2ca30595d9 滚动修改 2024-03-08 10:50:06 +08:00
1147192855@qq.com ff1b70d39d 列表页面完成 2024-03-08 10:49:16 +08:00
machuanyu 624fb083df 作业报告,数据快查 2024-03-08 10:24:25 +08:00
1147192855@qq.com e1db8ae9b9 no message 2024-03-06 18:15:43 +08:00
50 changed files with 5979 additions and 1115 deletions

6
.gitignore vendored
View File

@ -200,3 +200,9 @@ marking_app/lib/common/model/job/job_report_knowledge_model.g.dart
marking_app/lib/common/model/job/job_report_question_deatil_model.g.dart marking_app/lib/common/model/job/job_report_question_deatil_model.g.dart
marking_app/lib/common/model/job/job_do_marking_status_info.g.dart marking_app/lib/common/model/job/job_do_marking_status_info.g.dart
marking_app/lib/common/model/report/small_question.g.dart marking_app/lib/common/model/report/small_question.g.dart
marking_app/lib/pages/homework_correction/pages/job_list_participate_in_class.g.dart
marking_app/lib/common/model/job/job_favorite_model.g.dart
marking_app/lib/common/model/job/job_level_set_params.g.dart
marking_app/lib/common/model/job/job_student_goups.g.dart
marking_app/lib/common/model/job/job_student_level.g.dart
marking_app/lib/common/model/job/job_favorite_item_model.g.dart

View File

@ -54,6 +54,12 @@
<div class="content unicode" style="display: block;"> <div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe63e;</span>
<div class="name">Frame</div>
<div class="code-name">&amp;#xe63e;</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont">&#xe63d;</span> <span class="icon iconfont">&#xe63d;</span>
<div class="name">Frame</div> <div class="name">Frame</div>
@ -408,9 +414,9 @@
<pre><code class="language-css" <pre><code class="language-css"
>@font-face { >@font-face {
font-family: 'iconfont'; font-family: 'iconfont';
src: url('iconfont.woff2?t=1706671294868') format('woff2'), src: url('iconfont.woff2?t=1710142362036') format('woff2'),
url('iconfont.woff?t=1706671294868') format('woff'), url('iconfont.woff?t=1710142362036') format('woff'),
url('iconfont.ttf?t=1706671294868') format('truetype'); url('iconfont.ttf?t=1710142362036') format('truetype');
} }
</code></pre> </code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3> <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@ -436,6 +442,15 @@
<div class="content font-class"> <div class="content font-class">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-Frame14"></span>
<div class="name">
Frame
</div>
<div class="code-name">.icon-Frame14
</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont icon-Frame13"></span> <span class="icon iconfont icon-Frame13"></span>
<div class="name"> <div class="name">
@ -967,6 +982,14 @@
<div class="content symbol"> <div class="content symbol">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-Frame14"></use>
</svg>
<div class="name">Frame</div>
<div class="code-name">#icon-Frame14</div>
</li>
<li class="dib"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-Frame13"></use> <use xlink:href="#icon-Frame13"></use>

View File

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 3423846 */ font-family: "iconfont"; /* Project id 3423846 */
src: url('iconfont.woff2?t=1706671294868') format('woff2'), src: url('iconfont.woff2?t=1710142362036') format('woff2'),
url('iconfont.woff?t=1706671294868') format('woff'), url('iconfont.woff?t=1710142362036') format('woff'),
url('iconfont.ttf?t=1706671294868') format('truetype'); url('iconfont.ttf?t=1710142362036') format('truetype');
} }
.iconfont { .iconfont {
@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-Frame14:before {
content: "\e63e";
}
.icon-Frame13:before { .icon-Frame13:before {
content: "\e63d"; content: "\e63d";
} }

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,13 @@
"css_prefix_text": "icon-", "css_prefix_text": "icon-",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "39483566",
"name": "Frame",
"font_class": "Frame14",
"unicode": "e63e",
"unicode_decimal": 58942
},
{ {
"icon_id": "39175701", "icon_id": "39175701",
"name": "Frame", "name": "Frame",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

View File

@ -15,15 +15,16 @@ class RequestConfig {
static const devLoginBaseUrl = "http://192.168.2.9:6400"; // static const devLoginBaseUrl = "http://192.168.2.9:6400"; //
static const devBaseUrlOfReport = "http://192.168.2.9:4000"; // */ static const devBaseUrlOfReport = "http://192.168.2.9:4000"; // */
static const devBaseUrl = "https://mk-hw.23544.com"; // static const devBaseUrl = "https://mhw.qwit.top"; //
static const devLoginBaseUrl = "https://mk-hw.23544.com"; // static const devLoginBaseUrl = "https://mhw.qwit.top"; //
static const devBaseUrlOfReport = "https://dc-api.23544.com"; // static const devBaseUrlOfReport = "https://mhw.qwit.top"; //
static const proBaseUrlOfHomework = "https://mhw.qwit.top/hw"; //
/* 正式地址 */ /* 正式地址 */
static const proBaseUrl = "https://mk-hw.23544.com"; // static const proBaseUrl = "https://mk-hw.23544.com"; //
static const proLoginBaseUrl = "https://mk-hw.23544.com"; // static const proLoginBaseUrl = "https://mk-hw.23544.com"; //
static const proBaseUrlOfReport = "https://dc-api.23544.com"; // static const proBaseUrlOfReport = "https://dc-api.23544.com"; //
static const proBaseUrlOfHomework = "https://mk-hw.23544.com/hw"; // // static const proBaseUrlOfHomework = "https://mk-hw.23544.com/hw"; //
static const hwProxyKeywords = "/hw"; // static const hwProxyKeywords = "/hw"; //

View File

@ -0,0 +1,10 @@
//
enum JobMarkingTypeEnum {
UNUSED(name: '未使用废弃', indexValue: 0),
JOB(name: '作业', indexValue: 1),
EXAMINATION(name: '考试', indexValue: 2);
const JobMarkingTypeEnum({required this.name, required this.indexValue});
final String name;
final int indexValue;
}

View File

@ -0,0 +1,125 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_data_report.g.dart';
@JsonSerializable()
class JobDataReport extends Object {
@JsonKey(name: 'jobId')
int jobId;
@JsonKey(name: 'jobName')
String jobName;
@JsonKey(name: 'gradeName')
String gradeName;
@JsonKey(name: 'className')
String? className;
@JsonKey(name: 'validCount')
int validCount;
@JsonKey(name: 'noAnswerCount')
int noAnswerCount;
@JsonKey(name: 'kgValidRate')
double kgValidRate;
@JsonKey(name: 'kgQuestionCount')
int kgQuestionCount;
@JsonKey(name: 'zgValidRate')
double zgValidRate;
@JsonKey(name: 'zgQuestionCount')
int zgQuestionCount;
@JsonKey(name: 'studentDetails')
List<StudentDetails> studentDetails;
JobDataReport(this.jobId,this.jobName,this.gradeName,this.className,this.validCount,this.noAnswerCount,this.kgValidRate,this.kgQuestionCount,this.zgValidRate,this.zgQuestionCount,this.studentDetails,);
factory JobDataReport.fromJson(Map<String, dynamic> srcJson) => _$JobDataReportFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobDataReportToJson(this);
}
@JsonSerializable()
class StudentDetails extends Object {
@JsonKey(name: 'studentId')
int? studentId;
@JsonKey(name: 'studentName')
String? studentName;
@JsonKey(name: 'kgValidCount')
int kgValidCount;
@JsonKey(name: 'kgValidRate')
int kgValidRate;
@JsonKey(name: 'zgValidCount')
int zgValidCount;
@JsonKey(name: 'zgValidRate')
int zgValidRate;
@JsonKey(name: 'kgDetails')
List<KgDetails> kgDetails;
@JsonKey(name: 'zgDetails')
List<KgDetails> zgDetails;
StudentDetails(this.studentId,this.studentName,this.kgValidCount,this.kgValidRate,this.zgValidCount,this.zgValidRate,this.kgDetails,this.zgDetails,);
factory StudentDetails.fromJson(Map<String, dynamic> srcJson) => _$StudentDetailsFromJson(srcJson);
Map<String, dynamic> toJson() => _$StudentDetailsToJson(this);
}
@JsonSerializable()
class KgDetails extends Object {
@JsonKey(name: 'questionNo')
String questionNo;
@JsonKey(name: 'questionId')
int questionId;
@JsonKey(name: 'partName')
String partName;
@JsonKey(name: 'state')
int state;
@JsonKey(name: 'studentAnswer')
String? studentAnswer;
@JsonKey(name: 'questionAnswer')
String? questionAnswer;
@JsonKey(name: 'useTime')
int? useTime;
@JsonKey(name: 'annotateAnswers')
String? annotateAnswers;
@JsonKey(name: 'score')
double? score;
KgDetails(this.questionNo,this.questionId,this.partName,this.state,this.studentAnswer,this.questionAnswer,this.useTime,this.annotateAnswers,this.score,);
factory KgDetails.fromJson(Map<String, dynamic> srcJson) => _$KgDetailsFromJson(srcJson);
Map<String, dynamic> toJson() => _$KgDetailsToJson(this);
}

View File

@ -0,0 +1,91 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'job_data_report.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
JobDataReport _$JobDataReportFromJson(Map<String, dynamic> json) =>
JobDataReport(
json['jobId'] as int,
json['jobName'] as String,
json['gradeName'] as String,
json['className'] as String?,
json['validCount'] as int,
json['noAnswerCount'] as int,
(json['kgValidRate'] as num).toDouble(),
json['kgQuestionCount'] as int,
(json['zgValidRate'] as num).toDouble(),
json['zgQuestionCount'] as int,
(json['studentDetails'] as List<dynamic>)
.map((e) => StudentDetails.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$JobDataReportToJson(JobDataReport instance) =>
<String, dynamic>{
'jobId': instance.jobId,
'jobName': instance.jobName,
'gradeName': instance.gradeName,
'className': instance.className,
'validCount': instance.validCount,
'noAnswerCount': instance.noAnswerCount,
'kgValidRate': instance.kgValidRate,
'kgQuestionCount': instance.kgQuestionCount,
'zgValidRate': instance.zgValidRate,
'zgQuestionCount': instance.zgQuestionCount,
'studentDetails': instance.studentDetails,
};
StudentDetails _$StudentDetailsFromJson(Map<String, dynamic> json) =>
StudentDetails(
json['studentId'] as int,
json['studentName'] as String,
json['kgValidCount'] as int,
json['kgValidRate'] as int,
json['zgValidCount'] as int,
json['zgValidRate'] as int,
(json['kgDetails'] as List<dynamic>)
.map((e) => KgDetails.fromJson(e as Map<String, dynamic>))
.toList(),
(json['zgDetails'] as List<dynamic>)
.map((e) => KgDetails.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$StudentDetailsToJson(StudentDetails instance) =>
<String, dynamic>{
'studentId': instance.studentId,
'studentName': instance.studentName,
'kgValidCount': instance.kgValidCount,
'kgValidRate': instance.kgValidRate,
'zgValidCount': instance.zgValidCount,
'zgValidRate': instance.zgValidRate,
'kgDetails': instance.kgDetails,
'zgDetails': instance.zgDetails,
};
KgDetails _$KgDetailsFromJson(Map<String, dynamic> json) => KgDetails(
json['questionNo'] as String,
json['questionId'] as int,
json['partName'] as String,
json['state'] as int,
json['studentAnswer'] as String?,
json['questionAnswer'] as String?,
json['useTime'] as int?,
json['annotateAnswers'] as String?,
(json['score'] as num?)?.toDouble(),
);
Map<String, dynamic> _$KgDetailsToJson(KgDetails instance) => <String, dynamic>{
'questionNo': instance.questionNo,
'questionId': instance.questionId,
'partName': instance.partName,
'state': instance.state,
'studentAnswer': instance.studentAnswer,
'questionAnswer': instance.questionAnswer,
'useTime': instance.useTime,
'annotateAnswers': instance.annotateAnswers,
'score': instance.score,
};

View File

@ -0,0 +1,95 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_fav_student.g.dart';
@JsonSerializable()
class JobFavStudent 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;
JobFavStudent(this.page,this.pageSize,this.total,this.totalPages,this.items,this.hasPrevPage,this.hasNextPage,);
factory JobFavStudent.fromJson(Map<String, dynamic> srcJson) => _$JobFavStudentFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobFavStudentToJson(this);
}
@JsonSerializable()
class Items extends Object {
@JsonKey(name: 'id')
String id;
@JsonKey(name: 'teacherId')
int teacherId;
@JsonKey(name: 'teacherAccount')
String teacherAccount;
@JsonKey(name: 'folderName')
String folderName;
@JsonKey(name: 'jobId')
int jobId;
@JsonKey(name: 'jobName')
String jobName;
@JsonKey(name: 'studentId')
int studentId;
@JsonKey(name: 'studentName')
String studentName;
@JsonKey(name: 'className')
String className;
@JsonKey(name: 'questionPage')
int questionPage;
@JsonKey(name: 'questionPicture')
String questionPicture;
@JsonKey(name: 'createTime')
String createTime;
@JsonKey(name: 'schoolName')
String schoolName;
@JsonKey(name: 'gradeName')
String gradeName;
@JsonKey(name: 'studentClassName')
String studentClassName;
Items(this.id,this.teacherId,this.teacherAccount,this.folderName,this.jobId,this.jobName,this.studentId,this.studentName,this.className,this.questionPage,this.questionPicture,this.createTime,this.schoolName,this.gradeName,this.studentClassName,);
factory Items.fromJson(Map<String, dynamic> srcJson) => _$ItemsFromJson(srcJson);
Map<String, dynamic> toJson() => _$ItemsToJson(this);
}

View File

@ -0,0 +1,25 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_favorite_item_model.g.dart';
@JsonSerializable()
class JobFavoriteItemModel extends Object {
@JsonKey(name: 'studentId')
int studentId;
@JsonKey(name: 'studentName')
String studentName;
@JsonKey(name: 'createTime')
String createTime;
JobFavoriteItemModel(
this.studentId,
this.studentName,
this.createTime,
);
factory JobFavoriteItemModel.fromJson(Map<String, dynamic> srcJson) => _$JobFavoriteItemModelFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobFavoriteItemModelToJson(this);
}

View File

@ -0,0 +1,33 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_favorite_model.g.dart';
@JsonSerializable()
class JobFavoriteModel extends Object {
@JsonKey(name: 'schoolId')
int schoolId;
@JsonKey(name: 'gradeId')
int gradeId;
@JsonKey(name: 'graduationYear')
String graduationYear;
@JsonKey(name: 'className')
String className;
@JsonKey(name: 'count')
int count;
JobFavoriteModel(
this.schoolId,
this.gradeId,
this.graduationYear,
this.className,
this.count,
);
factory JobFavoriteModel.fromJson(Map<String, dynamic> srcJson) => _$JobFavoriteModelFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobFavoriteModelToJson(this);
}

View File

@ -0,0 +1,23 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_level_set_params.g.dart';
@JsonSerializable()
class JobLevelSetParams extends Object {
@JsonKey(name: 'studentGroupDetailId')
int studentGroupDetailId;
@JsonKey(name: 'readLevel')
int readLevel;
JobLevelSetParams(this.studentGroupDetailId,this.readLevel,);
factory JobLevelSetParams.fromJson(Map<String, dynamic> srcJson) => _$JobLevelSetParamsFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobLevelSetParamsToJson(this);
}

View File

@ -51,6 +51,12 @@ class JobReportModel extends Object {
@JsonKey(name: 'overallTitles') @JsonKey(name: 'overallTitles')
List<OverallTitles> overallTitles; List<OverallTitles> overallTitles;
@JsonKey(name: 'kgReport')
KgReport kgReport;
@JsonKey(name: 'zgReport')
ZgReport zgReport;
// -- // --
@JsonKey(name: 'allpairsStudents') @JsonKey(name: 'allpairsStudents')
List<StudentAnswerInfos>? allpairsStudents; List<StudentAnswerInfos>? allpairsStudents;
@ -82,7 +88,10 @@ class JobReportModel extends Object {
this.knowledgeInfos, this.knowledgeInfos,
this.questionAnswerInfos, this.questionAnswerInfos,
this.studentAnswerInfos, this.studentAnswerInfos,
this.overallTitles, [ this.overallTitles,
this.kgReport,
this.zgReport,
[
this.allpairsStudents, this.allpairsStudents,
this.passStudents, this.passStudents,
this.disqualifiedStudents, this.disqualifiedStudents,
@ -274,3 +283,84 @@ class OverallTitles extends Object {
Map<String, dynamic> toJson() => _$OverallTitlesToJson(this); Map<String, dynamic> toJson() => _$OverallTitlesToJson(this);
} }
@JsonSerializable()
class KgReport extends Object {
@JsonKey(name: 'correctRate')
int correctRate;
@JsonKey(name: 'details')
List<Details> details;
KgReport(this.correctRate,this.details,);
factory KgReport.fromJson(Map<String, dynamic> srcJson) => _$KgReportFromJson(srcJson);
Map<String, dynamic> toJson() => _$KgReportToJson(this);
}
@JsonSerializable()
class ZgReport extends Object {
@JsonKey(name: 'correctRate')
int correctRate;
@JsonKey(name: 'details')
List<Details> details;
ZgReport(this.correctRate,this.details,);
factory ZgReport.fromJson(Map<String, dynamic> srcJson) => _$ZgReportFromJson(srcJson);
Map<String, dynamic> toJson() => _$ZgReportToJson(this);
}
@JsonSerializable()
class Details extends Object {
@JsonKey(name: 'questionNo')
String questionNo;
@JsonKey(name: 'questionId')
int questionId;
@JsonKey(name: 'partName')
String partName;
@JsonKey(name: 'questionType')
int questionType;
@JsonKey(name: 'validRate')
int validRate;
@JsonKey(name: 'validCount')
String validCount;
@JsonKey(name: 'validStudentNames')
List<String> validStudentNames;
@JsonKey(name: 'correctRate')
int correctRate;
@JsonKey(name: 'questionAnswer')
String questionAnswer;
@JsonKey(name: 'questionPicture')
String? questionPicture;
@JsonKey(name: 'priorityGeneral')
String priorityGeneral;
@JsonKey(name: 'priorityStudentNames')
List<String> priorityStudentNames;
Details(this.questionNo,this.questionId,this.partName,this.questionType,this.validRate,this.validCount,this.validStudentNames,this.correctRate,this.questionAnswer,this.questionPicture,this.priorityGeneral,this.priorityStudentNames,);
factory Details.fromJson(Map<String, dynamic> srcJson) => _$DetailsFromJson(srcJson);
Map<String, dynamic> toJson() => _$DetailsToJson(this);
}

View File

@ -0,0 +1,26 @@
import 'package:json_annotation/json_annotation.dart';
part "job_student_goups.g.dart";
@JsonSerializable()
class JobStudentGroups extends Object {
@JsonKey(name: 'groupId')
int groupId;
@JsonKey(name: 'groupName')
String groupName;
@JsonKey(name: 'classNames')
List<String> classNames;
JobStudentGroups(this.groupId,this.groupName,this.classNames,);
factory JobStudentGroups.fromJson(Map<String, dynamic> srcJson) => _$JobStudentGroupsFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobStudentGroupsToJson(this);
}

View File

@ -0,0 +1,32 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_student_level.g.dart';
@JsonSerializable()
class JobStudentLevel extends Object {
@JsonKey(name: 'studentGroupDetailId')
int studentGroupDetailId;
@JsonKey(name: 'studentId')
int studentId;
@JsonKey(name: 'studentName')
String studentName;
@JsonKey(name: 'createTime')
String createTime;
@JsonKey(name: 'readLevel')
int readLevel;
JobStudentLevel(this.studentGroupDetailId,this.studentId,this.studentName,this.createTime,this.readLevel,);
factory JobStudentLevel.fromJson(Map<String, dynamic> srcJson) => _$JobStudentLevelFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobStudentLevelToJson(this);
}

View File

@ -1,4 +1,5 @@
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import 'package:marking_app/common/model/enum/job_marking_type_enum.dart';
part 'job_task_item.g.dart'; part 'job_task_item.g.dart';
@ -40,8 +41,8 @@ class JobTaskItem extends Object {
@JsonKey(name: 'precision') @JsonKey(name: 'precision')
double precision; double precision;
@JsonKey(name: 'markingTasks') // @JsonKey(name: 'markingTasks')
List<MarkingTasks> markingTasks; // List<MarkingTasks> markingTasks;
@JsonKey(name: 'createTime') @JsonKey(name: 'createTime')
String createTime; String createTime;
@ -49,6 +50,14 @@ class JobTaskItem extends Object {
@JsonKey(name: 'progressPercentage') @JsonKey(name: 'progressPercentage')
double progressPercentage; // double progressPercentage; //
@JsonKey(name: 'markingType')
int markingType; //
@JsonKey(name: 'markingTypeEnum')
JobMarkingTypeEnum markingTypeEnum; //
int taskCount; //
JobTaskItem( JobTaskItem(
this.id, this.id,
this.title, this.title,
@ -62,10 +71,12 @@ class JobTaskItem extends Object {
this.objectivePrecision, this.objectivePrecision,
this.subjectivePrecision, this.subjectivePrecision,
this.precision, this.precision,
this.markingTasks, // this.markingTasks,
this.createTime, { this.createTime,
this.progressPercentage = 0, this.markingType,
}) { this.taskCount,
{this.progressPercentage = 0,
this.markingTypeEnum = JobMarkingTypeEnum.UNUSED}) {
try { try {
progressPercentage = (finishCount / totalCount) * 100; progressPercentage = (finishCount / totalCount) * 100;
if (progressPercentage.isNaN) { if (progressPercentage.isNaN) {
@ -76,6 +87,11 @@ class JobTaskItem extends Object {
} catch (e) { } catch (e) {
progressPercentage = 0; progressPercentage = 0;
} }
try {
markingTypeEnum = JobMarkingTypeEnum.values[this.markingType];
} catch (e) {
markingTypeEnum = JobMarkingTypeEnum.UNUSED;
}
} }
factory JobTaskItem.fromJson(Map<String, dynamic> srcJson) => _$JobTaskItemFromJson(srcJson); factory JobTaskItem.fromJson(Map<String, dynamic> srcJson) => _$JobTaskItemFromJson(srcJson);
@ -91,6 +107,10 @@ class MarkingTasks extends Object {
@JsonKey(name: 'className') @JsonKey(name: 'className')
String className; String className;
int dpcSchoolId;
int dpcGradeId;
@JsonKey(name: 'teacherName') @JsonKey(name: 'teacherName')
String teacherName; String teacherName;
@ -132,8 +152,14 @@ class MarkingTasks extends Object {
@JsonKey(name: 'canGoReview') @JsonKey(name: 'canGoReview')
bool canGoReview; // bool canGoReview; //
/** 前端自定义字段 */
@JsonKey(name: 'collectNumber')
int collectNumber; //
MarkingTasks( MarkingTasks(
this.id, this.id,
this.dpcSchoolId,
this.dpcGradeId,
this.className, this.className,
this.teacherName, this.teacherName,
this.isFinish, this.isFinish,
@ -141,13 +167,14 @@ class MarkingTasks extends Object {
this.commitStudentCount, this.commitStudentCount,
this.totalCount, this.totalCount,
this.finishCount, this.finishCount,
this.precision,
this.objectivePrecision, this.objectivePrecision,
this.subjectivePrecision, this.subjectivePrecision,
this.precision,
this.canMarking, { this.canMarking, {
this.progressPercentage = 0, this.progressPercentage = 0,
this.canGoReview = true, this.canGoReview = true,
this.finishTime, this.finishTime,
this.collectNumber = 0,
}) { }) {
try { try {
progressPercentage = (finishCount / totalCount) * 100; progressPercentage = (finishCount / totalCount) * 100;
@ -158,6 +185,11 @@ class MarkingTasks extends Object {
} catch (e) { } catch (e) {
progressPercentage = 0; progressPercentage = 0;
} }
try {
precision = precision / 100;
objectivePrecision = objectivePrecision / 100;
subjectivePrecision = subjectivePrecision / 100;
} catch (e) {}
canGoReview = totalCount > 0 && canMarking && !isFinish; canGoReview = totalCount > 0 && canMarking && !isFinish;
} }

View File

@ -21,12 +21,22 @@ class MarkingListParams extends BasePage {
@JsonKey(name: 'PageType') @JsonKey(name: 'PageType')
int pageType; int pageType;
String? startTime;
String? endTime;
int? markingType; // 1 2
MarkingListParams({ MarkingListParams({
required this.isFinish, required this.isFinish,
required this.pageType, required this.pageType,
required page, required page,
required limit, required limit,
}) : super(page, limit); this.markingType,
this.startTime,
this.endTime,
}) : super(page, limit) {
this.markingType ??= 1;
}
factory MarkingListParams.fromJson(Map<String, dynamic> srcJson) => _$MarkingListParamsFromJson(srcJson); factory MarkingListParams.fromJson(Map<String, dynamic> srcJson) => _$MarkingListParamsFromJson(srcJson);

View File

@ -10,6 +10,7 @@ import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -83,6 +84,28 @@ class _MyAppState extends State<MyApp> {
title: '远轩阅卷系统', title: '远轩阅卷系统',
navigatorKey: TheGlobal.navigatorKey, navigatorKey: TheGlobal.navigatorKey,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
// locale: const Locale('zh', 'CN'), // ,
// supportedLocales: [
// const Locale('zh', 'CN'), //
// // locale可以在这里添加
// ],
// flutter_localizations依赖
supportedLocales: [
const Locale('zh', 'CN'), //
// locale可以在这里添加
],
localizationsDelegates: [
// ...delegates
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, // 使Cupertino风格的组件
// ...delegates
],
localeResolutionCallback: (locale, supportedLocales) {
// locale解析逻辑
// Locale对象
return locale;
},
theme: ThemeData( theme: ThemeData(
primarySwatch: createMaterialColor(const Color.fromRGBO(46, 91, 255, 1)), primarySwatch: createMaterialColor(const Color.fromRGBO(46, 91, 255, 1)),
// textTheme: Typography.englishLike2018.apply(fontSizeFactor: 1.sp,), // textTheme: Typography.englishLike2018.apply(fontSizeFactor: 1.sp,),

View File

@ -357,29 +357,6 @@ Widget $theTabBar({required TabController controller, ValueChanged<int>? onTap})
isScrollable: true, isScrollable: true,
labelColor: const Color.fromRGBO(45, 56, 76, 1), labelColor: const Color.fromRGBO(45, 56, 76, 1),
indicatorSize: TabBarIndicatorSize.label, // indicatorSize: TabBarIndicatorSize.label, //
// labelPadding: EdgeInsets.symmetric(vertical: 0), //
// background: linear-gradient(270deg, #2E5BFF 30.23%, rgba(46, 91, 255, 0.00) 96.59%);
// indicatorColor: RectangleIndicator(),
// indicator: BoxDecoration(
// gradient: LinearGradient(
// begin: Alignment.centerLeft,
// end: Alignment.centerRight,
// colors: [
// Color.fromRGBO(46, 91, 255, 0.00),
// Color(0xFF2E5BFF),
// ],
// stops: [0.3023, 0.9659],
// // transform: GradientRotation(3.14 / 2), //270
// ),
// ),
// indicator: BoxDecoration(
// //
// gradient: LinearGradient(
// colors: [Colors.yellow, Colors.green], //
// begin: Alignment.centerLeft,
// end: Alignment.centerRight,
// ),
// ),
onTap: onTap, onTap: onTap,
tabs: const <Widget>[Tab(text: '阅卷'), Tab(text: '作业')], tabs: const <Widget>[Tab(text: '阅卷'), Tab(text: '作业')],
), ),

View File

@ -46,30 +46,29 @@ class HomeworkTasksViewItem extends StatelessWidget with CommonMixin {
/// @param {bool} className /// @param {bool} className
/// @param {bool} submitted () /// @param {bool} submitted ()
Future<void> showStudents( Future<void> showStudents(
BuildContext context, BuildContext context, [
List<int> taskIds, [
bool? submitted = false, bool? submitted = false,
String? className, String? className,
]) async { ]) async {
ToastUtils.showLoading(); ToastUtils.showLoading();
List<JobConcernedWithStudent> students = []; List<JobConcernedWithStudent> students = [];
try { // try {
RestClient _client = await getClient(); // RestClient _client = await getClient();
BaseStructureResult<List<JobConcernedWithStudent>> _result = await _client.getJobWithStudents( // BaseStructureResult<List<JobConcernedWithStudent>> _result = await _client.getJobWithStudents(
JobConcernedWithStudentParams(taskIds, isCommit: submitted), // JobConcernedWithStudentParams(taskIds, isCommit: submitted),
); // );
if (!_result.success) { // if (!_result.success) {
return ToastUtils.showError(_result.message ?? '获取学生列表失败'); // return ToastUtils.showError(_result.message ?? '获取学生列表失败');
} // }
if (_result.data?.isEmpty ?? true) { // if (_result.data?.isEmpty ?? true) {
return ToastUtils.showError('获取到的学生列表为空'); // return ToastUtils.showError('获取到的学生列表为空');
} // }
students = _result.data!; // students = _result.data!;
} catch (e) { // } catch (e) {
return ToastUtils.showError('获取学生列表失败'); // return ToastUtils.showError('获取学生列表失败');
} finally { // } finally {
ToastUtils.dismiss(); // ToastUtils.dismiss();
} // }
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
@ -125,28 +124,19 @@ class HomeworkTasksViewItem extends StatelessWidget with CommonMixin {
); );
} }
void oneClickReview(int taskId) async {
try {
ToastUtils.showLoading();
RestClient _client = await getClient();
BaseStructureResult<bool> res = await _client.toJobOneClickReview(taskId);
if (res.success) return call();
ToastUtils.showError(res.message ?? '操作失败');
} catch (e) {
} finally {
ToastUtils.dismiss();
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return completed return completed
? $CompletedHomeworkView(jobTaskItem: jobTaskItem, showStudentsCall: showStudents) ? $CompletedHomeworkView(jobTaskItem: jobTaskItem, showStudentsCall: showStudents)
: $UnfinishedHomework( : InkWell(
jobTaskItem: jobTaskItem, onTap: () {
refreshCallback: call, String url =
endReviewCallback: endReview, '${RouterManager.jobListParticipateInClassPath}?&jobId=${jobTaskItem.id}&genderName=${Uri.encodeComponent(jobTaskItem.genderName)}&jobName=${Uri.encodeComponent(jobTaskItem.title)}';
oneClickReviewCallback: oneClickReview, RouterManager.router.navigateTo(context, url, transition: getTransition()).then((value) {
if (value != null && value == true) call();
});
},
child: $UnfinishedHomework(jobTaskItem: jobTaskItem),
); );
} }
} }
@ -155,9 +145,15 @@ class HomeworkTasksViewItem extends StatelessWidget with CommonMixin {
@hwidget @hwidget
Widget $completedHomeworkView(BuildContext context, Widget $completedHomeworkView(BuildContext context,
{required JobTaskItem jobTaskItem, required ShowStudentsCall showStudentsCall}) { {required JobTaskItem jobTaskItem, required ShowStudentsCall showStudentsCall}) {
return Container( return InkWell(
onTap: () {
String url =
'${RouterManager.jobListParticipateInClassPath}?&jobId=${jobTaskItem.id}&genderName=${Uri.encodeComponent(jobTaskItem.genderName)}&jobName=${Uri.encodeComponent(jobTaskItem.title)}&completed=${true}';
RouterManager.router.navigateTo(context, url, transition: getTransition());
},
child: Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 20.h, horizontal: 10.w), padding: EdgeInsets.only(top: 20.h),
margin: EdgeInsets.only(bottom: 12.h), margin: EdgeInsets.only(bottom: 12.h),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r), borderRadius: BorderRadius.circular(6.r),
@ -174,7 +170,9 @@ Widget $completedHomeworkView(BuildContext context,
child: Column( child: Column(
children: [ children: [
// //
Row( Padding(
padding: EdgeInsets.symmetric(horizontal: 10.w),
child: Row(
children: [ children: [
Container( Container(
width: 32.w, width: 32.w,
@ -201,132 +199,114 @@ Widget $completedHomeworkView(BuildContext context,
) )
], ],
), ),
),
SizedBox(height: 12.h), SizedBox(height: 12.h),
Row( Padding(
padding: EdgeInsets.symmetric(horizontal: 10.w),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
quickText( quickText(
jobTaskItem.subjectName, jobTaskItem.createTime.substring(0, 10),
color: Color.fromRGBO(97, 97, 97, 1), color: Color.fromRGBO(97, 97, 97, 1),
size: 14.sp, size: 14.sp,
fontWeight: FontWeight.w500,
),
quickText(' / ', color: Color.fromRGBO(76, 199, 147, 1), size: 12.sp, fontWeight: FontWeight.w500),
quickText(
'参与班级:${jobTaskItem.taskCount}',
color: Color.fromRGBO(76, 199, 147, 1),
size: 12.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
quickText(' / ', color: Color.fromRGBO(130, 130, 130, 1), size: 12.sp, fontWeight: FontWeight.w500), quickText(' / ', color: Color.fromRGBO(116, 145, 253, 1), size: 12.sp, fontWeight: FontWeight.w500),
Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
quickText('题量:', color: Color.fromRGBO(130, 130, 130, 1), size: 13.sp),
quickText( quickText(
jobTaskItem.totalCount, '科目:' + jobTaskItem.subjectName,
color: Color.fromRGBO(97, 97, 97, 1), color: Color.fromRGBO(116, 145, 253, 1),
size: 14.sp, size: 12.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w600,
), ),
], ],
), ),
), ),
quickText(' / ', color: Color.fromRGBO(130, 130, 130, 1), size: 12.sp, fontWeight: FontWeight.w500),
quickText(
jobTaskItem.createTime.substring(0, 16),
color: Color.fromRGBO(97, 97, 97, 1),
size: 14.sp,
fontWeight: FontWeight.w500,
),
],
),
SizedBox(height: 20.h), SizedBox(height: 20.h),
$CompletedHomeworkInfoBox( Container(
segmentation: false, padding: EdgeInsets.symmetric(vertical: 8.h),
showStudentsCall: showStudentsCall, decoration: BoxDecoration(
unsubmittedQuantity: jobTaskItem.studentCount - jobTaskItem.commitStudentCount, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(6.r), bottomRight: Radius.circular(6.r)),
submittedQuantity: jobTaskItem.commitStudentCount, color: Colors.white,
precision: jobTaskItem.precision / 100, boxShadow: [
objectivePrecision: jobTaskItem.objectivePrecision / 100, BoxShadow(
subjectivePrecision: jobTaskItem.subjectivePrecision / 100, color: const Color.fromRGBO(0, 0, 0, 0.15),
taskIds: jobTaskItem.markingTasks.map((e) => e.id).toList(), offset: Offset(0, -0.0001), //y轴偏移量
blurRadius: 4, //
spreadRadius: 0, //
)
],
), ),
InkWell( child: Row(children: [
onTap: () { Expanded(
child: InkWell(
onTap: () => easyThrottle('go_to_homework_report', () {
RouterManager.router.navigateTo( RouterManager.router.navigateTo(
context, context,
RouterManager.jobReportPagePath + '?title=${Uri.encodeComponent(jobTaskItem.title)}&id=${jobTaskItem.id}', RouterManager.jobReportPagePath +
'?title=${Uri.encodeComponent(jobTaskItem.title)}&id=${jobTaskItem.id}',
transition: getTransition(), transition: getTransition(),
); );
}, }),
child: Row(
children: [
Expanded(flex: 1, child: SizedBox()),
Expanded(
flex: 9,
child: Container( child: Container(
alignment: Alignment.center, alignment: Alignment.center,
margin: EdgeInsets.only(top: 20.h), child: quickText('查看报告', color: Color.fromRGBO(118, 118, 118, 1), size: 12.sp),
padding: EdgeInsets.symmetric(vertical: 7.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [Color.fromRGBO(95, 197, 255, 1), Color.fromRGBO(61, 68, 255, 0.82)],
), ),
)),
]),
), ),
child: quickText('查看报告', color: Colors.white, size: 12.sp), // $CompletedHomeworkInfoBox(
), // segmentation: false,
), // showStudentsCall: showStudentsCall,
Expanded(flex: 1, child: SizedBox()), // unsubmittedQuantity: jobTaskItem.studentCount - jobTaskItem.commitStudentCount,
], // submittedQuantity: jobTaskItem.commitStudentCount,
), // precision: jobTaskItem.precision / 100,
), // objectivePrecision: jobTaskItem.objectivePrecision / 100,
SizedBox(height: 10.h), // subjectivePrecision: jobTaskItem.subjectivePrecision / 100,
ExpansionTile(
tilePadding: EdgeInsets.only(right: 10.w, bottom: 0),
title: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
// badges.Badge(
// position: badges.BadgePosition.topEnd(top: -3.r, end: -12.r),
// badgeStyle: BadgeStyle(badgeColor: Theme.of(context).primaryColor.withOpacity(0.7)),
// badgeContent: Text(
// jobTaskItem.markingTasks.length.toString(),
// style: TextStyle(color: Colors.white, fontSize: 10.sp),
// ), // ),
// child: quickText('班级列表 ', size: 17.sp), // InkWell(
// onTap: () {
// RouterManager.router.navigateTo(
// context,
// RouterManager.jobReportPagePath + '?title=${Uri.encodeComponent(jobTaskItem.title)}&id=${jobTaskItem.id}',
// transition: getTransition(),
// );
// },
// child: Row(
// children: [
// Expanded(flex: 1, child: SizedBox()),
// Expanded(
// flex: 9,
// child: Container(
// alignment: Alignment.center,
// margin: EdgeInsets.only(top: 20.h),
// padding: EdgeInsets.symmetric(vertical: 7.h),
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(20),
// gradient: LinearGradient(
// begin: Alignment.centerLeft,
// end: Alignment.centerRight,
// colors: [Color.fromRGBO(95, 197, 255, 1), Color.fromRGBO(61, 68, 255, 0.82)],
// ), // ),
badges.Badge( // ),
badgeStyle: badges.BadgeStyle( // child: quickText('查看报告', color: Colors.white, size: 12.sp),
shape: badges.BadgeShape.square, // ),
borderRadius: BorderRadius.circular(5.r), // ),
padding: EdgeInsets.all(2.r), // Expanded(flex: 1, child: SizedBox()),
badgeGradient: badges.BadgeGradient.linear( // ],
colors: [ // ),
Colors.purple, // )
Colors.blue,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
position: badges.BadgePosition.topEnd(top: -2.r, end: -8.r),
badgeContent: Text(
jobTaskItem.markingTasks.length.toString(),
style: TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold),
),
child: quickText('班级列表 ', size: 17.sp),
),
], ],
), ),
childrenPadding: EdgeInsets.only(top: 0.h),
children: jobTaskItem.markingTasks.map((e) {
return $CompletedHomeworkChildView(
jobTaskItem: jobTaskItem,
taskItem: e,
showStudentsCall: showStudentsCall,
);
}).toList(),
),
],
), ),
); );
} }
@ -364,7 +344,6 @@ Widget $completedHomeworkChildView(
submittedQuantity: taskItem.commitStudentCount, submittedQuantity: taskItem.commitStudentCount,
unsubmittedQuantity: taskItem.studentCount - taskItem.commitStudentCount, unsubmittedQuantity: taskItem.studentCount - taskItem.commitStudentCount,
showStudentsCall: showStudentsCall, showStudentsCall: showStudentsCall,
taskIds: [taskItem.id],
className: taskItem.className, className: taskItem.className,
), ),
], ],
@ -375,7 +354,6 @@ Widget $completedHomeworkChildView(
@swidget @swidget
Widget $completedHomeworkBtn( Widget $completedHomeworkBtn(
BuildContext context, { BuildContext context, {
required List<int> taskIds,
required int submittedQuantity, required int submittedQuantity,
required int unsubmittedQuantity, required int unsubmittedQuantity,
required ShowStudentsCall showStudentsCall, required ShowStudentsCall showStudentsCall,
@ -391,7 +369,7 @@ Widget $completedHomeworkBtn(
child: InkWell( child: InkWell(
onTap: () { onTap: () {
if (unsubmittedQuantity <= 0) return ToastUtils.showInfo('没有未提交的作业'); if (unsubmittedQuantity <= 0) return ToastUtils.showInfo('没有未提交的作业');
showStudentsCall(context, taskIds, false, className); showStudentsCall(context, false, className);
}, },
borderRadius: BorderRadius.circular(8.r), borderRadius: BorderRadius.circular(8.r),
child: Container( child: Container(
@ -413,7 +391,7 @@ Widget $completedHomeworkBtn(
child: InkWell( child: InkWell(
onTap: () async { onTap: () async {
if (submittedQuantity <= 0) return ToastUtils.showInfo('没有已提交的作业'); if (submittedQuantity <= 0) return ToastUtils.showInfo('没有已提交的作业');
showStudentsCall(context, taskIds, true, className); showStudentsCall(context, true, className);
}, },
borderRadius: BorderRadius.circular(8.r), borderRadius: BorderRadius.circular(8.r),
child: Container( child: Container(
@ -511,7 +489,6 @@ Widget $completedHomeworkProgressBar(
@swidget @swidget
Widget $completedHomeworkInfoBox( Widget $completedHomeworkInfoBox(
BuildContext context, { BuildContext context, {
required List<int> taskIds,
required int unsubmittedQuantity, required int unsubmittedQuantity,
required int submittedQuantity, required int submittedQuantity,
required double objectivePrecision, // required double objectivePrecision, //
@ -524,7 +501,6 @@ Widget $completedHomeworkInfoBox(
return Column( return Column(
children: [ children: [
$CompletedHomeworkBtn( $CompletedHomeworkBtn(
taskIds: taskIds,
className: className, className: className,
unsubmittedQuantity: unsubmittedQuantity, unsubmittedQuantity: unsubmittedQuantity,
submittedQuantity: submittedQuantity, submittedQuantity: submittedQuantity,
@ -557,13 +533,7 @@ Widget $completedHomeworkInfoBox(
// view // view
@swidget @swidget
Widget $unfinishedHomework( Widget $unfinishedHomework(BuildContext context, {required JobTaskItem jobTaskItem}) {
BuildContext context, {
required JobTaskItem jobTaskItem,
required VoidCallback refreshCallback,
required EndReviewCall endReviewCallback,
required Function(int) oneClickReviewCallback,
}) {
return Stack( return Stack(
alignment: const FractionalOffset(0.95, 0), alignment: const FractionalOffset(0.95, 0),
children: [ children: [
@ -599,7 +569,9 @@ Widget $unfinishedHomework(
alignment: Alignment.center, alignment: Alignment.center,
padding: EdgeInsets.only(left: 2.w), padding: EdgeInsets.only(left: 2.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color.fromRGBO(104, 136, 253, 1), color: jobTaskItem.markingTypeEnum.name == '作业'
? const Color.fromRGBO(104, 136, 253, 1)
: const Color.fromRGBO(255, 175, 56, 1),
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: Radius.circular(18.r), topLeft: Radius.circular(18.r),
topRight: Radius.circular(3.r), topRight: Radius.circular(3.r),
@ -608,7 +580,7 @@ Widget $unfinishedHomework(
), ),
), ),
margin: EdgeInsets.only(right: 4.w), margin: EdgeInsets.only(right: 4.w),
child: quickText('作业', color: Colors.white, size: 10.sp), child: quickText(jobTaskItem.markingTypeEnum.name, color: Colors.white, size: 10.sp),
), ),
quickText( quickText(
jobTaskItem.title, jobTaskItem.title,
@ -653,50 +625,6 @@ Widget $unfinishedHomework(
), ),
], ],
), ),
//
$UnfinishedBtn(
isChild: false,
jobTaskItem: jobTaskItem,
endCallback: endReviewCallback,
refreshcall: refreshCallback,
),
SizedBox(height: 20.h),
ExpansionTile(
tilePadding: EdgeInsets.only(right: 10.w),
title: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
badges.Badge(
badgeStyle: badges.BadgeStyle(
shape: badges.BadgeShape.square,
borderRadius: BorderRadius.circular(5.r),
padding: EdgeInsets.all(2.r),
badgeGradient: badges.BadgeGradient.linear(
colors: [Colors.purple, Colors.blue],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
position: badges.BadgePosition.topEnd(top: -2.r, end: -8.r),
badgeContent: Text(
jobTaskItem.markingTasks.length.toString(),
style: TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold),
),
child: quickText('班级列表 ', size: 17.sp),
),
],
),
children: jobTaskItem.markingTasks.map((e) {
return $UnfinishedClassItem(
jobTaskItem: jobTaskItem,
jobTaskClassItem: e,
endReviewCallback: endReviewCallback,
refreshCallback: refreshCallback,
oneClickReviewCallback: oneClickReviewCallback,
);
}).toList(),
),
], ],
), ),
), ),
@ -740,512 +668,14 @@ Widget $unfinishedHomework(
), ),
backgroundColor: Color.fromRGBO(244, 244, 244, 1), backgroundColor: Color.fromRGBO(244, 244, 244, 1),
), ),
// Container(
// child: Container(
// color: Colors.red,
// height: 40.r,
// width: 40.r,
// )
// ),
), ),
], ],
); );
} }
// ()
@swidget
Widget $unfinishedBtn(
BuildContext context, {
required JobTaskItem jobTaskItem,
required VoidCallback refreshcall,
required EndReviewCall endCallback,
MarkingTasks? jobTaskClassItem,
bool isChild = true,
}) {
if (!isChild) {
MarkingTasks? theCanReviewChild = jobTaskItem.markingTasks.firstWhereOrNull((e) => e.canGoReview);
List<MarkingTasks> canEndTaskChilds = jobTaskItem.markingTasks.where((e) => !e.isFinish && e.canMarking).toList();
return Container(
margin: EdgeInsets.only(top: 22.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
flex: 2,
child: Material(
color: theCanReviewChild != null ? Colors.white : Colors.grey[300],
borderRadius: BorderRadius.circular(30.r),
child: InkWell(
onTap: () {
MarkingTasks? markingTask =
jobTaskItem.markingTasks.firstWhereOrNull((e) => e.canMarking && e.totalCount > 0 && !e.isFinish);
if (markingTask == null) {
ToastUtils.showInfo('没有找到可以批阅的任务');
// AchievementView(
// elevation: 0.5,
// duration: Duration(seconds: 1),
// title: "提示",
// subTitle: "没有找到可以批阅的任务",
// color: Theme.of(context).primaryColor,
// ).show(context);
return;
}
String url =
'${RouterManager.markingHomeworkDoPath}?taskId=${markingTask.id}&jobId=${jobTaskItem.id}&taskName=${Uri.encodeComponent(jobTaskItem.title)}&className=${Uri.encodeComponent(jobTaskItem.genderName + markingTask.className)}';
RouterManager.router.navigateTo(context, url, transition: getTransition()).then((value) {
if (value != null && value == true) refreshcall();
});
},
borderRadius: BorderRadius.circular(30.r),
child: Container(
height: 36.h,
padding: EdgeInsets.symmetric(vertical: 3.h),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.r),
border: Border.all(color: Theme.of(context).primaryColor),
),
child: quickText('批阅', color: Theme.of(context).primaryColor, size: 14.sp),
),
),
),
),
Expanded(
flex: 1,
child: SizedBox(width: 5.w),
),
Expanded(
flex: 2,
child: Material(
color: canEndTaskChilds.isNotEmpty ? Color.fromRGBO(104, 136, 253, 1) : Colors.grey,
borderRadius: BorderRadius.circular(30.r),
child: InkWell(
onTap: () async {
List<MarkingTasks> childTasks =
jobTaskItem.markingTasks.where((e) => !e.isFinish && e.canMarking).toList();
if (childTasks.isEmpty) return ToastUtils.showInfo('没有可以结束的任务');
//
List<MarkingTasks> incompleteTasks = childTasks.where((e) => e.finishCount < e.totalCount).toList();
if (incompleteTasks.isNotEmpty) {
var continueFlag = await showDialog<bool>(
context: context,
builder: (BuildContext context1) {
return AlertDialog(
title: Text('未完成批阅提示'),
content: Text('当前批阅任务未完成,请确认需要结束此任务?'),
actions: <Widget>[
TextButton(
child: Text(''),
onPressed: () {
//
Navigator.of(context1).pop(false);
},
),
TextButton(
child: Text(''),
onPressed: () {
Navigator.of(context1).pop(true);
},
),
],
);
},
);
if (continueFlag == null || !continueFlag) {
return;
}
}
showDialog(
context: context,
builder: (BuildContext context1) {
return AlertDialog(
title: Text('提示'),
content: Text('确认完成以下${childTasks.map((e) => e.className).toList().join(",")}的批阅任务?'),
actions: <Widget>[
TextButton(
child: Text(''),
onPressed: () {
//
Navigator.of(context1).pop();
},
),
TextButton(
child: Text('确定'),
onPressed: () async {
try {
bool result = await endCallback(childTasks);
if (result) refreshcall();
} catch (e) {
} finally {
ToastUtils.dismiss();
Navigator.of(context1).pop();
}
},
),
],
);
},
);
},
borderRadius: BorderRadius.circular(30.r),
child: Container(
height: 36.h,
padding: EdgeInsets.symmetric(vertical: 3.5.h),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.r),
),
child: quickText('结束批阅', size: 14.sp, color: Colors.white),
),
),
),
),
],
),
);
}
if (!jobTaskClassItem!.canMarking)
return Container(
alignment: Alignment.centerRight,
child: jobTaskClassItem.isFinish
? Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
quickText(jobTaskClassItem.finishTime?.substring(0, 16),
size: 10.sp, color: Color.fromRGBO(170, 170, 170, 1)),
SizedBox(width: 4.w),
quickText('已批阅', size: 10.sp, color: Theme.of(context).primaryColor),
],
)
: quickText(
'待批阅',
size: 10.sp,
color: Color.fromRGBO(255, 138, 0, 1),
),
);
return Container(
child: jobTaskClassItem.isFinish
? Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
quickText(jobTaskClassItem.finishTime?.substring(0, 16),
size: 12.sp, color: Color.fromRGBO(170, 170, 170, 1)),
SizedBox(width: 4.w),
quickText('已批阅', size: 13.sp, color: Theme.of(context).primaryColor),
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
flex: 5,
child: Material(
color: jobTaskClassItem.canGoReview ? Colors.white : Colors.grey[300],
borderRadius: BorderRadius.circular(4.r),
child: InkWell(
onTap: () {
if (jobTaskClassItem.totalCount <= 0) {
return ToastUtils.showInfo('没有找到可以批阅的任务');
}
if (!jobTaskClassItem.canMarking) {
return AchievementView(
elevation: 0.5,
duration: Duration(seconds: 1),
title: "提示",
subTitle: "此账号无法批阅该任务",
color: Theme.of(context).primaryColor,
).show(context);
}
if (jobTaskClassItem.isFinish) {
return AchievementView(
elevation: 0.5,
duration: Duration(seconds: 1),
title: "提示",
subTitle: "此批阅任务已完成",
color: Theme.of(context).primaryColor,
).show(context);
}
String url =
'${RouterManager.markingHomeworkDoPath}?taskId=${jobTaskClassItem.id}&jobId=${jobTaskItem.id}&taskName=${Uri.encodeComponent(jobTaskItem.title)}&className=${Uri.encodeComponent(jobTaskItem.genderName + jobTaskClassItem.className)}';
RouterManager.router.navigateTo(context, url, transition: getTransition()).then((value) {
if (value == true) refreshcall();
});
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 6.h),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
border: Border.all(color: Theme.of(context).primaryColor),
),
child: quickText('批阅', color: Theme.of(context).primaryColor, size: 12.sp),
),
),
)),
Expanded(flex: 1, child: SizedBox()),
Expanded(
flex: 5,
child: Material(
color: !jobTaskClassItem.isFinish && jobTaskClassItem.canMarking
? Color.fromRGBO(237, 240, 255, 1)
: Colors.grey,
borderRadius: BorderRadius.circular(4.r),
child: InkWell(
onTap: () async {
if (!jobTaskClassItem.canMarking) return ToastUtils.showInfo('此任务非该账号任务');
if (jobTaskClassItem.isFinish) return ToastUtils.showInfo('此任务已经结束');
//
if (jobTaskClassItem.finishCount < jobTaskClassItem.totalCount) {
var continueFlag = await showDialog<bool>(
context: context,
builder: (BuildContext context1) {
return AlertDialog(
title: Text('未完成批阅提示'),
content: Text('当前批阅任务未完成,请确认需要结束此任务?'),
actions: <Widget>[
TextButton(
child: Text(''),
onPressed: () {
//
Navigator.of(context1).pop(false);
},
),
TextButton(
child: Text(''),
onPressed: () {
Navigator.of(context1).pop(true);
},
),
],
);
},
);
if (continueFlag == null || !continueFlag) {
return;
}
}
showDialog(
context: context,
builder: (BuildContext context1) {
return AlertDialog(
title: Text('提示'),
content: Text('确认完成当前${jobTaskClassItem.className}批阅任务?'),
actions: <Widget>[
TextButton(
child: Text(''),
onPressed: () {
//
Navigator.of(context1).pop();
},
),
TextButton(
child: Text('确定'),
onPressed: () async {
try {
bool result = await endCallback([jobTaskClassItem]);
if (result) refreshcall();
} catch (e) {
} finally {
ToastUtils.dismiss();
Navigator.of(context1).pop();
}
},
),
],
);
},
);
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 6.h),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
border: Border.all(color: Color.fromRGBO(130, 156, 255, 1)),
),
child: quickText('结束批阅', size: 12.sp, color: Color.fromRGBO(104, 136, 253, 1)),
),
),
)),
],
),
);
}
// view
@swidget
Widget $unfinishedClassItem(
BuildContext context, {
required JobTaskItem jobTaskItem,
required MarkingTasks jobTaskClassItem,
required VoidCallback refreshCallback,
required EndReviewCall endReviewCallback,
required Function(int) oneClickReviewCallback,
}) {
return Container(
padding: EdgeInsets.only(bottom: 14.w),
margin: EdgeInsets.only(bottom: 20.h),
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Color.fromRGBO(233, 233, 233, 1), width: 1.r))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: quickText(jobTaskItem.genderName + jobTaskClassItem.className,
color: Color.fromRGBO(255, 123, 1, 1), size: 14.sp)),
if (!jobTaskClassItem.isFinish)
Expanded(
child: Container(
child: Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.r),
boxShadow: [
BoxShadow(
color: Color.fromRGBO(104, 136, 253, 1),
spreadRadius: 0.5,
blurRadius: 1,
offset: Offset(0, 0),
),
],
),
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: 10.h,
animationDuration: 2500,
percent: jobTaskClassItem.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: [
Theme.of(context).primaryColor.withOpacity(0.1),
Theme.of(context).primaryColor,
],
),
// linearStrokeCap: LinearStrokeCap.butt,
// progressColor: Theme.of(context).primaryColor,
backgroundColor: Colors.white,
barRadius: Radius.circular(10.r),
),
),
),
SizedBox(width: 4.w),
quickText('${getDoubleRemoveZero(jobTaskClassItem.progressPercentage)}%',
size: 10.sp, color: Color.fromRGBO(104, 136, 253, 1))
],
),
),
),
],
),
SizedBox(height: 14.h),
Container(
child: Row(
children: [
Expanded(
child: Row(children: [
quickText('题量:${jobTaskClassItem.totalCount}'),
SizedBox(width: 20.w),
quickText(jobTaskClassItem.teacherName)
])),
Expanded(
child: $UnfinishedBtn(
jobTaskItem: jobTaskItem,
jobTaskClassItem: jobTaskClassItem,
endCallback: endReviewCallback,
refreshcall: refreshCallback,
),
),
],
),
),
if (jobTaskClassItem.canGoReview) SizedBox(height: 6.h),
if (jobTaskClassItem.canGoReview)
Material(
borderRadius: BorderRadius.circular(30.r),
child: InkWell(
onTap: () => easyThrottle('OneClickReview', () async {
var continueFlag = await showDialog<bool>(
context: context,
builder: (BuildContext context1) {
return AlertDialog(
title: Text('一键批阅'),
content: Text('一键批阅后,默认学生答题结果全部正确,是否进行此操作?'),
actions: <Widget>[
TextButton(
child: Text(''),
onPressed: () {
//
Navigator.of(context1).pop(false);
},
),
TextButton(
child: Text(''),
onPressed: () {
Navigator.of(context1).pop(true);
},
),
],
);
},
);
if (continueFlag == null || !continueFlag) return;
oneClickReviewCallback(jobTaskClassItem.id);
}),
borderRadius: BorderRadius.circular(30.r),
child: Container(
height: 20.h,
constraints: BoxConstraints(minWidth: 50.w, maxWidth: 60.w),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(30.r),
border: Border.all(color: Color.fromRGBO(76, 199, 147, 1)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
quickText('一键批阅', color: Color.fromRGBO(76, 199, 147, 1), size: 10.sp),
Padding(
padding: EdgeInsets.only(top: 1.1.h),
child: Icon(Icons.arrow_forward_ios, size: 8.sp, color: Color.fromRGBO(76, 199, 147, 1)),
),
],
),
),
),
),
],
),
);
}
typedef EndReviewCall = Future<bool> Function(List<MarkingTasks> markingTasks); typedef EndReviewCall = Future<bool> Function(List<MarkingTasks> markingTasks);
typedef ShowStudentsCall = Future<void> Function( typedef ShowStudentsCall = Future<void> Function(
BuildContext context, BuildContext context, [
List<int> taskIds, [
bool? submitted, bool? submitted,
String? className, String? className,
]); ]);

View File

@ -9,6 +9,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart'; import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:marking_app/common/mixin/common.dart'; import 'package:marking_app/common/mixin/common.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart';
@ -18,6 +19,7 @@ import 'package:marking_app/common/config/request_config.dart';
import 'package:marking_app/common/model/job/job_task_item.dart'; import 'package:marking_app/common/model/job/job_task_item.dart';
import 'package:marking_app/pages/homework_correction/components/new_version_of_homework/homework_tasks_view_item.dart'; import 'package:marking_app/pages/homework_correction/components/new_version_of_homework/homework_tasks_view_item.dart';
import 'package:marking_app/provider/review_provider.dart'; import 'package:marking_app/provider/review_provider.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/index.dart'; import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/my_text.dart'; import 'package:marking_app/utils/my_text.dart';
import 'package:marking_app/utils/request/rest_client.dart'; import 'package:marking_app/utils/request/rest_client.dart';
@ -25,6 +27,7 @@ import 'package:marking_app/common/model/common/base_page_data.dart';
import 'package:marking_app/common/model/marking/marking_list_params.dart'; import 'package:marking_app/common/model/marking/marking_list_params.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart'; import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/easy_refresh/mixin/refresh_data_handle.dart'; import 'package:marking_app/utils/easy_refresh/mixin/refresh_data_handle.dart';
import 'package:syncfusion_flutter_datepicker/datepicker.dart';
part 'index.g.dart'; part 'index.g.dart';
@ -39,7 +42,7 @@ class HomeworkCorrection extends StatefulHookConsumerWidget {
class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection> class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
with with
CommonMixin, CommonMixin,
SingleTickerProviderStateMixin, TickerProviderStateMixin,
RefreshDataHandle<JobTaskItem, MarkingListParams>, RefreshDataHandle<JobTaskItem, MarkingListParams>,
AutomaticKeepAliveClientMixin { AutomaticKeepAliveClientMixin {
@override @override
@ -47,6 +50,8 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
/* Tab控制器 */ /* Tab控制器 */
late TabController _tabController; late TabController _tabController;
late TabController _tabController2;
int _tabIndex = 0; int _tabIndex = 0;
bool completedToRefresh = true; bool completedToRefresh = true;
@ -95,6 +100,7 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
length: 2, length: 2,
vsync: this, vsync: this,
); );
_tabController2 = TabController(length: 4, vsync: this);
_refreshController1 = EasyRefreshController(); _refreshController1 = EasyRefreshController();
_refreshController2 = EasyRefreshController(); _refreshController2 = EasyRefreshController();
@ -117,6 +123,7 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
if (_currentTaskIdListener != null) { if (_currentTaskIdListener != null) {
_currentTaskIdListener!(); _currentTaskIdListener!();
} }
_tabController2.dispose();
_tabController.dispose(); _tabController.dispose();
_refreshController1.dispose(); _refreshController1.dispose();
_refreshController2.dispose(); _refreshController2.dispose();
@ -167,11 +174,9 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top), margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
padding: EdgeInsets.only(bottom: 9.h, top: 4.h), padding: EdgeInsets.only(bottom: 9.h, top: 4.h),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Expanded( Expanded(flex: 1, child: SizedBox()),
flex: 1,
child: SizedBox(),
),
Expanded( Expanded(
flex: 4, flex: 4,
child: Container( child: Container(
@ -254,11 +259,41 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
), ),
Expanded( Expanded(
flex: 1, flex: 1,
child: SizedBox(), child: InkWell(
onTap: () {
RouterManager.router.navigateTo(context, RouterManager.jobStudentGroupPath,
transition: getTransition());
},
child: Icon(IconData(0xe63e, fontFamily: "AlibabaIcon"),
color: Color.fromRGBO(44, 48, 63, 1), size: 24.sp),
),
), ),
], ],
), ),
), ),
if (_tabIndex == 1)
$CompletedJobConditionFilter(
controller: _tabController2,
jobType: params2.markingType ?? 1,
customTime: _tabController2.index != 3 || (params2.startTime == null && params2.endTime == null)
? null
: PickerDateRange(
params2.startTime == null ? null : DateTime.parse(params2.startTime!),
params2.endTime == null ? null : DateTime.parse(params2.endTime!),
),
onJobTypeTap: (int jobTypeVal) {
params2.markingType = jobTypeVal;
_refreshController2.callRefresh();
},
onTimeFilter: (String? startTime, String? endTime) {
if (startTime == null && endTime == null && _tabController2.index == 3) {
_tabController2.animateTo(0);
}
params2.endTime = endTime;
params2.startTime = startTime;
_refreshController2.callRefresh();
},
),
Expanded( Expanded(
child: IndexedStack( child: IndexedStack(
index: _tabIndex, index: _tabIndex,
@ -304,6 +339,7 @@ Widget $easyRefresh({
required int tab, required int tab,
}) { }) {
bool completed = tab == 2; // bool completed = tab == 2; //
bool isPadFlag = isPad();
return EasyRefresh( return EasyRefresh(
firstRefresh: true, firstRefresh: true,
taskIndependence: true, taskIndependence: true,
@ -313,8 +349,21 @@ Widget $easyRefresh({
controller: controller, controller: controller,
header: MaterialHeader(), header: MaterialHeader(),
footer: TaurusFooter(), footer: TaurusFooter(),
child: ListView.builder( child: completed && isPadFlag
padding: EdgeInsets.only(top: 11.h, bottom: 10.h, left: 16.w, right: 16.w), ? GridView(
padding: EdgeInsets.only(top: 11.h, bottom: 10.h, left: 12.w, right: 12.w),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, //widget
mainAxisSpacing: 10.h,
crossAxisSpacing: 6.w,
childAspectRatio: 2.2 //1widget
),
children: data.map((e) {
return $ReviewedItem(jobTaskItem: e);
}).toList(),
)
: ListView.builder(
padding: EdgeInsets.only(top: 11.h, bottom: 10.h, left: 12.w, right: 12.w),
itemBuilder: (context, index) { itemBuilder: (context, index) {
return HomeworkTasksViewItem( return HomeworkTasksViewItem(
completed: completed, completed: completed,
@ -328,3 +377,346 @@ Widget $easyRefresh({
onLoad: () => onLoad(controller, params, tab), onLoad: () => onLoad(controller, params, tab),
); );
} }
@swidget
Widget $reviewedItem(BuildContext context, {required JobTaskItem jobTaskItem}) {
EdgeInsets padEdg = EdgeInsets.symmetric(horizontal: 10.w);
return InkWell(
onTap: () {
String url =
'${RouterManager.jobListParticipateInClassPath}?&jobId=${jobTaskItem.id}&genderName=${Uri.encodeComponent(jobTaskItem.genderName)}&jobName=${Uri.encodeComponent(jobTaskItem.title)}&completed=${true}';
RouterManager.router.navigateTo(context, url, transition: getTransition());
},
child: Container(
padding: EdgeInsets.only(top: 10.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(210, 216, 241, 1),
offset: Offset.zero, //y轴偏移量
blurRadius: 5.8, //
spreadRadius: 0, //
)
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//
Padding(
padding: padEdg,
child: Row(
children: [
Container(
width: 32.w,
height: 18.h,
alignment: Alignment.center,
padding: EdgeInsets.only(left: 2.w),
decoration: BoxDecoration(
color: jobTaskItem.markingTypeEnum.name == '作业'
? const Color.fromRGBO(104, 136, 253, 1)
: const Color.fromRGBO(255, 175, 56, 1),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(18.r),
topRight: Radius.circular(3.r),
bottomLeft: Radius.circular(4.r),
bottomRight: Radius.circular(4.r),
),
),
margin: EdgeInsets.only(right: 4.w),
child: quickText(jobTaskItem.markingTypeEnum.name, color: Colors.white, size: 10.sp),
),
quickText(
jobTaskItem.title,
size: 16.sp,
color: Color.fromRGBO(70, 70, 70, 1),
fontWeight: FontWeight.bold,
)
],
),
),
Padding(
padding: padEdg,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
quickText(
jobTaskItem.createTime.substring(0, 10),
color: Color.fromRGBO(97, 97, 97, 1),
size: 10.sp,
fontWeight: FontWeight.w500,
),
quickText(' / ', color: Color.fromRGBO(76, 199, 147, 1), size: 10.sp, fontWeight: FontWeight.w500),
quickText(
'参与班级:${jobTaskItem.taskCount}',
color: Color.fromRGBO(76, 199, 147, 1),
size: 10.sp,
fontWeight: FontWeight.w600,
),
quickText(' / ', color: Color.fromRGBO(116, 145, 253, 1), size: 10.sp, fontWeight: FontWeight.w500),
quickText(
'科目:' + jobTaskItem.subjectName,
color: Color.fromRGBO(116, 145, 253, 1),
size: 10.sp,
fontWeight: FontWeight.w600,
),
],
),
),
GestureDetector(
onTap: () => easyThrottle('go_to_homework_report', () {
RouterManager.router.navigateTo(
context,
RouterManager.jobReportPagePath +
'?title=${Uri.encodeComponent(jobTaskItem.title)}&id=${jobTaskItem.id}',
transition: getTransition(),
);
}),
child: Container(
padding: EdgeInsets.symmetric(vertical: 6.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(6.r), bottomRight: Radius.circular(6.r)),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(0, 0, 0, 0.15),
offset: Offset(0, -0.0001), //y轴偏移量
blurRadius: 4, //
spreadRadius: 0, //
)
],
),
child: Row(children: [
Expanded(
child: Container(
alignment: Alignment.center,
child: quickText('查看报告', color: Color.fromRGBO(118, 118, 118, 1), size: 11.sp),
),
),
]),
),
),
],
),
),
);
}
//
@swidget
Widget $theTabBar({required TabController controller, ValueChanged<int>? onTap, PickerDateRange? customTime}) {
var customTimeStr = '自定义';
if (customTime != null) {
customTimeStr = customTime.startDate?.toString().substring(0, 10) ?? '';
if (customTime.endDate != null) {
print(customTime.startDate!.year == customTime.endDate!.year);
if (!isPad() && customTime.startDate!.year == customTime.endDate!.year) {
customTimeStr =
customTime.startDate.toString().substring(5, 10) + '~${customTime.endDate.toString().substring(5, 10)}';
} else {
customTimeStr += '~${customTime.endDate?.toString().substring(0, 10)}';
}
}
}
return Container(
alignment: Alignment.centerLeft,
child: TabBar(
controller: 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: const Color.fromRGBO(45, 56, 76, 1),
indicatorSize: TabBarIndicatorSize.label, //
onTap: onTap,
tabs: <Widget>[
const Tab(text: '全部'),
const Tab(text: '近一周'),
const Tab(text: '近一月'),
Tab(text: customTimeStr),
],
),
);
}
///
@hwidget
Widget $completedJobConditionFilter(BuildContext context,
{required TabController controller,
required int jobType,
PickerDateRange? customTime,
required ValueChanged<int> onJobTypeTap,
required Function(String? startTime, String? endTime) onTimeFilter}) {
List<Map<String, dynamic>> jobTypes = [
{'type': 1, 'name': '作业'},
{'type': 2, 'name': '考试'}
];
var jobTypeState = useState(0);
var customTimeState = useState<PickerDateRange?>(null);
useEffect(() {
if (jobTypeState.value != jobType) jobTypeState.value = jobType;
if (customTimeState.value != customTime) customTimeState.value = customTime;
return () {};
}, []);
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: 36.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: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
$TheTabBar(
controller: controller,
customTime: customTimeState.value,
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: //
// DateTimeRange? range = await showDateRangePicker(
// // locale: const Locale('zh', 'CN'),
// locale: const Locale('zh', 'CN'),
// context: context,
// confirmText: '搜索',
// initialEntryMode: DatePickerEntryMode.calendarOnly,
// currentDate: DateTime.now(),
// firstDate: DateTime.now().subtract(const Duration(days: 4)),
// lastDate: DateTime.now().add(const Duration(days: 3)),
// );
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);
},
onCancel: () {
Navigator.of(context1).pop();
},
selectionMode: DateRangePickerSelectionMode.range,
initialSelectedRange: customTimeState.value,
),
),
);
});
// 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.value = dialogData;
}
},
),
Expanded(child: SizedBox()),
Container(
width: 74.r,
margin: EdgeInsets.symmetric(vertical: 5.h),
padding: EdgeInsets.symmetric(horizontal: 10.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(
top: Radius.elliptical(6, 6),
bottom: Radius.elliptical(6, 6),
),
),
child: DropdownButton(
icon: Icon(Icons.expand_more_outlined),
padding: EdgeInsets.zero,
// value: params2.jobType ?? 1,
value: jobType,
style: TextStyle(color: Color.fromRGBO(89, 89, 89, 1), fontSize: 12.sp),
underline: Container(),
isExpanded: true,
items: jobTypes.map((e) {
return DropdownMenuItem(
value: e['type'],
child: quickText(e['name'], size: 12.sp, color: Colors.black),
);
}).toList(),
onChanged: (dynamic value) {
if (value != null) {
jobTypeState.value = value;
onJobTypeTap(value as int);
}
// jobTypeState
},
),
)
],
),
);
}

View File

@ -0,0 +1,253 @@
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: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_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/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/request/rest_client.dart';
class JobPriorityReviewSet extends StatefulWidget {
final String groupId;
const JobPriorityReviewSet({Key? key,required this.groupId}) : super(key: key);
@override
State<JobPriorityReviewSet> createState() => _JobPriorityReviewSetState();
}
class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
with CommonMixin,SingleTickerProviderStateMixin {
late final EasyRefreshController refreshController;
late TabController tabController;
int tabIndex = 0;
List levelList = [];
@override
void initState() {
super.initState();
EasyLoading.show(status: 'loading...');
refreshController = EasyRefreshController();
tabController =
TabController(initialIndex: tabIndex, length: 2, vsync: this);
getReadLevel();
}
void getReadLevel() async{
RestClient _client = await getClient();
BaseStructureResult<List<JobStudentLevel>> res = await _client.getJobReadLevel(widget.groupId,tabIndex == 0?1:0);
setState(() {
if(res.code == 200){
levelList = res.data!;
}else{
levelList = [];
}
});
EasyLoading.dismiss();
refreshController.finishRefresh();
}
void setJobReadLevel(int studentId,int level) async{
RestClient _client = await getClient();
JobLevelSetParams params = JobLevelSetParams(studentId, level);
BaseStructureResult res = await _client.getSetJobReadLevel(params);
if(res.code == 200){
getReadLevel();
}
}
@override
void dispose() {
super.dispose();
refreshController.dispose();
tabController.dispose();
}
@override
Widget build(BuildContext context) {
bool isPadFlag = isPad();
return Scaffold(
backgroundColor: Color.fromRGBO(245, 245, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'优先批阅人配置',
style: TextStyle(fontSize: 16.sp, color: Color(0xFF333333)),
),
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 14.r),
child: TabBar(
onTap: (int val) {
print(val);
setState(() {
tabIndex = val;
});
EasyLoading.show(status: 'loading...');
getReadLevel();
},
tabs: [
SizedBox(
width: (MediaQuery.of(context).size.width - 28.r) /2,
child: Tab(
text: '优先批阅',
),
),
SizedBox(
width: (MediaQuery.of(context).size.width - 28.r) /2,
child: Tab(
text: '默认批阅',
),
)
],
controller: tabController,
unselectedLabelStyle: TextStyle(
fontSize: 14.sp, color:Color(0xFF666666)),
labelStyle: TextStyle(
fontSize: 14.sp,
color: Color(0xFF6888FD),
),
isScrollable: true,
labelColor: Color(0xFF6888FD),
unselectedLabelColor: Color(0xFF666666),
indicatorSize: TabBarIndicatorSize.label,
labelPadding: const EdgeInsets.all(0),
),
),
Expanded(
child:Padding(
padding: EdgeInsets.symmetric(vertical:14.r,horizontal: 14.r),
child: EasyRefresh(
firstRefresh: true,
taskIndependence: true,
controller: refreshController,
header: MaterialHeader(),
footer: TaurusFooter(),
onRefresh: () async{
getReadLevel();
},
child: levelList.length>0?isPadFlag?GridView(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10.r,
crossAxisSpacing: 10.r,
childAspectRatio: 556 / 112,
),children: List.generate(levelList.length, (index) {
JobStudentLevel item = levelList[index];
return Container(
padding: EdgeInsets.symmetric(horizontal: 15.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(item.studentName,style: TextStyle(fontSize: 12.sp,color: Color(0xFF6888FD)),),
tabIndex == 0?InkWell(
onTap: (){
setJobReadLevel(item.studentGroupDetailId,0);
EasyLoading.show(status: 'loading...');
},
child: Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.r)),
color: Color(0xFF6888FD),
),
child: Center(
child:Text('取消优先',style: TextStyle(fontSize: 10.sp,color: Colors.white),),
),
),
):InkWell(
onTap: (){
setJobReadLevel(item.studentGroupDetailId,1);
EasyLoading.show(status: 'loading...');
},
child: Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.r)),
color: Color(0xFFFFFFFF),
border: Border.all(width: 1.r,color: Color(0xFF6888FD)),
),
child: Center(
child:Text('设为优先',style: TextStyle(fontSize: 10.sp,color: Color(0xFF6888FD)),),
),
),
)
],
),
);
}),):ListView.builder(itemBuilder: (context,index){
JobStudentLevel item = levelList[index];
return Container(
padding: EdgeInsets.symmetric(vertical:20.r,horizontal: 15.r),
margin: EdgeInsets.only(bottom: 15.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(item.studentName,style: TextStyle(fontSize: 12.sp,color: Color(0xFF6888FD)),),
tabIndex == 0?InkWell(
onTap: (){
setJobReadLevel(item.studentGroupDetailId,0);
EasyLoading.show(status: 'loading...');
},
child: Container(
height: 24.r,
width: 82.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.r)),
color: Color(0xFF6888FD),
),
child: Center(
child:Text('取消优先',style: TextStyle(fontSize: 10.sp,color: Colors.white),),
),
),
):InkWell(
onTap: (){
setJobReadLevel(item.studentGroupDetailId,1);
EasyLoading.show(status: 'loading...');
},
child: Container(
height: 24.r,
width: 82.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.r)),
color: Color(0xFFFFFFFF),
border: Border.all(width: 1.r,color: Color(0xFF6888FD)),
),
child: Center(
child:Text('设为优先',style: TextStyle(fontSize: 10.sp,color: Color(0xFF6888FD)),),
),
),
)
],
),
);
},itemCount: levelList.length,):MyEmptyWidget(),
),
),
)
],
),
);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,227 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_screenutil/flutter_screenutil.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_goups.dart';
import 'package:marking_app/common/model/user/user_info.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/fast_data.dart';
import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/request/rest_client.dart';
class JobStudentGroup extends StatefulWidget {
const JobStudentGroup({Key? key}) : super(key: key);
@override
State<JobStudentGroup> createState() => _JobStudentGroupState();
}
class _JobStudentGroupState extends State<JobStudentGroup> with CommonMixin {
late final EasyRefreshController refreshController;
late String loginName;
List studentGroups = [];
@override
void initState() {
super.initState();
refreshController = EasyRefreshController();
FastData fastData = FastData.getInstance();
fastData.getUser().then((value) {
if (value == null || value == '') return;
Map<String, dynamic> userInfo = json.decode(value);
setState(() {
loginName = userInfo['loginName'];
});
getStudentGroups();
print(userInfo);
});
}
void getStudentGroups() async {
RestClient _client = await getClient();
BaseStructureResult<List<JobStudentGroups>> res =
await _client.getJobLevelStudentGroups(loginName);
setState(() {
if(res.code == 200){
studentGroups = res.data!;
}else{
studentGroups = [];
}
});
refreshController.finishRefresh();
}
@override
void dispose() {
super.dispose();
refreshController.dispose();
}
@override
Widget build(BuildContext context) {
bool isPadFlag = isPad();
return Scaffold(
backgroundColor: Color.fromRGBO(245, 245, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'我的学生分组',
style: TextStyle(fontSize: 16.sp, color: Color(0xFF333333)),
),
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
),
body: Padding(
padding: EdgeInsets.only(top: 15.r, left: 14.r, right: 14.r),
child: EasyRefresh(
firstRefresh: false,
taskIndependence: true,
controller: refreshController,
header: MaterialHeader(),
footer: TaurusFooter(),
onRefresh: () async{
getStudentGroups();
},
child: studentGroups != null && studentGroups.length > 0
? isPadFlag?GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10.r,
crossAxisSpacing: 10.r,
childAspectRatio: 556 / 112,
),
children: List.generate(studentGroups.length, (index) {
JobStudentGroups item = studentGroups[index];
String classNames = item.classNames.join(" ");
return Container(
padding: EdgeInsets.symmetric(horizontal: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(right: 8.r),
child: Text(
item.groupName,
style: TextStyle(
fontSize: 10.sp, color: Color(0xFF6888FD)),
),
),
Expanded(
child: Text(
classNames,
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFF999999),
overflow: TextOverflow.ellipsis,
),
textAlign: TextAlign.end,
),
),
InkWell(
onTap: (){
RouterManager.router.navigateTo(context, '${RouterManager.jobPriorityReviewSetPath}?&groupId=${item.groupId}',transition: getTransition());
},
child: Container(
margin: EdgeInsets.only(left: 5.r),
height: 20.r,
width: 55.r,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20.r)),
color: Color(0xFF6888FD),
),
child: Center(
child: Text(
'设置',
style: TextStyle(
fontSize: 10.sp, color: Colors.white),
),
),
),
)
],
),
);
}),
):ListView.builder(
itemBuilder: (context,index){
JobStudentGroups item = studentGroups[index];
String classNames = item.classNames.join(" ");
return Container(
padding: EdgeInsets.symmetric(vertical:15.r,horizontal: 10.r),
margin: EdgeInsets.only(bottom: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(right: 8.r),
child: Text(
item.groupName,
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF6888FD)),
),
),
Expanded(
child: Text(
classNames,
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF999999),
overflow: TextOverflow.ellipsis,
),
textAlign: TextAlign.end,
),
),
InkWell(
onTap: (){
RouterManager.router.navigateTo(context, '${RouterManager.jobPriorityReviewSetPath}?&groupId=${item.groupId}',transition: getTransition());
},
child: Container(
margin: EdgeInsets.only(left: 5.r),
height: 24.r,
width: 55.r,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20.r)),
color: Color(0xFF6888FD),
),
child: Center(
child: Text(
'设置',
style: TextStyle(
fontSize: 10.sp, color: Colors.white),
),
),
),
)
],
),
);
},
itemCount: studentGroups.length,
)
: Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height/2 - 200.r),
child: MyEmptyWidget(),
),
),
),
);
}
}

View File

@ -0,0 +1,105 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:photo_view/photo_view_gallery.dart';
class FavoriteStudentDialog extends StatefulWidget {
const FavoriteStudentDialog({Key? key}) : super(key: key);
@override
State<FavoriteStudentDialog> createState() => _FavoriteStudentDialogState();
}
class _FavoriteStudentDialogState extends State<FavoriteStudentDialog> {
int defaultIndex = 1;
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
padding: EdgeInsets.symmetric(vertical: 10.r, horizontal: 14.r),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
'14班 张小凡',
style: TextStyle(fontSize: 12.sp, color: Color(0xFF4E73FD)),
),
Expanded(child: Container()),
Text(
'6题',
style: TextStyle(fontSize: 12.sp, color: Color(0xFF868686)),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 8.r),
child: Image.asset(
'assets/images/favorite_delete_icon.png',
width: 22.r,
height: 22.r,
),
),
InkWell(
onTap: (){
Navigator.pop(context);
},
child: Image.asset(
'assets/images/favorite_dialog_close.png',
width: 22.r,
height: 22.r,
),
),
],
),
SizedBox(height: 10.r,),
Expanded(
child: Container(
color:Color(0xFF868686),
width: MediaQuery.of(context).size.width,
/* child: PhotoViewGallery.builder(
scrollPhysics: const BouncingScrollPhysics(),
builder: (BuildContext context, int index) {
return PhotoViewGalleryPageOptions(
imageProvider: NetworkImage(widget.imageItems[index]),
);
},
itemCount: 2,
pageController:PageController(initialPage: defaultIndex),
// onPageChanged: (){},
scrollDirection: Axis.horizontal,
),*/
),
),
Padding(
padding:EdgeInsets.symmetric(vertical: 15.r),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: (MediaQuery.of(context).size.width - 78.r)/2 - 10.r,
height: 28.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(6.r)),
border: Border.all(width: 1.r,color: Color(0xFFCACACA),style: BorderStyle.solid),
),
child: Center(child: Text('上一页',style: TextStyle(fontSize: 10.r,color: Color(0xFF505E6E)),)),
),
Container(
width: (MediaQuery.of(context).size.width - 78.r)/2 - 10.r,
height: 28.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(6.r)),
border: Border.all(width: 1.r,color: Color(0xFFCACACA),style: BorderStyle.solid),
),
child: Center(child: Text('下一页',style: TextStyle(fontSize: 10.r,color: Color(0xFF505E6E)),)),
),
],
),
)
],
),
);
}
}

View File

@ -0,0 +1,338 @@
import 'dart:convert';
import 'package:flutter/material.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_fav_student.dart';
import 'package:marking_app/common/model/job/job_favorite_item_model.dart';
import 'package:marking_app/common/model/job/job_report_join_class.dart';
import 'package:marking_app/pages/homework_correction/pages/favorite_student_dialog.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';
///
class JobFavorite extends StatefulWidget {
final int jobId;
final int schoolId;
final int gradeId;
final String className;
final String jobName;
const JobFavorite({
required this.jobId,
required this.schoolId,
required this.gradeId,
required this.className,
required this.jobName,
super.key,
});
@override
State<JobFavorite> createState() => _JobFavoriteState();
}
class _JobFavoriteState extends State<JobFavorite> with CommonMixin {
late Future<List<Items>?> _future;
List<JobReportJoinClass>? involveClasses = [];
JobReportJoinClass? classData;
late String loginName;
final int pageSize = 100;
@override
void initState() {
super.initState();
FastData fastData = FastData.getInstance();
fastData.getUser().then((value) {
if (value == null || value == '') return;
Map<String, dynamic> userInfo = json.decode(value);
setState(() {
loginName = userInfo['loginName'];
});
});
getInvolveClasses();
_future = getData();
}
Future<List<Items>> getData() async {
var _client = await getClient();
var result = await _client.getListOfJobFavorites(
widget.jobId, widget.jobName, widget.className,loginName,pageSize);
return result.data!.items;
}
Future<void> toGoCancelFavorite(int jobId, int studentId) async {
var _client = await getClient();
var result = await _client.toJobCancelFavorite(jobId, studentId);
if (result.success && (result.data ?? false)) {
_future = getData();
}
}
Future<void> getInvolveClasses() async {
try {
RestClient _client = await getClient();
BaseStructureResult<List<JobReportJoinClass>> result =
await _client.getJobReportJoinClasses(widget.jobId);
if (result.success) {
toUpState(setState, () {
involveClasses = [
JobReportJoinClass(-1, '全部', -1, '全部', '全部', '全部', -1, -1, '-1'),
...(result.data ?? [])
];
involveClasses?.forEach((element) {
if(element.className == widget.className && element.gradeId == widget.gradeId && element.schoolId == widget.schoolId){
classData = element;
}
});
}, mounted);
}
print('involveClasses=${involveClasses!.length}');
_future = getData();
} catch (e) {
print(e);
}
}
void showStudentDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
insetPadding: EdgeInsets.all(25.r),
content: FavoriteStudentDialog(),
contentPadding: EdgeInsets.all(0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15.r))));
},
);
}
@override
Widget build(BuildContext context) {
bool isPadFlag = isPad();
return Scaffold(
backgroundColor: Color.fromRGBO(245, 245, 245, 1),
appBar: AppBar(
// titleSpacing: 0,
elevation: 0.0,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () => Navigator.of(context).pop()),
iconTheme: IconThemeData(color: Colors.black),
title: quickText('收藏夹'),
centerTitle: true,
backgroundColor: Colors.white,
),
body: MyFutureBuilder.buildFutureBuilderOfSingleInstance<
List<Items>>(
context,
_future,
(List<Items>? datas) {
/* if (datas == null)
return Container(
child: Center(
child: quickText('请求错误'),
),
);*/
print('datas${datas}');
List pageList = [];
List groupList = [];
if(datas!.length>0){
for (var item in datas) {
pageList.add(item.questionPage);
}
pageList = pageList.toSet().toList();
for (var page in pageList) {
var printList = datas.where((element) => element.questionPage == page).toList();
groupList.add({"questionPage": page, "list": printList});
}
}
return Container(
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(vertical: 0.r, horizontal: 14.r),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'函数A的对称性研究',
style:
TextStyle(fontSize: 14.sp, color: Color(0xFF3C3C3C)),
),
//
Container(
padding: EdgeInsets.symmetric(vertical: 10.h, horizontal: 10.w),
child: Row(
children: [
$classSelection(involveClasses, classData,
call: (JobReportJoinClass _classData) {
classData = _classData;
if (_classData.gradeId == -1) classData = null;
_future = getData();
toUpState(setState, () {}, mounted);
}),
// Expanded(child: Text('')),
],
),
),
],
),
),
Container(
width: MediaQuery.of(context).size.width,
height: 1.r,
decoration: BoxDecoration(
color: Color(0xFFCCCCCC),
),
),
Expanded(
child: isPadFlag? Padding(
padding: EdgeInsets.only(top: 10.r,bottom:8.r,left: 14.r,right: 14.r),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(bottom: 5.r),
child: Text('第六题',style: TextStyle(fontSize: 14.sp,color: Color(0xFF2E5BFF)),),
),
GridView(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 8.r,
crossAxisSpacing: 10.r,
childAspectRatio: 556 / 112,
),
shrinkWrap: true,
children: [
Container(
padding: EdgeInsets.symmetric(vertical: 5.r,horizontal: 10.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(6.r)),
),
child: InkWell(
onTap: (){
showStudentDialog(context);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
quickText('张小凡',
color: Color(0xFF333333),
size: 12.sp),
Expanded(child: Container()),
Padding(
padding:EdgeInsets.only(right: 8.r),
child: Text('12班',style: TextStyle(fontSize: 12.sp,color: Color(0xFF666666)),),
),
InkWell(
onTap: () async {
print('删除');
},
child: Image.asset('assets/images/favorite_delete_icon.png',width: 26.r,height: 26.r,),
),
],
),
),
),
],),
],
),
):ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
// Items item = datas[index];
return Padding(
padding: EdgeInsets.only(top: 10.r,bottom:8.r,left: 14.r,right: 14.r),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(bottom: 5.r),
child: Text('第六题',style: TextStyle(fontSize: 14.sp,color: Color(0xFF2E5BFF)),),
),
Container(
padding: EdgeInsets.symmetric(vertical: 5.r,horizontal: 10.r),
margin: EdgeInsets.only(top: 5.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(6.r)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
quickText('张小凡',
color: Color(0xFF333333),
size: 14.sp),
Expanded(child: Container()),
Padding(
padding:EdgeInsets.only(right: 8.r),
child: Text('12班',style: TextStyle(fontSize: 14.sp,color: Color(0xFF666666)),),
),
InkWell(
onTap: () async {},
child: Image.asset('assets/images/favorite_delete_icon.png',width: 32.r,height: 32.r,),
),
],
),
),
],
),
);
},
// itemCount: datas.length,
itemCount: 10,
),
),
],
));
},
),
);
}
}
///
@swidget
Widget $classSelection(
List<JobReportJoinClass>? involveClasses, JobReportJoinClass? classData,
{required Function(JobReportJoinClass) call}) {
if (involveClasses == null)
return Container(child: quickText('点击重试')); //
return Container(
// width: 200.r,
padding: EdgeInsets.symmetric(horizontal: 10.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(
top: Radius.elliptical(10, 10),
bottom: Radius.elliptical(10, 10),
)),
child: DropdownButton(
value: classData?.uniqueId ?? '-1',
style: TextStyle(color: Color.fromRGBO(89, 89, 89, 1), fontSize: 12.sp),
underline: Container(),
// isExpanded:true,
items: involveClasses.map((e) {
return DropdownMenuItem(
value: e.uniqueId!,
child: quickText(e.uniqueId == '-1'?e.graduationYear:e.graduationYear + e.className,
size: 12.sp, color: Colors.black),
);
}).toList(),
onChanged: (String? value) {
if (value == null) return;
call(involveClasses.firstWhere((element) => element.uniqueId == value));
},
),
);
}

View File

@ -0,0 +1,163 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.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_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/utils/request/rest_client.dart';
import 'package:marking_app/utils/toast_utils.dart';
class QuickCheckPersonal extends StatefulWidget {
final int jobId;
final int studentId;
const QuickCheckPersonal(
{Key? key, required this.jobId, required this.studentId})
: super(key: key);
@override
State<QuickCheckPersonal> createState() => _QuickCheckPersonalState();
}
class _QuickCheckPersonalState extends State<QuickCheckPersonal>
with CommonMixin {
StudentDetails? studentInfo;
void initState() {
super.initState();
EasyLoading.show(status: 'loading...');
getJobPersonal();
}
void getJobPersonal() async {
RestClient _client = await getClient();
Map<String, dynamic> params = {};
params['jobid'] = widget.jobId;
// params['jobid'] = '521646983660101';
params['studentId'] = widget.studentId;
BaseStructureResult<StudentDetails?> data =
await _client.getJobPersonalReport(params);
if(data.data!.studentId != null){
setState(() {
studentInfo = data.data;
});
}else{
Navigator.pop(context);
ToastUtils.showError('暂无数据');
}
EasyLoading.dismiss();
}
@override
Widget build(BuildContext context) {
if (studentInfo == null) {
return Container();
}
return Scaffold(
backgroundColor: Color.fromRGBO(245, 245, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
studentInfo!.studentName!,
style: TextStyle(fontSize: 16.sp, color: Color(0xFF000000)),
),
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
),
body: SingleChildScrollView(
child: Column(
children: [
//
Container(
padding: EdgeInsets.symmetric(vertical: 14.r, horizontal: 10.r),
margin: EdgeInsets.symmetric(vertical: 14.r, horizontal: 14.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(6.r)),
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
'客观题',
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF5C5C5C)),
),
SizedBox(
width: 10.r,
),
Text(
'${studentInfo!.kgValidRate}%',
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF6888FD)),
),
],
),
SizedBox(height: 10.r,),
SizedBox(
height: studentInfo!.kgDetails.length>8?300.r:studentInfo!.kgDetails.length * 40.r + 40.r,
child: StudentKgTable(
headList: ['题号', '学生答案', '标准答案'],
bodyList: studentInfo!.kgDetails,
),
)
],
),
),
SizedBox(height: 15.r,),
//
Container(
padding: EdgeInsets.symmetric(vertical: 14.r, horizontal: 10.r),
margin: EdgeInsets.symmetric(vertical: 14.r, horizontal: 14.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(6.r)),
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
'主观题',
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF5C5C5C)),
),
SizedBox(
width: 10.r,
),
Text(
'${studentInfo!.zgValidRate}%',
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF6888FD)),
),
],
),
SizedBox(height: 10.r,),
SizedBox(
height: studentInfo!.zgDetails.length>8?300.r:studentInfo!.zgDetails.length * 40.r + 40.r,
child: StudentZgTable(
headList: ['题号', '用时', '批注结果','答案','批注'],
bodyList: studentInfo!.zgDetails,
),
)
],
),
),
],
),
),
);
}
}

View File

@ -0,0 +1,334 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/cupertino.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: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_data_report.dart';
import 'package:marking_app/common/model/job/job_report_join_class.dart';
import 'package:marking_app/pages/homework_correction/widget/quick_student_data_table.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';
import 'package:percent_indicator/linear_percent_indicator.dart';
class QuickDataCheckPage extends StatefulWidget {
final int jobId;
final String className;
const QuickDataCheckPage({Key? key, required this.jobId,required this.className}) : super(key: key);
@override
State<QuickDataCheckPage> createState() => _QuickDataCheckPageState();
}
class _QuickDataCheckPageState extends State<QuickDataCheckPage> with CommonMixin {
JobDataReport? jobData;
void initState() {
super.initState();
EasyLoading.show(status:'loading...');
getJobDataReport();
}
void getJobDataReport() async {
RestClient _client = await getClient();
Map<String, dynamic> params = {};
params['jobid'] = widget.jobId;
print(widget.jobId);
BaseStructureResult<JobDataReport?> data =
await _client.getJobDataCenterReport(params);
EasyLoading.dismiss();
if(data.code == 200){
setState(() {
jobData = data.data;
});
}
}
@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: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF6889FD),
Color(0xFFF5F5F5),
],
stops: [
0.09,
0.3
])),
child: Column(
children: [
Row(
children: [
IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.white),
onPressed: () => Navigator.of(context).pop(),
),
Expanded(
child: Center(
child: Text(
'数据快查',
style: TextStyle(fontSize: 16.sp, color: Colors.white),
))),
],
),
SizedBox(height:10.r),
jobData != null?
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,
),
Text(
widget.className,
style: TextStyle(fontSize: 14.r, color: Colors.white),
)
],
),
),
Container(
padding: EdgeInsets.symmetric(vertical: 10.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: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 14.r,
height: 14.r,
decoration: BoxDecoration(
color: 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: 14.r,
height: 14.r,
decoration: BoxDecoration(
color: Color(0xFF6888FD),
borderRadius:
BorderRadius.all(Radius.circular(7.r))),
),
SizedBox(
width: 6.r,
),
Text(
'未提交',
style: TextStyle(
fontSize: 12.sp, color: Color(0xFF333333)),
)
],
),
//
SizedBox(
height: MediaQuery.of(context).size.width * 0.5,
child: PieChart(
PieChartData(
borderData: FlBorderData(show: false),
sectionsSpace: 0,
centerSpaceRadius: MediaQuery.of(context).size.width * 0.1,
sections: [
PieChartSectionData(
color: Color(0xFF4CC793),
value: jobData!.validCount/(jobData!.validCount+jobData!.noAnswerCount) * 100,
radius: MediaQuery.of(context).size.width * 0.1 + 5,
title: '${jobData!.validCount}',
titleStyle: TextStyle(
fontSize: 14.sp,
color: Colors.white,
),
),
PieChartSectionData(
color: Color(0xFF6888FD),
value: jobData!.noAnswerCount/(jobData!.validCount+jobData!.noAnswerCount) * 100,
radius: MediaQuery.of(context).size.width * 0.1,
title: '${jobData!.noAnswerCount}',
titleStyle: TextStyle(
fontSize: 14.sp,
color: Colors.white,
),
),
],
),
),
),
//
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'客观题答题进度',
style: TextStyle(
fontSize: 10.sp, color: Color(0xFF8B8B8B)),
),
Text('${doubleToStringAsFixed(jobData!.kgValidRate)}%',
style: TextStyle(
fontSize: 10.sp, color: 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: jobData!.kgValidRate/100,
progressColor: Color(0xFFFF7F22),
backgroundColor: Color(0xFFEAEAEA),
barRadius: Radius.circular(10.r),
)),
],
),
SizedBox(height: 20.r),
//
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'主观题答题进度',
style: TextStyle(
fontSize: 10.sp, color: Color(0xFF8B8B8B)),
),
Text(
'${doubleToStringAsFixed(jobData!.zgValidRate)}%',
style: TextStyle(
fontSize: 10.sp, color: 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: jobData!.zgValidRate/100,
progressColor: Color(0xFFFF7F22),
backgroundColor: Color(0xFFEAEAEA),
barRadius: Radius.circular(10.r),
)),
],
),
],
),
),
Container(
padding: EdgeInsets.symmetric(vertical: 10.r, horizontal: 10.r),
margin: EdgeInsets.symmetric(vertical: 10.r, horizontal: 14.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(6.r))),
child: Column(
children: [
InkWell(
onTap: (){
jobData!.studentDetails.sort((a, b) {
int num1 = a.kgValidRate + a.zgValidRate;
int num2 = b.kgValidRate + b.zgValidRate;
return num2.compareTo(num1);
});
setState(() {
jobData!.studentDetails;
});
},
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
'未提交排序',
style: TextStyle(
fontSize: 12.sp, color: Color(0xFF6888FD)),
),
SizedBox(
width: 10.r,
),
Image.asset(
'assets/images/sort_icon.png',
width: 14.r,
height: 14.r,
),
],
),
),
SizedBox(height: 10.r,),
SizedBox(
height: jobData!.studentDetails.length>5?350.r:jobData!.studentDetails.length * 50.r + 40.r,
child: QuickStudentDataTable(
headList: ['学生姓名','客观题','主观题','客观题错题','主观题错题'],
bodyList: jobData!.studentDetails,
jobId: widget.jobId,
fixedRows: 1,
fixedCols: 0,
),
)
],
),
),
],
),
)):Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height/2 - 200.r),
child: MyEmptyWidget(),
)
],
),
),
);
}
}

View File

@ -0,0 +1,229 @@
import 'package:data_table_2/data_table_2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/model/job/job_data_report.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/index.dart';
class QuickStudentDataTable extends StatefulWidget {
final List headList;
final List bodyList;
final int? fixedRows;
final int? fixedCols;
final int jobId;
const QuickStudentDataTable({
Key? key,
required this.headList,
required this.bodyList,
required this.jobId,
this.fixedCols = 0,
this.fixedRows = 0,
}) : super(key: key);
@override
State<QuickStudentDataTable> createState() => _QuickStudentDataTableState();
}
class _QuickStudentDataTableState extends State<QuickStudentDataTable> {
final ScrollController _controller = ScrollController();
int? _sortColumnIndex;
bool _sortAscending = true;
DataRow _getRow(int index, [Color? color]) {
assert(index >= 0);
StudentDetails item = widget.bodyList[index];
int num = 0;
item.kgDetails.forEach((element) {
if (element.state == 0) {
num = num + 1;
}
});
item.zgDetails.forEach((element) {
if (element.state == 0) {
num = num + 1;
}
});
return DataRow2.byIndex(
index: index,
color: color != null
? num == 0
? MaterialStateProperty.all(color)
: MaterialStateProperty.all(Color(0xFFFFD79C))
: null,
cells: [
DataCell(InkWell(
onTap: () {
RouterManager.router.navigateTo(
context,
RouterManager.quickCheckPersonalPath +
'?jobId=${widget.jobId}&studentId=${item.studentId}',
transition: getTransition(),
);
},
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(item.studentName!,
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF6888FD))),
SizedBox(
width: 5.r,
),
Image.asset(
'assets/images/job_data_right_icon.png',
width: 10.r,
height: 10.r,
)
],
),
),
),
)),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(
'${(item.kgValidRate / 100 * item.kgValidCount).toInt()}/${item.kgValidCount}',
style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(
'${(item.zgValidRate / 100 * item.zgValidCount).toInt()}/${item.zgValidCount}',
style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
DataCell(
Padding(
padding: EdgeInsets.symmetric(vertical: 2.r, horizontal: 5.r),
child: SingleChildScrollView(
child: Wrap(
direction: Axis.horizontal,
alignment: WrapAlignment.center,
spacing: 2,
runSpacing: 2,
children: List.generate(item.kgDetails.length, (index) {
KgDetails kgInfo = item.kgDetails[index];
return Container(
width: 14.r,
height: 14.r,
decoration: BoxDecoration(
color: kgInfo.state == 0
? Color(0xFFD9D9D9)
: kgInfo.state == 1
? Color(0xFFFF7474)
: Color(0xFF4CC793),
borderRadius: BorderRadius.all(Radius.circular(7.r))),
child: Center(
child: Text(
kgInfo.questionNo,
style: TextStyle(
fontSize: 10.sp,
color: kgInfo.state == 0
? Color(0xFF525252)
: Colors.white),
)),
);
})),
),
),
),
DataCell(
Padding(
padding: EdgeInsets.symmetric(vertical: 2.r, horizontal: 5.r),
child: SingleChildScrollView(
child: Wrap(
direction: Axis.horizontal,
alignment: WrapAlignment.center,
spacing: 2,
runSpacing: 2,
children: List.generate(item.zgDetails.length, (index) {
KgDetails kgInfo = item.zgDetails[index];
return Container(
width: 14.r,
height: 14.r,
decoration: BoxDecoration(
color: kgInfo.state == 0
? Color(0xFFD9D9D9)
: kgInfo.state == 1
? Color(0xFFFF7474)
: Color(0xFF4CC793),
borderRadius: BorderRadius.all(Radius.circular(7.r))),
child: Center(
child: Text(
kgInfo.questionNo,
style: TextStyle(
fontSize: 10.sp,
color: kgInfo.state == 0
? Color(0xFF525252)
: Colors.white),
)),
);
})),
),
),
),
],
);
}
@override
Widget build(BuildContext context) {
return DataTable2(
dividerThickness: 0,
scrollController: _controller,
columnSpacing: 0,
horizontalMargin: 0,
bottomMargin: 0,
dataRowHeight: 50.r,
border: TableBorder(
horizontalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
bottom: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
verticalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid)),
headingRowColor: MaterialStateProperty.resolveWith((states) =>
widget.fixedCols! > 0 ? Colors.white : Colors.transparent),
/* headingRowDecoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.grey[400]!,
Colors.grey[200]!,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),*/
headingRowDecoration: BoxDecoration(color: Color(0xFFE6E6E6)),
fixedColumnsColor: Color(0xFFE6E6E6),
fixedCornerColor: Colors.grey[400],
minWidth: MediaQuery.of(context).size.width,
fixedTopRows: widget.fixedRows!,
fixedLeftColumns: widget.fixedCols!,
sortColumnIndex: _sortColumnIndex,
sortAscending: _sortAscending,
// onSelectAll: (val) => setState(() => selectAll(val)),
columns: List.generate(widget.headList.length, (index) {
var item = widget.headList[index];
return DataColumn2(
label: Center(
child: Text(item,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF505767))),
),
// size: ColumnSize.S,
fixedWidth: (MediaQuery.of(context).size.width - 20.r - 28.r) / 5,
);
}),
rows: List<DataRow>.generate(widget.bodyList.length,
(index) => _getRow(index, Color(0xFFF5F5F5))));
}
}

View File

@ -0,0 +1,148 @@
import 'package:data_table_2/data_table_2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
class ReportTable extends StatefulWidget {
final List headList;
final List bodyList;
final int? fixedRows;
final int? fixedCols;
final bool? isKG;
const ReportTable({
Key? key,
required this.headList,
required this.bodyList,
this.fixedCols = 0,
this.fixedRows = 0,
this.isKG = false,
}) : super(key: key);
@override
State<ReportTable> createState() => _ReportTableState();
}
class _ReportTableState extends State<ReportTable> {
final ScrollController _controller = ScrollController();
int? _sortColumnIndex;
bool _sortAscending = true;
DataRow _getRow(int index, [Color? color]) {
assert(index >= 0);
var item = widget.bodyList[index];
return DataRow2.byIndex(
index: index,
color: color != null ? MaterialStateProperty.all(color) : null,
cells: [
DataCell( Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child:
Text(item.questionNo,
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
DataCell( Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child:
Text('${item.validRate}%',
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
DataCell( Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child:
Text(item.validCount,
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF4CC793))),
),
)),
DataCell( Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child:
Text('${item.correctRate}%',
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
DataCell( Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child:
Text(
widget.isKG == true?'原题':item.questionAnswer,
style:
TextStyle(fontSize: 12.sp, color: widget.isKG == true?Color(0xFFFF8A00):Color(0xFF4CC793))),
),
)),
DataCell( Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child:
Text(item.priorityGeneral,
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF6888FD))),
),
)),
],
);
}
@override
Widget build(BuildContext context) {
return DataTable2(
dividerThickness: 0,
scrollController: _controller,
columnSpacing: 0,
horizontalMargin: 0,
dataRowHeight:40.r,
bottomMargin: 0,
border: TableBorder(
horizontalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
bottom: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
verticalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid)),
headingRowColor: MaterialStateProperty.resolveWith((states) =>
widget.fixedCols! > 0 ? Colors.white : Colors.transparent),
/* headingRowDecoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.grey[400]!,
Colors.grey[200]!,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),*/
headingRowDecoration: BoxDecoration(color: Color(0xFFE6E6E6)),
fixedColumnsColor: Color(0xFFE6E6E6),
fixedCornerColor: Colors.grey[400],
minWidth: widget.headList.length > 6?80.r * widget.headList.length:MediaQuery.of(context).size.width,
fixedTopRows: widget.fixedRows!,
fixedLeftColumns: widget.fixedCols!,
sortColumnIndex: _sortColumnIndex,
sortAscending: _sortAscending,
// onSelectAll: (val) => setState(() => selectAll(val)),
columns: List.generate(widget.headList.length, (index) {
var item = widget.headList[index];
return DataColumn2(
label: Center(
child: Text(item,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF505767))),
),
// size: ColumnSize.S,
fixedWidth: index == 0 ? 40.r:widget.headList.length > 6 ?80.r:(MediaQuery.of(context).size.width)/widget.headList.length,
);
}),
rows: List<DataRow>.generate(widget.bodyList.length,
(index) => _getRow(index, Color(0xFFF5F5F5))));
}
}

View File

@ -0,0 +1,103 @@
import 'package:data_table_2/data_table_2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/model/job/job_data_report.dart';
class StudentKgTable extends StatefulWidget {
final List headList;
final List bodyList;
final int? fixedRows;
final int? fixedCols;
const StudentKgTable({
Key? key,
required this.headList,
required this.bodyList,
this.fixedCols = 0,
this.fixedRows = 0,
}) : super(key: key);
@override
State<StudentKgTable> createState() => _StudentKgTableState();
}
class _StudentKgTableState extends State<StudentKgTable> {
final ScrollController _controller = ScrollController();
int? _sortColumnIndex;
bool _sortAscending = true;
DataRow _getRow(int index, [Color? color]) {
assert(index >= 0);
KgDetails item = widget.bodyList[index];
return DataRow2.byIndex(
index: index,
color: color != null ? MaterialStateProperty.all(color): null,
cells: [
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.questionNo,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF6888FD))),
),
)),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.studentAnswer == null?'未作答':item.studentAnswer!,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.annotateAnswers == null ?'':item.annotateAnswers!,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
],
);
}
@override
Widget build(BuildContext context) {
return DataTable2(
dividerThickness: 0,
scrollController: _controller,
columnSpacing: 0,
horizontalMargin: 0,
bottomMargin: 0,
dataRowHeight: 40.r,
headingRowHeight: 40.r,
border: TableBorder(
horizontalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
bottom: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
verticalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid)),
headingRowColor: MaterialStateProperty.resolveWith((states) =>
widget.fixedCols! > 0 ? Colors.white : Colors.transparent),
headingRowDecoration: BoxDecoration(color: Color(0xFFE6E6E6)),
fixedColumnsColor: Color(0xFFE6E6E6),
fixedCornerColor: Colors.grey[400],
minWidth: MediaQuery.of(context).size.width,
fixedTopRows: widget.fixedRows!,
fixedLeftColumns: widget.fixedCols!,
sortColumnIndex: _sortColumnIndex,
sortAscending: _sortAscending,
// onSelectAll: (val) => setState(() => selectAll(val)),
columns: List.generate(widget.headList.length, (index) {
var item = widget.headList[index];
return DataColumn2(
label: Center(
child: Text(item,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF505767))),
),
// size: ColumnSize.S,
fixedWidth: (MediaQuery.of(context).size.width - 20.r - 28.r)/3,
);
}),
rows: List<DataRow>.generate(widget.bodyList.length,
(index) => _getRow(index, Color(0xFFF5F5F5))));
}
}

View File

@ -0,0 +1,157 @@
import 'package:data_table_2/data_table_2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/model/job/job_data_report.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
class StudentZgTable extends StatefulWidget {
final List headList;
final List bodyList;
final int? fixedRows;
final int? fixedCols;
const StudentZgTable({
Key? key,
required this.headList,
required this.bodyList,
this.fixedCols = 0,
this.fixedRows = 0,
}) : super(key: key);
@override
State<StudentZgTable> createState() => _StudentZgTableState();
}
class _StudentZgTableState extends State<StudentZgTable> {
final ScrollController _controller = ScrollController();
int? _sortColumnIndex;
bool _sortAscending = true;
void showImgDialog(BuildContext context,String imgUrl){
showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
// insetPadding: EdgeInsets.symmetric(vertical: 20.r,horizontal: 20.r),
contentPadding: EdgeInsets.all(20.r),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15.r))),
content: SizedBox(
width: MediaQuery.of(context).size.width * 0.6,
height: MediaQuery.of(context).size.height * 0.6,
child: Column(
children: [
Center(
child: Text('批注答案',style: TextStyle(fontSize: 15.sp,color: Color(0xFF3C3C3C)),),
),
SizedBox(height: 10.r,),
Image.network(imgUrl,fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) {
return Padding(
padding: EdgeInsets.only(top: 20.r),
child: const MyEmptyWidget());
}),
],
),
),
);
});
}
DataRow _getRow(int index, [Color? color]) {
assert(index >= 0);
KgDetails item = widget.bodyList[index];
return DataRow2.byIndex(
index: index,
color: color != null ? MaterialStateProperty.all(color): null,
cells: [
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.questionNo,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF6888FD))),
),
)),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.useTime.toString(),
style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: item.state == 2?
Image.asset('assets/images/job_personal_correct_icon.png',width: 18.r,height: 18.r,):
Image.asset('assets/images/job_personal_error_icon.png',width: 10.r,height: 10.r,),
),
)),
DataCell(InkWell(
onTap: (){
showImgDialog(context,item.studentAnswer!);
},
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text('查看',
style: TextStyle(fontSize: 12.sp, color: Color(0xFF3661FE))),
),
),
)),
DataCell(InkWell(
onTap: (){
showImgDialog(context,item.annotateAnswers!);
},
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text('查看',
style: TextStyle(fontSize: 12.sp, color: Color(0xFF3661FE))),
),
),
)),
],
);
}
@override
Widget build(BuildContext context) {
return DataTable2(
dividerThickness: 0,
scrollController: _controller,
columnSpacing: 0,
horizontalMargin: 0,
bottomMargin: 0,
headingRowHeight: 40.r,
dataRowHeight: 40.r,
border: TableBorder(
horizontalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
bottom: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
verticalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid)),
headingRowColor: MaterialStateProperty.resolveWith((states) =>
widget.fixedCols! > 0 ? Colors.white : Colors.transparent),
headingRowDecoration: BoxDecoration(color: Color(0xFFE6E6E6)),
fixedColumnsColor: Color(0xFFE6E6E6),
fixedCornerColor: Colors.grey[400],
minWidth: MediaQuery.of(context).size.width,
fixedTopRows: widget.fixedRows!,
fixedLeftColumns: widget.fixedCols!,
sortColumnIndex: _sortColumnIndex,
sortAscending: _sortAscending,
// onSelectAll: (val) => setState(() => selectAll(val)),
columns: List.generate(widget.headList.length, (index) {
var item = widget.headList[index];
return DataColumn2(
label: Center(
child: Text(item,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF505767))),
),
// size: ColumnSize.S,
fixedWidth: (MediaQuery.of(context).size.width - 20.r - 28.r)/5,
);
}),
rows: List<DataRow>.generate(widget.bodyList.length,
(index) => _getRow(index, Color(0xFFF5F5F5))));
}
}

View File

@ -0,0 +1,266 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/model/job/job_report_model.dart';
import 'package:marking_app/utils/index.dart';
class TopCount extends StatelessWidget {
final JobReportModel data;
const TopCount(this.data,{Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 10.r),
margin: EdgeInsets.symmetric(vertical: 10.r, horizontal: 10.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(6.r)),
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 81.r,
padding: EdgeInsets.symmetric(
vertical: 10.r, horizontal: 6.r),
decoration: BoxDecoration(
border: Border.all(
width: 1.r,
color: Color(0xFF4CC793),
style: BorderStyle.solid),
borderRadius: BorderRadius.all(Radius.circular(6.r)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
doubleToStringAsFixed(data.finishRate),
style: TextStyle(
fontSize: 24.sp,
color: Color(0xFF4CC793),
fontWeight: FontWeight.w600),
),
Text(
'%',
style: TextStyle(
fontSize: 16.sp,
color: Color(0xFF4CC793),
fontWeight: FontWeight.w600),
),
],
),
SizedBox(
height: 15.r,
child: Row(
children: [
Text(
data.validCount.toString(),
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFFB0B0B0)),
),
Text(
'/',
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFFB0B0B0)),
),
Text(
data.studentCount.toString(),
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFFB0B0B0)),
),
],
),
),
Text(
'完成率',
style: TextStyle(
fontSize: 12.sp, color: Color(0xFF818181)),
)
],
),
),
Container(
width: 81.r,
padding: EdgeInsets.symmetric(
vertical: 10.r, horizontal: 6.r),
decoration: BoxDecoration(
border: Border.all(
width: 1.r,
color: Color(0xFF4CC793),
style: BorderStyle.solid),
borderRadius: BorderRadius.all(Radius.circular(6.r)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
doubleToStringAsFixed(data.correctRate),
style: TextStyle(
fontSize: 24.sp,
color: Color(0xFF4CC793),
fontWeight: FontWeight.w600),
),
Text(
'%',
style: TextStyle(
fontSize: 16.sp,
color: Color(0xFF4CC793),
fontWeight: FontWeight.w600),
),
],
),
SizedBox(
height: 15.r,
),
Text(
'正确率',
style: TextStyle(
fontSize: 12.sp, color: Color(0xFF818181)),
)
],
),
),
Container(
width: 81.r,
padding: EdgeInsets.symmetric(
vertical: 10.r, horizontal: 6.r),
decoration: BoxDecoration(
border: Border.all(
width: 1.r,
color: Color(0xFF4CC793),
style: BorderStyle.solid),
borderRadius: BorderRadius.all(Radius.circular(6.r)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
data.allCorrect.toString(),
style: TextStyle(
fontSize: 24.sp,
color: Color(0xFF4CC793),
fontWeight: FontWeight.w600),
),
Text(
'',
style: TextStyle(
fontSize: 16.sp,
color: Color(0xFF4CC793),
fontWeight: FontWeight.w600),
),
],
),
SizedBox(
height: 10.r,
),
Text(
'全对',
style: TextStyle(
fontSize: 12.sp, color: Color(0xFF818181)),
)
],
),
),
],
),
SizedBox(
height: 15.r,
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 15.r),
child: GridView.builder(
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 150 / 46,
crossAxisSpacing: 2.r, // Widget
mainAxisSpacing: 2.r, // Widget
crossAxisCount: 2, // Widget
),
itemCount: data.overallTitles.length,
itemBuilder: (BuildContext context, index){
var item = data.overallTitles[index];
Color bgColor = Color(0xFF4CC793);
if(item.title == ''){
bgColor = Color(0xFF4CC793);
}else if(item.title == ''){
bgColor = Color(0xFFF8700D);
}else if(item.title == ''){
bgColor = Color(0xFF4CC7B8);
}else if(item.title == ''){
bgColor = Color(0xFFFF6F6F);
}
return Container(
padding: EdgeInsets.symmetric(vertical: 10.r),
width: (MediaQuery.of(context).size.width - 55.r) / 2,
color: Color(0xFFF5F5F5),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
width: (MediaQuery.of(context).size.width - 55.r)/4 - 20.r,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
width: 28.r,
height: 28.r,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: bgColor,
width: 1.r,
style: BorderStyle.solid),
borderRadius: BorderRadius.circular(14.r)),
child: Center(
child: Text(
item.title,
style: TextStyle(
color: bgColor, fontSize: 14.r),
)),
),
],
),
),
SizedBox(
width: 20.r,
),
Text(
item.count.toString(),
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.w600,
color: Color(0xFF595959)),
),
Text(
'',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Color(0xFF595959)),
),
],
),
);
},
),
),
],
),
);
}
}

View File

@ -10,7 +10,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/config/request_config.dart'; import 'package:marking_app/common/config/request_config.dart';
@ -21,8 +20,6 @@ import 'package:marking_app/common/model/event_bus/marking_statistics_bus.dart';
import 'package:marking_app/common/model/marking/marking_statistics.dart'; import 'package:marking_app/common/model/marking/marking_statistics.dart';
import 'package:marking_app/pages/common/event_bus_mixin.dart'; import 'package:marking_app/pages/common/event_bus_mixin.dart';
import 'package:marking_app/provider/review_provider.dart'; import 'package:marking_app/provider/review_provider.dart';
import 'package:marking_app/utils/anti_shake_throttling.dart';
import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/request/rest_client.dart'; import 'package:marking_app/utils/request/rest_client.dart';
import 'package:marking_app/common/model/common/base_page_data.dart'; import 'package:marking_app/common/model/common/base_page_data.dart';
import 'package:marking_app/common/model/marking/marking_item.dart'; import 'package:marking_app/common/model/marking/marking_item.dart';

View File

@ -11,7 +11,7 @@ class TopUserInfo extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final userState = ref.watch(userProvider); final userState = ref.read(userProvider);
return InkWell( return InkWell(
onTap: () { onTap: () {

View File

@ -14,9 +14,14 @@ import 'package:flutter/material.dart';
import 'package:marking_app/common/model/enum/marking_list_type.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/common/startUpPage.dart';
import 'package:marking_app/pages/homework_correction/do_papers_job_exam.dart'; import 'package:marking_app/pages/homework_correction/do_papers_job_exam.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_report.dart';
import 'package:marking_app/pages/homework_correction/job_student_group.dart';
import 'package:marking_app/pages/homework_correction/pages/job_favorite.dart';
import 'package:marking_app/pages/homework_correction/pages/job_list_participate_in_class.dart';
import 'package:marking_app/pages/homework_correction/review_job.dart'; import 'package:marking_app/pages/homework_correction/review_job.dart';
import 'package:marking_app/pages/homework_correction/quick_check_personal.dart';
import 'package:marking_app/pages/homework_correction/quick_data_check.dart';
import 'package:marking_app/pages/login/index.dart'; import 'package:marking_app/pages/login/index.dart';
import 'package:marking_app/pages/mainPage.dart'; import 'package:marking_app/pages/mainPage.dart';
import 'package:marking_app/pages/marking/do_papers.dart'; import 'package:marking_app/pages/marking/do_papers.dart';
@ -53,12 +58,21 @@ class RouterManager {
static const String jobReportPagePath = '/job/report/index'; static const String jobReportPagePath = '/job/report/index';
// ==> // ==>
static const String jobExamPagePath = '/job/exam/index'; static const String jobExamPagePath = '/job/exam/index';
// ==> ==>
static const String jobListParticipateInClassPath = '/job/list/participateInClass';
// ==>
static const String jobFavoritePagePath = '/job/favorite/index';
static const String reportClassTeacherPath = 'report/details/reportClassTeacher'; static const String reportClassTeacherPath = 'report/details/reportClassTeacher';
static const String reportSubjectTeacherPath = 'report/details/reportSubjectTeacher'; static const String reportSubjectTeacherPath = 'report/details/reportSubjectTeacher';
static const String reportPersonalSubjectPath = 'report/details/reportPersonalSubject'; static const String reportPersonalSubjectPath = 'report/details/reportPersonalSubject';
static const String userMinePath = 'user/mine/index'; static const String userMinePath = 'user/mine/index';
static const String reportDetailPath = '/report_detail/index'; static const String reportDetailPath = '/report_detail/index';
static const String quickDataCheckPath = '/homework_correction/quick_data_check';
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';
// TheMine // TheMine
static final FluroRouter router = FluroRouter(); static final FluroRouter router = FluroRouter();
@ -173,7 +187,16 @@ class RouterManager {
static final _jobReportPageHandler = Handler(handlerFunc: (BuildContext? context, Map<String, List<String>> params) { static final _jobReportPageHandler = Handler(handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
int id = int.parse(params['id']![0]); int id = int.parse(params['id']![0]);
String title = params['title']![0]; String title = params['title']![0];
return JobReport(id: id, title: title); int? schoolId;
if (params['schoolId'] != null && params['schoolId']![0] != null && params['schoolId']![0] != 'null') {
schoolId = int.parse(params['schoolId']![0]);
}
int? gradeId;
if (params['gradeId'] != null && params['gradeId']![0] != null && params['gradeId']![0] != 'null') {
gradeId = int.parse(params['gradeId']![0]);
}
String? className = params['className']?[0];
return JobReport(id: id, title: title, schoolId: schoolId, gradeId: gradeId, className: className);
}); });
// //
@ -239,6 +262,61 @@ class RouterManager {
}, },
); );
static final _jobListParticipateInClassHandler = Handler(
handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
int jobId = int.parse(params['jobId']![0]);
String jobName = params['jobName']![0];
String genderName = params['genderName']![0];
// ignore: sdk_version_since
bool completed = bool.parse(params['completed']?[0] ?? 'false');
return JobListParticipateInClass(jobId: jobId, jobName: jobName, genderName: genderName, completed: completed);
},
);
//
static final _quickDataCheckPageHandler = Handler(
handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
int jobId = int.parse(params['jobId']![0]);
String className = params['className']![0];
return QuickDataCheckPage(jobId: jobId, className: className);
},
);
// -
static final _quickCheckPersonalPageHandler = Handler(
handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
int jobId = int.parse(params['jobId']![0]);
int studentId = int.parse(params['studentId']![0]);
return QuickCheckPersonal(jobId: jobId, studentId: studentId);
},
);
//
static final _jobPriorityReviewSetPageHandler = Handler(
handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
String groupId = params['groupId']![0];
return JobPriorityReviewSet(groupId: groupId);
},
);
//
static final _jobStudentGroupPageHandler = Handler(
handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
return JobStudentGroup();
},
);
//
static final _jobFavoritePagePathHandler = Handler(
handlerFunc: (BuildContext? context, Map<String, List<String>> params) {
int jobId = int.parse(params['jobId']![0]);
int gradeId = int.parse(params['gradeId']![0]);
int schoolId = int.parse(params['schoolId']![0]);
String className = params['className']![0];
String jobName = params['jobName']![0];
return JobFavorite(jobId: jobId, gradeId: gradeId, schoolId: schoolId, className: className,jobName:jobName);
},
);
// //
// static final _doMarkingPapers = Handler(handlerFunc: (BuildContext? context, Map<String, List<String>> params) => MarkingPapers()); // static final _doMarkingPapers = Handler(handlerFunc: (BuildContext? context, Map<String, List<String>> params) => MarkingPapers());
@ -273,6 +351,15 @@ class RouterManager {
router.define(reportDetailPath, handler: _reportDetailPath, transitionType: TransitionType.material); router.define(reportDetailPath, handler: _reportDetailPath, transitionType: TransitionType.material);
router.define(jobReportPagePath, handler: _jobReportPageHandler, transitionType: TransitionType.material); router.define(jobReportPagePath, handler: _jobReportPageHandler, transitionType: TransitionType.material);
router.define(jobExamPagePath, handler: _jobExamPageHandler, transitionType: TransitionType.material); router.define(jobExamPagePath, handler: _jobExamPageHandler, transitionType: TransitionType.material);
router.define(jobListParticipateInClassPath,
handler: _jobListParticipateInClassHandler, transitionType: TransitionType.material);
router.define(quickDataCheckPath, handler: _quickDataCheckPageHandler, transitionType: TransitionType.material);
router.define(quickCheckPersonalPath,
handler: _quickCheckPersonalPageHandler, transitionType: TransitionType.material);
router.define(jobPriorityReviewSetPath,
handler: _jobPriorityReviewSetPageHandler, transitionType: TransitionType.material);
router.define(jobStudentGroupPath, handler: _jobStudentGroupPageHandler, transitionType: TransitionType.material);
router.define(jobFavoritePagePath, handler: _jobFavoritePagePathHandler, transitionType: TransitionType.material);
// getTransition() // getTransition()

View File

@ -21,6 +21,7 @@ import 'dart:math';
import 'package:fluro/fluro.dart'; import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/config/request_config.dart'; import 'package:marking_app/common/config/request_config.dart';
export "./colorUtils.dart"; export "./colorUtils.dart";
@ -105,6 +106,11 @@ void toPrint({required dynamic val, bool toPrintJson = false}) {
if (printSwitch && val != null) toPrintJson ? printJson(val) : print(val); if (printSwitch && val != null) toPrintJson ? printJson(val) : print(val);
} }
//
bool isPad([double mobilePhoneScale = 1.2]) {
return ScreenUtil().scaleWidth > mobilePhoneScale;
}
class EUMNoScrollBehavior extends ScrollBehavior { class EUMNoScrollBehavior extends ScrollBehavior {
@override @override
Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) { Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) {

View File

@ -15,7 +15,12 @@ import 'package:marking_app/common/model/common/upload_img_secret_key.dart';
import 'package:marking_app/common/model/job/job_collect_params.dart'; import 'package:marking_app/common/model/job/job_collect_params.dart';
import 'package:marking_app/common/model/job/job_concerned_with_student.dart'; import 'package:marking_app/common/model/job/job_concerned_with_student.dart';
import 'package:marking_app/common/model/job/job_concerned_with_student_params.dart'; import 'package:marking_app/common/model/job/job_concerned_with_student_params.dart';
import 'package:marking_app/common/model/job/job_data_report.dart';
import 'package:marking_app/common/model/job/job_do_marking_status_info.dart'; import 'package:marking_app/common/model/job/job_do_marking_status_info.dart';
import 'package:marking_app/common/model/job/job_fav_student.dart';
import 'package:marking_app/common/model/job/job_favorite_item_model.dart';
import 'package:marking_app/common/model/job/job_favorite_model.dart';
import 'package:marking_app/common/model/job/job_level_set_params.dart';
import 'package:marking_app/common/model/job/job_note_taking_trajectory.dart'; import 'package:marking_app/common/model/job/job_note_taking_trajectory.dart';
import 'package:marking_app/common/model/job/job_page_tab.dart'; import 'package:marking_app/common/model/job/job_page_tab.dart';
import 'package:marking_app/common/model/job/job_report_join_class.dart'; import 'package:marking_app/common/model/job/job_report_join_class.dart';
@ -23,6 +28,8 @@ import 'package:marking_app/common/model/job/job_report_knowledge_model.dart';
import 'package:marking_app/common/model/job/job_report_model.dart'; 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_report_question_deatil_model.dart';
import 'package:marking_app/common/model/job/job_review_submission.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_level.dart';
import 'package:marking_app/common/model/job/job_task_item.dart'; import 'package:marking_app/common/model/job/job_task_item.dart';
import 'package:marking_app/common/model/job/marking_text_question_job.dart'; import 'package:marking_app/common/model/job/marking_text_question_job.dart';
import 'package:marking_app/common/model/job/marking_text_question_job_params.dart'; import 'package:marking_app/common/model/job/marking_text_question_job_params.dart';
@ -285,4 +292,52 @@ abstract class RestClient {
@the_retrofit.GET("/api/jobs/job-report-question-detail") @the_retrofit.GET("/api/jobs/job-report-question-detail")
Future<BaseStructureResult<List<JobReportQuestionDeatilModel>>> getJobReportQuestionDetail( Future<BaseStructureResult<List<JobReportQuestionDeatilModel>>> getJobReportQuestionDetail(
@the_retrofit.Query("jobid") int jobId, @the_retrofit.Query("questionid") int questionid); @the_retrofit.Query("jobid") int jobId, @the_retrofit.Query("questionid") int questionid);
// => ==>
@the_retrofit.GET("${RequestConfig.hwProxyKeywords}/api/Task/tasks")
Future<BaseStructureResult<List<MarkingTasks>>> getJobListParticipateInClass(
@the_retrofit.Query("markingId") int jobId);
// =>
@the_retrofit.GET("${RequestConfig.hwProxyKeywords}/dpc-api/api/read/job-favorite-count-by-class")
Future<BaseStructureResult<List<JobFavoriteModel>>> getListOfJobFavoriteNumber(
@the_retrofit.Query("jobid") int jobId);
// =>
@the_retrofit.GET("/api/jobs/fav-student-jobs")
Future<BaseStructureResult<JobFavStudent>> getListOfJobFavorites(
@the_retrofit.Query("JobId") int jobId,
@the_retrofit.Query("JobName") String jobName,
@the_retrofit.Query("className") String className,
@the_retrofit.Query("Account") String loginName,
@the_retrofit.Query("PageSize") int pageSize,
);
// =>
@the_retrofit.POST("${RequestConfig.hwProxyKeywords}/dpc-api/api/read/cancel-favorite")
Future<BaseStructureResult<bool>> toJobCancelFavorite(
@the_retrofit.Field() int jobId, @the_retrofit.Field() int studentId);
// =>
@the_retrofit.GET("/api/read/job-data-center-report")
Future<BaseStructureResult<JobDataReport>> getJobDataCenterReport(
@the_retrofit.Queries() Map<String, dynamic> params);
// => --
@the_retrofit.GET("/api/read/job-data-center-student-report")
Future<BaseStructureResult<StudentDetails>> getJobPersonalReport(@the_retrofit.Queries() Map<String, dynamic> params);
// =>
@the_retrofit.GET("/api/read/job-read-level-student-groups")
Future<BaseStructureResult<List<JobStudentGroups>>> getJobLevelStudentGroups(
@the_retrofit.Query("account") String account);
// =>
@the_retrofit.GET("/api/read/job-read-level")
Future<BaseStructureResult<List<JobStudentLevel>>> getJobReadLevel(
@the_retrofit.Query("GroupId") String groupId, @the_retrofit.Query("ReadLevel") int readLevel);
// => /
@the_retrofit.POST("/api/read/jc-job-read-level")
Future<BaseStructureResult> getSetJobReadLevel(@the_retrofit.Body() JobLevelSetParams params);
} }