修复优化页面,修复部分问题。暂时提交
This commit is contained in:
parent
70f658f87d
commit
b6af1f57a4
|
|
@ -180,7 +180,7 @@ class ShapeRecognizer {
|
|||
// return GestureType.none;
|
||||
}
|
||||
|
||||
/// 辅助函数:根据您的方案,判断一个组合是否构成半勾。
|
||||
/// 辅助函数:判断一个组合是否构成半勾。
|
||||
/// [checkCandidate] 可能是勾的笔画
|
||||
/// [crosserCandidate] 可能是交叉线的笔画
|
||||
/// [checkDetails] 勾的细节信息
|
||||
|
|
@ -217,7 +217,7 @@ class ShapeRecognizer {
|
|||
return false; // 交叉点或角度不满足条件,此组合失败。
|
||||
}
|
||||
|
||||
/// [新增] 专为“半勾”设计的交叉检测函数,以实现的判断方案。
|
||||
/// 专为“半勾”设计的交叉检测函数,以实现的判断方案。
|
||||
/// 它允许交叉点靠近 `checkLeg` 的终点,但对 `crossLine` 保持严格的内部交叉要求。
|
||||
Offset? _findIntersectionNearTip(
|
||||
Offset crossLineStart, Offset crossLineEnd, Offset checkLegStart, Offset checkLegEnd) {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ void main() async {
|
|||
statusBarColor: Colors.transparent, //状态栏背景颜色
|
||||
statusBarIconBrightness: Brightness.light // dark:一般显示黑色 light:一般显示白色
|
||||
));
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top]); // 屏幕刘海
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky, overlays: [SystemUiOverlay.top]); // 屏幕刘海
|
||||
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); // 屏幕强制竖屏
|
||||
runApp(const MyApp());
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class _GestureCanvasPageState extends State<GestureCanvasPage> {
|
|||
GestureType _recognizedGesture = GestureType.none;
|
||||
late ShapeRecognizer _recognizer;
|
||||
|
||||
// [新增] 用于控制是否显示可视化特征点的状态
|
||||
// 用于控制是否显示可视化特征点的状态
|
||||
bool _showSimplifiedPoints = true;
|
||||
|
||||
@override
|
||||
|
|
@ -123,7 +123,7 @@ class _GestureCanvasPageState extends State<GestureCanvasPage> {
|
|||
appBar: AppBar(
|
||||
title: const Text('手势识别 (可视化调试)'),
|
||||
actions: [
|
||||
// [新增] 在AppBar中添加一个信息提示
|
||||
// 在AppBar中添加一个信息提示
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 16.0),
|
||||
child: Icon(
|
||||
|
|
@ -179,7 +179,7 @@ class _GestureCanvasPageState extends State<GestureCanvasPage> {
|
|||
child: const Icon(Icons.clear),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
// [新增] 用于切换可视化模式的按钮
|
||||
// 用于切换可视化模式的按钮
|
||||
FloatingActionButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
|
|
@ -205,7 +205,7 @@ class _GestureCanvasPainter extends CustomPainter {
|
|||
final List<List<Offset>> allStrokes;
|
||||
final double rdpEpsilon;
|
||||
final bool showSimplifiedPoints;
|
||||
final Paint _debugPaint; // [新增] 专门用于绘制特征点的画笔
|
||||
final Paint _debugPaint; // 专门用于绘制特征点的画笔
|
||||
|
||||
_GestureCanvasPainter({
|
||||
required this.cachedImage,
|
||||
|
|
@ -218,7 +218,7 @@ class _GestureCanvasPainter extends CustomPainter {
|
|||
..strokeCap = StrokeCap.round
|
||||
..strokeWidth = 5.0
|
||||
..style = PaintingStyle.stroke,
|
||||
// [新增] 初始化调试画笔
|
||||
// 初始化调试画笔
|
||||
_debugPaint = Paint()
|
||||
..color = Colors.red
|
||||
..strokeCap = StrokeCap.round
|
||||
|
|
@ -241,7 +241,7 @@ class _GestureCanvasPainter extends CustomPainter {
|
|||
canvas.drawPath(path, _paint);
|
||||
}
|
||||
|
||||
// [新增] 步骤3: 如果开启了可视化,则绘制简化后的特征点
|
||||
// 步骤3: 如果开启了可视化,则绘制简化后的特征点
|
||||
if (showSimplifiedPoints) {
|
||||
// 为所有已完成的笔画绘制特征点
|
||||
for (final stroke in allStrokes) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import 'package:making_school_asignment_app/common/job/marking_models/do_paper_b
|
|||
import 'package:making_school_asignment_app/common/mixins/event_bus_mixin.dart';
|
||||
import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart';
|
||||
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||
|
||||
import '../configuration_files/index.dart';
|
||||
|
||||
|
|
@ -62,19 +61,23 @@ class _BottomAnnotationSwitchJobState extends State<BottomAnnotationSwitch>
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double iconSize = 18.sp;
|
||||
Color actionColor = Colors.white;
|
||||
Color defaultColor = const Color.fromRGBO(132, 146, 163, 1);
|
||||
|
||||
return SafeArea(
|
||||
left: false,
|
||||
right: false,
|
||||
top: false,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: _animationController.value * 64.h,
|
||||
height: _animationController.value * 70.h,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color.fromRGBO(83, 83, 83, 1),
|
||||
// padding: EdgeInsets.symmetric(vertical: 1.h),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, -2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
|
|
@ -87,109 +90,83 @@ class _BottomAnnotationSwitchJobState extends State<BottomAnnotationSwitch>
|
|||
children: [
|
||||
// 全对按钮
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: TextButton(
|
||||
child: quickText('全 对', color: Colors.white, size: 12.sp),
|
||||
onPressed: () => easyThrottle('homework_bottom_operation_bar_scoring_related',
|
||||
child: _buildActionButton(
|
||||
'全对',
|
||||
Icons.check_circle_outline,
|
||||
() => easyThrottle('homework_bottom_operation_bar_scoring_related',
|
||||
() => _homeworkLogic.allPairs(context)),
|
||||
isEnabled: !_homeworkLogic.state.submitLoading.value,
|
||||
isPrimary: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(width: 0.3.w, height: double.infinity, color: Colors.white),
|
||||
Container(width: 0.5.w, height: double.infinity, color: Colors.white.withOpacity(0.3)),
|
||||
// 注解笔
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: IconButton(
|
||||
icon: Obx(() {
|
||||
return Icon(
|
||||
child: Obx(() => _buildIconButton(
|
||||
const IconData(0xe635, fontFamily: "AlibabaIcon"),
|
||||
size: iconSize,
|
||||
color: _logicControl.pen.value ? Theme.of(context).primaryColor : defaultColor,
|
||||
);
|
||||
}),
|
||||
onPressed: () => easyThrottle('homework_bottom_action_bar_annotations', () {
|
||||
() => easyThrottle('homework_bottom_action_bar_annotations', () {
|
||||
// 互斥:启用注解笔,禁用滑动
|
||||
_logicControl.gestureMove.value = false;
|
||||
_logicControl.pen.value = !_logicControl.pen.value;
|
||||
_logicControl.pen.value = true;
|
||||
}),
|
||||
isActive: _logicControl.pen.value,
|
||||
tooltip: '注解笔',
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(width: 0.3.w, height: double.infinity, color: Colors.white),
|
||||
Container(width: 0.5.w, height: double.infinity, color: Colors.white.withOpacity(0.3)),
|
||||
// 滑动试题
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: IconButton(
|
||||
icon: Obx(
|
||||
() {
|
||||
return Icon(
|
||||
child: Obx(() => _buildIconButton(
|
||||
const IconData(0xe636, fontFamily: "AlibabaIcon"),
|
||||
size: iconSize,
|
||||
color: _logicControl.gestureMove.value ? actionColor : defaultColor,
|
||||
);
|
||||
},
|
||||
),
|
||||
onPressed: () => easyThrottle('homework_bottom_action_bar_annotations', () {
|
||||
() => easyThrottle('homework_bottom_action_bar_annotations', () {
|
||||
// 互斥:启用滑动,禁用注解笔
|
||||
_logicControl.pen.value = false;
|
||||
_logicControl.gestureMove.value = !_logicControl.gestureMove.value;
|
||||
_logicControl.gestureMove.value = true;
|
||||
}),
|
||||
),
|
||||
),
|
||||
isActive: _logicControl.gestureMove.value,
|
||||
tooltip: '滑动试题',
|
||||
)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(width: double.infinity, color: Colors.white, height: 0.35.h),
|
||||
Container(width: double.infinity, color: Colors.white.withOpacity(0.3), height: 0.5.h),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
// 全错按钮
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: TextButton(
|
||||
onPressed: () => easyThrottle('homework_bottom_operation_bar_scoring_related',
|
||||
child: _buildActionButton(
|
||||
'全错',
|
||||
Icons.cancel_outlined,
|
||||
() => easyThrottle('homework_bottom_operation_bar_scoring_related',
|
||||
() => _homeworkLogic.allWrongRating(context)),
|
||||
child: quickText('全 错', color: Colors.white, size: 12.sp),
|
||||
isEnabled: !_homeworkLogic.state.submitLoading.value,
|
||||
isPrimary: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(width: 0.3.w, height: double.infinity, color: Colors.white),
|
||||
Container(width: 0.5.w, height: double.infinity, color: Colors.white.withOpacity(0.3)),
|
||||
// 撤销上一步
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: IconButton(
|
||||
onPressed: () => easyThrottle(
|
||||
child: _buildIconButton(
|
||||
const IconData(0xe638, fontFamily: "AlibabaIcon"),
|
||||
() => easyThrottle(
|
||||
'homework_bottom_action_bar_annotations',
|
||||
() => eventFire(model: BottomOperationBar(revokeAll: false, revokePreStep: true)),
|
||||
),
|
||||
icon: Icon(const IconData(0xe638, fontFamily: "AlibabaIcon"),
|
||||
size: iconSize, color: defaultColor),
|
||||
tooltip: '撤销上一步',
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(width: 0.3.w, height: double.infinity, color: Colors.white),
|
||||
Container(width: 0.5.w, height: double.infinity, color: Colors.white.withOpacity(0.3)),
|
||||
// 全部撤销
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: IconButton(
|
||||
icon: Icon(const IconData(0xe637, fontFamily: "AlibabaIcon"),
|
||||
size: iconSize, color: defaultColor),
|
||||
onPressed: () => easyThrottle(
|
||||
child: _buildIconButton(
|
||||
const IconData(0xe637, fontFamily: "AlibabaIcon"),
|
||||
() => easyThrottle(
|
||||
'homework_bottom_action_bar_annotations',
|
||||
() => eventFire(model: BottomOperationBar(revokeAll: true, revokePreStep: false)),
|
||||
),
|
||||
),
|
||||
tooltip: '全部撤销',
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -198,49 +175,36 @@ class _BottomAnnotationSwitchJobState extends State<BottomAnnotationSwitch>
|
|||
],
|
||||
),
|
||||
),
|
||||
Container(width: 0.3.w, height: double.infinity, color: Colors.white),
|
||||
Container(width: 0.5.w, height: double.infinity, color: Colors.white.withOpacity(0.3)),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: TextButton(
|
||||
onPressed: () => easyThrottle(
|
||||
child: _buildActionButton(
|
||||
'取消',
|
||||
Icons.clear,
|
||||
() => easyThrottle(
|
||||
'homework_bottom_operation_bar_scoring_related', () => _homeworkLogic.cancelAllRatings()),
|
||||
child: quickText('取 消', size: 14.sp, color: Colors.white),
|
||||
isEnabled: true,
|
||||
isPrimary: false,
|
||||
isSecondary: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(width: 0.3.w, height: double.infinity, color: Colors.white),
|
||||
Container(width: 0.5.w, height: double.infinity, color: Colors.white.withOpacity(0.3)),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: TextButton(
|
||||
onPressed: () => easyThrottle(
|
||||
child: Obx(() {
|
||||
final submitLoading = _homeworkLogic.state.submitLoading.value;
|
||||
return _buildActionButton(
|
||||
'提交',
|
||||
Icons.send,
|
||||
() => easyThrottle(
|
||||
'homework_bottom_operation_bar_scoring_related', () => _homeworkLogic.submit(context)),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Obx(() {
|
||||
if (_homeworkLogic.state.submitLoading.value) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(right: 4.w),
|
||||
child: const SizedBox(
|
||||
width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2)),
|
||||
isEnabled: !submitLoading,
|
||||
isPrimary: true,
|
||||
isLoading: submitLoading,
|
||||
);
|
||||
}
|
||||
return const SizedBox();
|
||||
}),
|
||||
quickText('提 交', size: 14.sp, color: Theme.of(context).primaryColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -249,4 +213,124 @@ class _BottomAnnotationSwitchJobState extends State<BottomAnnotationSwitch>
|
|||
),
|
||||
));
|
||||
}
|
||||
|
||||
Widget _buildActionButton(
|
||||
String text,
|
||||
IconData icon,
|
||||
VoidCallback? onPressed, {
|
||||
required bool isEnabled,
|
||||
required bool isPrimary,
|
||||
bool isSecondary = false,
|
||||
bool isLoading = false,
|
||||
}) {
|
||||
final primaryColor = Theme.of(context).primaryColor;
|
||||
const defaultColor = Color.fromRGBO(132, 146, 163, 1);
|
||||
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: isEnabled ? onPressed : null,
|
||||
child: Semantics(
|
||||
label: text,
|
||||
hint: isLoading ? '正在处理中' : (isEnabled ? '点击执行$text操作' : '$text按钮已禁用'),
|
||||
button: true,
|
||||
enabled: isEnabled && !isLoading,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: isPrimary
|
||||
? (isEnabled ? primaryColor : primaryColor.withOpacity(0.5))
|
||||
: isSecondary
|
||||
? Colors.transparent
|
||||
: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(4.r),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (isLoading)
|
||||
SizedBox(
|
||||
width: 16.w,
|
||||
height: 16.w,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
isPrimary ? Colors.white : primaryColor,
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
Icon(
|
||||
icon,
|
||||
size: 16.sp,
|
||||
color: isEnabled
|
||||
? (isPrimary ? Colors.white : (isSecondary ? Colors.white70 : defaultColor))
|
||||
: Colors.white38,
|
||||
),
|
||||
SizedBox(height: 2.h),
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color: isEnabled
|
||||
? (isPrimary ? Colors.white : (isSecondary ? Colors.white70 : Colors.white))
|
||||
: Colors.white38,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildIconButton(
|
||||
IconData icon,
|
||||
VoidCallback? onPressed, {
|
||||
bool isActive = false,
|
||||
String? tooltip,
|
||||
}) {
|
||||
final primaryColor = Theme.of(context).primaryColor;
|
||||
const defaultColor = Color.fromRGBO(132, 146, 163, 1);
|
||||
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: onPressed,
|
||||
child: Tooltip(
|
||||
message: tooltip ?? '',
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: isActive ? primaryColor.withOpacity(0.2) : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(4.r),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
size: 18.sp,
|
||||
color: isActive ? primaryColor : defaultColor,
|
||||
),
|
||||
SizedBox(height: 2.h),
|
||||
Container(
|
||||
width: 4.w,
|
||||
height: 4.w,
|
||||
decoration: BoxDecoration(
|
||||
color: isActive ? primaryColor : Colors.transparent,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ 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/utils/anti_shake_throttling.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/configuration_files/index.dart';
|
||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||
|
|
@ -61,7 +60,8 @@ class DropdownSwitchStudentsType extends StatelessWidget {
|
|||
items: sateData.value?.templateIdKeys?.map((e) {
|
||||
return DropdownMenuItem(
|
||||
value: e,
|
||||
child: quickText('${sateData.value!.templateIdKeyMap![e]}页', color: const Color.fromRGBO(79, 79, 79, 1), size: 14.sp),
|
||||
child: quickText('${sateData.value!.templateIdKeyMap![e]}页',
|
||||
color: const Color.fromRGBO(79, 79, 79, 1), size: 14.sp),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) {
|
||||
|
|
@ -77,7 +77,9 @@ class DropdownSwitchStudentsType extends StatelessWidget {
|
|||
final students = sateData.value?.students ?? [];
|
||||
|
||||
// 获取当前学生姓名
|
||||
final currentStudent = currentStudentId != null ? students.firstWhereOrNull((e) => e.id == currentStudentId) : null;
|
||||
final currentStudent = currentStudentId != null
|
||||
? students.firstWhereOrNull((e) => e.id == currentStudentId)
|
||||
: null;
|
||||
|
||||
final studentName = currentStudent?.name ?? '当前学生';
|
||||
final questionNumber = templateIdKeyMap?[value] ?? '当前选择页';
|
||||
|
|
@ -95,7 +97,7 @@ class DropdownSwitchStudentsType extends StatelessWidget {
|
|||
}),
|
||||
),
|
||||
),
|
||||
const Expanded(flex: 1, child: SizedBox()),
|
||||
SizedBox(width: 8.w),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Stack(
|
||||
|
|
@ -120,7 +122,9 @@ class DropdownSwitchStudentsType extends StatelessWidget {
|
|||
alignment: const FractionalOffset(0, 0.62),
|
||||
children: [
|
||||
Container(
|
||||
padding: sateData.value?.studentId != e.id && e.isPriority ? EdgeInsets.only(left: 14.w) : null,
|
||||
padding: sateData.value?.studentId != e.id && e.isPriority
|
||||
? EdgeInsets.only(left: 14.w)
|
||||
: null,
|
||||
child: quickText(
|
||||
e.name,
|
||||
size: 14.sp,
|
||||
|
|
@ -134,7 +138,9 @@ class DropdownSwitchStudentsType extends StatelessWidget {
|
|||
Icon(
|
||||
const IconData(0xe63d, fontFamily: "AlibabaIcon"),
|
||||
size: 12.sp,
|
||||
color: e.isPriority ? Theme.of(context).primaryColor : const Color.fromRGBO(164, 164, 164, 1),
|
||||
color: e.isPriority
|
||||
? Theme.of(context).primaryColor
|
||||
: const Color.fromRGBO(164, 164, 164, 1),
|
||||
),
|
||||
quickText('优先', size: 4.sp, color: Colors.white),
|
||||
],
|
||||
|
|
@ -161,7 +167,9 @@ class DropdownSwitchStudentsType extends StatelessWidget {
|
|||
return Icon(
|
||||
const IconData(0xe63d, fontFamily: "AlibabaIcon"),
|
||||
size: 12.sp,
|
||||
color: sateData.value?.priority ?? false ? Theme.of(context).primaryColor : const Color.fromRGBO(164, 164, 164, 1),
|
||||
color: sateData.value?.priority ?? false
|
||||
? Theme.of(context).primaryColor
|
||||
: const Color.fromRGBO(164, 164, 164, 1),
|
||||
);
|
||||
}),
|
||||
quickText('优先', size: 4.sp, color: Colors.white),
|
||||
|
|
@ -173,9 +181,9 @@ class DropdownSwitchStudentsType extends StatelessWidget {
|
|||
),
|
||||
// const Expanded(flex: 1, child: SizedBox()),
|
||||
SizedBox(width: 8.w),
|
||||
Expanded(
|
||||
flex: isPad() ? 4 : 5,
|
||||
child: const Row(
|
||||
const Expanded(
|
||||
flex: 5,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
|
|
@ -208,7 +216,8 @@ Widget $studentHandwriting(BuildContext context) {
|
|||
if (templateIdKeyMap != null && templateId != null) {
|
||||
pageNum = templateIdKeyMap[templateId];
|
||||
}
|
||||
await showAnswerHandwriting(context, homeworkId: homeworkId, studentId: studentId, templateId: templateId, pageNum: pageNum);
|
||||
await showAnswerHandwriting(context,
|
||||
homeworkId: homeworkId, studentId: studentId, templateId: templateId, pageNum: pageNum);
|
||||
ToastUtils.dismiss();
|
||||
},
|
||||
),
|
||||
|
|
@ -238,7 +247,10 @@ Widget $continueToReview(BuildContext context, {bool isFloatingAction = false})
|
|||
int? annotatedCount = data?.annotatedCount; // 批阅数量
|
||||
// || (submitCount == annotatedCount || (param.templateId == null && param.studentId == null))
|
||||
// if (data == null || (data.needAnnotate ? true : data.totalUnAnnotateCount <= 0) ) return const SizedBox();
|
||||
if (data == null || (data.needAnnotate ? (data.continuePage == null ? true : data.continuePage!.templateId == data.templateId) : data.totalUnAnnotateCount <= 0)) return const SizedBox();
|
||||
if (data == null ||
|
||||
(data.needAnnotate
|
||||
? (data.continuePage == null ? true : data.continuePage!.templateId == data.templateId)
|
||||
: data.totalUnAnnotateCount <= 0)) return const SizedBox();
|
||||
callFun() => easyThrottle(
|
||||
'DO_PAPERS_JOB_CONTINUE_TO_REVIEW',
|
||||
() {
|
||||
|
|
@ -292,7 +304,11 @@ Widget $historyHomework(BuildContext context) {
|
|||
var currentStudent = sateData.value!.students.firstWhereOrNull((e) => e.id == studentId);
|
||||
if (currentStudent == null) return;
|
||||
var theState = Get.find<HomeworkReviewLogic>().state;
|
||||
Get.toNamed(Routes.studentWorkDetailPage, arguments: {'studentId': studentId, 'studentName': currentStudent.name, 'subject': theState.param.value.subject});
|
||||
Get.toNamed(Routes.studentWorkDetailPage, arguments: {
|
||||
'studentId': studentId,
|
||||
'studentName': currentStudent.name,
|
||||
'subject': theState.param.value.subject
|
||||
});
|
||||
}),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
|
|
|
|||
|
|
@ -547,20 +547,18 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
|||
// }
|
||||
// (dy / theScale) - (max(0, imageHeightOffsetStart) / theScale) + ((sateData.zoomOffset?.dy.abs() ?? 0) / theScale),
|
||||
|
||||
var zoomWtdthSpaceVal = zoomFile.getZoomFileOffsetStartWidth(zoomState.initScale.value ?? 1);
|
||||
var leftOffset = zoomFile.getZoomFileOffsetStartWidth(theScale);
|
||||
var topOffset = max(0, imageHeightOffsetStart);
|
||||
|
||||
localPosition = Offset(
|
||||
(localPosition.dx -
|
||||
zoomFile.getZoomFileOffsetStartWidth(zoomState.initScale.value ?? 1) +
|
||||
((zoomWtdthSpaceVal <= 0.1) ? (sateData.zoomOffset?.dx.abs() ?? 0) : 0)) /
|
||||
theScale,
|
||||
(dy -
|
||||
max(0, imageHeightOffsetStart) +
|
||||
((zoomFile.imageHeightOffsetStart == null || zoomFile.imageHeightOffsetStart! <= 0.1)
|
||||
? (sateData.zoomOffset?.dy.abs() ?? 0)
|
||||
: 0)) /
|
||||
theScale,
|
||||
);
|
||||
// 优先使用变换矩阵获得当前内容平移(有符号,右/下为正,左/上为负)
|
||||
final translation = logic.zoomController.value.getTranslation();
|
||||
final panDx = translation.x;
|
||||
final panDy = translation.y;
|
||||
|
||||
// 将屏幕触点换算到图片坐标:先去除图片在容器中的留白,再减去内容平移,最后按缩放反算
|
||||
final correctedDx = (localPosition.dx - leftOffset - panDx) / theScale;
|
||||
final correctedDy = (dy - topOffset - panDy) / theScale;
|
||||
localPosition = Offset(correctedDx, correctedDy);
|
||||
|
||||
/// 判断当前点和上一个点的距离 判断是否是多指
|
||||
if (Platform.isAndroid) {
|
||||
|
|
@ -579,13 +577,13 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
|||
var isPen = annotationState.pen.value;
|
||||
var showZgtAnnotate = sateData.data.value?.showZgtAnnotate;
|
||||
|
||||
print(sateData.data.value!.zgtAnswer);
|
||||
return Container(
|
||||
height: double.infinity,
|
||||
width: double.infinity,
|
||||
alignment: Alignment.center,
|
||||
child: IgnorePointer(
|
||||
ignoring: isPen,
|
||||
// 仅当“滑动试题”启用时,让 Zoom 接收触摸;否则屏蔽以避免与批注冲突
|
||||
ignoring: !annotationState.gestureMove.value,
|
||||
child:
|
||||
// ZoomView(
|
||||
// key: zoomKey.value,
|
||||
|
|
@ -600,7 +598,8 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
|||
// onContentOffset: logic.zoomLogic.onPanUpPosition,
|
||||
// ),
|
||||
|
||||
Zoom(
|
||||
Obx(
|
||||
() => Zoom(
|
||||
key: zoomKey.value,
|
||||
// initTotalZoomOut: true, // 展示全部内容 初始化不产生滚动条
|
||||
zoomSensibility: 0.05,
|
||||
|
|
@ -627,7 +626,7 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
|||
key: logic.pictureOverviewKey,
|
||||
child: CustomPaint(
|
||||
// isComplex: true,
|
||||
size: Size(maxWidth, zoomState.zoomFile.value!.actualHeight!),
|
||||
size: Size(maxWidth, actualHeight),
|
||||
foregroundPainter: DrawingPainter(ctrl: vnHandWritings),
|
||||
// child: $TheCachedNetworkImage(
|
||||
// imgWidth: maxWidth,
|
||||
|
|
@ -645,7 +644,7 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
|
|||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:dio/dio.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:making_school_asignment_app/common/job/annotate_list_to_refresh.dart';
|
||||
import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_param.dart';
|
||||
|
|
@ -18,7 +19,6 @@ import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dar
|
|||
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/upload_oss_img_utils.dart';
|
||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:zoom_widget/zoom_widget.dart' as zoomWidget;
|
||||
|
||||
|
|
@ -88,7 +88,6 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
|
|||
@override
|
||||
void onInit() {
|
||||
appBarHeight = MediaQuery.of(Get.context!).padding.top;
|
||||
print("appBarHeight :$appBarHeight");
|
||||
// WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); // 屏幕刘海
|
||||
|
|
@ -158,17 +157,13 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
|
|||
}
|
||||
|
||||
void getData() async {
|
||||
// 防止重复请求
|
||||
if (state.submitLoading.value) return;
|
||||
|
||||
var timerControl = Timer(const Duration(milliseconds: 300), () => ToastUtils.showLoading());
|
||||
try {
|
||||
DoPaperDetailsResult data = await getClient().getDoPaperDetails(state.param.value);
|
||||
|
||||
// var studentQuestions = data.studentQuestions;
|
||||
// // 第0个的下标数据不需要处理
|
||||
// for (var i = 0; i < studentQuestions.length; i++) {
|
||||
// var item = studentQuestions[i];
|
||||
|
||||
// item.topHeight = itemPre.height;
|
||||
// }
|
||||
state.getDataError.value = false;
|
||||
state.handwritings = [];
|
||||
|
||||
|
|
@ -179,8 +174,8 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
|
|||
state.data.value = data;
|
||||
} catch (e) {
|
||||
print('获取数据报错了:$e');
|
||||
// ToastUtils.showError('未获取到试题数据,请重试');
|
||||
state.getDataError.value = true;
|
||||
ToastUtils.showError('获取试题数据失败,请检查网络连接后重试');
|
||||
} finally {
|
||||
if (timerControl.isActive) timerControl.cancel();
|
||||
ToastUtils.dismiss();
|
||||
|
|
@ -278,18 +273,24 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
|
|||
ToastUtils.showInfo("正在提交批阅数据,请勿重复操作");
|
||||
return;
|
||||
}
|
||||
|
||||
state.submitLoading.value = true;
|
||||
var data = state.data.value;
|
||||
if (data == null) return;
|
||||
|
||||
if ((state.data.value?.studentQuestions.isEmpty ?? true) || (state.studentQuestions.value?.isEmpty ?? true)) {
|
||||
if (data == null) {
|
||||
ToastUtils.showError('数据异常,请重新加载');
|
||||
return;
|
||||
}
|
||||
|
||||
if ((state.data.value?.studentQuestions.isEmpty ?? true) || (state.studentQuestions.value?.isEmpty ?? true)) {
|
||||
ToastUtils.showError('没有可批阅的试题');
|
||||
return;
|
||||
}
|
||||
|
||||
var studentQuestions = state.studentQuestions.value!.where((e) => e.useTime != null && e.useTime! > 0).toList();
|
||||
// 跳过学生未作答的题
|
||||
var noRatingElement = studentQuestions.firstWhereOrNull((e) => e.studentScore == null);
|
||||
if (noRatingElement != null) {
|
||||
ToastUtils.showInfo('${noRatingElement.questionNo}题请评分');
|
||||
ToastUtils.showInfo('第${noRatingElement.questionNo}题请评分');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -320,35 +321,13 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
|
|||
if (totalUnAnnotateCount <= 0) {
|
||||
// 批阅完成
|
||||
if (!state.lastQuestionPrompt) {
|
||||
await showDialog(
|
||||
context: Get.context ?? context,
|
||||
builder: (BuildContext context1) {
|
||||
return AlertDialog(
|
||||
title: quickText('批阅已完成'),
|
||||
content: const Text('暂无更多批阅项'),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('继续'),
|
||||
onPressed: () {
|
||||
state.lastQuestionPrompt = true;
|
||||
Navigator.of(context1).pop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('退出批阅'),
|
||||
onPressed: () {
|
||||
Navigator.of(context1).pop();
|
||||
Get.back();
|
||||
}),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
await _showCompletionDialog(context);
|
||||
} else {
|
||||
ToastUtils.showSuccess("已经提交", duration: const Duration(milliseconds: 800));
|
||||
ToastUtils.showSuccess("批阅已提交", duration: const Duration(milliseconds: 800));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var newParams = DoPaperDetailsParam.fromJson(state.param.value.toJson());
|
||||
if (totalUnAnnotateCount > 0) {
|
||||
// 当前批阅任务完成 重复提交后 停留在当前数据位置
|
||||
|
|
@ -356,14 +335,52 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
|
|||
newParams.studentId = null;
|
||||
}
|
||||
state.param.value = newParams;
|
||||
ToastUtils.showSuccess("批阅已提交");
|
||||
});
|
||||
} catch (_) {
|
||||
print("批阅提交报错 $_");
|
||||
} catch (e) {
|
||||
print("批阅提交报错 $e");
|
||||
ToastUtils.showError('提交失败,请检查网络连接后重试');
|
||||
} finally {
|
||||
state.submitLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showCompletionDialog(BuildContext context) async {
|
||||
await showDialog(
|
||||
context: Get.context ?? context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context1) {
|
||||
return AlertDialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(Icons.check_circle, color: Colors.green, size: 24.sp),
|
||||
SizedBox(width: 8.w),
|
||||
Text('批阅已完成', style: TextStyle(fontSize: 18.sp, fontWeight: FontWeight.w600)),
|
||||
],
|
||||
),
|
||||
content: Text('暂无更多批阅项,是否继续?', style: TextStyle(fontSize: 14.sp)),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text('退出批阅', style: TextStyle(color: Colors.grey[600])),
|
||||
onPressed: () {
|
||||
Navigator.of(context1).pop();
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text('继续', style: TextStyle(color: Theme.of(context).primaryColor)),
|
||||
onPressed: () {
|
||||
state.lastQuestionPrompt = true;
|
||||
Navigator.of(context1).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> toFavorite() async {
|
||||
try {
|
||||
var data = state.data.value!;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|||
import 'package:get/get.dart';
|
||||
import 'package:making_school_asignment_app/common/job/annotate_list_to_refresh.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 'package:making_school_asignment_app/page/home_page/children/homework_review/components/bottom_operation_bar.dart';
|
||||
import 'package:making_school_asignment_app/page/home_page/children/homework_review/components/question_paper_view.dart';
|
||||
|
|
@ -55,8 +54,16 @@ class HomeworkReview extends StatelessWidget {
|
|||
children: [
|
||||
SizedBox(width: 5.w),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.arrow_back_ios, color: Colors.black), onPressed: () => Get.back()),
|
||||
Expanded(child: quickText(sateData.param.value.homeworkName, size: 18.sp).paddingOnly(top: 2.h)),
|
||||
icon: const Icon(Icons.arrow_back_ios, color: Colors.black),
|
||||
onPressed: () => Get.back(),
|
||||
tooltip: '返回'),
|
||||
Expanded(
|
||||
child: Text(
|
||||
sateData.param.value.homeworkName,
|
||||
style: TextStyle(fontSize: 18.sp, fontWeight: FontWeight.w600),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const FavoriteWidget(),
|
||||
SizedBox(width: 10.w),
|
||||
const ReturnToHomepage(),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import 'package:get/get.dart';
|
|||
import 'package:making_school_asignment_app/common/job/work_student.dart';
|
||||
import 'package:making_school_asignment_app/common/job/work_student_params.dart';
|
||||
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
||||
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
||||
|
||||
import 'home_state.dart';
|
||||
|
||||
|
|
@ -24,16 +23,20 @@ class HomeLogic extends GetxController with RequestToolMixin, GetTickerProviderS
|
|||
}
|
||||
|
||||
void getList() async {
|
||||
try {
|
||||
params.pageNumber = state.pageNumber;
|
||||
WorkStudent data = await getClient().getUnAnnotateList(params);
|
||||
state.totalCount.value = data.totalCount;
|
||||
state.readOver.value = data.items.length;
|
||||
/* if(params.pageNumber == 1){
|
||||
state.workList.value = data.items;
|
||||
}else{
|
||||
state.workList.addAll(data.items);
|
||||
|
||||
// 完成刷新
|
||||
refreshController.finishRefresh();
|
||||
} catch (e) {
|
||||
print('获取作业列表失败: $e');
|
||||
// 完成刷新并显示错误
|
||||
refreshController.finishRefresh();
|
||||
// 可以在这里添加错误提示
|
||||
}
|
||||
refreshController.finishRefresh();*/
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -40,117 +40,270 @@ class HomePage extends GetxKeepAliveWidget<HomeLogic> {
|
|||
enableControlFinishLoad: true,
|
||||
controller: controller.refreshController,
|
||||
header: MaterialHeader(),
|
||||
// footer: TaurusFooter(),
|
||||
onRefresh: () async {
|
||||
state.pageNumber = 1;
|
||||
return controller.getList();
|
||||
},
|
||||
// onLoad: () async {
|
||||
// if (state.workList.length < state.totalCount.value) {
|
||||
// state.pageNumber++;
|
||||
// return logic.getList();
|
||||
// }
|
||||
// },
|
||||
child: Stack(
|
||||
children: [
|
||||
Image.asset(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
// 顶部横幅区域
|
||||
SliverAppBar(
|
||||
expandedHeight: 300.h,
|
||||
floating: false,
|
||||
pinned: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
background: Image.asset(
|
||||
'assets/images/home_banner.png',
|
||||
width: Get.width,
|
||||
fit: BoxFit.fill,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 300.h),
|
||||
),
|
||||
),
|
||||
// 主要内容区域
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 20.r),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(30.r), topRight: Radius.circular(30.r))),
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(30.r), topRight: Radius.circular(30.r)),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 15.r),
|
||||
SizedBox(height: 20.r),
|
||||
// 标题区域
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.assignment_outlined,
|
||||
size: 24.sp,
|
||||
color: const Color(0xFF4F4F4F),
|
||||
),
|
||||
SizedBox(width: 8.r),
|
||||
Text(
|
||||
'我的作业管理',
|
||||
style: TextStyle(fontSize: 20.sp, color: const Color(0xFF676666), fontWeight: FontWeight.w600),
|
||||
style: TextStyle(
|
||||
fontSize: 22.sp, color: const Color(0xFF2C2C2C), fontWeight: FontWeight.w700),
|
||||
),
|
||||
SizedBox(height: 15.r),
|
||||
const Spacer(),
|
||||
// 刷新按钮
|
||||
Obx(() => IconButton(
|
||||
onPressed: state.totalCount.value > 0 ? () => controller.getList() : null,
|
||||
icon: Icon(
|
||||
Icons.refresh,
|
||||
size: 20.sp,
|
||||
color: const Color(0xFF4F4F4F),
|
||||
),
|
||||
tooltip: '刷新数据',
|
||||
)),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20.r),
|
||||
// 统计信息卡片
|
||||
Container(
|
||||
padding: EdgeInsets.all(16.r),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF8F9FA),
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
border: Border.all(color: const Color(0xFFE9ECEF), width: 1),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildStatCard(
|
||||
'待批阅',
|
||||
state.totalCount.value.toString(),
|
||||
const Color(0xFFFF6969),
|
||||
Icons.assignment_turned_in,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 16.r),
|
||||
Expanded(
|
||||
child: _buildStatCard(
|
||||
'已批阅',
|
||||
'0', // 这里可以添加已批阅数量
|
||||
const Color(0xFF28A745),
|
||||
Icons.check_circle_outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.r),
|
||||
// 功能菜单网格
|
||||
_buildMenuGrid(context, state),
|
||||
SizedBox(height: 20.r),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatCard(String title, String value, Color color, IconData icon) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(12.r),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(icon, color: color, size: 20.sp),
|
||||
SizedBox(height: 4.r),
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(
|
||||
fontSize: 18.sp,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: const Color(0xFF6C757D),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMenuGrid(BuildContext context, dynamic state) {
|
||||
return Column(
|
||||
children: [
|
||||
// 第一行
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Obx(() {
|
||||
return $MenuItem(
|
||||
child: Obx(() => $menuItem(
|
||||
bgImg: 'assets/images/home_bg_01.png',
|
||||
name: '作业批阅',
|
||||
value: state.totalCount.value.toString(),
|
||||
value: state.totalCount.value > 0 ? state.totalCount.value.toString() : null,
|
||||
url: Routes.readOverPage,
|
||||
);
|
||||
}),
|
||||
isPrimary: true,
|
||||
)),
|
||||
),
|
||||
SizedBox(width: 20.r),
|
||||
const Expanded(
|
||||
child: $MenuItem(
|
||||
SizedBox(width: 16.r),
|
||||
Expanded(
|
||||
child: $menuItem(
|
||||
bgImg: 'assets/images/home_bg_02.png',
|
||||
name: '知识点掌握',
|
||||
url: Routes.studentHistoryWorkPage,
|
||||
page: 'points'),
|
||||
page: 'points',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20.r),
|
||||
SizedBox(height: 16.r),
|
||||
// 第二行
|
||||
Row(
|
||||
children: [
|
||||
const Expanded(
|
||||
child: $MenuItem(
|
||||
Expanded(
|
||||
child: $menuItem(
|
||||
bgImg: 'assets/images/home_bg_03.png',
|
||||
name: '学生历史作业',
|
||||
url: Routes.studentHistoryWorkPage,
|
||||
page: 'history'),
|
||||
page: 'history',
|
||||
),
|
||||
SizedBox(width: 20.r),
|
||||
const Expanded(
|
||||
child: $MenuItem(
|
||||
bgImg: 'assets/images/home_bg_04.png', name: '答题轨迹', url: Routes.answerTrajectoryPage),
|
||||
),
|
||||
SizedBox(width: 16.r),
|
||||
Expanded(
|
||||
child: $menuItem(bgImg: 'assets/images/home_bg_04.png', name: '答题轨迹', url: Routes.answerTrajectoryPage),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20.r),
|
||||
SizedBox(height: 16.r),
|
||||
// 第三行
|
||||
Row(
|
||||
children: [
|
||||
const $MenuItem(
|
||||
Expanded(
|
||||
child: $menuItem(
|
||||
bgImg: 'assets/images/home_bg_05.png',
|
||||
name: '优先批阅设定',
|
||||
url: Routes.studentHistoryWorkPage,
|
||||
page: 'set',
|
||||
),
|
||||
SizedBox(width: 20.r),
|
||||
),
|
||||
SizedBox(width: 16.r),
|
||||
// 占位空间
|
||||
const Expanded(child: SizedBox()),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 15.h),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@swidget
|
||||
Widget $menuItem({required String bgImg, required String name, String? value, required String url, String? page}) {
|
||||
return InkWell(
|
||||
Widget $menuItem({
|
||||
required String bgImg,
|
||||
required String name,
|
||||
String? value,
|
||||
required String url,
|
||||
String? page,
|
||||
bool isPrimary = false,
|
||||
}) {
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Get.toNamed(url, arguments: {'page': page ?? ''});
|
||||
},
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
child: Semantics(
|
||||
label: '$name${value != null ? ',待处理数量:$value' : ''}',
|
||||
hint: '点击进入$name页面',
|
||||
button: true,
|
||||
child: Container(
|
||||
width: (Get.width - 60.r) / 2,
|
||||
height: (Get.width - 60.r) / 2 * 86 / 164,
|
||||
padding: EdgeInsets.symmetric(vertical: 15.r, horizontal: 15.r),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(bgImg),
|
||||
fit: BoxFit.contain,
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
gradient: isPrimary
|
||||
? const LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
Color(0xFF667eea),
|
||||
Color(0xFF764ba2),
|
||||
],
|
||||
)
|
||||
: null,
|
||||
color: isPrimary ? null : Colors.white,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.08),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
image: !isPrimary
|
||||
? DecorationImage(
|
||||
image: AssetImage(bgImg),
|
||||
fit: BoxFit.cover,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Colors.white.withOpacity(0.9),
|
||||
BlendMode.srcATop,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
|
@ -159,40 +312,64 @@ Widget $menuItem({required String bgImg, required String name, String? value, re
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
Expanded(
|
||||
child: Text(
|
||||
name,
|
||||
style: TextStyle(fontSize: 14.sp, color: const Color(0xFF4F4F4F), fontWeight: FontWeight.w600),
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: isPrimary ? Colors.white : const Color(0xFF2C2C2C),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
if (value != null && value != '')
|
||||
Container(
|
||||
width: 18.r,
|
||||
height: 18.r,
|
||||
Semantics(
|
||||
label: '待处理数量:$value',
|
||||
child: Container(
|
||||
width: 20.r,
|
||||
height: 20.r,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFFF6969),
|
||||
borderRadius: BorderRadius.all(Radius.circular(9.r)),
|
||||
color: isPrimary ? Colors.white : const Color(0xFFFF6969),
|
||||
borderRadius: BorderRadius.all(Radius.circular(10.r)),
|
||||
),
|
||||
child: Text(
|
||||
value,
|
||||
style: TextStyle(fontSize: 10.sp, color: Colors.white, fontWeight: FontWeight.w600),
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color: isPrimary ? const Color(0xFFFF6969) : Colors.white,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (isPrimary)
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 14.sp,
|
||||
color: Colors.white,
|
||||
)
|
||||
else
|
||||
Image.asset(
|
||||
'assets/images/home_right_icon.png',
|
||||
width: 16.r,
|
||||
height: 16.r,
|
||||
semanticLabel: '进入图标',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,8 +68,9 @@ dependencies:
|
|||
# zoom_widget: ^2.0.1
|
||||
zoom_widget:
|
||||
git:
|
||||
url: https://github.com/semakers/zoom-widget.git
|
||||
ref: a35c9da6afe405c23b5897b449683d424016e9f1
|
||||
url: https://gitea.23544.com/wangyang/zoom_widget.git
|
||||
# url: https://github.com/semakers/zoom-widget.git
|
||||
# ref: a35c9da6afe405c23b5897b449683d424016e9f1
|
||||
# start retrofit请求封装
|
||||
retrofit: ^4.1.0
|
||||
json_annotation: 4.9.0
|
||||
|
|
|
|||
Loading…
Reference in New Issue