Compare commits

...

5 Commits

11 changed files with 1695 additions and 0 deletions

3
.gitignore vendored
View File

@ -184,3 +184,6 @@ marking_app/lib/pages/homework_correction/eventBus/do_papers_job_refresh_bus.g.d
marking_app/lib/pages/homework_correction/eventBus/job_do_papers_switch_operation_sub_bus.g.dart
marking_app/lib/pages/homework_correction/eventBus/job_notes_view_bus.g.dart
marking_app/lib/pages/homework_correction/eventBus/job_notes_view_bus.g.dart
marking_app/lib/common/model/job/job_report_model.g.dart
marking_app/lib/common/model/job/job_report_join_class.g.dart
marking_app/lib/pages/homework_correction/job_report.g.dart

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,45 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_report_join_class.g.dart';
@JsonSerializable()
class JobReportJoinClass extends Object {
@JsonKey(name: 'schoolId')
int schoolId;
@JsonKey(name: 'schoolName')
String schoolName;
@JsonKey(name: 'gradeId')
int gradeId;
@JsonKey(name: 'gradeName')
String gradeName;
@JsonKey(name: 'graduationYear')
String graduationYear;
@JsonKey(name: 'className')
String className;
@JsonKey(name: 'toBeSubmitCount')
int toBeSubmitCount;
@JsonKey(name: 'submitCount')
int submitCount;
JobReportJoinClass(
this.schoolId,
this.schoolName,
this.gradeId,
this.gradeName,
this.graduationYear,
this.className,
this.toBeSubmitCount,
this.submitCount,
);
factory JobReportJoinClass.fromJson(Map<String, dynamic> srcJson) => _$JobReportJoinClassFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobReportJoinClassToJson(this);
}

View File

@ -0,0 +1,223 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_report_model.g.dart';
@JsonSerializable()
class JobReportModel extends Object {
@JsonKey(name: 'studentCount')
int studentCount;
@JsonKey(name: 'finishRate')
double finishRate;
@JsonKey(name: 'correctRate')
double correctRate;
@JsonKey(name: 'errorRate')
double errorRate;
@JsonKey(name: 'validCount')
int validCount;
@JsonKey(name: 'allCorrect')
int allCorrect;
@JsonKey(name: 'passCount')
int passCount;
@JsonKey(name: 'failCount')
int failCount;
@JsonKey(name: 'noAnswerCount')
int noAnswerCount;
@JsonKey(name: 'score')
int score;
@JsonKey(name: 'scoreTitle')
String scoreTitle;
@JsonKey(name: 'knowledgeInfos')
List<KnowledgeInfos> knowledgeInfos;
@JsonKey(name: 'questionAnswerInfos')
List<QuestionAnswerInfos> questionAnswerInfos;
@JsonKey(name: 'studentAnswerInfos')
List<StudentAnswerInfos> studentAnswerInfos;
@JsonKey(name: 'overallTitles')
List<OverallTitles> overallTitles;
JobReportModel(
this.studentCount,
this.finishRate,
this.correctRate,
this.errorRate,
this.validCount,
this.allCorrect,
this.passCount,
this.failCount,
this.noAnswerCount,
this.score,
this.scoreTitle,
this.knowledgeInfos,
this.questionAnswerInfos,
this.studentAnswerInfos,
this.overallTitles,
);
factory JobReportModel.fromJson(Map<String, dynamic> srcJson) => _$JobReportModelFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobReportModelToJson(this);
}
@JsonSerializable()
class KnowledgeInfos extends Object {
@JsonKey(name: 'knowledgeId')
int knowledgeId;
@JsonKey(name: 'knowledgeName')
String knowledgeName;
@JsonKey(name: 'rate')
double rate;
KnowledgeInfos(
this.knowledgeId,
this.knowledgeName,
this.rate,
);
factory KnowledgeInfos.fromJson(Map<String, dynamic> srcJson) => _$KnowledgeInfosFromJson(srcJson);
Map<String, dynamic> toJson() => _$KnowledgeInfosToJson(this);
}
@JsonSerializable()
class QuestionAnswerInfos extends Object {
@JsonKey(name: 'questionId')
int questionId;
@JsonKey(name: 'questionType')
int questionType;
@JsonKey(name: 'partName')
String partName;
@JsonKey(name: 'questionNo')
String questionNo;
@JsonKey(name: 'finishInfos')
List<FinishInfos> finishInfos;
@JsonKey(name: 'correctRate')
double correctRate;
@JsonKey(name: 'errorRate')
double errorRate;
@JsonKey(name: 'noAnswerRate')
double noAnswerRate;
QuestionAnswerInfos(
this.questionId,
this.questionType,
this.partName,
this.questionNo,
this.finishInfos,
this.correctRate,
this.errorRate,
this.noAnswerRate,
);
factory QuestionAnswerInfos.fromJson(Map<String, dynamic> srcJson) => _$QuestionAnswerInfosFromJson(srcJson);
Map<String, dynamic> toJson() => _$QuestionAnswerInfosToJson(this);
}
@JsonSerializable()
class FinishInfos extends Object {
@JsonKey(name: 'title')
String title;
@JsonKey(name: 'finishCount')
int finishCount;
@JsonKey(name: 'correctRate')
double correctRate;
FinishInfos(
this.title,
this.finishCount,
this.correctRate,
);
factory FinishInfos.fromJson(Map<String, dynamic> srcJson) => _$FinishInfosFromJson(srcJson);
Map<String, dynamic> toJson() => _$FinishInfosToJson(this);
}
@JsonSerializable()
class StudentAnswerInfos extends Object {
@JsonKey(name: 'studentId')
int studentId;
@JsonKey(name: 'studentName')
String studentName;
@JsonKey(name: 'useTime')
int useTime;
@JsonKey(name: 'correctRate')
double correctRate;
@JsonKey(name: 'finishRate')
double finishRate;
@JsonKey(name: 'noAnswerCount')
int noAnswerCount;
@JsonKey(name: 'ranking')
int ranking;
@JsonKey(name: 'score')
int score;
@JsonKey(name: 'scoreTitle')
String scoreTitle;
StudentAnswerInfos(
this.studentId,
this.studentName,
this.useTime,
this.correctRate,
this.finishRate,
this.noAnswerCount,
this.ranking,
this.score,
this.scoreTitle,
);
factory StudentAnswerInfos.fromJson(Map<String, dynamic> srcJson) => _$StudentAnswerInfosFromJson(srcJson);
Map<String, dynamic> toJson() => _$StudentAnswerInfosToJson(this);
}
@JsonSerializable()
class OverallTitles extends Object {
@JsonKey(name: 'title')
String title;
@JsonKey(name: 'count')
int count;
OverallTitles(
this.title,
this.count,
);
factory OverallTitles.fromJson(Map<String, dynamic> srcJson) => _$OverallTitlesFromJson(srcJson);
Map<String, dynamic> toJson() => _$OverallTitlesToJson(this);
}

View File

@ -247,6 +247,32 @@ Widget $completedHomeworkView(BuildContext context,
subjectivePrecision: jobTaskItem.subjectivePrecision / 100,
taskIds: jobTaskItem.markingTasks.map((e) => e.id).toList(),
),
InkWell(
onTap: () {},
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)],
),
),
child: quickText('查看报告', color: Colors.white, size: 12.sp),
),
),
Expanded(flex: 1, child: SizedBox()),
],
),
),
SizedBox(height: 10.h),
ExpansionTile(
tilePadding: EdgeInsets.only(right: 10.w, bottom: 0),

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,181 @@
import 'package:flutter/material.dart';
import 'package:marking_app/utils/index.dart';
/// : 线
class FlutterWaveLoading extends StatefulWidget {
final double width;
final double height;
final double waveHeight;
final Color color;
final double strokeWidth;
final double progress;
final double factor;
final int secondAlpha;
final double borderRadius;
final bool isOval;
final int milliseconds;
FlutterWaveLoading(
{this.width = 100,
this.height = 100 / 0.618,
this.factor = 1,
this.waveHeight = 5,
this.progress = 0.5,
this.color = Colors.green,
this.strokeWidth = 3,
this.secondAlpha = 88,
this.isOval = false,
this.milliseconds = 3000,
this.borderRadius = 20});
@override
_FlutterWaveLoadingState createState() => _FlutterWaveLoadingState();
}
class _FlutterWaveLoadingState extends State<FlutterWaveLoading> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation _anim;
@override
void initState() {
_controller = AnimationController(vsync: this, duration: Duration(milliseconds: widget.milliseconds))
..addListener(toSetState)
..repeat();
_anim = CurveTween(curve: Curves.linear).animate(_controller);
super.initState();
}
void toSetState() => toUpState(setState, () {}, mounted);
@override
void dispose() {
try {
_controller
..removeListener(toSetState)
..dispose();
} catch (e) {
print('报错了.........');
print(e);
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return UnconstrainedBox(
child: Container(
width: widget.width,
height: widget.height,
child: CustomPaint(
painter: BezierPainter(
factor: _anim.value,
waveHeight: widget.waveHeight,
progress: widget.progress,
color: widget.color,
strokeWidth: widget.strokeWidth,
secondAlpha: widget.secondAlpha,
isOval: widget.isOval,
borderRadius: widget.borderRadius),
),
),
);
}
}
class BezierPainter extends CustomPainter {
late Paint _mainPaint;
late Path _mainPath;
double waveWidth = 80;
late double wrapHeight;
final double waveHeight;
final Color color;
final double strokeWidth;
final double progress;
final double factor;
final int secondAlpha;
final double borderRadius;
final bool isOval;
BezierPainter(
{this.factor = 1,
this.waveHeight = 8,
this.progress = 0.5,
this.color = Colors.green,
this.strokeWidth = 3,
this.secondAlpha = 88,
this.isOval = false,
this.borderRadius = 20}) {
_mainPaint = Paint()
..color = Colors.yellow
..style = PaintingStyle.stroke
..strokeWidth = 2;
_mainPath = Path();
}
@override
void paint(Canvas canvas, Size size) {
// print(size);
waveWidth = size.width / 2;
wrapHeight = size.height;
Path path = Path();
if (!isOval) {
path.addRRect(RRect.fromRectXY(Offset(0, 0) & size, borderRadius, borderRadius));
canvas.clipPath(path);
//
// canvas.drawPath(
// path,
// _mainPaint
// ..strokeWidth = strokeWidth
// ..color = color);
}
if (isOval) {
path.addOval(Offset(0, 0) & size);
canvas.clipPath(path);
canvas.drawPath(
path,
_mainPaint
..strokeWidth = strokeWidth
..color = color);
}
canvas.translate(0, wrapHeight);
canvas.save();
canvas.translate(0, waveHeight);
canvas.save();
canvas.translate(-4 * waveWidth + 2 * waveWidth * factor, 0);
drawWave(canvas);
canvas.drawPath(
_mainPath,
_mainPaint
..style = PaintingStyle.fill
..color = color.withAlpha(88));
canvas.restore();
canvas.translate(-4 * waveWidth + 2 * waveWidth * factor * 2, 0);
drawWave(canvas);
canvas.drawPath(
_mainPath,
_mainPaint
..style = PaintingStyle.fill
..color = color);
canvas.restore();
}
void drawWave(Canvas canvas) {
_mainPath.moveTo(0, 0);
_mainPath.relativeLineTo(0, -wrapHeight * progress);
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, -waveHeight * 2, waveWidth, 0);
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0);
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, -waveHeight * 2, waveWidth, 0);
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0);
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, -waveHeight * 2, waveWidth, 0);
_mainPath.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0);
_mainPath.relativeLineTo(0, wrapHeight);
_mainPath.relativeLineTo(-waveWidth * 3 * 2.0, 0);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}

View File

@ -17,6 +17,8 @@ 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_note_taking_trajectory.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_model.dart';
import 'package:marking_app/common/model/job/job_review_submission.dart';
import 'package:marking_app/common/model/job/job_task_item.dart';
import 'package:marking_app/common/model/job/marking_text_question_job.dart';
@ -247,4 +249,12 @@ abstract class RestClient {
// =>
@the_retrofit.POST("${RequestConfig.hwProxyKeywords}/api/Marking/auto")
Future<BaseStructureResult<bool>> toJobOneClickReview(@the_retrofit.Field() int taskId);
// =>
@the_retrofit.GET("/api/jobs/job-report")
Future<BaseStructureResult<JobReportModel>> getJobReport(@the_retrofit.Queries() Map<String, dynamic> params);
// =>
@the_retrofit.GET("/api/jobs/student-job-for-class")
Future<BaseStructureResult<List<JobReportJoinClass>>> getJobReportJoinClasses(@the_retrofit.Query("jobId") int jobId);
}