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 { 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 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 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? 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(); } }