no message

This commit is contained in:
1147192855@qq.com 2024-06-21 18:48:14 +08:00
parent 47eb2ad17c
commit e73d1ddaab
12 changed files with 1536 additions and 84 deletions

View File

@ -4,7 +4,9 @@ import 'package:dio/dio.dart' hide Headers;
import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_param.dart';
import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_result.dart';
import 'package:making_school_asignment_app/common/job/marking_models/favor_param.dart';
import 'package:making_school_asignment_app/common/job/marking_models/original_manuscript_handwriting_params.dart';
import 'package:making_school_asignment_app/common/job/marking_models/review_submission_params.dart';
import 'package:making_school_asignment_app/page/home_page/children/homework_review/components/job_handwriting.dart';
import 'package:retrofit/retrofit.dart';
import 'package:making_school_asignment_app/common/job/annotated_class.dart';
import 'package:making_school_asignment_app/common/job/class_item.dart';
@ -126,12 +128,11 @@ abstract class RetrofitClient {
@POST("/api/hms/Annotate/AnnotateSubmit")
Future reviewSubmission(@Body() ReviewSubmissionParams param);
// 稿
@GET("/api/hms/HmsReport/GetStudentPaperHandwriting")
Future<JobHandwriting> getOriginalManuscriptHandwriting(@Queries() OriginalManuscriptHandwritingParams param);
// OSS key
@GET("/api/infra/Oss/GetPresignedUri")
Future getOssPresignedUri(@Query('key') String key);
// OSS
@PUT('{theUrl}')
@Headers(<String, dynamic>{'Content-Type': ''})
Future<void> uploadImag(@Path() String theUrl, @Part() File file);
}

View File

@ -0,0 +1,35 @@
// 稿
import 'package:json_annotation/json_annotation.dart';
part 'original_manuscript_handwriting_params.g.dart';
@JsonSerializable(checked: true, includeIfNull: false)
class OriginalManuscriptHandwritingParams extends Object {
@JsonKey(name: 'homeworkId')
String homeworkId;
@JsonKey(name: 'studentId')
int studentId;
@JsonKey(name: 'templateId')
int? templateId;
@JsonKey(name: 'questionNo')
int? questionNo;
@JsonKey(name: 'pageNum')
int? pageNum;
OriginalManuscriptHandwritingParams({
required this.homeworkId,
required this.studentId,
this.templateId,
this.pageNum,
this.questionNo,
});
factory OriginalManuscriptHandwritingParams.fromJson(Map<String, dynamic> srcJson) => _$OriginalManuscriptHandwritingParamsFromJson(srcJson);
Map<String, dynamic> toJson() => _$OriginalManuscriptHandwritingParamsToJson(this);
}

View File

@ -0,0 +1,65 @@
import 'package:json_annotation/json_annotation.dart';
part 'my_time_util.g.dart';
//
TimeUnitModel? convertMilliseconds(int milliseconds) {
try {
int hours = milliseconds ~/ (1000 * 60 * 60);
int minutes = (milliseconds % (1000 * 60 * 60)) ~/ (1000 * 60);
int seconds = (milliseconds % (1000 * 60)) ~/ 1000;
if ((milliseconds % 1000) > 500) seconds += 1;
return TimeUnitModel(hours, minutes, seconds);
} catch (e) {
print('时间转换报错');
}
return null;
}
//
TimeUnitModel? convertSeconds(int totalSeconds) {
try {
int hours = totalSeconds ~/ 3600; // 3600
int remainingSeconds = totalSeconds % 3600; // 3600
int minutes = remainingSeconds ~/ 60; // 60
int seconds = remainingSeconds % 60; // 60
return TimeUnitModel(hours, minutes, seconds);
} catch (e) {
print('时间转换报错');
}
return null;
}
@JsonSerializable()
class TimeUnitModel extends Object {
int hours;
int minutes;
int seconds;
TimeUnitModel(this.hours, this.minutes, this.seconds);
factory TimeUnitModel.fromJson(Map<String, dynamic> srcJson) => _$TimeUnitModelFromJson(srcJson);
Map<String, dynamic> toJson() => _$TimeUnitModelToJson(this);
@override
String toString() {
var timeStr = '';
if (hours > 0) {
timeStr += '${hours > 9 ? hours : '0' + hours.toString()} ';
}
if (minutes > 0) {
timeStr += '${minutes > 9 ? minutes : '0' + minutes.toString()}';
}
if (timeStr.length > 0) {
timeStr += ':${seconds > 9 ? seconds : '0' + seconds.toString()}';
} else {
timeStr += '00:${seconds > 9 ? seconds : '0' + seconds.toString()}';
}
return timeStr;
}
}

View File

@ -12,6 +12,7 @@ import 'package:making_school_asignment_app/common/config/colorUtils.dart';
// Text使用
Text quickText(text,
{double? size,
double? wordSpacing,
Color color = CommonColors.defaultColor,
TextAlign? align,
FontWeight? fontWeight,
@ -28,6 +29,7 @@ Text quickText(text,
fontSize: size,
color: color,
fontWeight: fontWeight,
wordSpacing: wordSpacing,
),
);
}

View File

