Compare commits

..

No commits in common. "e73d1ddaab6e115f0fa5ec067f7f4d8085642216" and "63658cf6e133f81308930c11daa4525c14013414" have entirely different histories.

16 changed files with 238 additions and 1769 deletions

View File

@ -4,9 +4,7 @@ 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';
@ -128,11 +126,12 @@ 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

@ -18,7 +18,7 @@ class DoPaperDetailsResult extends Object {
@JsonKey(name: 'templateIdKeyMap')
Map<int, int>? templateIdKeyMap;
@JsonKey(name: 'submitStudents') //
@JsonKey(name: 'students')
List<PaperStudents> students;
@JsonKey(name: 'templateId')
@ -59,9 +59,8 @@ class DoPaperDetailsResult extends Object {
@JsonKey(name: 'studentQuestions')
List<StudentQuestions> studentQuestions;
//
@JsonKey(name: 'unSubmitStudents')
List<PaperStudents> unSubmitStudents;
Object unSubmitStudents;
@JsonKey(name: 'lastPage')
LastPage? lastPage;
@ -69,12 +68,7 @@ class DoPaperDetailsResult extends Object {
@JsonKey(name: 'nextPage')
NextPage? nextPage;
//
@JsonKey(name: 'totalUnAnnotateCount')
int totalUnAnnotateCount;
DoPaperDetailsResult(
this.totalUnAnnotateCount,
this.templateIds,
this.students,
this.templateId,
@ -117,8 +111,8 @@ class DoPaperDetailsResult extends Object {
if (annotateTime != null) showZgtAnnotate = '${showZgtAnnotate!}?$annotateTime';
}
// print('学生作答图片:${annotatedCount}');
// print('老师批注图片提交数量:${submitCount}');
print('学生作答图片:${zgtAnswer}');
print('老师批注图片${showZgtAnnotate}');
}
factory DoPaperDetailsResult.fromJson(Map<String, dynamic> srcJson) => _$DoPaperDetailsResultFromJson(srcJson);
@ -134,7 +128,6 @@ class PaperStudents extends Object {
@JsonKey(name: 'name')
String name;
//
@JsonKey(name: 'isPriority')
bool isPriority;

View File

@ -1,35 +0,0 @@
// 稿
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

@ -1,65 +0,0 @@
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

@ -39,7 +39,6 @@ class MyApp extends StatelessWidget {
splitScreenMode: true,*/
builder: () => GetMaterialApp(
title: '作业',
debugShowCheckedModeBanner: false,
theme: ThemeData(
brightness: Brightness.light,
primarySwatch: createMaterialColor(const Color.fromRGBO(46, 91, 255, 1)),
@ -52,7 +51,8 @@ class MyApp extends StatelessWidget {
colorScheme: const ColorScheme.light(
//
primary: Color.fromRGBO(46, 91, 255, 1),
)),
)
),
enableLog: true,
logWriterCallback: (text, {bool isError = false}) {
// isError ? LoggerUtils.e(text) : LoggerUtils.i(text);

View File

@ -12,7 +12,6 @@ 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,
@ -29,7 +28,6 @@ Text quickText(text,
fontSize: size,
color: color,
fontWeight: fontWeight,
wordSpacing: wordSpacing,
),
);
}

View File

@ -90,42 +90,11 @@ 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: 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),
],
),
],
),
);
return DropdownMenuItem(value: e.id, child: quickText(e.name, color: const Color.fromRGBO(79, 79, 79, 1), size: 14.sp));
}).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

@ -1,63 +0,0 @@
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

@ -1,969 +0,0 @@
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

@ -1,171 +0,0 @@
//
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

