Marking.Client.Moblie/marking_app/lib/components/marking/marking_seting.dart

603 lines
22 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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(),
),
),
],
),
);
}