@ -90,11 +90,42 @@ class _DropdownSwitchStudentsTypeState extends State<DropdownSwitchStudentsType>
value: sateData.value?.studentId,
underline: Container(),
isExpanded: true,
onTap: () {
print('数据..................');
},
items: sateData.value?.students.map((e) {
return DropdownMenuItem(value: e.id, child: quickText(e.name, color: const Color.fromRGBO(79, 79, 79, 1), size: 14.sp));
return DropdownMenuItem(
value: e.id,
child: Stack(
alignment: const FractionalOffset(0, 0.62),
children: [
Container(
padding: sateData.value?.studentId != e.id && e.isPriority ? EdgeInsets.only(left: 14.w) : null,
child: quickText(
e.name,
size: 14.sp,
color: const Color.fromRGBO(79, 79, 79, 1),
),
),
if (e.isPriority && sateData.value?.studentId != e.id)
Stack(
alignment: const FractionalOffset(0.52, 0.24),
children: [
Icon(
const IconData(0xe63d, fontFamily: "AlibabaIcon"),
size: 12.sp,
color: e.isPriority ? const Color.fromRGBO(76, 199, 147, 1) : const Color.fromRGBO(164, 164, 164, 1),
),
quickText('优先', size: 4.sp, color: Colors.white),
],
),
],
),
);
}).toList(),
hint: const Text('请选择学生'), //
onChanged: (value) {
print('1111111111');
if (logic.state.param.value.studentId == value) return;
logic.state.param.value.studentId = value;
logic.state.param.value = DoPaperDetailsParam.fromJson(logic.state.param.value.toJson());

View File

@ -0,0 +1,63 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:making_school_asignment_app/common/config/request_config.dart';
part 'job_handwriting.g.dart';
@JsonSerializable()
class JobHandwriting extends Object {
@JsonKey(name: 'lattices')
List<Lattices> lattices;
@JsonKey(name: 'paperPicture')
String paperPicture;
@JsonKey(name: 'pageNum')
int pageNum;
@JsonKey(name: 'pageCount')
int pageCount;
JobHandwriting(this.lattices, this.paperPicture, this.pageNum, this.pageCount);
factory JobHandwriting.fromJson(Map<String, dynamic> srcJson) => _$JobHandwritingFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobHandwritingToJson(this);
}
@JsonSerializable()
class Lattices extends Object {
//
@JsonKey(name: 'stroke')
int stroke;
@JsonKey(name: 'x')
double x;
@JsonKey(name: 'y')
double y;
@JsonKey(name: 'time')
int time;
@JsonKey(name: 'intervalTime')
int intervalTime;
@JsonKey(name: 'initialization')
bool initialization;
Lattices(this.stroke, this.x, this.y, this.time, [this.intervalTime = 0, this.initialization = false]);
factory Lattices.fromJson(Map<String, dynamic> srcJson) => _$LatticesFromJson(srcJson);
Map<String, dynamic> toJson() => _$LatticesToJson(this);
/**
*
* @param double scaleRatio
*/
void toInitialization(double scaleRatio) {
x = x * scaleRatio;
y = y * scaleRatio;
initialization = true;
}
}

View File

@ -0,0 +1,969 @@
import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:get/get.dart';
import 'package:making_school_asignment_app/common/job/marking_models/do_test_questions_image_info.dart';
import 'package:making_school_asignment_app/common/job/marking_models/original_manuscript_handwriting_params.dart';
import 'package:making_school_asignment_app/common/mixins/event_bus_mixin.dart';
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart';
import 'package:making_school_asignment_app/common/utils/cached_network_img.dart';
import 'package:making_school_asignment_app/common/utils/my_time_util.dart';
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
import 'package:making_school_asignment_app/common/utils/utils.dart';
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
import 'package:making_school_asignment_app/page/home_page/children/homework_review/components/job_handwriting.dart';
import 'configuration_files/logic.dart';
import 'configuration_files/states.dart';
part 'answer_handwriting_view.g.dart';
///
class AnswerHandwriting extends Dialog {
final String homeworkId;
final int studentId;
final int? templateId;
final int? pageNum;
final int? questionNo;
final Function closeCall;
AnswerHandwriting(
{super.key, required this.homeworkId, required this.studentId, required this.closeCall, this.templateId, this.pageNum, this.questionNo}) {
Get.find<HandwritingLogic>().params.value = OriginalManuscriptHandwritingParams(
homeworkId: homeworkId,
studentId: studentId,
templateId: templateId,
pageNum: pageNum,
questionNo: questionNo,
);
}
final _handwritingLogic = Get.find<HandwritingLogic>();
@override
Widget build(BuildContext context) {
return Center(
child: Container(
height: ScreenUtil().screenHeight / 1.2,
width: ScreenUtil().screenWidth - (ScreenUtil().scaleWidth < 1.5 ? 40.r : 40.r),
alignment: Alignment.center,
child: AnswerHandwritingMainBox(
handwritingLogic: _handwritingLogic,
homeworkId: homeworkId,
templateId: templateId,
studentId: studentId,
pageNum: pageNum,
questionNo: questionNo,
closeCall: closeCall,
),
),
);
}
}
Future<void> showAnswerHandwriting(
BuildContext context, {
required String homeworkId,
required int studentId,
int? templateId,
int? pageNum,
int? questionNo,
}) async {
try {
backCall() {
Navigator.of(context).pop();
}
Get.put(HandwritingLogic(backCall));
await showDialog(
context: context,
builder: (BuildContext context) => AnswerHandwriting(
homeworkId: homeworkId,
templateId: templateId,
studentId: studentId,
pageNum: pageNum,
questionNo: questionNo,
closeCall: backCall,
),
);
} finally {
Get.delete<HandwritingLogic>();
}
}
//
class AnswerHandwritingMainBox extends HookWidget with EventBusMixin {
AnswerHandwritingMainBox({
required this.handwritingLogic,
required this.homeworkId,
required this.studentId,
required this.closeCall,
this.templateId,
this.pageNum,
this.questionNo,
super.key,
});
final HandwritingLogic handwritingLogic;
final String homeworkId;
final int? templateId;
final int studentId;
final int? pageNum;
final int? questionNo;
final Function closeCall;
@override
Widget build(BuildContext context) {
var _useStateModel = UseMainBoxState.use(homeworkId, studentId, pageNum, questionNo, templateId);
useValueChanged<JobHandwriting?, void>(_useStateModel.handwritingData.value, (_, __) {
var theData = _useStateModel.handwritingData.value;
_useStateModel.pageNum.value = theData?.pageNum;
_useStateModel.pageCount.value = theData?.pageCount ?? 0;
_useStateModel.playPause.value = false;
_useStateModel.constantFastSpeed.value = false;
// Future.delayed(Duration.zero, () {
// _useStateModel.handwritingKey.currentState?.ref.read(jobHandwritingDrawingTrajectoryProvider.notifier).setVal([]);
// });
// _useStateModel.handwritingDetail.value = _useStateModel.getHandwritingDetail(theData);
});
useValueChanged<int?, void>(_useStateModel.pageNum.value, (oldVal, __) {
if (oldVal != null && oldVal != _useStateModel.pageNum.value) {
_useStateModel.questionNo = null;
// _useStateModel.getData().catchError((e) => closeCall());
}
});
JobHandwriting? data = _useStateModel.handwritingData.value;
HandwritingInfo? dataDetail = _useStateModel.handwritingDetail.value;
// if (data == null || dataDetail == null) return Container();
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Stack(
alignment: const FractionalOffset(0, 0.5),
children: [
//
LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
return HandwritingDrawBox(
boxWidth: constraints.maxWidth,
boxHeight: constraints.maxHeight,
key: _useStateModel.handwritingKey,
);
}),
PageNumberBox(),
PreviousNutton(), //
NextPageButton(), //
],
),
),
$BottomPlaybar(handwritingLogic),
],
);
}
}
class UseMainBoxState with RequestToolMixin {
final String homeworkId;
final int studentId;
final int? templateId;
int? questionNo;
final ValueNotifier<int?> pageNum;
final ValueNotifier<int> pageCount;
final ValueNotifier<JobHandwriting?> handwritingData;
final ValueNotifier<HandwritingInfo?> handwritingDetail;
final ValueNotifier<bool> playPause; //
final ValueNotifier<bool> constantFastSpeed; //
GlobalKey<_HandwritingDrawBoxState> handwritingKey;
UseMainBoxState._({
required this.homeworkId,
required this.templateId,
required this.studentId,
required this.pageNum,
required this.handwritingData,
required this.questionNo,
required this.pageCount,
required this.playPause,
required this.constantFastSpeed,
required this.handwritingDetail,
required this.handwritingKey,
});
//
factory UseMainBoxState.use(String homeworkId, int studentId, [int? pageNum, int? questionNo, int? templateId]) {
return UseMainBoxState._(
homeworkId: homeworkId,
templateId: templateId,
studentId: studentId,
questionNo: questionNo,
pageNum: useState(pageNum),
handwritingData: useState(null),
handwritingDetail: useState(null),
pageCount: useState(0),
playPause: useState(false),
constantFastSpeed: useState(false),
handwritingKey: GlobalKey(),
);
}
}
///
class PreviousNutton extends StatelessWidget {
PreviousNutton({super.key});
final HandwritingLogic handwritingLogic = Get.find<HandwritingLogic>();
@override
Widget build(BuildContext context) {
return Obx(() {
if (handwritingLogic.resultData.value?.pageNum != null && handwritingLogic.resultData.value!.pageNum > 1) {
return Positioned(
left: 3.w,
child: FloatingActionButton(
heroTag: '点击前往上一题',
tooltip: '点击前往上一题',
focusColor: Theme.of(context).primaryColor,
backgroundColor: const Color.fromRGBO(24, 32, 32, 0.1),
elevation: 6.r,
onPressed: () => easyThrottle('answer_handwriting_previous', () {
var resultData = handwritingLogic.resultData.value;
var params = handwritingLogic.params.value;
if (resultData == null || params == null) return;
params.pageNum = resultData.pageNum - 1;
handwritingLogic.params.value = OriginalManuscriptHandwritingParams.fromJson(params.toJson());
// handwritingLogic.params.value = params;
}),
child: Icon(Icons.arrow_back_ios, color: Colors.white, size: 22.sp),
),
);
}
return const SizedBox();
});
}
}
///
class NextPageButton extends StatelessWidget {
final HandwritingLogic handwritingLogic = Get.find<HandwritingLogic>();
NextPageButton({super.key});
@override
Widget build(BuildContext context) {
return Obx(() {
if (handwritingLogic.resultData.value?.pageNum != null &&
handwritingLogic.resultData.value!.pageNum < handwritingLogic.resultData.value!.pageCount) {
return Positioned(
right: 3.w,
child: FloatingActionButton(
heroTag: '点击前往下一题',
tooltip: '点击前往下一题',
elevation: 6.r,
backgroundColor: const Color.fromRGBO(24, 32, 32, 0.1),
onPressed: () => easyThrottle('answer_handwriting_next', () {
var resultData = handwritingLogic.resultData.value;
var params = handwritingLogic.params.value;
if (resultData == null || params == null) return;
params.pageNum = resultData.pageNum + 1;
handwritingLogic.params.value = OriginalManuscriptHandwritingParams.fromJson(params.toJson());
}),
child: Icon(Icons.arrow_forward_ios, color: Colors.white, size: 22.sp),
),
);
}
return const SizedBox();
});
}
}
//
class HandwritingDrawBox extends StatefulWidget {
final double boxWidth;
final double boxHeight;
const HandwritingDrawBox({required this.boxWidth, required this.boxHeight, super.key});
@override
State<HandwritingDrawBox> createState() => _HandwritingDrawBoxState();
}
class _HandwritingDrawBoxState extends State<HandwritingDrawBox> with EventBusMixin {
HandwritingLogic handwritingLogic = Get.find<HandwritingLogic>(); //
ImageStream? imageStream; //
late ImageStreamListener theImageStreamListener; //
late ValueNotifier<List<GestureHandwritingRecording>> _vnHandWritings;
late ValueNotifier<List<GestureHandwritingRecording>> _vnPrimaryHandWritings;
late StreamSubscription showManuscriptStream;
late StreamSubscription executionDataStream;
List<List<GestureHandwritingRecording>> _packagedHandwritingDatas = [];
List<GestureHandwritingRecording> _packagedHandwritingDataAll = []; //
List<GestureHandwritingRecording> pendingData = []; //
List<Timer> timers = [];
int handwritingTime = 0;
int handwritingDuration = 0;
double speed = 2.0; //
@override
void initState() {
super.initState(); /* */
theImageStreamListener = ImageStreamListener((ImageInfo info, bool _) {
//
WidgetsBinding.instance.addPostFrameCallback((_) {
//
handwritingLogic.imagInfoModel.value = TestQuestionsImageInfo(
url: handwritingLogic.resultData.value!.paperPicture,
boxWidth: widget.boxWidth,
boxHeight: widget.boxHeight,
imageWidth: info.image.width.toDouble(),
imageHeight: info.image.height.toDouble(),
);
});
});
_vnHandWritings = ValueNotifier<List<GestureHandwritingRecording>>([]);
_vnPrimaryHandWritings = ValueNotifier<List<GestureHandwritingRecording>>(_packagedHandwritingDataAll);
handwritingLogic.toolbar.initialization.listen((e) {
//
if (e) {
_packagedHandwritingDatas = handwritingLogic.packagedHandwritingDatas.value;
_packagedHandwritingDataAll = handwritingLogic.packagedHandwritingDataAll.value;
} else {
_packagedHandwritingDatas = [];
_packagedHandwritingDataAll = [];
}
_vnPrimaryHandWritings.value = [..._packagedHandwritingDataAll]; //
// eventFire(model: JobHandwritingPlaybarBus);
});
showManuscriptStream = handwritingLogic.toolbar.showManuscript.listen((e) {
// 稿
if (e) {
// 稿
eventFire(model: JobHandwritingPlaybarBus(false)); //
_vnPrimaryHandWritings.value = [..._packagedHandwritingDataAll];
} else {
// 稿
_vnPrimaryHandWritings.value = [];
}
});
executionDataStream = handwritingLogic.toolbar.executionData.listen((e) {
print('555555555555555555555555555555');
_vnHandWritings.value = e;
});
eventOn(callback: (e) {
switch (e.runtimeType) {
case JobHandwritingRunTimeBus:
var _model = (e as JobHandwritingRunTimeBus);
var _runtime = _model.runTimeVal;
handwritingDuration = _model.totalVal;
handwritingTime = _runtime;
if (_runtime <= 0) {
pendingData.clear();
}
break;
case JobHandwritingDragProgressBarBus:
var _model = (e as JobHandwritingDragProgressBarBus);
dragProgressBarInitData(_model.changeVal, _model.totalVal);
break;
case JobHandwritingPlaybarBus:
//
var _val = e as JobHandwritingPlaybarBus;
if (_val.play) {
//
toGoPlay();
} else {
//
toGoPause(_val.recalculate);
}
break;
case PlaybackSpeedBus:
//
var _model = (e as PlaybackSpeedBus);
speed = _model.speed;
dragProgressBarInitData(handwritingDuration - handwritingTime, handwritingDuration);
break;
default:
}
});
}
@override
void dispose() {
imageStream?.removeListener(theImageStreamListener);
showManuscriptStream.cancel();
executionDataStream.cancel();
eventCancel();
super.dispose();
}
//
Future<void> toGoPause(bool recalculate) async {
timers.forEach((e) {
if (e.isActive) e.cancel();
});
timers = [];
// -=
if (recalculate && pendingData.isNotEmpty && handwritingTime > 0 && (handwritingDuration - handwritingTime > 0)) {
//
pendingData = pendingData.map((e) {
return GestureHandwritingRecording(
stroke: e.stroke,
data: e.data,
usageTime: e.usageTime,
intervalTime: e.intervalTime - (handwritingDuration - handwritingTime) * 1000,
);
}).toList();
}
}
///
Future<void> toGoPlay() async {
try {
var executableData = _packagedHandwritingDataAll;
if (pendingData.isNotEmpty) {
//
executableData = pendingData;
} else {
//
pendingData.addAll(_packagedHandwritingDataAll);
handwritingLogic.toolbar.executionData.value = []; //
}
handwritingLogic.toolbar.showManuscript.value = false;
executableData.forEach((e) {
var ter = Timer(Duration(milliseconds: e.intervalTime ~/ speed), () => zhixinCall(e));
timers.add(ter);
});
} catch (e) {
print('播放报错:$e');
}
}
Future<void> zhixinCall(GestureHandwritingRecording e) async {
if (mounted) {
List<GestureHandwritingRecording> trajectorys = handwritingLogic.toolbar.executionData.value..add(e);
handwritingLogic.toolbar.executionData.value = List.from(trajectorys);
pendingData.remove(e); //
}
}
///
/// @param startTime
Future<void> dragProgressBarInitData(int startTime, int totalDuration) async {
eventFire(model: JobHandwritingPlaybarBus(false, false));
timers.forEach((e) {
if (e.isActive) e.cancel();
});
timers = [];
pendingData.clear();
if (startTime == 0) {
handwritingLogic.toolbar.executionData.value = []; //
pendingData.addAll(_packagedHandwritingDataAll);
} else {
//
startTime = startTime * 1000; //
List<GestureHandwritingRecording> executeImmediately = []; //
List<GestureHandwritingRecording> waitingExecution = []; //
for (var i = 0; i < _packagedHandwritingDataAll.length; i++) {
var item = _packagedHandwritingDataAll[i];
if (item.intervalTime < startTime) {
//
executeImmediately.add(item);
} else {
var intervalTime = item.intervalTime - startTime;
//
waitingExecution.add(GestureHandwritingRecording(
stroke: item.stroke,
data: item.data,
usageTime: item.usageTime,
intervalTime: intervalTime,
));
}
}
pendingData = waitingExecution;
handwritingLogic.toolbar.executionData.value = executeImmediately;
}
eventFire(model: JobHandwritingPlaybarBus(true));
}
@override
Widget build(BuildContext context) {
return Obx(() {
print('进入了....................');
var paperPicture = handwritingLogic.resultData.value?.paperPicture;
if (paperPicture == null) return const SizedBox();
print('显示原稿:${handwritingLogic.toolbar.showManuscript.value} 数据:${_vnPrimaryHandWritings.value.length}');
return RepaintBoundary(
child: CustomPaint(
foregroundPainter: HandWritingDrawingPainter(
ctrl: handwritingLogic.toolbar.showManuscript.value ? _vnPrimaryHandWritings : _vnHandWritings,
),
child: $TheCachedNetworkImage(
imageUrl: paperPicture,
(context, imageProvider) {
Image imageWidget = Image(image: imageProvider, fit: BoxFit.contain);
if (handwritingLogic.imagInfoModel.value == null) {
imageStream?.removeListener(theImageStreamListener);
imageStream = imageWidget.image.resolve(const ImageConfiguration());
imageStream?.addListener(theImageStreamListener);
}
return imageWidget;
},
),
),
);
});
}
}
class HandWritingDrawingPainter extends CustomPainter {
final ValueNotifier<List<GestureHandwritingRecording>> ctrl;
HandWritingDrawingPainter({required this.ctrl}) : super(repaint: ctrl);
//[]
final Paint paintBrush = Paint()
//
..color = Colors.black
//
..strokeCap = StrokeCap.round
//齿
..isAntiAlias = true
//
// ..style = PaintingStyle.fill
//
..style = PaintingStyle.stroke
..strokeWidth = 0.5.r;
@override
void paint(Canvas canvas, Size size) {
// canvas.drawPoints(PointMode.points, thePoints, paintBrush);
canvas.save();
var points = ctrl.value;
var _length = points.length;
for (int i = 0; i < _length; i++) {
GestureHandwritingRecording item = points[i];
GestureHandwritingRecording? nextItem = i + 1 < _length ? points[i + 1] : null;
Offset offsetData = item.data;
Offset? nextOffsetData = nextItem?.data;
if (nextOffsetData != null && item.stroke == nextItem?.stroke) {
canvas.drawLine(offsetData, nextOffsetData, paintBrush);
}
}
canvas.restore();
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
if (oldDelegate is HandWritingDrawingPainter) {
var repaint = ctrl.value.length != oldDelegate.ctrl.value.length || oldDelegate.ctrl.value != ctrl.value;
print('调用是否绘制:$repaint');
return repaint;
}
return true; // oldDelegate MyCustomPainter
}
}
//
class PageNumberBox extends StatelessWidget {
PageNumberBox({super.key});
final HandwritingLogic handwritingLogic = Get.find<HandwritingLogic>(); //
@override
Widget build(BuildContext context) {
return Positioned(
top: 6.h,
right: 4.w,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.h),
decoration: BoxDecoration(
color: const Color.fromRGBO(0, 0, 0, 0.47),
borderRadius: BorderRadius.circular(5.r),
),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Obx(() {
return quickText('${handwritingLogic.resultData.value?.pageNum}', color: Colors.white, size: 11.sp, align: TextAlign.end);
}),
quickText('/', color: Colors.white, size: 10.sp, align: TextAlign.end),
Obx(() {
return quickText('${handwritingLogic.resultData.value?.pageCount}', color: Colors.white, size: 8.sp, align: TextAlign.end);
}),
],
)),
);
}
}
@hwidget
Widget $bottomPlaybar(BuildContext context, HandwritingLogic handwritingLogic) {
var timeConsuming = useState(0);
var handwritingInfo = useState<HandwritingInfo?>(null);
var usePlaybar = UseBottomPlaybar.use(timeConsuming.value);
useValueChanged<int, void>(timeConsuming.value, (_, __) {
usePlaybar.playTimingSuspend();
usePlaybar.playPause.value = false;
var seds = timeConsuming.value ~/ 1000;
if ((timeConsuming.value % 1000) > 500) seds += 1;
usePlaybar.handwritingDuration.value = seds;
usePlaybar.constantFastSpeed.value = PlaybackSpeed.DOUBLE_SPEED;
});
useValueChanged<int, void>(usePlaybar.handwritingDuration.value, (_, __) {
usePlaybar.useTime.value = usePlaybar.handwritingDuration.value;
});
//
useValueChanged<PlaybackSpeed, void>(usePlaybar.constantFastSpeed.value, (_, __) {
usePlaybar.eventFire(model: PlaybackSpeedBus(usePlaybar.constantFastSpeed.value.speed));
//
usePlaybar.playTimingSuspend();
usePlaybar.playTimingStarts();
});
//
useValueChanged<int, void>(usePlaybar.useTime.value, (_, __) {
var _runtime = usePlaybar.useTime.value;
if (_runtime <= 0 || usePlaybar.handwritingDuration.value == _runtime) {
Future.delayed(Duration.zero, () => (usePlaybar.playPause.value = false)); //
}
usePlaybar.eventFire(model: JobHandwritingRunTimeBus(_runtime, usePlaybar.handwritingDuration.value));
});
useEffect(() {
//
var initialization = handwritingLogic.toolbar.initialization.listen((e) {
usePlaybar.handWritingReady.value = e;
});
var handwritingInfoStream = handwritingLogic.handwritingInfo.listen((e) {
//
if (e == null) return;
handwritingInfo.value = e;
timeConsuming.value = e.timeConsuming;
});
usePlaybar.eventOn(callback: (e) {
switch (e.runtimeType) {
case JobHandwritingPlaybarBus:
//
var _val = e as JobHandwritingPlaybarBus;
if (_val.play) {
//
usePlaybar.playTimingStarts();
if (!usePlaybar.playPause.value) usePlaybar.playPause.value = true;
} else {
//
usePlaybar.playTimingSuspend();
if (usePlaybar.playPause.value) usePlaybar.playPause.value = false;
}
break;
case JobHandwritingGetReadyBus:
//
Future.delayed(Duration.zero, () => (usePlaybar.handWritingReady.value = true));
break;
default:
}
});
return () {
try {
initialization.cancel();
usePlaybar.eventCancel();
handwritingInfoStream.cancel();
usePlaybar.timer.value?.cancel();
} catch (e) {
print(e);
}
};
}, []);
return Container(
height: 62.h,
padding: EdgeInsets.symmetric(horizontal: 10.w),
alignment: Alignment.center,
color: Color.fromRGBO(0, 0, 0, 0.4),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (usePlaybar.handWritingReady.value)
InkWell(
onTap: () => easyThrottle('job_handwriting_play_pause', () {
if (usePlaybar.handwritingDuration.value == 0) return ToastUtils.showInfo('没有笔迹');
usePlaybar.playPause.value = !usePlaybar.playPause.value;
usePlaybar.eventFire(model: JobHandwritingPlaybarBus(usePlaybar.playPause.value));
}),
child: Icon(
!usePlaybar.playPause.value ? Icons.play_circle_outline : Icons.pause_circle_outline,
color: Colors.white,
size: 28.r,
),
)
else
SpinKitPouringHourGlassRefined(size: 40.sp, color: Colors.white),
SizedBox(width: 6.w),
Expanded(
child: LayoutBuilder(builder: (context, constraints) {
final double containerWidth = constraints.maxWidth; //
var unitScale = containerWidth / timeConsuming.value; //
var pauseIntervalsLength = handwritingInfo.value?.pauseInterval.length ?? 0;
List<Widget> pauseTickMarks = handwritingInfo.value?.pauseInterval.asMap().keys.map((e) {
bool isLast = e == pauseIntervalsLength - 1;
bool isFirst = e == 0;
var item = handwritingInfo.value!.pauseInterval[e];
return Positioned(
top: 0,
left: unitScale * item.startTime,
child: Container(
width: unitScale * (item.apart ?? 0),
height: 10.h,
decoration: BoxDecoration(
color: Color.fromRGBO(202, 201, 201, 1),
borderRadius: isFirst
? BorderRadius.only(topLeft: Radius.circular(8.r), bottomLeft: Radius.circular(10.r))
: (isLast ? BorderRadius.only(topRight: Radius.circular(8.r), bottomRight: Radius.circular(10.r)) : null),
),
),
);
}).toList() ??
[];
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Stack(
children: [
Container(
height: 10.h,
width: containerWidth,
decoration: BoxDecoration(
// color: Color.fromRGBO(146, 146, 146, 1),
color: Colors.white,
borderRadius: BorderRadius.circular(50.r),
),
),
...pauseTickMarks,
Container(
height: 10.h,
width: containerWidth,
// color: Theme.of(context).primaryColor,
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: 10.h, //
trackShape: RoundedRectSliderTrackShape(), //
activeTrackColor: Theme.of(context).primaryColor, //
inactiveTrackColor: Colors.transparent, //
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 0, disabledThumbRadius: 0),
thumbColor: Colors.white, //
overlayShape: RoundSliderOverlayShape(overlayRadius: 0),
overlayColor: Colors.black54, //
// valueIndicatorShape: PaddleSliderValueIndicatorShape(), //
),
child: Slider(
value: (usePlaybar.handwritingDuration.value - usePlaybar.useTime.value).toDouble(),
min: 0.0,
max: usePlaybar.handwritingDuration.value.toDouble(),
inactiveColor: Colors.transparent,
onChangeEnd: (value) {
if (!usePlaybar.handWritingReady.value) return;
usePlaybar.playTimingSuspend(); //
usePlaybar.eventFire(model: JobHandwritingDragProgressBarBus(value.toInt(), usePlaybar.handwritingDuration.value));
usePlaybar.useTime.value = usePlaybar.handwritingDuration.value - value.toInt();
},
onChanged: (double value) {
if (!usePlaybar.handWritingReady.value) return;
usePlaybar.useTime.value = usePlaybar.handwritingDuration.value - value.toInt();
},
),
),
),
],
),
SizedBox(height: 8.h),
SizedBox(
width: containerWidth,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
quickText('累计停顿:${handwritingInfo.value?.pauseCount ?? 0}', color: Colors.white, size: 7.sp),
quickText(convertSeconds(usePlaybar.useTime.value)?.toString() ?? '', color: Colors.white, size: 7.sp),
],
),
)
],
);
}),
),
SizedBox(width: 16.w),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
onTap: () => easyThrottle('job_handwriting_speed', () {
var theIndex = PlaybackSpeed.values.indexOf(usePlaybar.constantFastSpeed.value);
if (theIndex == PlaybackSpeed.values.length - 1) {
theIndex = -1;
}
usePlaybar.constantFastSpeed.value = PlaybackSpeed.values[theIndex + 1];
}, duration: Duration(milliseconds: 500)),
child: Container(
// alignment: Alignment.,
padding: EdgeInsets.symmetric(horizontal: 3.w, vertical: 1.5.h),
decoration: BoxDecoration(color: Color.fromRGBO(182, 197, 250, 1), borderRadius: BorderRadius.circular(4.r)),
child: quickText(
'${usePlaybar.constantFastSpeed.value.name}',
color: Color.fromRGBO(79, 114, 244, 1),
size: 8.sp,
align: TextAlign.center,
),
),
),
SizedBox(height: 7.h),
StudentManuscriptBtn(handwritingLogic),
],
),
],
),
);
}
// 稿
class StudentManuscriptBtn extends StatelessWidget {
final HandwritingLogic handwritingLogic;
const StudentManuscriptBtn(this.handwritingLogic, {super.key});
@override
Widget build(BuildContext context) {
return Obx(() {
print('显示原噶:${handwritingLogic.toolbar.showManuscript.value}');
return InkWell(
onTap: () => easyThrottle('job_handwriting_udent_manuscript', () {
var showManuscript = handwritingLogic.toolbar.showManuscript.value;
handwritingLogic.toolbar.showManuscript.value = !showManuscript;
}),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 3.w, vertical: 1.5.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: handwritingLogic.toolbar.showManuscript.value ? Theme.of(context).primaryColor : Colors.grey,
),
child: quickText('学生原稿', color: Colors.white, size: 8.sp, align: TextAlign.center),
),
);
});
}
}
class SysjTime extends StatefulWidget {
const SysjTime({super.key});
@override
State<SysjTime> createState() => _SysjTimeState();
}
class _SysjTimeState extends State<SysjTime> with EventBusMixin<JobHandwritingRunTimeBus> {
int useTime = 0;
@override
void initState() {
super.initState();
// eventOn(callback: (JobHandwritingRunTimeBus e) {
// useTime = e.runTimeVal;
// toUpState(setState, () {}, mounted);
// });
}
@override
void dispose() {
eventCancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return quickText(convertSeconds(useTime)?.toString() ?? '', color: Colors.white, size: 7.sp);
}
}
class UseBottomPlaybar with EventBusMixin {
final ValueNotifier<int> handwritingDuration; //
final ValueNotifier<bool> playPause; //
final ValueNotifier<PlaybackSpeed> constantFastSpeed; //
final ValueNotifier<bool> handWritingReady;
final ValueNotifier<int> useTime; //
final ValueNotifier<Timer?> timer;
UseBottomPlaybar._(
{required this.handWritingReady,
required this.handwritingDuration,
required this.playPause,
required this.constantFastSpeed,
required this.useTime,
required this.timer});
//
factory UseBottomPlaybar.use(int milliseconds) {
int handwritingDuration = milliseconds ~/ 1000;
if ((milliseconds % 1000) > 500) handwritingDuration += 1;
return UseBottomPlaybar._(
playPause: useState(false),
constantFastSpeed: useState(PlaybackSpeed.DOUBLE_SPEED), //
useTime: useState(handwritingDuration),
timer: useState(null),
handwritingDuration: useState(handwritingDuration),
handWritingReady: useState(false),
);
}
///
void playTimingStarts() {
if (useTime.value > 0) {
timer.value?.cancel();
timer.value = Timer.periodic(Duration(milliseconds: 1000 ~/ constantFastSpeed.value.speed), (theTime) {
useTime.value -= 1;
if (useTime.value < 0) {
theTime.cancel();
timer.value?.cancel();
timer.value = null;
useTime.value = handwritingDuration.value;
}
});
}
}
///
void playTimingSuspend() {
timer.value?.cancel();
timer.value = null;
}
}