@ -1,110 +0,0 @@
//
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,9 +1,11 @@
import 'package:flutter/cupertino.dart';
import 'dart:async';
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';
@ -34,9 +36,7 @@ class _QuestionPaperViewState extends State<QuestionPaperView> {
@override
Widget build(BuildContext context) {
return Stack(
children: [
Row(
return Row(
children: [
//
Expanded(
@ -49,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,
@ -95,8 +95,6 @@ class _QuestionPaperViewState extends State<QuestionPaperView> {
);
}),
),
//
$TotalSubmitCountView(sateData)
],
);
}),
@ -104,122 +102,10 @@ class _QuestionPaperViewState extends State<QuestionPaperView> {
//
Expanded(flex: 2, child: $QuestionNumberView(sateData)),
],
),
Obx(() {
if (!sateData.getDataError.value) return const SizedBox();
return Center(
child: CupertinoButton(
color: Colors.grey[300],
onPressed: () => easyThrottle('home_work_reload_data', () {
sateData.param.value = DoPaperDetailsParam.fromJson(sateData.param.value.toJson());
}),
child: quickText('重新请求', color: Colors.black38),
),
);
}),
],
);
}
}
//
@swidget
Widget $totalSubmitCountView(BuildContext context, HomeworkReviewState sateData) {
return Obx(() {
var data = sateData.data.value;
if (data == null) return Container();
return Positioned(
bottom: 10.h,
right: 8.w,
child: InkWell(
onTap: () async {
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: 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),
],
),
),
);
});
}
//
@hwidget
Widget $questionNumberView(BuildContext context, HomeworkReviewState sateData) {

View File

@ -16,7 +16,6 @@ import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dar
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
import 'package:making_school_asignment_app/common/utils/upload_oss_img_utils.dart';
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
import 'package:making_school_asignment_app/page/home_page/children/job_report/widget/personnel_data_overview.dart';
//
class HomeworkReviewState {
@ -31,9 +30,6 @@ class HomeworkReviewState {
late bool? panQuestView;
late Rx<TestQuestionsImageInfo?> imageScale;
List<dynamic> handwritings = [];
bool needRefresh = false;
bool lastQuestionPrompt = false; //
Rx<bool> getDataError = false.obs; //
// late String dateEnd = '';
// late int knowledgeId = 0;
@ -103,14 +99,9 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin {
// item.topHeight = itemPre.height;
// }
state.getDataError.value = false;
state.data.value = data;
state.handwritings = [];
state.studentQuestions.value = data.studentQuestions;
} catch (e) {
print('获取数据报错了:$e');
ToastUtils.showError('获取试题数据出错,请重试');
state.getDataError.value = true;
} finally {
if (timerControl.isActive) timerControl.cancel();
@ -196,6 +187,8 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin {
options: Options(contentType: null, headers: {Headers.contentLengthHeader: bytes.length}),
);
// var res = await getClient().uploadImag(resUrl, file);
return imgKey;
} catch (e) {
print('图片上传失败');
@ -242,28 +235,20 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin {
);
}).toList()))
.then((e) async {
state.needRefresh = true;
var totalUnAnnotateCount = data.totalUnAnnotateCount;
if (data.annotateTime == null) totalUnAnnotateCount -= 1;
if (totalUnAnnotateCount <= 0 && !state.lastQuestionPrompt) {
var annotatedCount = data.annotatedCount + 1; //
var submitCount = data.submitCount; //
if (annotatedCount == submitCount) {
//
showDialog(
context: context,
builder: (BuildContext context1) {
return AlertDialog(
title: quickText('批阅已完成'),
content: const Text('暂无更多待批阅项'),
title: quickText('完成批阅提示'),
content: const Text('暂无更多待批阅项,是否返回主页?'),
actions: <Widget>[
TextButton(child: const Text(''), onPressed: () => Navigator.of(context1).pop()),
TextButton(
child: const Text('继续'),
onPressed: () {
state.lastQuestionPrompt = true;
Navigator.of(context1).pop();
},
),
TextButton(
child: const Text('退出批阅'),
child: const Text(''),
onPressed: () {
Navigator.of(context1).pop();
Get.back();
@ -275,11 +260,8 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin {
return;
}
var newParams = DoPaperDetailsParam.fromJson(state.param.value.toJson());
if (totalUnAnnotateCount > 0) {
//
newParams.templateId = null;
newParams.studentId = null;
}
state.param.value = newParams;
});
}

View File

@ -4,7 +4,6 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:making_school_asignment_app/page/global_widget/ReturnToHomepage.dart';
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
import 'package:making_school_asignment_app/page/home_page/children/annotate_class/annotate_class_logic.dart';
import 'components/bottom_operation_bar.dart';
import 'components/button_floating_action.dart';
@ -23,7 +22,6 @@ class HomeworkReview extends StatefulWidget {
class _HomeworkReviewState extends State<HomeworkReview> {
final logic = Get.find<HomeworkReviewLogic>();
final sateData = Get.find<HomeworkReviewLogic>().state;
final AnnotateClassLogic _controller = Get.find<AnnotateClassLogic>();
@override
void initState() {
@ -39,13 +37,7 @@ class _HomeworkReviewState extends State<HomeworkReview> {
@override
Widget build(BuildContext context) {
return PopScope(
canPop: false,
onPopInvoked: (e) {
if (e && sateData.needRefresh) _controller.getList();
},
child: SafeArea(
child: Scaffold(
return Scaffold(
appBar: AppBar(
// titleSpacing: 0,
leading: IconButton(icon: const Icon(Icons.arrow_back_ios), onPressed: () => Get.back()),
@ -53,7 +45,11 @@ class _HomeworkReviewState extends State<HomeworkReview> {
title: quickText(sateData.param.value.homeworkName),
backgroundColor: Colors.white,
elevation: 0,
actions: [const FavoriteWidget(), SizedBox(width: 5.w), const ReturnToHomepage()],
actions: [
const FavoriteWidget(),
SizedBox(width: 5.w),
const ReturnToHomepage(),
],
),
body: SafeArea(
child: Column(
@ -62,14 +58,12 @@ class _HomeworkReviewState extends State<HomeworkReview> {
const DropdownSwitchStudentsType(),
SizedBox(height: 1.h),
const Expanded(child: QuestionPaperView()),
const BottomAnnotationSwitch()
const BottomAnnotationSwitch(),
],
),
),
// floatingActionButton: const ButtonFloatingAction(),
// floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
),
),
floatingActionButton: const ButtonFloatingAction(),
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
);
}
}

View File

@ -3,7 +3,6 @@ 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';
@ -75,7 +74,11 @@ class _StudentPersonalPageState extends State<StudentPersonalPage> {
width: 10.r,
),
InkWell(
onTap: () => showAnswerHandwriting(context, homeworkId: state.homeworkId, studentId: state.studentId),
onTap: () {
/* showAnswerHandwriting(context, jobId: widget.jobId, studentId: widget.studentId).then((value) {
ref.read(jobHandwritingDrawingTrajectoryProvider.notifier).setVal([]);
});*/
},
child: Container(
width: 93.r,
height: 28.r,

View File

@ -24,9 +24,12 @@ class HomePage extends StatefulWidget {
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
class _HomePageState extends State<HomePage>
with AutomaticKeepAliveClientMixin {
final logic = Get.find<HomeLogic>();
final state = Get.find<HomeLogic>().state;
final state = Get
.find<HomeLogic>()
.state;
@override
bool get wantKeepAlive => true;
@ -35,8 +38,7 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
Widget build(BuildContext context) {
super.build(context);
var spaceWidth = SizedBox(height: ScreenUtil().screenWidth / 19);
return SafeArea(
child: AnnotatedRegion(
return AnnotatedRegion(
value: const SystemUiOverlayStyle(
systemNavigationBarColor: Color(0xFF000000),
systemNavigationBarDividerColor: null,
@ -51,13 +53,13 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
controller: logic.refreshController,
header: MaterialHeader(),
footer: TaurusFooter(),
onRefresh: () async {
onRefresh: () async{
state.pageNumber = 1;
return logic.getList();
},
onLoad: () async {
if (state.workList.length < state.totalCount) {
state.pageNumber++;
onLoad: () async{
if(state.workList.length<state.totalCount){
state.pageNumber ++;
return logic.getList();
}
},
@ -73,21 +75,28 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
),
),
),*/
SizedBox(height: 30.h),
Obx(() {
return $TermRow([
EntranceModel(title: '作业批阅', image: 'assets/images/job_home_marking.png', navigationUrl: Routes.readOverPage),
EntranceModel(title: '作业批阅',
image: 'assets/images/job_home_marking.png',
navigationUrl: Routes.readOverPage),
EntranceModel(
title: '学生历史作业',
image: 'assets/images/job_home_history.png',
navigationUrl: Routes.studentHistoryWorkPage,
page: 'history',
),
EntranceModel(title: '知识点点掌握', image: 'assets/images/job_home_knowledge.png', navigationUrl: Routes.knowledgePointsGraspPage)
EntranceModel(title: '知识点点掌握',
image: 'assets/images/job_home_knowledge.png',
navigationUrl: Routes.knowledgePointsGraspPage)
], state.readOver.value);
}),
spaceWidth,
$TermRow([
EntranceModel(title: '答题轨迹', image: 'assets/images/job_home_answer_record.png', navigationUrl: Routes.answerTrajectoryPage),
EntranceModel(title: '答题轨迹',
image: 'assets/images/job_home_answer_record.png',
navigationUrl: Routes.answerTrajectoryPage),
EntranceModel(
title: '优先批阅设定',
image: 'assets/images/job_home_youxian.png',
@ -118,7 +127,7 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
'id': item.id,
'name': item.name,
'grade': item.grade,
'subject': item.subject,
'subject':item.subject,
});
},
child: Container(
@ -127,7 +136,8 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
children: [
SizedBox(height: 4.h),
Container(
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 10.w),
padding: EdgeInsets.symmetric(
vertical: 16.h, horizontal: 10.w),
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
@ -142,18 +152,25 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment
.spaceBetween,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment
.start,
children: [
Container(
width: Utils.isPad() ? 32.w : 38.w,
height: 18.h,
alignment: Alignment.center,
padding: EdgeInsets.only(left: Utils.isPad() ? 2.w : 3.w),
padding: EdgeInsets.only(
left: Utils.isPad() ? 2.w : 3.w),
decoration: BoxDecoration(
color: state.type == 1 ? const Color.fromRGBO(104, 136, 253, 1) : const Color.fromRGBO(255, 175, 56, 1),
color: state.type == 1
? const Color.fromRGBO(
104, 136, 253, 1)
: const Color.fromRGBO(
255, 175, 56, 1),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(14.r),
topRight: Radius.circular(3.r),
@ -162,14 +179,17 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
),
),
margin: EdgeInsets.only(right: 4.w),
child: quickText(state.type == 1 ? '作业' : '考试', color: Colors.white, size: 10.sp),
child: quickText(
state.type == 1 ? '作业' : '考试',
color: Colors.white, size: 10.sp),
),
Expanded(
child: quickText(
item.name,
maxLines: 2,
size: Utils.isPad() ? 14.sp : 16.sp,
color: const Color.fromRGBO(70, 70, 70, 1),
color: const Color.fromRGBO(
70, 70, 70, 1),
fontWeight: FontWeight.bold,
),
)
@ -181,24 +201,41 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
children: [
quickText(
EnumUtils.formatSubject(item.subject),
color: const Color.fromRGBO(97, 97, 97, 1),
color: const Color.fromRGBO(
97, 97, 97, 1),
size: 12.sp,
),
quickText(' / ', color: const Color.fromRGBO(130, 130, 130, 1), size: 11.sp, fontWeight: FontWeight.w500),
quickText(' / ',
color: const Color.fromRGBO(
130, 130, 130, 1),
size: 11.sp,
fontWeight: FontWeight.w500),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment
.end,
children: [
quickText('题量:', color: const Color.fromRGBO(130, 130, 130, 1), size: 11.sp),
quickText('题量:',
color: const Color.fromRGBO(
130, 130, 130, 1),
size: 11.sp),
quickText(
'${item.questionCount! - item.annotateCount!}',
color: const Color.fromRGBO(97, 97, 97, 1),
color: const Color.fromRGBO(
97, 97, 97, 1),
size: 13.sp,
),
],
),
quickText(' / ', color: const Color.fromRGBO(130, 130, 130, 1), size: 11.sp, fontWeight: FontWeight.w500),
quickText(DateTime.parse(item.publishTime).toString().substring(0, 10),
color: const Color.fromRGBO(97, 97, 97, 1), size: 12.sp),
quickText(' / ',
color: const Color.fromRGBO(
130, 130, 130, 1),
size: 11.sp,
fontWeight: FontWeight.w500),
quickText(DateTime.parse(item.publishTime)
.toString()
.substring(0, 10),
color: const Color.fromRGBO(
97, 97, 97, 1), size: 12.sp),
],
),
SizedBox(height: 10.h),
@ -207,16 +244,21 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.r),
borderRadius: BorderRadius.circular(
10.r),
),
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: 8.h,
animationDuration: 2500,
percent: item.annotateRate == null ? 0 : item.annotateRate! / 100,
progressColor: const Color(0xFF6888FD),
backgroundColor: const Color(0xFFE8E8E8),
percent: item.annotateRate == null
? 0
: item.annotateRate! / 100,
progressColor: const Color(
0xFF6888FD),
backgroundColor: const Color(
0xFFE8E8E8),
barRadius: Radius.circular(10.r),
),
),
@ -224,7 +266,10 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
SizedBox(
width: 10.r,
),
quickText('${item.annotateRate!.toStringAsFixed(0)}%', size: 10.sp, color: const Color(0xFF464646)),
quickText(
'${item.annotateRate!.toStringAsFixed(
0)}%', size: 10.sp,
color: const Color(0xFF464646)),
],
),
// FavoriteButton(jobTaskItem.id, jobTaskItem.title),
@ -242,7 +287,7 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
],
),
),
));
);
}
@override
@ -258,7 +303,8 @@ class EntranceModel extends Object {
String navigationUrl;
String? page;
EntranceModel({required this.title, required this.image, required this.navigationUrl, this.page});
EntranceModel(
{required this.title, required this.image, required this.navigationUrl, this.page});
}
@swidget
@ -267,7 +313,8 @@ Widget $termRow(BuildContext context, List<EntranceModel> items, int? data) {
Widget childWidget;
switch (leng) {
case 1:
childWidget = Row(children: [Expanded(child: $TermItem(items[0], data!))]);
childWidget =
Row(children: [Expanded(child: $TermItem(items[0], data!))]);
break;
case 2:
childWidget = Row(children: [
@ -301,11 +348,13 @@ Widget $termRow(BuildContext context, List<EntranceModel> items, int? data) {
childWidget = Container();
}
return Container(padding: EdgeInsets.symmetric(horizontal: 14.w), child: childWidget);
return Container(
padding: EdgeInsets.symmetric(horizontal: 14.w), child: childWidget);
}
@swidget
Widget $termItem(BuildContext context, EntranceModel e, int data, {double? theHeight}) {
Widget $termItem(BuildContext context, EntranceModel e, int data,
{double? theHeight}) {
bool isJob = e.title == '作业批阅';
return Material(
@ -334,10 +383,13 @@ Widget $termItem(BuildContext context, EntranceModel e, int data, {double? theHe
badgeStyle: badges.BadgeStyle(
badgeColor: const Color.fromRGBO(255, 105, 105, 1),
shape: badges.BadgeShape.square,
borderRadius: BorderRadius.only(topLeft: Radius.circular(10.r), topRight: Radius.circular(8.5.r), bottomRight: Radius.circular(8.5.r)),
borderRadius: BorderRadius.only(topLeft: Radius.circular(10.r),
topRight: Radius.circular(8.5.r),
bottomRight: Radius.circular(8.5.r)),
// borderSide: BorderSide(color: Colors.white, width: 2),
elevation: 1,
padding: EdgeInsets.symmetric(horizontal: Utils.isPad() ? 11.w : 16.w, vertical: 2.h),
padding: EdgeInsets.symmetric(
horizontal: Utils.isPad() ? 11.w : 16.w, vertical: 2.h),
),
position: badges.BadgePosition.topEnd(top: 10.r, end: 10.r),
child: Container(
@ -360,17 +412,23 @@ Widget $termItem(BuildContext context, EntranceModel e, int data, {double? theHe
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(e.image, height: 32.r, width: 32.r, fit: BoxFit.cover),
Image.asset(
e.image, height: 32.r, width: 32.r, fit: BoxFit.cover),
SizedBox(height: 6.r),
quickText(e.title, size: 12.sp, color: const Color.fromRGBO(79, 79, 79, 1), fontWeight: FontWeight.w500),
quickText(e.title, size: 12.sp,
color: const Color.fromRGBO(79, 79, 79, 1),
fontWeight: FontWeight.w500),
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(e.image, height: 32.r, width: 32.r, fit: BoxFit.cover),
Image.asset(
e.image, height: 32.r, width: 32.r, fit: BoxFit.cover),
SizedBox(width: 6.r),
quickText(e.title, size: 12.sp, color: const Color.fromRGBO(79, 79, 79, 1), fontWeight: FontWeight.w500),
quickText(e.title, size: 12.sp,
color: const Color.fromRGBO(79, 79, 79, 1),
fontWeight: FontWeight.w500),
],
),
),