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

471 lines
15 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:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/model/marking/marking_text_question.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';
// 输入型打分键盘
class InputKeyboard extends StatefulHookConsumerWidget {
BoxDecoration? dexs;
BoxDecoration? notDexs;
TextStyle? theSty;
QuestionTer? qter;
final MarkingTextQuestion data;
String questScore; // 当前分值
String totalScore; // 总分
bool hasSubtopic = false; // 是否有小题
int subtopicIndex; // 小题下标
SynchroScoreCallback synchroScore;
GestureTapCallback submitCall;
GestureTapCallback closeKeyboard;
InputKeyboard({
required this.data,
required this.questScore,
required this.totalScore,
required this.synchroScore,
required this.subtopicIndex,
required this.submitCall,
required this.closeKeyboard,
this.dexs,
this.notDexs,
this.theSty,
Key? key,
}) : super(key: key) {
hasSubtopic = data.subQuestionDetailList.isNotEmpty; // 是否有小题
dexs = dexs ??
BoxDecoration(
color: const Color.fromRGBO(249, 250, 254, 1),
borderRadius: BorderRadius.all(Radius.circular(4.w)),
border: Border.all(
width: 0.5.w,
color: const Color.fromRGBO(224, 230, 255, 1),
),
);
notDexs = notDexs ??
BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(4.w)),
border: Border.all(
width: 0.5.w,
color: const Color.fromRGBO(224, 230, 255, 1),
),
);
theSty = theSty ??
TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w400,
color: const Color.fromRGBO(80, 87, 103, 1),
);
qter = QuestionTer(item: data);
}
@override
_InputTypeKeyboardState createState() => _InputTypeKeyboardState();
}
class _InputTypeKeyboardState extends ConsumerState<InputKeyboard> {
String questScore = ''; // 已打分值
bool hasZeroPointFive = false;
late Offset keyboardOrigin; // 键盘滑动起始坐标
late Offset keyboarddestination; // 键盘滑动截止坐标
late RemoveListener _markingSubtopicSwitchingListener;
@override
void initState() {
super.initState();
widget.qter?.addListener(() {
hasZeroPointFive = false;
});
_markingSubtopicSwitchingListener = ref.read(markingSubtopicSwitchingProvider.notifier).addListener((state) {
if (widget.subtopicIndex != state) widget.subtopicIndex = state;
if (widget.subtopicIndex > -1 && widget.hasSubtopic) {
toUpState(setState, () {
questScore = (widget.data.subQuestionDetailList[state].subQuestionGotScore ?? '').toString();
}, mounted);
}
}, fireImmediately: false);
}
@override
void dispose() {
super.dispose();
_markingSubtopicSwitchingListener();
widget.qter?.dispose();
}
// 清空得分
void cleanCurrentScore() {
toUpState(setState, () {
hasZeroPointFive = false;
questScore = '';
}, mounted);
widget.synchroScore(
score: 0,
continueScoring: false,
hasSubtopic: widget.hasSubtopic,
cleanScore: true,
);
}
// 同步小题得分
void synchroScore(String score, {bool full = false, bool zeroScore = false}) {
MarkingTextQuestion currentQuestion = widget.data;
bool hasSubtopic = widget.hasSubtopic; // 是否有小题
int subtopicIndex = widget.subtopicIndex; // 小题下标
List<SubQuestions> subQuestionDetailList = currentQuestion.subQuestionDetailList; // 小题集合
double totalScore =
hasSubtopic ? subQuestionDetailList[subtopicIndex].subQuestionScore : currentQuestion.totalScore; // 总分
double? doubleScore;
if (zeroScore) {
doubleScore = 0;
} else if (full) {
doubleScore = totalScore;
} else {
String newquestScore = questScore;
/** 这是拼接打分 如1+1 = 11
if (questScore != '') {
List<String> theScores = questScore.split('.');
if (theScores.length > 1) {
if (theScores[1] == '0') {
newquestScore = theScores[0];
} else {
newquestScore = '';
}
// newquestScore
}
}
*/
// doubleScore = double.parse(newquestScore + score); // 当前得分
doubleScore = double.parse(newquestScore == '' ? '0' : newquestScore) + double.parse(score);
print('最终得分111${doubleScore}');
}
if (!full) {
// 非满分
if (doubleScore > totalScore) {
// ToastUtils.showError('打分不得高于本${hasSubtopic ? '小' : ''}题总分,$totalScore 分');
// score = '';
// doubleScore = null;
// return;
// 打分超过满分就定义为满分
score = totalScore.toString();
} else {
score = doubleScore.toString();
}
} else {
score = totalScore.toString();
}
// 处理得分小数点 小数点后为0 取整
List scoreStrList = score.toString().split('.');
if (scoreStrList.length > 1) {
if (double.parse(scoreStrList[1]) == 0) {
score = scoreStrList[0];
doubleScore = double.parse(score);
}
}
toUpState(setState, () {
hasZeroPointFive = full || questScore.split('.').length > 1; // 包含了小数0.5
questScore = score;
}, mounted);
widget.synchroScore(score: doubleScore, continueScoring: hasZeroPointFive, hasSubtopic: hasSubtopic);
}
@override
Widget build(BuildContext context) {
BoxDecoration _notDexs = widget.notDexs!;
BoxDecoration _dexs = widget.dexs!;
SubQuestions? subQuest; // 小题
List<SubQuestions>? subQuestionDetailList; // 小题集合
if (widget.hasSubtopic) {
subQuestionDetailList = widget.data.subQuestionDetailList;
subQuest = subQuestionDetailList[widget.subtopicIndex];
}
return Container(
width: 94.w,
height: ScreenUtil().screenHeight - 60.h,
padding: EdgeInsets.all(6.w),
margin: EdgeInsets.symmetric(vertical: 10.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4.w),
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(46, 91, 255, 0.2),
offset: Offset(2.w, 2.h), //阴影y轴偏移量
blurRadius: 14, //阴影模糊程度
spreadRadius: 0.5, //阴影扩散程度
)
],
),
child: GestureDetector(
behavior: HitTestBehavior.translucent,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// 当前分值
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: 53.w,
height: 20.w,
padding: EdgeInsets.symmetric(horizontal: 10.w),
alignment: Alignment.centerLeft,
decoration: widget.dexs,
child: Text(widget.questScore, style: widget.theSty),
),
InkWell(
onTap: cleanCurrentScore,
child: Container(
width: 24.w,
height: 20.w,
alignment: Alignment.center,
decoration: widget.dexs,
child: Icon(
Icons.clear_sharp,
size: 24.sp,
color: const Color.fromRGBO(80, 87, 103, 1),
),
),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ScoreButton(
'满分',
widget.theSty!,
widget.dexs!,
(val) {
synchroScore(widget.hasSubtopic ? (subQuest!.subQuestionScore.toString()) : widget.totalScore,
full: true);
},
),
ScoreButton(
'零分',
widget.theSty!,
widget.dexs!,
(val) => synchroScore('0', zeroScore: true),
),
ScoreButton(
'.5',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ScoreButton(
'7',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
ScoreButton(
'8',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
ScoreButton(
'9',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ScoreButton(
'4',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
ScoreButton(
'5',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
ScoreButton(
'6',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ScoreButton(
'1',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
ScoreButton(
'2',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
ScoreButton(
'3',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ScoreButton(
'0',
widget.theSty!,
hasZeroPointFive ? _notDexs : _dexs,
(val) {
if (!hasZeroPointFive) {
synchroScore(val);
}
},
),
InkWell(
onTap: () {
easyThrottle('toMarkingVal', () => widget.submitCall(), duration: Duration(seconds: 1));
},
child: Container(
width: 53.w,
height: 20.w,
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color.fromRGBO(54, 97, 255, 1),
borderRadius: BorderRadius.all(Radius.circular(4.w)),
border: Border.all(width: 0.5.w, color: const Color.fromRGBO(224, 230, 255, 1)),
),
child: Text(
'提 交',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
),
),
],
),
],
),
onPanStart: (DragStartDetails detail) => keyboardOrigin = detail.localPosition,
onPanUpdate: (DragUpdateDetails detail) => keyboarddestination = detail.localPosition,
onPanEnd: (DragEndDetails details) {
bool flag = (keyboardOrigin.dy - keyboarddestination.dy).abs() > 50.0 ||
(keyboardOrigin.dx - keyboarddestination.dx).abs() > 40.0;
if (!flag) return;
widget.closeKeyboard();
},
),
);
}
}
// 打分按钮
// ignore: must_be_immutable
class ScoreButton extends StatelessWidget {
String scoreVal;
Function call;
final TextStyle _theSty;
final BoxDecoration dexs;
ScoreButton(this.scoreVal, this._theSty, this.dexs, this.call, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () => call(scoreVal),
child: Container(
width: 24.w,
height: 20.w,
alignment: Alignment.center,
decoration: dexs,
child: Text(scoreVal, style: _theSty),
),
);
}
}
// 监听试题数据变化
class QuestionTer extends ChangeNotifier {
MarkingTextQuestion item;
QuestionTer({required this.item}) {
notifyListeners();
}
}