View File

@ -0,0 +1,171 @@
//
import 'dart:ui';
import 'package:get/get.dart';
import 'package:making_school_asignment_app/common/job/marking_models/do_test_questions_image_info.dart';
import 'package:making_school_asignment_app/common/job/marking_models/original_manuscript_handwriting_params.dart';
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
import 'package:making_school_asignment_app/page/home_page/children/homework_review/components/job_handwriting.dart';
import 'package:making_school_asignment_app/page/home_page/children/homework_review/components/original_manuscript_handwriting/configuration_files/states.dart';
class HandwritingLogic extends GetxController with RequestToolMixin {
Rx<JobHandwriting?> resultData = Rx<JobHandwriting?>(null); //
Rx<HandwritingInfo?> handwritingInfo = Rx<HandwritingInfo?>(null); //
Rx<List<List<GestureHandwritingRecording>>> packagedHandwritingDatas = Rx<List<List<GestureHandwritingRecording>>>([]);
Rx<List<GestureHandwritingRecording>> packagedHandwritingDataAll = Rx<List<GestureHandwritingRecording>>([]); //
Rx<OriginalManuscriptHandwritingParams?> params = Rx<OriginalManuscriptHandwritingParams?>(null); //
Rx<TestQuestionsImageInfo?> imagInfoModel = Rx<TestQuestionsImageInfo?>(null); //
late ToolbarControl toolbar;
final Function backCall;
HandwritingLogic(this.backCall);
@override
void onInit() {
toolbar = ToolbarControl(
showManuscript: Rx<bool>(false), //
initialization: Rx<bool>(false), //
executionData: Rx<List<GestureHandwritingRecording>>([]), //
);
ever(params, (callback) => getData());
ever(imagInfoModel, (callback) {
//
handwritingInfo.value = getHandwritingDetail(resultData.value);
getCalculatedSize();
});
super.onInit();
}
Future<void> getData() async {
if (params.value == null) return;
try {
ToastUtils.showLoading();
toolbar.initialization.value = false;
imagInfoModel.value = null;
var res = await getClient().getOriginalManuscriptHandwriting(params.value!);
resultData.value = res;
} catch (e) {
ToastUtils.showError('获取笔迹数据报错,请重试');
backCall();
} finally {
ToastUtils.dismiss();
}
}
//
Future<void> getCalculatedSize() async {
if (imagInfoModel.value == null || handwritingInfo.value == null) return;
Map<int, List<Lattices>> mapData = handwritingInfo.value!.strokeMap;
double scaleRatio = imagInfoModel.value!.scaleRatio;
if (mapData.isNotEmpty) {
List<int> keys = mapData.keys.toList();
List<List<GestureHandwritingRecording>> _packagedHandwritingDatas = [];
List<GestureHandwritingRecording> _packagedHandwritingDataAll = [];
for (var i = 0; i < keys.length; i++) {
List<GestureHandwritingRecording> newTrajectoryData = mapData[keys[i]]!.map((e) {
double theX = e.x;
double theY = e.y;
if (!e.initialization) {
//
e.toInitialization(scaleRatio);
theX = e.x;
theY = e.y;
}
return GestureHandwritingRecording(
data: Offset(theX, theY),
usageTime: e.time.toInt(),
intervalTime: e.intervalTime,
stroke: e.stroke,
);
}).toList();
newTrajectoryData.sort((a, b) => a.usageTime.compareTo(b.usageTime));
_packagedHandwritingDatas.add(newTrajectoryData);
_packagedHandwritingDataAll.addAll(newTrajectoryData);
}
packagedHandwritingDatas.value = _packagedHandwritingDatas; //
packagedHandwritingDataAll.value = _packagedHandwritingDataAll; //
toolbar.showManuscript.value = true; // 稿
toolbar.initialization.value = true; //
// Future.delayed(Duration.zero, () => eventFire(model: JobHandwritingGetReadyBus())); //
}
}
HandwritingInfo? getHandwritingDetail(JobHandwriting? theData) {
if (theData == null) return null;
//
// var lattices = Map<int, List<Lattices>>.fromIterable(
// theData.lattices,
// key: (key) => key.stroke,
// value: (value) {
// // return theData.lattices.where((item) => item.stroke == value.stroke).toList()..sort((a, b) => a.time.compareTo(b.time));
// return theData.lattices.where((item) => item.stroke == value.stroke).toList();
// },
// );
var lattices = <int, List<Lattices>>{};
var theLattices = theData.lattices;
for (var i = 0; i < theLattices.length; i++) {
Lattices item = theLattices[i];
if (!lattices.containsKey(item.stroke)) lattices[item.stroke] = [];
lattices[item.stroke]!.add(item); //
}
List<int> latticeKeys = lattices.keys.toList(); //
int timeConsuming = 0;
if (latticeKeys.isNotEmpty) {
//
List<Lattices>? firstAction = lattices[latticeKeys[0]];
List<Lattices>? lastAction = lattices[latticeKeys[latticeKeys.length - 1]];
int firstTime = 0;
int lastTime = 0;
if (firstAction?.isNotEmpty ?? false) {
//
firstTime = firstAction![0].time;
}
if (lastAction?.isNotEmpty ?? false) {
//
lastTime = lastAction![0].time;
}
timeConsuming = lastTime - firstTime;
}
var pauseCount = 0; //
List<PauseIntervalTime> pauseInterval = [];
for (var i = 0; i < latticeKeys.length; i++) {
var currentLattices = lattices[latticeKeys[i]]!; //
var prevLattices = i == 0 ? null : lattices[latticeKeys[i - 1]]!; //
for (var j = 0; j < currentLattices.length; j++) {
var intervalTime = 0;
var lattice = currentLattices[j];
if (j != 0) {
var prevItem = currentLattices[j - 1];
var adjacentSpacingTime = lattice.time - prevItem.time;
intervalTime = adjacentSpacingTime + prevItem.intervalTime;
if (adjacentSpacingTime > 5000) {
// 5
pauseCount++;
pauseInterval.add(PauseIntervalTime(startTime: prevItem.intervalTime, endTime: intervalTime));
}
} else {
if (i != 0 && prevLattices != null) {
var prevLatticeLastItem = prevLattices[prevLattices.length - 1];
var adjacentSpacingTime = lattice.time - prevLatticeLastItem.time;
intervalTime = adjacentSpacingTime + prevLatticeLastItem.intervalTime;
if (adjacentSpacingTime > 5000) {
// 5
pauseCount++;
pauseInterval.add(PauseIntervalTime(startTime: prevLatticeLastItem.intervalTime, endTime: intervalTime));
}
}
}
lattice.intervalTime = intervalTime;
}
}
return HandwritingInfo(pauseCount, timeConsuming, lattices, pauseInterval);
}
}

