no message
This commit is contained in:
parent
54f27b0d72
commit
382840a3aa
|
|
@ -4,7 +4,7 @@ import 'package:making_school_asignment_app/common/config/request_config.dart';
|
||||||
|
|
||||||
part 'do_paper_details_result.g.dart';
|
part 'do_paper_details_result.g.dart';
|
||||||
|
|
||||||
@JsonSerializable(checked: true)
|
@JsonSerializable(checked: true, includeIfNull: false)
|
||||||
class DoPaperDetailsResult extends Object {
|
class DoPaperDetailsResult extends Object {
|
||||||
@JsonKey(name: 'templateIds')
|
@JsonKey(name: 'templateIds')
|
||||||
Map<String, bool> templateIds;
|
Map<String, bool> templateIds;
|
||||||
|
|
@ -17,7 +17,7 @@ class DoPaperDetailsResult extends Object {
|
||||||
@JsonKey(name: 'templateIdKeyMap')
|
@JsonKey(name: 'templateIdKeyMap')
|
||||||
Map<int, int>? templateIdKeyMap;
|
Map<int, int>? templateIdKeyMap;
|
||||||
|
|
||||||
@JsonKey(name: 'submitStudents') // 当前页 总提交学生集合
|
@JsonKey(name: 'submitStudents', toJson: _paperStudentsToJson) // 当前页 总提交学生集合
|
||||||
List<PaperStudents> students;
|
List<PaperStudents> students;
|
||||||
|
|
||||||
@JsonKey(name: 'templateId')
|
@JsonKey(name: 'templateId')
|
||||||
|
|
@ -55,17 +55,17 @@ class DoPaperDetailsResult extends Object {
|
||||||
@JsonKey(name: 'isFav')
|
@JsonKey(name: 'isFav')
|
||||||
bool isFav;
|
bool isFav;
|
||||||
|
|
||||||
@JsonKey(name: 'studentQuestions')
|
@JsonKey(name: 'studentQuestions', toJson: _studentQuestionsToJson)
|
||||||
List<StudentQuestions> studentQuestions;
|
List<StudentQuestions> studentQuestions;
|
||||||
|
|
||||||
// 当前页 未提交学生集合
|
// 当前页 未提交学生集合
|
||||||
@JsonKey(name: 'unSubmitStudents')
|
@JsonKey(name: 'unSubmitStudents', toJson: _paperStudentsToJson)
|
||||||
List<PaperStudents> unSubmitStudents;
|
List<PaperStudents> unSubmitStudents;
|
||||||
|
|
||||||
@JsonKey(name: 'lastPage')
|
@JsonKey(name: 'lastPage', toJson: _lastPageToJson)
|
||||||
LastPage? lastPage;
|
LastPage? lastPage;
|
||||||
|
|
||||||
@JsonKey(name: 'nextPage')
|
@JsonKey(name: 'nextPage', toJson: _nextPageToJson)
|
||||||
NextPage? nextPage;
|
NextPage? nextPage;
|
||||||
|
|
||||||
// 所有页 总待提交数量
|
// 所有页 总待提交数量
|
||||||
|
|
@ -112,27 +112,34 @@ class DoPaperDetailsResult extends Object {
|
||||||
var currentStudent = students.firstWhereOrNull((e) => e.id == studentId);
|
var currentStudent = students.firstWhereOrNull((e) => e.id == studentId);
|
||||||
if (currentStudent != null) priority = currentStudent.isPriority;
|
if (currentStudent != null) priority = currentStudent.isPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!zgtAnswer.contains(RequestConfig.imgUrl)) {
|
||||||
zgtAnswer = '${RequestConfig.imgUrl}$zgtAnswer?$lastAnswerTime';
|
zgtAnswer = '${RequestConfig.imgUrl}$zgtAnswer?$lastAnswerTime';
|
||||||
|
}
|
||||||
|
|
||||||
if (zgtAnnotate?.isNotEmpty ?? false) {
|
if (zgtAnnotate?.isNotEmpty ?? false) {
|
||||||
showZgtAnnotate = RequestConfig.imgUrl + zgtAnnotate!; // 批注图片地址赋值
|
showZgtAnnotate = RequestConfig.imgUrl + zgtAnnotate!; // 批注图片地址赋值
|
||||||
if (annotateTime != null)
|
if (annotateTime != null) showZgtAnnotate = '${showZgtAnnotate!}?$annotateTime';
|
||||||
showZgtAnnotate = '${showZgtAnnotate!}?$annotateTime';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断当前试题是否需要批阅
|
// 判断当前试题是否需要批阅
|
||||||
if (annotateTime == null ||
|
if (annotateTime == null || studentQuestions.indexWhere((e) => e.studentScore == null) != -1) {
|
||||||
studentQuestions.indexWhere((e) => e.studentScore == null) != -1) {
|
|
||||||
needAnnotate = true;
|
needAnnotate = true;
|
||||||
}
|
}
|
||||||
// print('学生作答图片:${annotatedCount}');
|
// print('学生作答图片:${annotatedCount}');
|
||||||
// print('老师批注图片提交数量:${submitCount}');
|
// print('老师批注图片提交数量:${submitCount}');
|
||||||
}
|
}
|
||||||
|
|
||||||
factory DoPaperDetailsResult.fromJson(Map<String, dynamic> srcJson) =>
|
factory DoPaperDetailsResult.fromJson(Map<String, dynamic> srcJson) => _$DoPaperDetailsResultFromJson(srcJson);
|
||||||
_$DoPaperDetailsResultFromJson(srcJson);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => _$DoPaperDetailsResultToJson(this);
|
Map<String, dynamic> toJson() => _$DoPaperDetailsResultToJson(this);
|
||||||
|
|
||||||
|
static List<Map<String, dynamic>> _paperStudentsToJson(List<PaperStudents> examples) => examples.map((e) => e.toJson()).toList();
|
||||||
|
|
||||||
|
static List<Map<String, dynamic>> _studentQuestionsToJson(List<StudentQuestions> examples) => examples.map((e) => e.toJson()).toList();
|
||||||
|
|
||||||
|
static Map<String, dynamic>? _nextPageToJson(NextPage? example) => example?.toJson();
|
||||||
|
static Map<String, dynamic>? _lastPageToJson(LastPage? example) => example?.toJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
@ -153,8 +160,7 @@ class PaperStudents extends Object {
|
||||||
this.isPriority,
|
this.isPriority,
|
||||||
);
|
);
|
||||||
|
|
||||||
factory PaperStudents.fromJson(Map<String, dynamic> srcJson) =>
|
factory PaperStudents.fromJson(Map<String, dynamic> srcJson) => _$PaperStudentsFromJson(srcJson);
|
||||||
_$PaperStudentsFromJson(srcJson);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => _$PaperStudentsToJson(this);
|
Map<String, dynamic> toJson() => _$PaperStudentsToJson(this);
|
||||||
}
|
}
|
||||||
|
|
@ -206,8 +212,7 @@ class StudentQuestions extends Object {
|
||||||
this.useTime,
|
this.useTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory StudentQuestions.fromJson(Map<String, dynamic> srcJson) =>
|
factory StudentQuestions.fromJson(Map<String, dynamic> srcJson) => _$StudentQuestionsFromJson(srcJson);
|
||||||
_$StudentQuestionsFromJson(srcJson);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => _$StudentQuestionsToJson(this);
|
Map<String, dynamic> toJson() => _$StudentQuestionsToJson(this);
|
||||||
}
|
}
|
||||||
|
|
@ -225,8 +230,7 @@ class LastPage extends Object {
|
||||||
this.studentId,
|
this.studentId,
|
||||||
);
|
);
|
||||||
|
|
||||||
factory LastPage.fromJson(Map<String, dynamic> srcJson) =>
|
factory LastPage.fromJson(Map<String, dynamic> srcJson) => _$LastPageFromJson(srcJson);
|
||||||
_$LastPageFromJson(srcJson);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => _$LastPageToJson(this);
|
Map<String, dynamic> toJson() => _$LastPageToJson(this);
|
||||||
}
|
}
|
||||||
|
|
@ -244,8 +248,7 @@ class NextPage extends Object {
|
||||||
this.studentId,
|
this.studentId,
|
||||||
);
|
);
|
||||||
|
|
||||||
factory NextPage.fromJson(Map<String, dynamic> srcJson) =>
|
factory NextPage.fromJson(Map<String, dynamic> srcJson) => _$NextPageFromJson(srcJson);
|
||||||
_$NextPageFromJson(srcJson);
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => _$NextPageToJson(this);
|
Map<String, dynamic> toJson() => _$NextPageToJson(this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:get/get.dart' as getx;
|
import 'package:get/get.dart' as getx;
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:making_school_asignment_app/common/api/retrofit_client.dart';
|
import 'package:making_school_asignment_app/common/api/retrofit_client.dart';
|
||||||
import 'package:making_school_asignment_app/common/config/request_config.dart';
|
import 'package:making_school_asignment_app/common/config/request_config.dart';
|
||||||
|
|
@ -114,6 +115,10 @@ class AuthInterceptor extends Interceptor {
|
||||||
class ResponseHandle extends Interceptor {
|
class ResponseHandle extends Interceptor {
|
||||||
@override
|
@override
|
||||||
void onResponse(Response response, ResponseInterceptorHandler handler) {
|
void onResponse(Response response, ResponseInterceptorHandler handler) {
|
||||||
|
const isProd = bool.fromEnvironment('dart.vm.product');
|
||||||
|
if (!isProd && RequestConfig.requestDataPrinting) {
|
||||||
|
toPrint(val: response.data, toPrintJson: true);
|
||||||
|
}
|
||||||
if (RequestConfig.successCode.contains(response.statusCode)) {
|
if (RequestConfig.successCode.contains(response.statusCode)) {
|
||||||
//
|
//
|
||||||
String? token = response.headers.value('access-token');
|
String? token = response.headers.value('access-token');
|
||||||
|
|
@ -180,9 +185,11 @@ class TheError extends Interceptor {
|
||||||
message = '用户登录失效,请重新登录';
|
message = '用户登录失效,请重新登录';
|
||||||
|
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
|
if (getx.Get.currentRoute != Routes.login) {
|
||||||
UserStore.to.erase();
|
UserStore.to.erase();
|
||||||
StorageService.to.erase();
|
StorageService.to.erase();
|
||||||
getx.Get.offAllNamed(Routes.login);
|
getx.Get.offAllNamed(Routes.login);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 404:
|
case 404:
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/src/widgets/framework.dart';
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
@ -6,6 +8,8 @@ import 'package:making_school_asignment_app/common/job/homework_details.dart';
|
||||||
import 'package:making_school_asignment_app/page/home_page/children/quick_data_check/quick_data_check_state.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/quick_data_check/quick_data_check_state.dart';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
|
import '../config/request_config.dart';
|
||||||
|
|
||||||
class Utils {
|
class Utils {
|
||||||
static Utils? _instance;
|
static Utils? _instance;
|
||||||
Utils._internal();
|
Utils._internal();
|
||||||
|
|
@ -181,7 +185,6 @@ class Utils {
|
||||||
var minSec = secList.isNotEmpty ? secList.first : 0;
|
var minSec = secList.isNotEmpty ? secList.first : 0;
|
||||||
var secTime = secList.isNotEmpty ? maxSec - minSec : 0;
|
var secTime = secList.isNotEmpty ? maxSec - minSec : 0;
|
||||||
stu.ttlSec = second2HMS(secTime);
|
stu.ttlSec = second2HMS(secTime);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.students.sort((a, b) {
|
data.students.sort((a, b) {
|
||||||
|
|
@ -293,3 +296,24 @@ bool isPad([double mobilePhoneScale = 1.2]) {
|
||||||
void toUpState(Function(void Function()) setState, VoidCallback fn, bool mounted) {
|
void toUpState(Function(void Function()) setState, VoidCallback fn, bool mounted) {
|
||||||
if (mounted) setState(fn);
|
if (mounted) setState(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toPrint({required dynamic val, bool toPrintJson = false}) {
|
||||||
|
bool printSwitch = RequestConfig.printSwitch;
|
||||||
|
if (printSwitch && val != null) toPrintJson ? printJson(val) : print(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 单纯的Json格式输出打印
|
||||||
|
void printJson(Object object) {
|
||||||
|
try {
|
||||||
|
JsonEncoder encoder = const JsonEncoder.withIndent(' ');
|
||||||
|
var encoderString = encoder.convert(object);
|
||||||
|
// print(encoderString);
|
||||||
|
// 不使用print()方法是因为这是单条输出,如果过长无法显示全
|
||||||
|
// 所以使用debugPrint()
|
||||||
|
debugPrint(encoderString);
|
||||||
|
// 下面这语句的效果与debugPrint 相同
|
||||||
|
//encoderString.split('\n').forEach((element) => print(element));
|
||||||
|
} catch (e) {
|
||||||
|
toPrint(val: e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
@ -6,49 +5,29 @@ import 'package:functional_widget_annotation/functional_widget_annotation.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.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_param.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart';
|
import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/permission_describe_util.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/toast_utils.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/common/utils/utils.dart';
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.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/configuration_files/index.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/homework_review/configuration_files/index.dart';
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
|
||||||
|
|
||||||
import 'original_manuscript_handwriting/answer_handwriting_view.dart';
|
import 'original_manuscript_handwriting/answer_handwriting_view.dart';
|
||||||
|
|
||||||
part 'dropdown_switch_students_type.g.dart';
|
part 'dropdown_switch_students_type.g.dart';
|
||||||
|
|
||||||
/// 学生和页码切换
|
/// 学生和页码切换
|
||||||
class DropdownSwitchStudentsType extends StatefulWidget {
|
///
|
||||||
|
|
||||||
|
class DropdownSwitchStudentsType extends StatelessWidget {
|
||||||
const DropdownSwitchStudentsType({super.key});
|
const DropdownSwitchStudentsType({super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<DropdownSwitchStudentsType> createState() => _DropdownSwitchStudentsTypeState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _DropdownSwitchStudentsTypeState extends State<DropdownSwitchStudentsType> {
|
|
||||||
final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
|
|
||||||
final logic = Get.find<HomeworkReviewLogic>();
|
|
||||||
final sateData = Get.find<HomeworkReviewLogic>().state.data;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
deviceInfoPlugin.androidInfo.then((androidInfo) {
|
|
||||||
Permission storagePermission = androidInfo.version.sdkInt >= 33 ? Permission.manageExternalStorage : Permission.storage;
|
|
||||||
PermissionDescribeUtil.instance.toLaunchPermissionRequest(
|
|
||||||
context,
|
|
||||||
title: '储存权限请求',
|
|
||||||
describe: "为了提供更好的服务,需要获取到存储权限用于保存批阅痕迹并上传",
|
|
||||||
permissions: [storagePermission],
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final logic = Get.find<HomeworkReviewLogic>();
|
||||||
|
final sateData = logic.state.data;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
|
height: 30.h,
|
||||||
padding: EdgeInsets.only(bottom: 2.r, left: 12.r, right: 12.r),
|
padding: EdgeInsets.only(bottom: 2.r, left: 12.r, right: 12.r),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
|
|
|
||||||
|
|
@ -1,69 +1,25 @@
|
||||||
import 'dart:async';
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:making_school_asignment_app/common/api/retrofit_client.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/job/marking_models/favor_param.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/anti_shake_throttling.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/home_page/children/homework_review/configuration_files/index.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/homework_review/configuration_files/index.dart';
|
||||||
|
|
||||||
/// 自定义收藏组件
|
/// 自定义收藏组件
|
||||||
/// isFavorite 默认是否收藏
|
/// isFavorite 默认是否收藏
|
||||||
/// favoriteNum 默认收藏次数
|
/// favoriteNum 默认收藏次数
|
||||||
class FavoriteWidget extends StatefulWidget {
|
|
||||||
|
class FavoriteWidget extends StatelessWidget {
|
||||||
const FavoriteWidget({super.key});
|
const FavoriteWidget({super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<FavoriteWidget> createState() => _FavoriteState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _FavoriteState extends State<FavoriteWidget> with RequestToolMixin {
|
|
||||||
late StreamSubscription _listen;
|
|
||||||
final _controller = Get.find<HomeworkReviewLogic>();
|
|
||||||
final sateData = Get.find<HomeworkReviewLogic>().state;
|
|
||||||
RxBool favorite = false.obs; // 初始化数据
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
_listen = _controller.state.data.listen((e) {
|
|
||||||
if (e == null) return;
|
|
||||||
if (favorite.value != e.isFav) favorite.value = !favorite.value;
|
|
||||||
});
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_listen.cancel();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> toFavorite() async {
|
|
||||||
try {
|
|
||||||
var data = sateData.data.value!;
|
|
||||||
var param = sateData.param.value;
|
|
||||||
await getClient().toFavStudent(FavorParam(
|
|
||||||
homeworkId: param.homeworkId,
|
|
||||||
studentId: data.studentId,
|
|
||||||
templateId: data.templateId,
|
|
||||||
questionNo: data.studentQuestions[0].questionNo,
|
|
||||||
isFav: !data.isFav,
|
|
||||||
));
|
|
||||||
favorite.value = !data.isFav;
|
|
||||||
data.isFav = favorite.value;
|
|
||||||
} catch (e) {
|
|
||||||
ToastUtils.showError('操作失败,请重试');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final logic = Get.find<HomeworkReviewLogic>();
|
||||||
|
final sateData = logic.state;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 4.r),
|
padding: EdgeInsets.symmetric(horizontal: 4.r),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () => easyThrottle('homework_review_collect_btn', () => toFavorite(), duration: const Duration(milliseconds: 500)),
|
onTap: () => easyThrottle('homework_review_collect_btn', () => logic.toFavorite(), duration: const Duration(milliseconds: 500)),
|
||||||
splashColor: Colors.transparent,
|
splashColor: Colors.transparent,
|
||||||
highlightColor: Colors.transparent,
|
highlightColor: Colors.transparent,
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|
@ -73,7 +29,7 @@ class _FavoriteState extends State<FavoriteWidget> with RequestToolMixin {
|
||||||
return Icon(
|
return Icon(
|
||||||
const IconData(0xe63c, fontFamily: "AlibabaIcon"),
|
const IconData(0xe63c, fontFamily: "AlibabaIcon"),
|
||||||
size: 18.sp,
|
size: 18.sp,
|
||||||
color: favorite.value ? const Color.fromRGBO(255, 172, 48, 1) : const Color.fromRGBO(164, 164, 164, 1),
|
color: sateData.favorite.value ? const Color.fromRGBO(255, 172, 48, 1) : const Color.fromRGBO(164, 164, 164, 1),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
SizedBox(width: 6.w),
|
SizedBox(width: 6.w),
|
||||||
|
|
|
||||||
|
|
@ -14,26 +14,25 @@ import 'package:making_school_asignment_app/common/utils/cached_network_img.dart
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.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/configuration_files/index.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/homework_review/configuration_files/index.dart';
|
||||||
import 'package:percent_indicator/linear_percent_indicator.dart';
|
import 'package:percent_indicator/linear_percent_indicator.dart';
|
||||||
|
import 'package:zoom_widget/zoom_widget.dart';
|
||||||
|
|
||||||
import 'dropdown_switch_students_type.dart';
|
import '../configuration_files/zoom_logic.dart';
|
||||||
|
|
||||||
part 'question_paper_view.g.dart';
|
part 'question_paper_view.g.dart';
|
||||||
|
|
||||||
// 试题详情
|
// 试题详情
|
||||||
class QuestionPaperView extends StatefulWidget {
|
|
||||||
|
class QuestionPaperView extends StatelessWidget {
|
||||||
const QuestionPaperView({super.key});
|
const QuestionPaperView({super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<QuestionPaperView> createState() => _QuestionPaperViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _QuestionPaperViewState extends State<QuestionPaperView> {
|
|
||||||
final logic = Get.find<HomeworkReviewLogic>();
|
|
||||||
final sateData = Get.find<HomeworkReviewLogic>().state;
|
|
||||||
final annotationState = Get.find<HomeworkReviewLogic>().annotationState;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final zoomLogic = Get.find<ZoomLogic>();
|
||||||
|
final zoomState = zoomLogic.zoomState;
|
||||||
|
final logic = Get.find<HomeworkReviewLogic>();
|
||||||
|
final sateData = logic.state;
|
||||||
|
final annotationState = logic.annotationState;
|
||||||
|
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
|
|
@ -41,14 +40,40 @@ class _QuestionPaperViewState extends State<QuestionPaperView> {
|
||||||
// 试题图片视图
|
// 试题图片视图
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 7,
|
flex: 7,
|
||||||
child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
|
child: Obx(() {
|
||||||
|
ZoomFileModel? zoomFileModel = zoomState.zoomFile.value;
|
||||||
|
|
||||||
|
if (zoomFileModel == null) {
|
||||||
|
/// 计算高度
|
||||||
|
return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
|
||||||
var maxWidth = constraints.maxWidth;
|
var maxWidth = constraints.maxWidth;
|
||||||
var maxHeight = constraints.maxHeight;
|
var maxHeight = constraints.maxHeight;
|
||||||
|
// var maxHeight = ScreenUtil().screenHeight - 95.h - logic.appBarHeight; // 1187.2356785851596
|
||||||
|
// print("原始 视图的高度:${maxHeight1} $maxHeight ${MediaQuery.of(context).padding.top}");
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
zoomState.zoomFile.value = ZoomFileModel(viewWidth: maxWidth, viewHeight: maxHeight);
|
||||||
|
});
|
||||||
|
return SizedBox();
|
||||||
|
});
|
||||||
|
} else if (zoomFileModel.fileHeight == null) {
|
||||||
|
/// 文件未计算实际高度
|
||||||
|
return SizedBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxWidth = zoomFileModel.viewWidth;
|
||||||
|
var maxHeight = zoomFileModel.viewHeight;
|
||||||
|
print("文件的高度:${zoomFileModel.actualHeight!}");
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
// 主图
|
// 主图
|
||||||
QuestionImageView(maxWidth, maxHeight, sateData, annotationState, logic),
|
QuestionImageView(
|
||||||
|
maxWidth,
|
||||||
|
maxHeight,
|
||||||
|
sateData,
|
||||||
|
annotationState,
|
||||||
|
logic,
|
||||||
|
actualHeight: zoomFileModel.actualHeight!,
|
||||||
|
),
|
||||||
// 继续批阅按钮
|
// 继续批阅按钮
|
||||||
// Positioned(right: 3.w, bottom: 4.h, child: const $ContinueToReview(isFloatingAction: true)),
|
// Positioned(right: 3.w, bottom: 4.h, child: const $ContinueToReview(isFloatingAction: true)),
|
||||||
// 上一题按钮
|
// 上一题按钮
|
||||||
|
|
@ -81,6 +106,7 @@ class _QuestionPaperViewState extends State<QuestionPaperView> {
|
||||||
child: Obx(() {
|
child: Obx(() {
|
||||||
NextPage? nextPageVal = sateData.data.value?.nextPage;
|
NextPage? nextPageVal = sateData.data.value?.nextPage;
|
||||||
if (nextPageVal == null) return const SizedBox();
|
if (nextPageVal == null) return const SizedBox();
|
||||||
|
|
||||||
return FloatingActionButton(
|
return FloatingActionButton(
|
||||||
heroTag: '点击前往下一题',
|
heroTag: '点击前往下一题',
|
||||||
tooltip: '点击前往下一题',
|
tooltip: '点击前往下一题',
|
||||||
|
|
@ -108,14 +134,13 @@ class _QuestionPaperViewState extends State<QuestionPaperView> {
|
||||||
),
|
),
|
||||||
Obx(() {
|
Obx(() {
|
||||||
if (!sateData.getDataError.value) return const SizedBox();
|
if (!sateData.getDataError.value) return const SizedBox();
|
||||||
|
|
||||||
return Center(
|
return Center(
|
||||||
child: CupertinoButton(
|
child: CupertinoButton(
|
||||||
color: Colors.grey[300],
|
color: Colors.grey[300],
|
||||||
onPressed: () => easyThrottle('home_work_reload_data', () {
|
onPressed: () => easyThrottle('home_work_reload_data', () {
|
||||||
sateData.param.value = DoPaperDetailsParam.fromJson(sateData.param.value.toJson());
|
sateData.param.value = DoPaperDetailsParam.fromJson(sateData.param.value.toJson());
|
||||||
}),
|
}),
|
||||||
child: quickText('重新请求', color: Colors.black38),
|
child: quickText('再次请求', color: Colors.black38),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|
@ -234,7 +259,10 @@ Widget $questionNumberView(BuildContext context, HomeworkReviewLogic logic, Home
|
||||||
if (sateData.panQuestView == false) sateData.slide.value = scrollControllerNum.offset;
|
if (sateData.panQuestView == false) sateData.slide.value = scrollControllerNum.offset;
|
||||||
});
|
});
|
||||||
var listenVal = sateData.slide.listen((e) {
|
var listenVal = sateData.slide.listen((e) {
|
||||||
if (e != scrollControllerNum.offset && sateData.panQuestView == true) scrollControllerNum.jumpTo(e);
|
if (sateData.panQuestView != null && sateData.panQuestView == true && e != scrollControllerNum.offset) {
|
||||||
|
print("进来了试题题号视图");
|
||||||
|
scrollControllerNum.jumpTo(e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return () {
|
return () {
|
||||||
|
|
@ -270,7 +298,7 @@ Widget $questionNumberView(BuildContext context, HomeworkReviewLogic logic, Home
|
||||||
var actualImgHeight = imageVal.actualImgHeight; // 实际图片高度
|
var actualImgHeight = imageVal.actualImgHeight; // 实际图片高度
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
height: boxHeight > actualImgHeight ? boxHeight : actualImgHeight,
|
height: (boxHeight > actualImgHeight ? boxHeight : actualImgHeight) * (logic.state.initScale.value ?? 1),
|
||||||
padding: EdgeInsets.only(top: imageVal.remainingHeight > 0 ? imageVal.remainingHeight / 2 : 0),
|
padding: EdgeInsets.only(top: imageVal.remainingHeight > 0 ? imageVal.remainingHeight / 2 : 0),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
|
@ -292,6 +320,7 @@ Widget $questionNumberView(BuildContext context, HomeworkReviewLogic logic, Home
|
||||||
Widget $scoringQuestionsView(
|
Widget $scoringQuestionsView(
|
||||||
BuildContext context, HomeworkReviewLogic logic, StudentQuestions item, double scaleRatio, List<StudentQuestions>? studentQuestions) {
|
BuildContext context, HomeworkReviewLogic logic, StudentQuestions item, double scaleRatio, List<StudentQuestions>? studentQuestions) {
|
||||||
var studentScore = useState<int?>(item.studentScore);
|
var studentScore = useState<int?>(item.studentScore);
|
||||||
|
var initScale = useState<double>(logic.state.initScale.value ?? 1);
|
||||||
|
|
||||||
useValueChanged<int?, void>(studentScore.value, (_, __) {
|
useValueChanged<int?, void>(studentScore.value, (_, __) {
|
||||||
item.studentScore = studentScore.value;
|
item.studentScore = studentScore.value;
|
||||||
|
|
@ -304,6 +333,11 @@ Widget $scoringQuestionsView(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useValueChanged<double?, void>(logic.state.initScale.value, (_, __) {
|
||||||
|
print("数据了啦啦啦啦: ${logic.state.initScale}");
|
||||||
|
initScale.value = logic.state.initScale.value ?? 1;
|
||||||
|
});
|
||||||
|
|
||||||
useValueChanged<StudentQuestions, void>(item, (_, __) {
|
useValueChanged<StudentQuestions, void>(item, (_, __) {
|
||||||
studentScore.value = item.studentScore;
|
studentScore.value = item.studentScore;
|
||||||
});
|
});
|
||||||
|
|
@ -312,8 +346,9 @@ Widget $scoringQuestionsView(
|
||||||
return () {};
|
return () {};
|
||||||
}, []);
|
}, []);
|
||||||
var padinVal = item.correctRate > 0 ? EdgeInsets.only(top: 6.4.h) : EdgeInsets.symmetric(vertical: 2.h);
|
var padinVal = item.correctRate > 0 ? EdgeInsets.only(top: 6.4.h) : EdgeInsets.symmetric(vertical: 2.h);
|
||||||
|
print("高度: ${item.height! * scaleRatio * initScale.value}");
|
||||||
return Container(
|
return Container(
|
||||||
height: item.height! * scaleRatio,
|
height: item.height! * scaleRatio * initScale.value,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
child: item.useTime == 0
|
child: item.useTime == 0
|
||||||
? Container()
|
? Container()
|
||||||
|
|
@ -423,10 +458,11 @@ Widget $scoringQuestionsView(
|
||||||
class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar> {
|
class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar> {
|
||||||
final double maxWidth;
|
final double maxWidth;
|
||||||
final double maxHeight;
|
final double maxHeight;
|
||||||
|
final double actualHeight;
|
||||||
final HomeworkReviewLogic logic;
|
final HomeworkReviewLogic logic;
|
||||||
final HomeworkReviewState sateData;
|
final HomeworkReviewState sateData;
|
||||||
final HomeworkReviewAnnotationsControlState annotationState;
|
final HomeworkReviewAnnotationsControlState annotationState;
|
||||||
QuestionImageView(this.maxWidth, this.maxHeight, this.sateData, this.annotationState, this.logic, {super.key});
|
QuestionImageView(this.maxWidth, this.maxHeight, this.sateData, this.annotationState, this.logic, {required this.actualHeight, super.key});
|
||||||
|
|
||||||
/// 获取数组指定倒数具体值的下标
|
/// 获取数组指定倒数具体值的下标
|
||||||
int _findTargetIndex<T>(List<T> list, T target, [int reciprocal = 2]) {
|
int _findTargetIndex<T>(List<T> list, T target, [int reciprocal = 2]) {
|
||||||
|
|
@ -443,15 +479,26 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
||||||
int activePointers = 0;
|
int activePointers = 0;
|
||||||
|
|
||||||
ImageStream? imageStream;
|
ImageStream? imageStream;
|
||||||
|
var zoomKey = GlobalKey();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theMaxHeight = useState<double>(maxHeight);
|
final theMaxHeight = useState<double>(maxHeight);
|
||||||
|
|
||||||
useValueChanged<double, void>(maxHeight, (oldValue, __) => theMaxHeight.value = maxHeight);
|
useValueChanged<double, void>(maxHeight, (oldValue, __) => theMaxHeight.value = maxHeight);
|
||||||
final scrollControllerQuestion = useScrollController(); // 试题图片区域
|
// final imgActualHeight = useState<double?>(sateData.imageScale.value?.actualImgHeight);
|
||||||
|
// final scrollControllerQuestion = useScrollController(); // 试题图片区域
|
||||||
var vnHandWritings = useValueNotifier<List<dynamic>>([]);
|
var vnHandWritings = useValueNotifier<List<dynamic>>([]);
|
||||||
|
|
||||||
|
/// 滑动高度
|
||||||
|
var initPosition = useState<Offset?>(null);
|
||||||
|
|
||||||
var customPaintSize = useState<Size>(Size.zero);
|
var customPaintSize = useState<Size>(Size.zero);
|
||||||
|
|
||||||
|
// useValueChanged<double?, void>(sateData.imageScale.value?.actualImgHeight, (_, __) {
|
||||||
|
// imgActualHeight.value = sateData.imageScale.value?.actualImgHeight;
|
||||||
|
// });
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
var listenStream = sateData.data.listen((e) {
|
var listenStream = sateData.data.listen((e) {
|
||||||
// 数据清空
|
// 数据清空
|
||||||
|
|
@ -464,9 +511,21 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
||||||
sateData.imageScale.value?.actualImgHeight ?? 0,
|
sateData.imageScale.value?.actualImgHeight ?? 0,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var streamSubscriptionSlide = sateData.slide.listen((e) {
|
||||||
|
if (sateData.panQuestView != null &&
|
||||||
|
sateData.panQuestView == false &&
|
||||||
|
initPosition.value?.dy.abs().toInt().toDouble() != sateData.slide.value) {
|
||||||
|
if (sateData.zoomOffset != null) {
|
||||||
|
sateData.zoomOffset = Offset(sateData.zoomOffset!.dx, -sateData.slide.value);
|
||||||
|
}
|
||||||
|
initPosition.value = sateData.zoomOffset;
|
||||||
|
}
|
||||||
|
});
|
||||||
return () {
|
return () {
|
||||||
listenStream.cancel();
|
listenStream.cancel();
|
||||||
listenStreamImageScale.cancel();
|
listenStreamImageScale.cancel();
|
||||||
|
streamSubscriptionSlide.cancel();
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
@ -480,6 +539,7 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
||||||
imageHeight: info.image.height.toDouble(),
|
imageHeight: info.image.height.toDouble(),
|
||||||
url: sateData.data.value!.zgtAnswer,
|
url: sateData.data.value!.zgtAnswer,
|
||||||
);
|
);
|
||||||
|
print("这里的高度 ${theMaxHeight.value} $actualHeight ${sateData.imageScale.value?.actualImgHeight}");
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -557,42 +617,40 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
||||||
vnHandWritings.value = annotationsData;
|
vnHandWritings.value = annotationsData;
|
||||||
});
|
});
|
||||||
|
|
||||||
scrollControllerQuestion.addListener(() {
|
// scrollControllerQuestion.addListener(() {
|
||||||
sateData.slide.value = scrollControllerQuestion.offset;
|
// sateData.slide.value = scrollControllerQuestion.offset;
|
||||||
}); // 执行滚动相关的逻辑,例如打印滚动位置
|
// }); // 执行滚动相关的逻辑,例如打印滚动位置
|
||||||
|
|
||||||
var listenVal = sateData.slide.listen((e) {
|
// var listenVal = sateData.slide.listen((e) {
|
||||||
if (e != scrollControllerQuestion.offset && sateData.panQuestView == false) scrollControllerQuestion.jumpTo(e);
|
// if (e != scrollControllerQuestion.offset && sateData.panQuestView == false) scrollControllerQuestion.jumpTo(e);
|
||||||
});
|
// });
|
||||||
|
|
||||||
// 返回一个清理函数,在组件销毁时移除监听
|
// 返回一个清理函数,在组件销毁时移除监听
|
||||||
return () {
|
return () {
|
||||||
activePointers = 0;
|
activePointers = 0;
|
||||||
listenVal.cancel();
|
// listenVal.cancel();
|
||||||
imageStream?.removeListener(imageStreamListener.value);
|
imageStream?.removeListener(imageStreamListener.value);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
print("IIIIIII");
|
print("++++++++++++++++++++++ ${theMaxHeight.value}");
|
||||||
|
print("+++++ 位置:${initPosition.value}");
|
||||||
|
print("+++++ 缩放:${sateData.initScale.value}");
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
height: maxHeight,
|
// decoration: BoxDecoration(
|
||||||
// padding: EdgeInsets.only(bottom: 2.h, top: 2.h),
|
// boxShadow: [
|
||||||
|
// BoxShadow(
|
||||||
|
// color: Colors.grey.withOpacity(0.2),
|
||||||
|
// offset: Offset(-6.r, 1.r),
|
||||||
|
// blurRadius: 10.r,
|
||||||
|
// spreadRadius: 8.r,
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Obx(() {
|
width: maxWidth,
|
||||||
var imageUrl = sateData.data.value?.zgtAnswer;
|
// height: theMaxHeight.value,
|
||||||
var showZgtAnnotate = sateData.data.value?.showZgtAnnotate;
|
|
||||||
|
|
||||||
if (imageUrl == null) return const SizedBox();
|
|
||||||
|
|
||||||
print("KKKKKKKKKKKKKKKKKKKKKK");
|
|
||||||
return SingleChildScrollView(
|
|
||||||
controller: scrollControllerQuestion,
|
|
||||||
physics: !annotationState.pen.value ? const BouncingScrollPhysics() : const NeverScrollableScrollPhysics(),
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
scrollDirection: Axis.vertical, // 设置垂直滚动
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.2), offset: Offset(-6.r, 1.r), blurRadius: 10.r, spreadRadius: 8.r)]),
|
|
||||||
child: Listener(
|
child: Listener(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onPointerDown: (PointerDownEvent event) {
|
onPointerDown: (PointerDownEvent event) {
|
||||||
|
|
@ -618,23 +676,62 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
||||||
|
|
||||||
var imageScale = sateData.imageScale.value;
|
var imageScale = sateData.imageScale.value;
|
||||||
if (imageScale == null || !annotationState.pen.value) return;
|
if (imageScale == null || !annotationState.pen.value) return;
|
||||||
Offset localPosition = event.localPosition;
|
Offset localPosition = event.localPosition; // 相对
|
||||||
|
|
||||||
|
print("\\\\\\\\");
|
||||||
|
print(localPosition);
|
||||||
|
print("\\\\\\\\ ${imageScale.actualImgHeight}");
|
||||||
|
|
||||||
var dy = localPosition.dy;
|
var dy = localPosition.dy;
|
||||||
if (dy > imageScale.actualImgHeight || dy < 0) return; // 检查笔记是否超出图片范围
|
if (dy > imageScale.actualImgHeight || dy < 0) return; // 检查笔记是否超出图片范围
|
||||||
|
|
||||||
|
var theScale = sateData.initScale.value ?? 1;
|
||||||
|
|
||||||
|
/// 缩放后的基数
|
||||||
|
if (theScale != 1) {
|
||||||
|
localPosition = Offset(localPosition.dx / theScale, localPosition.dy / theScale);
|
||||||
|
var theZoomOffset = sateData.zoomOffset;
|
||||||
|
if (theZoomOffset != null) {
|
||||||
|
var dx = theZoomOffset.dx;
|
||||||
|
var dy = theZoomOffset.dy;
|
||||||
|
localPosition = Offset(localPosition.dx + dx, localPosition.dy + dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vnHandWritings.value = List.from(vnHandWritings.value)..add(localPosition);
|
vnHandWritings.value = List.from(vnHandWritings.value)..add(localPosition);
|
||||||
sateData.handwritings = vnHandWritings.value;
|
sateData.handwritings = vnHandWritings.value;
|
||||||
},
|
},
|
||||||
|
child: Obx(() {
|
||||||
|
var isPen = annotationState.pen.value;
|
||||||
|
var showZgtAnnotate = sateData.data.value?.showZgtAnnotate;
|
||||||
|
|
||||||
|
print("55555高度: ${actualHeight} ${initPosition.value}");
|
||||||
|
return IgnorePointer(
|
||||||
|
ignoring: isPen,
|
||||||
|
child: Zoom(
|
||||||
|
key: zoomKey,
|
||||||
|
// initTotalZoomOut: true, // 展示全部内容 初始化不产生滚动条
|
||||||
|
zoomSensibility: 0.05,
|
||||||
|
scrollWeight: 4.r,
|
||||||
|
doubleTapAnimDuration: Duration.zero,
|
||||||
|
maxZoomWidth: maxWidth,
|
||||||
|
maxZoomHeight: actualHeight,
|
||||||
|
canvasColor: Colors.transparent,
|
||||||
|
initPosition: initPosition.value,
|
||||||
|
initScale: sateData.initScale.value,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
onScaleUpdate: logic.onScaleUpdate,
|
||||||
|
onPositionUpdate: logic.onPanUpPosition,
|
||||||
|
child: Center(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
$TheCachedNetworkImage(
|
$TheCachedNetworkImage(
|
||||||
imageUrl: imageUrl,
|
imageUrl: sateData.data.value!.zgtAnswer,
|
||||||
imgWidth: maxWidth,
|
imgWidth: maxWidth,
|
||||||
(context, imageProvider) {
|
(context, imageProvider) {
|
||||||
Image imageWidget = Image(image: imageProvider, fit: BoxFit.fitWidth);
|
Image imageWidget = Image(image: imageProvider, fit: BoxFit.fitWidth);
|
||||||
imageStream?.removeListener(imageStreamListener.value);
|
imageStream?.removeListener(imageStreamListener.value);
|
||||||
imageStream = imageWidget.image.resolve(const ImageConfiguration())..addListener(imageStreamListener.value);
|
imageStream = imageWidget.image.resolve(const ImageConfiguration())..addListener(imageStreamListener.value);
|
||||||
// return imageWidget;
|
|
||||||
return imageWidget;
|
return imageWidget;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
@ -648,8 +745,7 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
||||||
? $TheCachedNetworkImage(
|
? $TheCachedNetworkImage(
|
||||||
imgWidth: maxWidth,
|
imgWidth: maxWidth,
|
||||||
imageUrl: showZgtAnnotate,
|
imageUrl: showZgtAnnotate,
|
||||||
(_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth),
|
(_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth))
|
||||||
)
|
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -659,7 +755,15 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// return Obx(() {
|
||||||
|
// var imageUrl = sateData.data.value?.zgtAnswer;
|
||||||
|
|
||||||
|
// if (imageUrl == null) return const SizedBox();
|
||||||
|
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
|
|
@ -10,11 +11,16 @@ import 'package:get/get.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_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/do_paper_details_result.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/do_test_questions_image_info.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/job/marking_models/favor_param.dart';
|
||||||
import 'package:making_school_asignment_app/common/job/marking_models/review_submission_params.dart';
|
import 'package:making_school_asignment_app/common/job/marking_models/review_submission_params.dart';
|
||||||
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/permission_describe_util.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
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/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/global_widget/my_text.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
|
import 'zoom_logic.dart';
|
||||||
|
|
||||||
// 数据
|
// 数据
|
||||||
class HomeworkReviewState {
|
class HomeworkReviewState {
|
||||||
|
|
@ -26,13 +32,16 @@ class HomeworkReviewState {
|
||||||
late Rx<DoPaperDetailsResult?> data;
|
late Rx<DoPaperDetailsResult?> data;
|
||||||
late Rx<List<StudentQuestions>?> studentQuestions;
|
late Rx<List<StudentQuestions>?> studentQuestions;
|
||||||
late Rx<double> slide; // 滑动位置
|
late Rx<double> slide; // 滑动位置
|
||||||
late bool? panQuestView;
|
bool? panQuestView = null;
|
||||||
late Rx<TestQuestionsImageInfo?> imageScale;
|
late Rx<TestQuestionsImageInfo?> imageScale;
|
||||||
List<dynamic> handwritings = [];
|
List<dynamic> handwritings = [];
|
||||||
bool needRefresh = false;
|
bool needRefresh = false;
|
||||||
bool lastQuestionPrompt = false; // 最后一题提示
|
bool lastQuestionPrompt = false; // 最后一题提示
|
||||||
Rx<bool> getDataError = false.obs; // 获取作业数据报错
|
Rx<bool> getDataError = false.obs; // 获取作业数据报错
|
||||||
|
|
||||||
|
Rx<double?> initScale = Rx<double?>(null);
|
||||||
|
Offset? zoomOffset;
|
||||||
|
RxBool favorite = false.obs; // 初始化数据
|
||||||
// late String dateEnd = '';
|
// late String dateEnd = '';
|
||||||
// late int knowledgeId = 0;
|
// late int knowledgeId = 0;
|
||||||
// late RxList<KnowledgeReportDetail> dataList = RxList();
|
// late RxList<KnowledgeReportDetail> dataList = RxList();
|
||||||
|
|
@ -53,7 +62,10 @@ class HomeworkReviewAnnotationsControlState {
|
||||||
|
|
||||||
class HomeworkReviewBinding extends Bindings {
|
class HomeworkReviewBinding extends Bindings {
|
||||||
@override
|
@override
|
||||||
void dependencies() => Get.lazyPut(() => HomeworkReviewLogic());
|
void dependencies() {
|
||||||
|
Get.lazyPut(() => HomeworkReviewLogic());
|
||||||
|
Get.lazyPut(() => ZoomLogic());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HomeworkReviewLogic extends GetxController with RequestToolMixin {
|
class HomeworkReviewLogic extends GetxController with RequestToolMixin {
|
||||||
|
|
@ -62,10 +74,16 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin {
|
||||||
late StreamSubscription<DoPaperDetailsResult?> _dataListen;
|
late StreamSubscription<DoPaperDetailsResult?> _dataListen;
|
||||||
final HomeworkReviewState state = HomeworkReviewState();
|
final HomeworkReviewState state = HomeworkReviewState();
|
||||||
final HomeworkReviewAnnotationsControlState annotationState = HomeworkReviewAnnotationsControlState();
|
final HomeworkReviewAnnotationsControlState annotationState = HomeworkReviewAnnotationsControlState();
|
||||||
|
double appBarHeight = 56;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
appBarHeight = MediaQuery.of(Get.context!).padding.top;
|
||||||
|
print("appBarHeight :$appBarHeight");
|
||||||
|
// WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
// SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); // 屏幕刘海
|
||||||
|
|
||||||
state.param = DoPaperDetailsParam(
|
state.param = DoPaperDetailsParam(
|
||||||
homeworkId: Get.arguments['homeworkId'],
|
homeworkId: Get.arguments['homeworkId'],
|
||||||
homeworkName: Get.arguments['homeworkName'],
|
homeworkName: Get.arguments['homeworkName'],
|
||||||
|
|
@ -76,18 +94,42 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin {
|
||||||
state.studentQuestions = Rx<List<StudentQuestions>?>(null);
|
state.studentQuestions = Rx<List<StudentQuestions>?>(null);
|
||||||
state.imageScale = Rx<TestQuestionsImageInfo?>(null);
|
state.imageScale = Rx<TestQuestionsImageInfo?>(null);
|
||||||
state.slide = 0.0.obs;
|
state.slide = 0.0.obs;
|
||||||
getData();
|
|
||||||
// 参数变化更新作业详情
|
// 参数变化更新作业详情
|
||||||
_paramListen = state.param.listen((e) => getData());
|
_paramListen = state.param.listen((e) => getData());
|
||||||
// 试题数据
|
// 试题数据
|
||||||
_dataListen = state.data.listen((e) => state.imageScale.value = null);
|
_dataListen = state.data.listen((e) {
|
||||||
|
if (e == null) return;
|
||||||
|
state.imageScale.value = null;
|
||||||
|
if (state.favorite.value != e.isFav) state.favorite.value = !state.favorite.value;
|
||||||
|
});
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => getData());
|
||||||
|
super.onInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void disposeId(Object id) {
|
void onReady() {
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
|
DeviceInfoPlugin().androidInfo.then((androidInfo) {
|
||||||
|
Permission storagePermission = androidInfo.version.sdkInt >= 33 ? Permission.manageExternalStorage : Permission.storage;
|
||||||
|
PermissionDescribeUtil.instance.toLaunchPermissionRequest(
|
||||||
|
Get.context,
|
||||||
|
title: '储存权限请求',
|
||||||
|
describe: "为了提供更好的服务,需要获取到存储权限用于保存批阅痕迹并上传",
|
||||||
|
permissions: [storagePermission],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
super.onReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]); // 屏幕刘海
|
||||||
_dataListen.cancel();
|
_dataListen.cancel();
|
||||||
_paramListen.cancel();
|
_paramListen.cancel();
|
||||||
super.disposeId(id);
|
super.onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void getData() async {
|
void getData() async {
|
||||||
|
|
@ -105,6 +147,7 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin {
|
||||||
state.data.value = data;
|
state.data.value = data;
|
||||||
state.handwritings = [];
|
state.handwritings = [];
|
||||||
state.studentQuestions.value = data.studentQuestions;
|
state.studentQuestions.value = data.studentQuestions;
|
||||||
|
state.initScale.value = null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('获取数据报错了:$e');
|
print('获取数据报错了:$e');
|
||||||
// ToastUtils.showError('未获取到试题数据,请重试');
|
// ToastUtils.showError('未获取到试题数据,请重试');
|
||||||
|
|
@ -280,4 +323,40 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin {
|
||||||
state.param.value = newParams;
|
state.param.value = newParams;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onPanUpPosition(Offset val) async {
|
||||||
|
// 手指在移动 非物体移动的位置
|
||||||
|
|
||||||
|
if (state.zoomOffset?.dy.toStringAsFixed(2) != val.dy.toStringAsFixed(2) ||
|
||||||
|
state.zoomOffset?.dx.toStringAsFixed(2) != val.dx.toStringAsFixed(2)) {
|
||||||
|
print('**************** 正在移动位置 YYY:${val.dy}');
|
||||||
|
print('**************** 正在移动位置 XXX:${val.dx}');
|
||||||
|
state.zoomOffset = val;
|
||||||
|
state.slide.value = val.dy.abs().toInt().toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缩放组件 ==> 缩放监听
|
||||||
|
void onScaleUpdate(double scale, double zoom) async {
|
||||||
|
state.initScale.value = zoom;
|
||||||
|
// print("$scale $zoom");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> toFavorite() async {
|
||||||
|
try {
|
||||||
|
var data = state.data.value!;
|
||||||
|
var param = state.param.value;
|
||||||
|
await getClient().toFavStudent(FavorParam(
|
||||||
|
homeworkId: param.homeworkId,
|
||||||
|
studentId: data.studentId,
|
||||||
|
templateId: data.templateId,
|
||||||
|
questionNo: data.studentQuestions[0].questionNo,
|
||||||
|
isFav: !data.isFav,
|
||||||
|
));
|
||||||
|
state.favorite.value = !data.isFav;
|
||||||
|
data.isFav = state.favorite.value;
|
||||||
|
} catch (e) {
|
||||||
|
ToastUtils.showError('操作失败,请重试');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
import 'dart:ui' show ImmutableBuffer, ImageDescriptor;
|
||||||
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
import 'index.dart';
|
||||||
|
|
||||||
|
part 'zoom_logic.g.dart';
|
||||||
|
|
||||||
|
class ZoomLogic extends GetxController {
|
||||||
|
final logic = Get.find<HomeworkReviewLogic>();
|
||||||
|
HomeworkReviewState get homeworkState => logic.state;
|
||||||
|
|
||||||
|
ZoomState zoomState = ZoomState(zoomFile: Rx<ZoomFileModel?>(null));
|
||||||
|
|
||||||
|
var oldTemplateId = null;
|
||||||
|
late StreamSubscription _streamHomework;
|
||||||
|
late StreamSubscription _streamZoomState;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onInit() {
|
||||||
|
oldTemplateId = zoomState.zoomFile.value?.templateId;
|
||||||
|
_streamZoomState = zoomState.zoomFile.listen((e) {
|
||||||
|
var templateId = e?.templateId;
|
||||||
|
print("ZOOMFILE 变化了 $templateId");
|
||||||
|
if (templateId == null) return;
|
||||||
|
|
||||||
|
var homeworkData = homeworkState.data.value;
|
||||||
|
var zgtAnswer = homeworkData?.zgtAnswer;
|
||||||
|
print("333333");
|
||||||
|
if (zgtAnswer == null) return;
|
||||||
|
print("444444 ${homeworkData!.templateId} 和 ${templateId}");
|
||||||
|
if (oldTemplateId == templateId) return;
|
||||||
|
|
||||||
|
// getNetworkImageDimensions(zgtAnswer);
|
||||||
|
|
||||||
|
// 第三方库网络图,图片会被解码并缓存于内存
|
||||||
|
oldTemplateId = templateId;
|
||||||
|
print("获取图片尺寸....");
|
||||||
|
CachedNetworkImageProvider(zgtAnswer).getImageSize().then((s) {
|
||||||
|
// 提取宽度和高度
|
||||||
|
if (s == null) return;
|
||||||
|
var oldVal = zoomState.zoomFile.value!;
|
||||||
|
oldVal.fileWidth = s.width;
|
||||||
|
oldVal.fileHeight = s.height;
|
||||||
|
zoomState.zoomFile.value = ZoomFileModel.fromJson(oldVal.toJson());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
_streamHomework = homeworkState.data.listen((e) {
|
||||||
|
print("HOMEWORKSTATE 变化了");
|
||||||
|
if (e == null || zoomState.zoomFile.value == null) return;
|
||||||
|
zoomState.zoomFile.value!.templateId = e.templateId;
|
||||||
|
print("666666 ${e.templateId}");
|
||||||
|
zoomState.zoomFile.value = ZoomFileModel.fromJson(zoomState.zoomFile.value!.toJson());
|
||||||
|
});
|
||||||
|
super.onInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose() {
|
||||||
|
_streamHomework.cancel();
|
||||||
|
_streamZoomState.cancel();
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ZoomState {
|
||||||
|
final Rx<ZoomFileModel?> zoomFile;
|
||||||
|
|
||||||
|
const ZoomState({required this.zoomFile});
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class ZoomFileModel extends Object {
|
||||||
|
double viewWidth; // 容器宽度
|
||||||
|
double viewHeight; // 容器高度
|
||||||
|
|
||||||
|
int? templateId; // 页码
|
||||||
|
|
||||||
|
double? fileWidth; // 文件宽度
|
||||||
|
double? fileHeight; // 文件高度
|
||||||
|
|
||||||
|
double? actualWidth; // 实际展示宽度
|
||||||
|
double? actualHeight; // 实际展示高度
|
||||||
|
|
||||||
|
ZoomFileModel({
|
||||||
|
required this.viewWidth,
|
||||||
|
required this.viewHeight,
|
||||||
|
this.templateId,
|
||||||
|
this.fileWidth,
|
||||||
|
this.fileHeight,
|
||||||
|
this.actualWidth,
|
||||||
|
this.actualHeight,
|
||||||
|
}) {
|
||||||
|
// 图片已视图宽为基准,高度自适应可滑动 图片的实际宽高都需要乘此基准值.
|
||||||
|
if (fileHeight == null || fileWidth == null) return;
|
||||||
|
|
||||||
|
var scaleRatio = viewWidth / fileWidth!;
|
||||||
|
actualWidth = fileWidth! * scaleRatio;
|
||||||
|
actualHeight = fileHeight! * scaleRatio;
|
||||||
|
|
||||||
|
// remainingHeight = boxHeight - actualImgHeight;
|
||||||
|
// imageHeightOffsetStart = remainingHeight / 2;
|
||||||
|
// imageHeightOffsetend = imageHeightOffsetStart + actualImgHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory ZoomFileModel.fromJson(Map<String, dynamic> srcJson) => _$ZoomFileModelFromJson(srcJson);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$ZoomFileModelToJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最终版
|
||||||
|
extension GetImageSize on ImageProvider {
|
||||||
|
Future<Size?> getImageSize({bool avoidDecode = false}) async {
|
||||||
|
if (avoidDecode) {
|
||||||
|
// 是否要免解码
|
||||||
|
final cacheStatus = await obtainCacheStatus(configuration: const ImageConfiguration());
|
||||||
|
final tracked = cacheStatus?.tracked ?? false;
|
||||||
|
// 内存缓存中存在时优先从缓存中取,不在内存缓存中时转换为 ImageDescriptor
|
||||||
|
if (!tracked) {
|
||||||
|
ImmutableBuffer? buffer;
|
||||||
|
if (this is AssetBundleImageProvider) {
|
||||||
|
final key = await obtainKey(const ImageConfiguration()) as AssetBundleImageKey;
|
||||||
|
buffer = await key.bundle.loadBuffer(key.name);
|
||||||
|
} else if (this is FileImage) {
|
||||||
|
final file = (this as FileImage).file;
|
||||||
|
final int lengthInBytes = await file.length();
|
||||||
|
if (lengthInBytes > 0) {
|
||||||
|
buffer = await ImmutableBuffer.fromFilePath(file.path);
|
||||||
|
}
|
||||||
|
} else if (this is MemoryImage) {
|
||||||
|
final bytes = (this as MemoryImage).bytes;
|
||||||
|
buffer = await ImmutableBuffer.fromUint8List(bytes);
|
||||||
|
}
|
||||||
|
if (buffer != null) {
|
||||||
|
final descriptor = await ImageDescriptor.encoded(buffer);
|
||||||
|
final size = Size(descriptor.width.toDouble(), descriptor.height.toDouble());
|
||||||
|
buffer.dispose();
|
||||||
|
descriptor.dispose();
|
||||||
|
if (!size.isEmpty) return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 免解码末开启或内存缓存已存在,最后再兜底上面未处理的情况
|
||||||
|
final completer = Completer<Size?>();
|
||||||
|
ImageStream imageStream = resolve(const ImageConfiguration());
|
||||||
|
|
||||||
|
ImageStreamListener? listener;
|
||||||
|
listener = ImageStreamListener(
|
||||||
|
(imageInfo, synchronousCall) {
|
||||||
|
if (!completer.isCompleted) {
|
||||||
|
completer.complete(Size(imageInfo.image.width.toDouble(), imageInfo.image.height.toDouble()));
|
||||||
|
}
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
imageInfo.dispose();
|
||||||
|
imageStream.removeListener(listener!);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onError: (exception, stackTrace) {
|
||||||
|
if (!completer.isCompleted) {
|
||||||
|
completer.complete();
|
||||||
|
}
|
||||||
|
imageStream.removeListener(listener!);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
imageStream.addListener(listener);
|
||||||
|
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,43 +7,22 @@ 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 'package:making_school_asignment_app/page/home_page/children/annotate_class/annotate_class_logic.dart';
|
||||||
import 'package:making_school_asignment_app/page/home_page/children/homework_review/components/question_paper_view.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/homework_review/components/question_paper_view.dart';
|
||||||
import 'package:making_school_asignment_app/page/home_page/home_logic.dart';
|
import 'package:making_school_asignment_app/page/home_page/home_logic.dart';
|
||||||
import 'package:zoom_widget/zoom_widget.dart';
|
|
||||||
|
|
||||||
import 'components/bottom_operation_bar.dart';
|
import 'components/bottom_operation_bar.dart';
|
||||||
import 'components/dropdown_switch_students_type.dart';
|
import 'components/dropdown_switch_students_type.dart';
|
||||||
import 'components/favorite_widget.dart';
|
import 'components/favorite_widget.dart';
|
||||||
import 'configuration_files/index.dart';
|
import 'configuration_files/index.dart';
|
||||||
|
|
||||||
class HomeworkReview extends StatefulWidget {
|
class HomeworkReview extends StatelessWidget {
|
||||||
const HomeworkReview({super.key});
|
const HomeworkReview({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<HomeworkReview> createState() => _HomeworkReviewState();
|
Widget build(BuildContext context) {
|
||||||
}
|
|
||||||
|
|
||||||
class _HomeworkReviewState extends State<HomeworkReview> {
|
|
||||||
final ScrollController controller = ScrollController();
|
|
||||||
final logic = Get.find<HomeworkReviewLogic>();
|
final logic = Get.find<HomeworkReviewLogic>();
|
||||||
final sateData = Get.find<HomeworkReviewLogic>().state;
|
final sateData = logic.state;
|
||||||
final AnnotateClassLogic _controller = Get.find<AnnotateClassLogic>();
|
final AnnotateClassLogic _controller = Get.find<AnnotateClassLogic>();
|
||||||
final HomeLogic _homeLogicController = Get.find<HomeLogic>();
|
final HomeLogic _homeLogicController = Get.find<HomeLogic>();
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); // 屏幕刘海
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
Get.delete<HomeworkReviewLogic>();
|
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]); // 屏幕刘海
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return PopScope(
|
return PopScope(
|
||||||
canPop: false,
|
canPop: false,
|
||||||
onPopInvoked: (e) {
|
onPopInvoked: (e) {
|
||||||
|
|
@ -65,23 +44,22 @@ class _HomeworkReviewState extends State<HomeworkReview> {
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
// 下拉切换
|
// 下拉切换 30.h
|
||||||
const DropdownSwitchStudentsType(),
|
const DropdownSwitchStudentsType(),
|
||||||
|
// +1
|
||||||
SizedBox(height: 1.h),
|
SizedBox(height: 1.h),
|
||||||
const Expanded(
|
const Expanded(child: QuestionPaperView()),
|
||||||
child: QuestionPaperView(),
|
// +64.h
|
||||||
|
|
||||||
// child: Container(
|
|
||||||
// height: double.infinity,
|
|
||||||
// width: double.infinity,
|
|
||||||
// color: Colors.red,
|
|
||||||
// ),
|
|
||||||
// child: QuestionPaperView(),
|
|
||||||
),
|
|
||||||
const BottomAnnotationSwitch()
|
const BottomAnnotationSwitch()
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// floatingActionButton: const ButtonFloatingAction(),
|
// floatingActionButton: FloatingActionButton(
|
||||||
|
// elevation: 8,
|
||||||
|
// tooltip: "点击打开工具栏",
|
||||||
|
// backgroundColor: Colors.white,
|
||||||
|
// onPressed: () {},
|
||||||
|
// child: Icon(Icons.edit, size: 20.sp, color: Theme.of(context).primaryColor),
|
||||||
|
// ),
|
||||||
// floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
|
// floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import 'package:making_school_asignment_app/common/store/user_store.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/toast_utils.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/common/utils/utils.dart';
|
||||||
import 'package:making_school_asignment_app/page/login_page/children/sys_protocol.dart';
|
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
import 'package:making_school_asignment_app/common/store/app_storage_key.dart';
|
import 'package:making_school_asignment_app/common/store/app_storage_key.dart';
|
||||||
|
|
||||||
|
|
@ -16,12 +15,6 @@ import 'login_state.dart';
|
||||||
class LoginLogic extends GetxController with RequestToolMixin {
|
class LoginLogic extends GetxController with RequestToolMixin {
|
||||||
final LoginState state = LoginState();
|
final LoginState state = LoginState();
|
||||||
|
|
||||||
@override
|
|
||||||
void onReady() {
|
|
||||||
// TODO: implement onReady
|
|
||||||
super.onReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
|
|
@ -37,6 +30,8 @@ class LoginLogic extends GetxController with RequestToolMixin {
|
||||||
state.passwordController.text = pwd;
|
state.passwordController.text = pwd;
|
||||||
state.keepPwd.value = true;
|
state.keepPwd.value = true;
|
||||||
}
|
}
|
||||||
|
state.userNameController.text = "AppleTester";
|
||||||
|
state.passwordController.text = "AppleTester123!";
|
||||||
|
|
||||||
state.pwdFocus = FocusNode();
|
state.pwdFocus = FocusNode();
|
||||||
state.theFocus = FocusNode();
|
state.theFocus = FocusNode();
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,12 @@ class _LoginPageState extends State<LoginPage> {
|
||||||
statusBarIconBrightness: Brightness.light,
|
statusBarIconBrightness: Brightness.light,
|
||||||
statusBarColor: Colors.transparent, //状态栏背景颜色
|
statusBarColor: Colors.transparent, //状态栏背景颜色
|
||||||
));
|
));
|
||||||
Future.delayed(Duration.zero, () => upgradeLogic.getAppUpgrade(context));
|
|
||||||
Future.delayed(Duration.zero, () => sysProtocol(context));
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
void dispose() {
|
await sysProtocol(context);
|
||||||
Get.delete<LoginLogic>();
|
await Future.delayed(Duration.zero, () => upgradeLogic.getAppUpgrade(context));
|
||||||
super.dispose();
|
});
|
||||||
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -231,7 +228,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||||
padding: EdgeInsets.only(right: 0.w),
|
padding: EdgeInsets.only(right: 0.w),
|
||||||
child: Obx(() {
|
child: Obx(() {
|
||||||
return Transform.scale(
|
return Transform.scale(
|
||||||
scale: 1.2,
|
scale: 1.0,
|
||||||
child: Checkbox(
|
child: Checkbox(
|
||||||
// activeColor: Colors.transparent, //去掉勾选时背景颜色
|
// activeColor: Colors.transparent, //去掉勾选时背景颜色
|
||||||
|
|
||||||
|
|
@ -309,8 +306,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 50.h,
|
height: 50.h,
|
||||||
child: Text('登 录', style: TextStyle(fontSize: 16.sp, color: Colors.white)),
|
child: quickText('登 录', size: 18.sp, color: Colors.white));
|
||||||
);
|
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
|
|
@ -320,7 +316,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||||
padding: EdgeInsets.only(right: 0.w),
|
padding: EdgeInsets.only(right: 0.w),
|
||||||
child: Obx(() {
|
child: Obx(() {
|
||||||
return Transform.scale(
|
return Transform.scale(
|
||||||
scale: 1.2,
|
scale: 1.0,
|
||||||
child: Checkbox(
|
child: Checkbox(
|
||||||
activeColor: Theme.of(context).primaryColor,
|
activeColor: Theme.of(context).primaryColor,
|
||||||
checkColor: Colors.white,
|
checkColor: Colors.white,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.0.1+2
|
version: 1.0.0+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.4.1 <4.0.0'
|
sdk: '>=3.4.1 <4.0.0'
|
||||||
|
|
@ -48,7 +48,7 @@ dependencies:
|
||||||
# http请求插件
|
# http请求插件
|
||||||
dio: ^5.4.2+1
|
dio: ^5.4.2+1
|
||||||
# 网络缓存图片
|
# 网络缓存图片
|
||||||
cached_network_image: ^3.2.1
|
cached_network_image: ^3.3.1
|
||||||
# 上拉加载和下拉刷新的组件
|
# 上拉加载和下拉刷新的组件
|
||||||
flutter_easyrefresh: ^2.2.2
|
flutter_easyrefresh: ^2.2.2
|
||||||
photo_view: ^0.15.0
|
photo_view: ^0.15.0
|
||||||
|
|
@ -98,7 +98,8 @@ dependencies:
|
||||||
app_settings: ^5.1.1
|
app_settings: ^5.1.1
|
||||||
device_info_plus: ^11.1.0
|
device_info_plus: ^11.1.0
|
||||||
zoom_widget: ^2.0.1
|
zoom_widget: ^2.0.1
|
||||||
|
zoom_pinch_overlay: ^1.4.3
|
||||||
|
flutter_html_2: ^0.1.0
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
@ -109,6 +110,7 @@ dev_dependencies:
|
||||||
json_serializable: ^6.6.2
|
json_serializable: ^6.6.2
|
||||||
# 分离样式
|
# 分离样式
|
||||||
functional_widget: ^0.10.2
|
functional_widget: ^0.10.2
|
||||||
|
analyzer: ^6.4.1
|
||||||
# The "flutter_lints" package below contains a set of recommended lints to
|
# The "flutter_lints" package below contains a set of recommended lints to
|
||||||
# encourage good coding practices. The lint set provided by the package is
|
# encourage good coding practices. The lint set provided by the package is
|
||||||
# activated in the `analysis_options.yaml` file located at the root of your
|
# activated in the `analysis_options.yaml` file located at the root of your
|
||||||
|
|
@ -120,6 +122,9 @@ dev_dependencies:
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
# The following section is specific to Flutter packages.
|
# The following section is specific to Flutter packages.
|
||||||
|
# dependency_overrides:
|
||||||
|
# collection: ^1.19.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
||||||
# The following line ensures that the Material Icons font is
|
# The following line ensures that the Material Icons font is
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue