From 8ab319c32e03c04cd22c82304bfe3339cb849002 Mon Sep 17 00:00:00 2001 From: "1147192855@qq.com" <1147192855@qq.com> Date: Fri, 26 Apr 2024 18:08:46 +0800 Subject: [PATCH] no message --- .../homework_correction/do_papers_job.dart | 6 +- .../use_switch_student_and_type.dart | 2 +- .../lib/pages/homework_correction/index.dart | 11 +- .../widget/answer_handwriting.dart | 296 ++++++++++-------- 4 files changed, 180 insertions(+), 135 deletions(-) diff --git a/marking_app/lib/pages/homework_correction/do_papers_job.dart b/marking_app/lib/pages/homework_correction/do_papers_job.dart index 703ae3c..5291ed9 100644 --- a/marking_app/lib/pages/homework_correction/do_papers_job.dart +++ b/marking_app/lib/pages/homework_correction/do_papers_job.dart @@ -290,7 +290,11 @@ Widget $dropdownBoxSwitchStudentsOrTypeView(BuildContext context, {required Func var _currentTab = _useSwitchStudentAndType.currentTab.value; var _pageIndex = _currentTab?.pageIndex; if (_currentTab == null || _pageIndex == null) return; - _useSwitchStudentAndType.refreshQuestionTypeData(context, taskId: taskId, exitCallback: exitCallback, getNewData: false).then((value) { + + var theLastQuestion = _currentTab.finishCount + 1 == _currentTab.total; // 当前提交的题是最后一题 + _useSwitchStudentAndType + .refreshQuestionTypeData(context, taskId: taskId, exitCallback: exitCallback, getNewData: theLastQuestion) + .then((value) { var params = MarkingTextQuestionJobTabParamsBus(taskId, _pageIndex); if (_currentTab.finishCount < _currentTab.total) { if (_currentTab.finishCount + 1 == _currentTab.total) { diff --git a/marking_app/lib/pages/homework_correction/hooks/do_papers_job/use_switch_student_and_type.dart b/marking_app/lib/pages/homework_correction/hooks/do_papers_job/use_switch_student_and_type.dart index 392b01f..c3ee127 100644 --- a/marking_app/lib/pages/homework_correction/hooks/do_papers_job/use_switch_student_and_type.dart +++ b/marking_app/lib/pages/homework_correction/hooks/do_papers_job/use_switch_student_and_type.dart @@ -140,7 +140,7 @@ class UseSwitchStudentAndType with CommonMixin, EventBusMixin { return tabJob; } } - ToastUtils.showSuccess('最后一题提交成功'); + // ToastUtils.showSuccess('最后一题提交成功'); } return tabJob; } diff --git a/marking_app/lib/pages/homework_correction/index.dart b/marking_app/lib/pages/homework_correction/index.dart index b3314ad..31788e1 100644 --- a/marking_app/lib/pages/homework_correction/index.dart +++ b/marking_app/lib/pages/homework_correction/index.dart @@ -261,19 +261,10 @@ class _HomeworkCorrectionState extends ConsumerState ), ), ), - Expanded( - flex: 1, - 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), - ), - ), + Expanded(flex: 1, child: SizedBox()), ], ), ), - if (_tabIndex == 1) $CompletedJobConditionFilter( controller: _tabController2, diff --git a/marking_app/lib/pages/homework_correction/widget/answer_handwriting.dart b/marking_app/lib/pages/homework_correction/widget/answer_handwriting.dart index 289579a..75800ec 100644 --- a/marking_app/lib/pages/homework_correction/widget/answer_handwriting.dart +++ b/marking_app/lib/pages/homework_correction/widget/answer_handwriting.dart @@ -111,6 +111,7 @@ class AnswerHandwritingMainBox extends HookWidget { HandwritingInfo? _dataDetail = _useStateModel.handwritingDetail.value; if (_data == null || _dataDetail == null) return Container(); + return Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, @@ -209,7 +210,6 @@ class UseMainBoxState with CommonMixin { HandwritingInfo? getHandwritingDetail(JobHandwriting? theData) { if (theData == null) return null; - print('开始时间:${DateTime.now().millisecondsSinceEpoch}'); // 笔画分组 // var lattices = Map>.fromIterable( // theData.lattices, @@ -374,6 +374,9 @@ class _HandwritingDrawBoxState extends ConsumerState with Ev TestQuestionsImageInfo? imagInfoModel; // 试题图片数据 late ImageStreamListener theImageStreamListener; + late ValueNotifier> _vnHandWritings; + + late RemoveListener _jobHandwritingDrawingTrajectoryListener; // 批注关闭监听 List> _packagedHandwritingDatas = []; List _packagedHandwritingDataAll = []; List pendingData = []; // 待执行数据 @@ -384,7 +387,10 @@ class _HandwritingDrawBoxState extends ConsumerState with Ev @override void initState() { super.initState(); - + _vnHandWritings = ValueNotifier>([]); + _jobHandwritingDrawingTrajectoryListener = ref.read(jobHandwritingDrawingTrajectoryProvider.notifier).addListener((state) { + _vnHandWritings.value = state; + }, fireImmediately: false); eventOn(callback: (e) { switch (e.runtimeType) { case JobHandwritingRunTimeBus: @@ -440,6 +446,8 @@ class _HandwritingDrawBoxState extends ConsumerState with Ev timers.forEach((e) { if (e.isActive) e.cancel(); }); + _jobHandwritingDrawingTrajectoryListener(); + _vnHandWritings.dispose(); try { imageStream?.removeListener(theImageStreamListener); eventCancel(); @@ -471,7 +479,6 @@ class _HandwritingDrawBoxState extends ConsumerState with Ev /// @param startTime 起始时间 单位秒 Future dragProgressBarInitData(int startTime, int totalDuration) async { eventFire(model: JobHandwritingPlaybarBus(false, false)); - timers.forEach((e) { if (e.isActive) e.cancel(); }); @@ -486,10 +493,11 @@ class _HandwritingDrawBoxState extends ConsumerState with Ev startTime = startTime * 1000; // 转为毫秒 List executeImmediately = []; // 立即执行数据 List waitingExecution = []; // 等待执行数据 + for (var i = 0; i < _packagedHandwritingDataAll.length; i++) { var item = _packagedHandwritingDataAll[i]; - if (item.intervalTime <= startTime) { + if (item.intervalTime < startTime) { // 需要直接装配到直接打印的容器 executeImmediately.add(item); } else { @@ -499,7 +507,7 @@ class _HandwritingDrawBoxState extends ConsumerState with Ev stroke: item.stroke, data: item.data, usageTime: item.usageTime, - intervalTime: intervalTime < 0 ? 0 : intervalTime, + intervalTime: intervalTime, )); } } @@ -569,26 +577,29 @@ class _HandwritingDrawBoxState extends ConsumerState with Ev @override Widget build(BuildContext context) { - List points = ref.watch(jobHandwritingDrawingTrajectoryProvider); return Container( alignment: Alignment.center, - child: CustomPaint( - foregroundPainter: DrawingPainter(points: points), - // size: Size(ScreenUtil().screenWidth - 60.r, widget.boxHeight), - child: RepaintBoundary( - child: $TheCachedNetworkImage( - imageUrl: widget.image, - (context, imageProvider) { - Image imageWidget = Image(image: imageProvider, fit: BoxFit.contain); - if (imagInfoModel == null) { - imageStream?.removeListener(theImageStreamListener); - // 视图中展示图片的尺寸计算获取 - imageStream = imageWidget.image.resolve(ImageConfiguration()); - imageStream?.addListener(theImageStreamListener); - } + child: RepaintBoundary( + child: CustomPaint( + willChange: true, + isComplex: true, + foregroundPainter: HandWritingDrawingPainter(ctrl: _vnHandWritings), + // size: Size(ScreenUtil().screenWidth - 60.r, widget.boxHeight), + child: RepaintBoundary( + child: $TheCachedNetworkImage( + imageUrl: widget.image, + (context, imageProvider) { + Image imageWidget = Image(image: imageProvider, fit: BoxFit.contain); + if (imagInfoModel == null) { + imageStream?.removeListener(theImageStreamListener); + // 视图中展示图片的尺寸计算获取 + imageStream = imageWidget.image.resolve(ImageConfiguration()); + imageStream?.addListener(theImageStreamListener); + } - return imageWidget; - }, + return imageWidget; + }, + ), ), ), ), @@ -596,16 +607,9 @@ class _HandwritingDrawBoxState extends ConsumerState with Ev } } -class DrawingPainter extends CustomPainter { - List points; - - DrawingPainter({required this.points}) : super(); - - // Paint paintBrush = Paint() - // ..color = Colors.black - // ..strokeCap = StrokeCap.round - // ..strokeWidth = 0.5.sp; - +class HandWritingDrawingPainter extends CustomPainter { + final ValueNotifier> ctrl; + HandWritingDrawingPainter({required this.ctrl}) : super(repaint: ctrl); //[定义画笔] final Paint paintBrush = Paint() //画笔颜色 @@ -613,30 +617,43 @@ class DrawingPainter extends CustomPainter { //画笔笔触类型 ..strokeCap = StrokeCap.round //是否启动抗锯齿 - // ..isAntiAlias = true + ..isAntiAlias = true //绘画风格,默认为填充 // ..style = PaintingStyle.fill //画笔的宽度 - ..strokeWidth = 0.6.r; + ..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; + print('正在绘制 ${_length}'); for (int i = 0; i < _length; i++) { GestureHandwritingRecording item = points[i]; - GestureHandwritingRecording? nextItem = i + 1 >= _length ? null : points[i + 1]; - Offset? offsetData = item.data; + 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(DrawingPainter oldDelegate) => true; + 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 的实例,则总是重绘 + } } @swidget @@ -665,11 +682,13 @@ Widget $pageNumberBox(int pageNum, int totalNum) { @hwidget Widget $bottomPlaybar(BuildContext context, int timeConsuming, int pauseCount, List pauseIntervals) { var usePlaybar = UseBottomPlaybar.use(timeConsuming); - useValueChanged(timeConsuming, (_, __) { + usePlaybar.playTimingSuspend(); + usePlaybar.playPause.value = false; var seds = timeConsuming ~/ 1000; if ((timeConsuming % 1000) > 500) seds += 1; usePlaybar.handwritingDuration.value = seds; + usePlaybar.constantFastSpeed.value = PlaybackSpeed.ORIGINAL_SPEED; }); useValueChanged(usePlaybar.handwritingDuration.value, (_, __) { @@ -700,11 +719,11 @@ Widget $bottomPlaybar(BuildContext context, int timeConsuming, int pauseCount, L if (_val.play) { // 开始播放 usePlaybar.playTimingStarts(); - if (!usePlaybar.playPause.value) usePlaybar.playPause.value = true; + if (!usePlaybar.playPause.value) Future.delayed(Duration.zero, () => usePlaybar.playPause.value = true); } else { // 暂停播放 usePlaybar.playTimingSuspend(); - if (usePlaybar.playPause.value) usePlaybar.playPause.value = false; + if (usePlaybar.playPause.value) Future.delayed(Duration.zero, () => usePlaybar.playPause.value = false); } break; case JobHandwritingGetReadyBus: @@ -736,6 +755,8 @@ Widget $bottomPlaybar(BuildContext context, int timeConsuming, int pauseCount, L 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)); }), @@ -749,93 +770,96 @@ Widget $bottomPlaybar(BuildContext context, int timeConsuming, int pauseCount, L SpinKitPouringHourGlassRefined(size: 40.sp, color: Colors.white), SizedBox(width: 6.w), Expanded( - child: LayoutBuilder( - builder: (context, constraints) { - final double containerWidth = constraints.maxWidth; // 展示区域总宽度 - // print('总刻度:$timeConsuming,宽度:$containerWidth'); - // print('总时长:${pauseIntervals.map((e) => e.toJson()).toList()}'); - var unitScale = containerWidth / timeConsuming; // 单位刻度 - var pauseIntervalsLength = pauseIntervals.length; - List pauseTickMarks = pauseIntervals.asMap().keys.map((e) { - bool isLast = e == pauseIntervalsLength - 1; - bool isFirst = e == 0; - var item = pauseIntervals[e]; - return Positioned( - top: 0, - left: unitScale * item.startTime, - child: Container( - width: unitScale * (item.apart ?? 0), - height: 8.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(); + child: LayoutBuilder(builder: (context, constraints) { + final double containerWidth = constraints.maxWidth; // 展示区域总宽度 + var unitScale = containerWidth / timeConsuming; // 单位刻度 + var pauseIntervalsLength = pauseIntervals.length; - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Stack( - children: [ - Container( - height: 8.h, - width: containerWidth, - decoration: BoxDecoration( - // color: Color.fromRGBO(146, 146, 146, 1), - color: Colors.white, - borderRadius: BorderRadius.circular(50.r), - ), - ), - ...pauseTickMarks, - Container( - height: 8.h, - // color: Theme.of(context).primaryColor, - child: SliderTheme( - data: SliderTheme.of(context).copyWith( - trackHeight: 8.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) { - usePlaybar.playTimingSuspend(); // 暂停计时器得暂停 - usePlaybar.eventFire(model: JobHandwritingDragProgressBarBus(value.toInt(), usePlaybar.handwritingDuration.value)); - usePlaybar.useTime.value = usePlaybar.handwritingDuration.value - value.toInt(); - }, - onChanged: (double value) { - usePlaybar.useTime.value = usePlaybar.handwritingDuration.value - value.toInt(); - }, - ), - ), - ), - ], + List pauseTickMarks = pauseIntervals.asMap().keys.map((e) { + bool isLast = e == pauseIntervalsLength - 1; + bool isFirst = e == 0; + var item = pauseIntervals[e]; + return Positioned( + top: 0, + left: unitScale * item.startTime, + child: Container( + width: unitScale * (item.apart ?? 0), + height: 8.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), ), - SizedBox(height: 4.h), - Row( + ), + ); + }).toList(); + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Stack( + children: [ + Container( + height: 8.h, + width: containerWidth, + decoration: BoxDecoration( + // color: Color.fromRGBO(146, 146, 146, 1), + color: Colors.white, + borderRadius: BorderRadius.circular(50.r), + ), + ), + ...pauseTickMarks, + Container( + height: 8.h, + width: containerWidth, + // color: Theme.of(context).primaryColor, + child: SliderTheme( + data: SliderTheme.of(context).copyWith( + trackHeight: 8.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: 4.h), + SizedBox( + width: containerWidth, + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ quickText('累计停顿:$pauseCount次', color: Colors.white, size: 7.sp), quickText(convertSeconds(usePlaybar.useTime.value)?.toString() ?? '', color: Colors.white, size: 7.sp), ], - ) - ], - ); - }, - ), + ), + ) + ], + ); + }), ), SizedBox(width: 16.w), InkWell( @@ -863,9 +887,34 @@ Widget $bottomPlaybar(BuildContext context, int timeConsuming, int pauseCount, L ); } -@swidget -Widget $pauseTickMark() { - return Container(); +class SysjTime extends StatefulWidget { + const SysjTime({super.key}); + + @override + State createState() => _SysjTimeState(); +} + +class _SysjTimeState extends State with EventBusMixin { + 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 { @@ -908,6 +957,7 @@ class UseBottomPlaybar with EventBusMixin { 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;