View File

@ -0,0 +1,110 @@
//
import 'dart:ui';
import 'package:get/get.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:making_school_asignment_app/page/home_page/children/homework_review/components/job_handwriting.dart';
part 'states.g.dart';
@JsonSerializable()
class HandwritingInfo extends Object {
int pauseCount; //
List<PauseIntervalTime> pauseInterval;
int timeConsuming; //
Map<int, List<Lattices>> strokeMap; //
HandwritingInfo(this.pauseCount, this.timeConsuming, this.strokeMap, this.pauseInterval);
factory HandwritingInfo.fromJson(Map<String, dynamic> srcJson) => _$HandwritingInfoFromJson(srcJson);
Map<String, dynamic> toJson() => _$HandwritingInfoToJson(this);
}
class ToolbarControl {
Rx<bool> showManuscript; // 稿
Rx<bool> initialization;
Rx<List<GestureHandwritingRecording>> executionData;
ToolbarControl({
required this.executionData,
required this.showManuscript,
required this.initialization,
});
}
//
enum PlaybackSpeed {
ORIGINAL_SPEED(name: '原速播放', speed: 1),
ONE_POINT_FIVE_SPEED(name: '1.5x播放', speed: 1.5),
DOUBLE_SPEED(name: '2.0x播放', speed: 2),
TRIPLE_SPEED(name: '3.0x播放', speed: 3),
FOUR_SPEED(name: '4.0x播放', speed: 4),
FIVE_SPEED(name: '5.0x播放', speed: 5),
SIX_SPEED(name: '6.0x播放', speed: 6);
const PlaybackSpeed({required this.name, required this.speed});
final double speed;
final String name;
}
@JsonSerializable()
class PauseIntervalTime extends Object {
int? apart;
int startTime;
int endTime;
PauseIntervalTime({required this.startTime, required this.endTime}) {
apart = endTime - startTime;
}
factory PauseIntervalTime.fromJson(Map<String, dynamic> srcJson) => _$PauseIntervalTimeFromJson(srcJson);
Map<String, dynamic> toJson() => _$PauseIntervalTimeToJson(this);
}
//
class JobHandwritingPlaybarBus {
bool play;
bool recalculate;
JobHandwritingPlaybarBus(this.play, [this.recalculate = true]);
}
// ()
class JobHandwritingGetReadyBus {
JobHandwritingGetReadyBus();
}
//
class JobHandwritingRunTimeBus {
int runTimeVal;
int totalVal;
JobHandwritingRunTimeBus(this.runTimeVal, this.totalVal);
}
//
class JobHandwritingDragProgressBarBus {
int changeVal;
int totalVal;
JobHandwritingDragProgressBarBus(this.changeVal, this.totalVal);
}
// /
class PlaybackSpeedBus {
double speed;
PlaybackSpeedBus(this.speed);
}
// (稿)
class GestureHandwritingRecording {
int stroke;
int usageTime; //
Offset data;
int intervalTime; //
GestureHandwritingRecording({
required this.stroke,
required this.data,
required this.usageTime,
required this.intervalTime,
});
}

