603 lines
22 KiB
Dart
603 lines
22 KiB
Dart
import 'package:achievement_view/achievement_view.dart';
|
||
import 'package:collection/collection.dart';
|
||
import 'package:flutter/cupertino.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||
// import 'package:flutter_neumorphic/flutter_neumorphic.dart';
|
||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
|
||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||
import 'package:marking_app/common/model/enum/KeyboardType.dart';
|
||
import 'package:marking_app/common/model/marking/do_marking_keyboard_model.dart';
|
||
import 'package:marking_app/common/model/marking/marking_common_score_items.dart';
|
||
import 'package:marking_app/provider/do_marking_provider.dart';
|
||
import 'package:marking_app/utils/index.dart';
|
||
import 'package:marking_app/utils/marking_utils/index.dart';
|
||
import 'package:marking_app/utils/my_text.dart';
|
||
import 'package:syncfusion_flutter_sliders/sliders.dart';
|
||
|
||
part 'marking_seting.g.dart';
|
||
|
||
// 阅卷设置页面
|
||
class MarkingSeting extends StatefulHookConsumerWidget {
|
||
final VoidCallbackFutureBool close;
|
||
final int markingUserId; // 试卷ID
|
||
final String questionNum; // 题型题号
|
||
double defaultScoreInterval; // 试题服务器间隔数据值
|
||
final double? questTotalScore; // 当前试题总分
|
||
final String? tagName; // 试题批次名称
|
||
MarkingSeting({
|
||
required this.defaultScoreInterval,
|
||
required this.close,
|
||
required this.markingUserId,
|
||
required this.questionNum,
|
||
this.tagName,
|
||
this.questTotalScore,
|
||
Key? key,
|
||
}) : super(key: key) {
|
||
defaultScoreInterval = defaultScoreInterval > 0 ? defaultScoreInterval : 1;
|
||
}
|
||
|
||
@override
|
||
_MarkingSetingState createState() => _MarkingSetingState();
|
||
}
|
||
|
||
class _MarkingSetingState extends ConsumerState<MarkingSeting> {
|
||
late List<TheDoMarkingKeyboardModel> keyboardTypes; // 键盘集合
|
||
late DoMarkingKeyboardModel keyboardModel; // 当前的键盘方式
|
||
late bool isHorizontal; // 是否横屏
|
||
SortKeyboard? sortType; // 键盘排序方式
|
||
late double scoreInterval; // 分值间隔设置
|
||
late int keyboardIndex; // 键盘下标
|
||
late bool autoSubmitToNextQuestion; // 提交并自动跳转下一题
|
||
late RemoveListener _markingKeyboardListener;
|
||
MarkingCommonScoreItems? _commonScoreItems;
|
||
@override
|
||
void initState() {
|
||
// 当前
|
||
_markingKeyboardListener = ref.read(markingKeyboardProvider.notifier).addListener((state) {
|
||
MarkingCommonScoreItems? theCommonScores = state.commonScores;
|
||
if (theCommonScores != null &&
|
||
widget.questionNum == theCommonScores.questionNum &&
|
||
widget.markingUserId == theCommonScores.id) {
|
||
_commonScoreItems = state.commonScores;
|
||
}
|
||
keyboardModel = state;
|
||
keyboardIndex = state.keyboard.index;
|
||
sortType = state.sort;
|
||
autoSubmitToNextQuestion = state.autoSubmitToNextQuestion;
|
||
scoreInterval = state.getScoreStepSize(
|
||
widget.markingUserId, widget.questionNum, widget.defaultScoreInterval); // 或者对应试卷和试题的步长
|
||
isHorizontal = state.screenDirection == ScreenDirection.HORIZONTAL_SCREEN;
|
||
|
||
keyboardTypes = KeyboardType.values.map((e) {
|
||
bool isCurrent = keyboardModel.keyboard == e; // 当前使用的键盘是不是当前这个键盘
|
||
bool isInput = e == KeyboardType.INPUT_TYPE;
|
||
|
||
DoMarkingKeyboardModel item = DoMarkingKeyboardModel(
|
||
keyboard: e,
|
||
open: isInput ? keyboardModel.open : true, // 只有输入型键盘可以开启关闭
|
||
guidePageDisplay: isInput ? keyboardModel.guidePageDisplay : false, // 只有输入型键盘有引导页
|
||
);
|
||
|
||
if (isCurrent) {
|
||
item.sort = state.sort;
|
||
item.autoSubmitToNextQuestion = state.autoSubmitToNextQuestion;
|
||
}
|
||
return TheDoMarkingKeyboardModel(item, isCurrent);
|
||
}).toList();
|
||
toSetUp();
|
||
});
|
||
super.initState();
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
super.dispose();
|
||
_markingKeyboardListener();
|
||
}
|
||
|
||
void toSetUp() {
|
||
toUpState(setState, () {}, mounted);
|
||
}
|
||
|
||
// 设置
|
||
void initMarkingSet() {
|
||
TheDoMarkingKeyboardModel theCurrent = keyboardTypes[keyboardIndex]; // 当前选中的键盘
|
||
DoMarkingKeyboardModel model = theCurrent.model;
|
||
switch (model.keyboard) {
|
||
case KeyboardType.INPUT_TYPE:
|
||
// 输入型键盘
|
||
break;
|
||
case KeyboardType.RIGHT_SELECTION:
|
||
case KeyboardType.BOTTOM_SELECTION:
|
||
// 底部键盘和右侧键盘
|
||
model.setScoreStepSize(
|
||
widget.markingUserId, widget.questionNum, widget.defaultScoreInterval, scoreInterval); // 设置分值
|
||
model.sort = sortType;
|
||
break;
|
||
}
|
||
model.screenDirection = keyboardModel.screenDirection;
|
||
model.autoSubmitToNextQuestion = autoSubmitToNextQuestion;
|
||
if (_commonScoreItems != null) model.commonScores = _commonScoreItems!.score.isNotEmpty ? _commonScoreItems : null;
|
||
ref.read(markingKeyboardProvider.notifier).toggleKeyboard(model);
|
||
setTimeOut(300, () => widget.close(true));
|
||
|
||
/// 取消保存数据确认按钮
|
||
// showDialog(
|
||
// // 表示点击灰色背景的时候是否消失弹出框
|
||
// barrierDismissible: false,
|
||
// context: context,
|
||
// builder: (context1) {
|
||
// return AlertDialog(content: quickText("请确定当前阅卷习惯配置?"), actions: <Widget>[
|
||
// TextButton(
|
||
// child: quickText("取消"),
|
||
// onPressed: () {
|
||
// Navigator.pop(context1, 'Cancle');
|
||
// },
|
||
// ),
|
||
// TextButton(
|
||
// child: quickText("确定", color: Theme.of(context).primaryColor),
|
||
// onPressed: () {
|
||
// TheDoMarkingKeyboardModel theCurrent = keyboardTypes[keyboardIndex]; // 当前选中的键盘
|
||
// DoMarkingKeyboardModel model = theCurrent.model;
|
||
// switch (model.keyboard) {
|
||
// case KeyboardType.INPUT_TYPE:
|
||
// // 输入型键盘
|
||
// break;
|
||
// case KeyboardType.RIGHT_SELECTION:
|
||
// case KeyboardType.BOTTOM_SELECTION:
|
||
// // 底部键盘和右侧键盘
|
||
// model.setScoreStepSize(widget.markingUserId, widget.questionNum, widget.defaultScoreInterval, scoreInterval); // 设置分值
|
||
// model.sort = sortType;
|
||
// break;
|
||
// }
|
||
// model.screenDirection = keyboardModel.screenDirection;
|
||
// model.autoSubmitToNextQuestion = autoSubmitToNextQuestion;
|
||
// ref.read(markingKeyboardProvider.notifier).toggleKeyboard(model);
|
||
// Navigator.pop(context1, 'Cancle');
|
||
// setTimeOut(300, () => widget.close(true));
|
||
// })
|
||
// ]);
|
||
// });
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Container(
|
||
height: double.infinity,
|
||
width: double.infinity,
|
||
color: const Color.fromARGB(255, 233, 232, 232),
|
||
child: Stack(
|
||
children: [
|
||
Container(
|
||
color: const Color.fromRGBO(249, 250, 254, 1),
|
||
alignment: Alignment.center,
|
||
child: quickText(
|
||
"学而有道",
|
||
size: 170.sp,
|
||
color: Color.fromRGBO(255, 255, 255, 1),
|
||
),
|
||
),
|
||
Column(
|
||
children: [
|
||
getHeadBox(),
|
||
Expanded(
|
||
child: Container(
|
||
width: double.infinity,
|
||
// color: const Color.fromARGB(255, 233, 232, 232),
|
||
padding: EdgeInsets.only(top: 12.h, left: 10.w),
|
||
child: ListView(
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
getKeyboardBox(),
|
||
getAutoNextQuestBox(),
|
||
getScoreIntervalSetBox(),
|
||
if (keyboardIndex != 0)
|
||
$CommonScoringList(
|
||
score: widget.questTotalScore!,
|
||
scoreInterval: scoreInterval,
|
||
commonScoreItems: _commonScoreItems,
|
||
call: (List<double> val) {
|
||
_commonScoreItems = MarkingCommonScoreItems(
|
||
id: widget.markingUserId,
|
||
questionNum: widget.questionNum,
|
||
score: val,
|
||
);
|
||
setState(() {});
|
||
},
|
||
),
|
||
getSetScoringRulesBox(),
|
||
],
|
||
),
|
||
),
|
||
)
|
||
],
|
||
)
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
// 获取键盘区域
|
||
Widget getKeyboardBox() {
|
||
bool isBroadwise = keyboardModel.screenDirection == ScreenDirection.HORIZONTAL_SCREEN; // 是否是横向
|
||
|
||
return SizedBox(
|
||
width: double.infinity,
|
||
child: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
quickText(
|
||
'键盘选择',
|
||
color: const Color.fromRGBO(45, 56, 76, 1),
|
||
size: 14.sp,
|
||
fontWeight: FontWeight.w500,
|
||
),
|
||
Wrap(
|
||
children: keyboardTypes.asMap().keys.map((e) {
|
||
TheDoMarkingKeyboardModel item = keyboardTypes[e];
|
||
bool isInputAndHor = !isHorizontal && item.model.keyboard == KeyboardType.INPUT_TYPE; // 横屏和输入键盘
|
||
return Padding(
|
||
padding: EdgeInsets.only(right: 36.w, left: isBroadwise ? 0 : 5.w),
|
||
child: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Container(
|
||
width: 8.w,
|
||
margin: EdgeInsets.only(right: isBroadwise ? 2.w : 8.w),
|
||
child: Checkbox(
|
||
tristate: isInputAndHor, // 三态复选框,默认 false,当设置为 true 时,设置 value = null,复选框中间会变成破折号(-)
|
||
activeColor: Theme.of(context).primaryColor,
|
||
checkColor: Colors.white,
|
||
value: isInputAndHor ? null : keyboardIndex == e,
|
||
onChanged: (value) {
|
||
if (keyboardIndex == e || isInputAndHor) return;
|
||
keyboardIndex = e;
|
||
DoMarkingKeyboardModel model = keyboardTypes[keyboardIndex].model;
|
||
if (model.keyboard != KeyboardType.INPUT_TYPE) {
|
||
// 不重置,若后面需要重置再打开
|
||
// scoreInterval = model.getScoreStepSize(widget.markingUserId, widget.questionNum, widget.defaultScoreInterval);
|
||
sortType ??= model.sort;
|
||
}
|
||
toSetUp();
|
||
},
|
||
),
|
||
),
|
||
InkWell(
|
||
onTap: () {
|
||
if (keyboardIndex == e || isInputAndHor) return;
|
||
keyboardIndex = e;
|
||
DoMarkingKeyboardModel model = keyboardTypes[keyboardIndex].model;
|
||
if (model.keyboard != KeyboardType.INPUT_TYPE) {
|
||
// 不重置,若后面需要重置再打开
|
||
// scoreInterval = model.getScoreStepSize(widget.markingUserId, widget.questionNum, widget.defaultScoreInterval);
|
||
sortType ??= model.sort;
|
||
}
|
||
toSetUp();
|
||
},
|
||
child: quickText(
|
||
item.title,
|
||
color: const Color.fromRGBO(80, 87, 103, 1),
|
||
size: 14.sp,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}).toList(),
|
||
),
|
||
SizedBox(height: 20.h),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
// 自动跳转下一题
|
||
Widget getAutoNextQuestBox() {
|
||
return Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
quickText(keyboardTypes[keyboardIndex].model.keyboard == KeyboardType.INPUT_TYPE ? '自动跳转下一题' : '自动提交',
|
||
size: 14.sp, color: const Color.fromRGBO(45, 56, 76, 1), fontWeight: FontWeight.bold),
|
||
Transform.scale(
|
||
scale: 0.7,
|
||
alignment: Alignment.centerLeft,
|
||
child: CupertinoSwitch(
|
||
value: autoSubmitToNextQuestion,
|
||
activeColor: Theme.of(context).primaryColor,
|
||
trackColor: const Color.fromRGBO(148, 163, 182, 1),
|
||
//dragStartBehavior: DragStartBehavior.start,
|
||
onChanged: (value) {
|
||
setState(() {
|
||
autoSubmitToNextQuestion = value;
|
||
});
|
||
},
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
// 给分规则区域
|
||
Widget getSetScoringRulesBox() {
|
||
if (keyboardTypes[keyboardIndex].model.keyboard == KeyboardType.INPUT_TYPE) {
|
||
return Container();
|
||
}
|
||
|
||
bool isBroadwise = keyboardModel.screenDirection == ScreenDirection.HORIZONTAL_SCREEN; // 是否是横向
|
||
|
||
return Container(
|
||
margin: EdgeInsets.only(top: 20.h),
|
||
child: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
quickText(
|
||
'键盘排序方式',
|
||
size: 14.sp,
|
||
color: const Color.fromRGBO(45, 56, 76, 1),
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
Wrap(
|
||
children: SortKeyboard.values
|
||
.where((element) => element != SortKeyboard.FULL_AND_AERO_TOP_INVERTED_ORDER)
|
||
.map((e) {
|
||
String title;
|
||
switch (e) {
|
||
case SortKeyboard.INVERTED_ORDER:
|
||
title = '按倒序排列';
|
||
break;
|
||
case SortKeyboard.FULL_AND_AERO_TOP:
|
||
// title = '顺序排列满分零分置顶';
|
||
title = '按顺序排列';
|
||
break;
|
||
case SortKeyboard.FULL_AND_AERO_TOP_INVERTED_ORDER:
|
||
title = '按倒序排列满分零分置顶';
|
||
break;
|
||
}
|
||
return Padding(
|
||
padding: EdgeInsets.only(right: 30.w),
|
||
child: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Container(
|
||
width: 8.w,
|
||
margin: EdgeInsets.only(right: isBroadwise ? 2.w : 8.w, left: isBroadwise ? 0 : 5.w),
|
||
child: Checkbox(
|
||
activeColor: Theme.of(context).primaryColor,
|
||
checkColor: Colors.white,
|
||
value: e == sortType,
|
||
onChanged: (value) {
|
||
sortType = e;
|
||
toSetUp();
|
||
},
|
||
),
|
||
),
|
||
InkWell(
|
||
onTap: () {
|
||
sortType = e;
|
||
toSetUp();
|
||
},
|
||
child: quickText(
|
||
title,
|
||
color: const Color.fromRGBO(80, 87, 103, 1),
|
||
size: 14.sp,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}).toList(),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
// 分值间隔设置
|
||
Widget getScoreIntervalSetBox() {
|
||
if (keyboardTypes[keyboardIndex].model.keyboard == KeyboardType.INPUT_TYPE) {
|
||
return Container();
|
||
}
|
||
|
||
bool isBroadwise = keyboardModel.screenDirection == ScreenDirection.HORIZONTAL_SCREEN; // 是否是横向
|
||
|
||
return Container(
|
||
margin: EdgeInsets.only(top: 20.h),
|
||
child: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
InkWell(
|
||
onTap: () {
|
||
AchievementView(title: "分值间隔", subTitle: "设定当前题目的分数按钮的间隔分值", color: Theme.of(context).primaryColor)
|
||
.show(context);
|
||
},
|
||
child: Row(
|
||
children: [
|
||
Container(
|
||
padding: EdgeInsets.only(right: 2.w),
|
||
alignment: Alignment.bottomLeft,
|
||
child: quickText(
|
||
'分值间隔设置',
|
||
size: 14.sp,
|
||
color: const Color.fromRGBO(45, 56, 76, 1),
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
Tooltip(
|
||
message: '这是一个提示',
|
||
child: Icon(Icons.help, color: Colors.black, size: 18.sp),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
SfSlider(
|
||
onChanged: (value) {
|
||
int flVal = value.floor();
|
||
double differenceVal = value - flVal;
|
||
if (differenceVal != 0) {
|
||
value = differenceVal > 0.5 ? value.ceil().toDouble() : flVal + 0.5;
|
||
}
|
||
if (widget.questTotalScore != null && value > widget.questTotalScore) {
|
||
value = widget.questTotalScore;
|
||
AchievementView(
|
||
icon: Icon(
|
||
Icons.warning_amber,
|
||
color: Colors.yellow,
|
||
size: 40.sp,
|
||
),
|
||
elevation: 0.5,
|
||
duration: Duration(seconds: 1),
|
||
title: "提示",
|
||
subTitle: "设定分值间隔不得大于当前分试题总分",
|
||
textStyleTitle: TextStyle(color: Colors.yellow),
|
||
color: Theme.of(context).primaryColor)
|
||
.show(context);
|
||
}
|
||
toUpState(setState, () => scoreInterval = value, mounted);
|
||
},
|
||
showTicks: true,
|
||
showLabels: true,
|
||
enableTooltip: true,
|
||
//值
|
||
value: scoreInterval,
|
||
//滑块划过的颜色
|
||
activeColor: Theme.of(context).primaryColor,
|
||
//滑块未划过的颜色
|
||
inactiveColor: Colors.grey[400],
|
||
min: 0.5,
|
||
max: 5,
|
||
interval: 0.5,
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
// 顶部区域
|
||
Widget getHeadBox() {
|
||
return Container(
|
||
height: 50.h,
|
||
color: const Color.fromRGBO(255, 255, 255, 1),
|
||
child: Row(
|
||
crossAxisAlignment: CrossAxisAlignment.center,
|
||
children: [
|
||
SizedBox(width: 10.w),
|
||
InkWell(
|
||
onTap: () => widget.close(false),
|
||
child: Icon(Icons.arrow_back_ios, size: 28.sp),
|
||
),
|
||
SizedBox(width: 4.w),
|
||
quickText('阅卷操作设置', size: 17.sp),
|
||
Expanded(
|
||
child: Container(
|
||
padding: EdgeInsets.only(right: 12.w),
|
||
alignment: Alignment.centerRight,
|
||
child: InkWell(
|
||
onTap: initMarkingSet,
|
||
child: quickText('保存', size: 18.sp, color: Theme.of(context).primaryColor),
|
||
),
|
||
),
|
||
)
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
void _showPopover(BuildContext context) {}
|
||
}
|
||
|
||
class TheDoMarkingKeyboardModel {
|
||
final DoMarkingKeyboardModel model;
|
||
bool current;
|
||
late String title;
|
||
|
||
TheDoMarkingKeyboardModel(this.model, this.current) {
|
||
switch (model.keyboard) {
|
||
case KeyboardType.INPUT_TYPE:
|
||
title = '输入型键盘';
|
||
break;
|
||
case KeyboardType.RIGHT_SELECTION:
|
||
title = '右侧选择型键盘';
|
||
break;
|
||
case KeyboardType.BOTTOM_SELECTION:
|
||
title = '底部选择型键盘';
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 常用打分项列表
|
||
@hwidget
|
||
Widget $commonScoringList(BuildContext context,
|
||
{required double score,
|
||
required double scoreInterval,
|
||
required MarkingCommonScoreItems? commonScoreItems,
|
||
required Function(List<double>) call}) {
|
||
List<int> array = List.generate(score.ceil() + 1, (index) => index).where((element) => element > 0).toList();
|
||
|
||
// useEffect(() {
|
||
// return () {};
|
||
// }, []);
|
||
return Container(
|
||
width: double.infinity,
|
||
height: 80.h,
|
||
margin: EdgeInsets.only(top: 30.h),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Container(
|
||
child:
|
||
quickText('常用打分项', size: 14.sp, color: const Color.fromRGBO(45, 56, 76, 1), fontWeight: FontWeight.bold),
|
||
),
|
||
SizedBox(height: 10.h),
|
||
Expanded(
|
||
child: ListView(
|
||
scrollDirection: Axis.horizontal, // 设置垂直滚动,
|
||
children: array.map((e) {
|
||
bool isSelected = (commonScoreItems?.score.contains(e) ?? false);
|
||
return InkWell(
|
||
splashColor: Colors.cyanAccent,
|
||
onTap: () {
|
||
var items = commonScoreItems?.score ?? [];
|
||
double val = e.toDouble();
|
||
if (items.contains(val))
|
||
items = items.where((e1) => e1 != val).toList();
|
||
else
|
||
items.add(val);
|
||
call(items);
|
||
},
|
||
child: Container(
|
||
width: 20.w,
|
||
height: 56.h,
|
||
margin: EdgeInsets.only(top: 3.h, right: 6.w),
|
||
alignment: Alignment.center,
|
||
decoration: BoxDecoration(
|
||
border: Border.all(
|
||
width: 1.h,
|
||
color: isSelected
|
||
? Theme.of(context).primaryColor.withOpacity(0.5)
|
||
: const Color.fromRGBO(224, 230, 255, 1),
|
||
),
|
||
color: isSelected ? Colors.white : Colors.grey[300],
|
||
borderRadius: BorderRadius.all(Radius.circular(2.w)),
|
||
),
|
||
child: quickText(
|
||
e,
|
||
size: 15.sp,
|
||
color: isSelected ? Theme.of(context).primaryColor : const Color.fromRGBO(148, 163, 182, 1),
|
||
),
|
||
),
|
||
);
|
||
}).toList(),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|