import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/custom_button.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; import 'package:qhd_prevention/pages/my_appbar.dart'; import '../../../http/ApiService.dart'; import '../../../tools/tools.dart'; // 替换为实际路径 class StudyPractisePage extends StatefulWidget { final String videoCoursewareId; const StudyPractisePage({Key? key, required this.videoCoursewareId}) : super(key: key); @override _PracticePageState createState() => _PracticePageState(); } class Question { final String questionDry; final String questionType; // '1','2','3','4' final Map options; final String answer; final String descr; bool correctAnswerShow; String checked; Question({ required this.questionDry, required this.questionType, required this.options, required this.answer, required this.descr, this.correctAnswerShow = false, this.checked = '', }); factory Question.fromJson(Map json) { final type = json['QUESTIONTYPE'] as String; Map opts = {}; if (type == '1' || type == '2' || type == '3') { opts['A'] = json['OPTIONA'] as String? ?? ''; opts['B'] = json['OPTIONB'] as String? ?? ''; if (type != '3') { opts['C'] = json['OPTIONC'] as String? ?? ''; opts['D'] = json['OPTIOND'] as String? ?? ''; } } return Question( questionDry: json['QUESTIONDRY'] as String? ?? '', questionType: type, options: opts, answer: json['ANSWER'] as String? ?? '', descr: json['DESCR'] as String? ?? '', ); } } class _PracticePageState extends State { int current = 0; List options = []; bool loading = true; final Map questionTypeMap = { '1': '单选题', '2': '多选题', '3': '判断题', '4': '填空题', }; @override void initState() { super.initState(); _getData(); } Future _getData() async { setState(() => loading = true); final res = await ApiService.questionListByVideo(widget.videoCoursewareId); if (res['result'] == 'success') { List list = res['varList'] as List; options = list.map((e) => Question.fromJson(e)).toList(); } else { options = []; } setState(() => loading = false); } void _chooseTopic(String type, String item) { final q = options[current]; if (q.correctAnswerShow) return; setState(() { if (type == 'radio' || type == 'judge') { q.checked = (q.checked == item) ? '' : item; _correctAnswerShow(); } else if (type == 'multiple') { List arr = q.checked.isNotEmpty ? q.checked.split(',') : []; if (arr.contains(item)) arr.remove(item); else arr.add(item); arr.sort(); q.checked = arr.join(','); } }); } void _correctAnswerShow() { final q = options[current]; if (q.questionType == '2' && q.checked.split(',').length < 2) { ToastUtil.showError(context, '多选题最少需要选择两个答案'); return; } if (q.checked.isNotEmpty) { setState(() => q.correctAnswerShow = true); } } Widget _buildOptions(Question q) { switch (q.questionType) { case '1': case '3': return Column( children: q.options.entries.map((e) { bool isChecked = q.checked == e.key; return _optionItem( label: e.key, text: e.value, active: !q.correctAnswerShow && isChecked, right: q.correctAnswerShow && q.answer == e.key && isChecked, err: q.correctAnswerShow && q.answer != e.key && isChecked, warning: q.correctAnswerShow && q.answer == e.key && !isChecked, onTap: () => _chooseTopic( q.questionType == '3' ? 'judge' : 'radio', e.key, ), ); }).toList(), ); case '2': return Column( children: [ ...q.options.entries.map((e) { bool isChecked = q.checked.split(',').contains(e.key); bool isCorrect = q.answer.split(',').contains(e.key); return _optionItem( label: e.key, text: e.value, multiple: true, active: !q.correctAnswerShow && isChecked, right: q.correctAnswerShow && isCorrect && isChecked, err: q.correctAnswerShow && !isCorrect && isChecked, warning: q.correctAnswerShow && isCorrect && !isChecked, onTap: () => _chooseTopic('multiple', e.key), ); }), if (!q.correctAnswerShow) ElevatedButton( onPressed: _correctAnswerShow, child: Text('确认答案'), ), ], ); case '4': return TextField( maxLength: 255, onChanged: (v) => q.checked = v, decoration: InputDecoration( hintText: '请输入内容', border: OutlineInputBorder(), ), ); default: return SizedBox.shrink(); } } Widget _optionItem({ required String label, required String text, bool active = false, bool right = false, bool err = false, bool warning = false, bool multiple = false, required VoidCallback onTap, }) { Color fg = Colors.black87; Color bg = Colors.grey.shade200; if (right) { fg = Colors.green; bg = Colors.green; } if (err) { fg = Colors.red; bg = Colors.red; } if (warning) { fg = Colors.green; bg = Colors.green; } if (active) fg = Colors.blue; return GestureDetector( onTap: onTap, child: Container( margin: EdgeInsets.symmetric(vertical: 8), child: Row( children: [ Container( width: 40, height: 40, alignment: Alignment.center, decoration: BoxDecoration( color: multiple ? Colors.transparent : (active ? Colors.blue : bg), shape: BoxShape.circle, ), child: multiple ? (right ? Icon(Icons.check_circle, color: Colors.green) : err ? Icon(Icons.cancel, color: Colors.red) : Text(label, style: TextStyle(color: fg))) : Text( label, style: TextStyle(color: multiple ? fg : Colors.white), ), ), SizedBox(width: 16), Expanded( child: Text(text, style: TextStyle(color: fg, fontSize: 16)), ), ], ), ), ); } String _renderAnswerText(Question q) { if (q.questionType == '3') return q.checked == 'A' ? '对' : '错'; return q.checked; } @override @override Widget build(BuildContext context) { final q = options.isNotEmpty ? options[current] : null; return Scaffold( appBar: MyAppbar(title: '课后练习'), body: loading ? Center(child: CircularProgressIndicator()) : options.isEmpty ? NoDataWidget.show() : Padding( padding: EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Stack( children: [ SizedBox( width: 1000, height: 60, child: Image.asset( 'assets/study/bgimg1.png', fit: BoxFit.fill, ), ), SizedBox( height: 60, child: Center( child: Text( '当前试题 ${current + 1}/${options.length}', style: TextStyle(color: Colors.white, fontSize: 17, fontWeight: FontWeight.bold), ), ), ) ], ), SizedBox(height: 16), if (q != null) ...[ Text( '${current + 1}. ${q.questionDry} (${questionTypeMap[q.questionType]})', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, ), ), SizedBox(height: 16), _buildOptions(q), if (q.correctAnswerShow) ...[ Divider(), Text('我的答案: ${_renderAnswerText(q)}'), Text('正确答案: ${q.answer}'), Text('权威解读: ${q.descr}'), ], ], Spacer(), Row( children: [ if (current > 0) Expanded( child: CustomButton( text: '上一题', textStyle: TextStyle(color: Colors.black54), backgroundColor: Colors.grey.shade200, onPressed: () => setState(() => current--), ), ), if (current > 0 && current < options.length - 1) SizedBox(width: 16), if (current < options.length - 1) Expanded( child: CustomButton( text: '下一题', backgroundColor: Colors.blue, onPressed: () => setState(() => current++), ), ), ], ), ], ), ), ); } }