View File

@ -1,12 +1,9 @@
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:get/get.dart';
import 'package:making_school_asignment_app/common/config/request_config.dart';
import 'package:making_school_asignment_app/common/job/marking_models/do_paper_bus.dart';
import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_param.dart';
import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_result.dart';
@ -52,7 +49,7 @@ class _QuestionPaperViewState extends State<QuestionPaperView> {
//
QuestionImageView(maxWidth, maxHeight, sateData, annotationState, logic),
//
Positioned(right: 3.w, bottom: 4.h, child: const $ContinueToReview(isFloatingAction: true)),
// Positioned(right: 3.w, bottom: 4.h, child: const $ContinueToReview(isFloatingAction: true)),
//
Positioned(
left: 2.w,
@ -126,6 +123,7 @@ class _QuestionPaperViewState extends State<QuestionPaperView> {
}
}
//
@swidget
Widget $totalSubmitCountView(BuildContext context, HomeworkReviewState sateData) {
return Obx(() {
@ -136,75 +134,86 @@ Widget $totalSubmitCountView(BuildContext context, HomeworkReviewState sateData)
right: 8.w,
child: InkWell(
onTap: () async {
// List<JobConcernedWithStudent>? students = await getStudents();
// if (students == null) return;
// students = students..sort((e, e1) => e.studentName.compareTo(e1.studentName));
// showModalBottomSheet(
// context: context,
// elevation: 10,
// backgroundColor: Colors.white,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.only(
// topLeft: Radius.circular(10.r),
// topRight: Radius.circular(10.r),
// ),
// ),
// builder: (BuildContext context) {
// return Padding(
// padding: EdgeInsets.symmetric(horizontal: 2.w),
// child: Column(
// children: [
// Container(
// margin: EdgeInsets.only(top: 14.h),
// child: quickText(
// '当前页未提交学生名单',
// size: 15.sp,
// fontWeight: FontWeight.bold,
// color: Color.fromRGBO(60, 60, 60, 1),
// ),
// ),
// SizedBox(height: 10.h),
// Expanded(
// child: ListView(
// padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 4.w),
// children: [
// Wrap(
// spacing: 6.0, // ()
// runSpacing: 4.0, //
// alignment: WrapAlignment.spaceAround, //沿
// children: students!.map((e) {
// return Chip(
// labelPadding: EdgeInsets.symmetric(vertical: 1.5.h, horizontal: 5.w),
// backgroundColor: Color.fromRGBO(239, 242, 255, 1),
// // avatar: CircleAvatar(
// // backgroundColor: Colors.white,
// // child: quickText(e.studentName.substring(0, 1),
// // size: 12.sp, color: Theme.of(context).primaryColor),
// // ),
// label: quickText(e.studentName, color: Color.fromRGBO(80, 94, 110, 1), size: 12.sp),
// );
// }).toList(),
// ),
// ],
// ),
// )
// ],
// ),
// );
// },
// );
var submitStudents = sateData.data.value?.students; //
showModalBottomSheet(
context: context,
elevation: 10,
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(10.r), topRight: Radius.circular(10.r))),
builder: (BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 2.w),
child: Column(
children: [
Container(
margin: EdgeInsets.only(top: 14.h),
child: quickText(
'${sateData.data.value!.templateIdKeyMap?[sateData.data.value!.templateId]}页未提交学生名单',
size: 15.sp,
fontWeight: FontWeight.bold,
color: const Color.fromRGBO(60, 60, 60, 1),
),
),
SizedBox(height: 10.h),
Expanded(
child: ListView(
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 4.w),
children: [
Wrap(
spacing: 7.2.w, // ()
runSpacing: 12.h, //
alignment: WrapAlignment.start, //沿
children: submitStudents!.map((e) {
return Stack(
alignment: const FractionalOffset(0.05, 0.09),
children: [
Container(
padding: EdgeInsets.only(top: 1.2.h, bottom: 1.5.h, left: 13.w, right: 5.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: const Color.fromRGBO(239, 242, 255, 1),
),
child: quickText(
e.name,
size: 12.sp,
wordSpacing: 2,
color: const Color.fromRGBO(80, 94, 110, 1),
),
),
Stack(
alignment: const FractionalOffset(0.52, 0.24),
children: [
Icon(
const IconData(0xe63d, fontFamily: "AlibabaIcon"),
size: 12.sp,
color: e.isPriority ? const Color.fromRGBO(76, 199, 147, 1) : const Color.fromRGBO(164, 164, 164, 1),
),
quickText('优先', size: 4.sp, color: Colors.white),
],
),
],
);
}).toList(),
),
],
),
)
],
),
);
},
);
},
child: Container(
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
quickText('已阅', color: const Color.fromRGBO(117, 117, 117, 1), size: 10.sp),
quickText(data.annotatedCount, color: const Color.fromRGBO(76, 199, 147, 1), size: 12.sp, fontWeight: FontWeight.bold),
quickText('/', color: const Color.fromRGBO(117, 117, 117, 1), size: 12.sp),
quickText(data.submitCount - data.annotatedCount, color: const Color.fromRGBO(117, 117, 117, 1), size: 10.sp),
],
),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
quickText('已阅', color: const Color.fromRGBO(117, 117, 117, 1), size: 10.sp),
quickText(data.annotatedCount, color: const Color.fromRGBO(76, 199, 147, 1), size: 12.sp, fontWeight: FontWeight.bold),
quickText('/', color: const Color.fromRGBO(117, 117, 117, 1), size: 12.sp),
quickText(data.submitCount - data.annotatedCount, color: const Color.fromRGBO(117, 117, 117, 1), size: 10.sp),
],
),
),
);

View File

@ -62,7 +62,6 @@ class _HomeworkReviewState extends State<HomeworkReview> {
const DropdownSwitchStudentsType(),
SizedBox(height: 1.h),
const Expanded(child: QuestionPaperView()),
const BottomAnnotationSwitch()
],
),

View File

@ -3,6 +3,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:making_school_asignment_app/common/utils/utils.dart';
import 'package:making_school_asignment_app/page/global_widget/ReturnToHomepage.dart';
import 'package:making_school_asignment_app/page/home_page/children/homework_review/components/original_manuscript_handwriting/answer_handwriting_view.dart';
import 'package:making_school_asignment_app/page/home_page/children/student_personal/widget/student_kg_table.dart';
import 'package:making_school_asignment_app/page/home_page/children/student_personal/widget/student_zg_table.dart';
import 'package:making_school_asignment_app/routes/app_pages.dart';
@ -74,11 +75,7 @@ class _StudentPersonalPageState extends State<StudentPersonalPage> {
width: 10.r,
),
InkWell(
onTap: () {
/* showAnswerHandwriting(context, jobId: widget.jobId, studentId: widget.studentId).then((value) {
ref.read(jobHandwritingDrawingTrajectoryProvider.notifier).setVal([]);
});*/
},
onTap: () => showAnswerHandwriting(context, homeworkId: state.homeworkId, studentId: state.studentId),
child: Container(
width: 93.r,
height: 28.r,