import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import '../../../constants/app_constants.dart'; import '../../../controllers/shared_preferences_storage_controller.dart'; import 'level-jilu.dart'; import 'flow-anim.dart'; import 'distinguish.dart'; import '../settings/offline-data.dart'; /// 时间: 2026-03-28 /// 功能: 诗词答题页面 /// 介绍: 基于 API 接口实现的诗词答题系统,支持获取题目、提交答案、获取提示 /// 最新变化: 添加自动加载下一题开关,隐藏提示标签,使用独立逻辑管理器 class PoetryLevelPage extends StatefulWidget { const PoetryLevelPage({super.key}); @override State createState() => _PoetryLevelPageState(); } class _PoetryLevelPageState extends State with TickerProviderStateMixin { final PoetryLevelManager _manager = PoetryLevelManager(); // 状态管理 bool _isLoading = true; bool _isSubmitting = false; Map? _currentQuestion; String? _errorMessage; int _score = 0; bool _autoLoadNext = true; // 答题状态 int? _selectedAnswer; String? _feedbackMessage; bool _showFeedback = false; bool _isAnswerCorrect = false; // 动画控制器 late AnimationController _successAnimationController; late AnimationController _shakeAnimationController; late Animation _scaleAnimation; late Animation _shakeAnimation; // 标签显示状态 bool _showTags = false; // 计时器 Timer? _tagTimer; // 答题记录统计 int _totalQuestions = 0; int _correctAnswers = 0; int _wrongAnswers = 0; int _totalTime = 0; int _hintCount = 0; int _skipCount = 0; DateTime? _questionStartTime; @override void initState() { super.initState(); _initializeAndLoadQuestion(); _successAnimationController = AnimationController( duration: const Duration(milliseconds: 600), vsync: this, ); _scaleAnimation = Tween(begin: 0.8, end: 1.2).animate( CurvedAnimation( parent: _successAnimationController, curve: Curves.elasticOut, ), ); _shakeAnimationController = AnimationController( duration: const Duration(milliseconds: 500), vsync: this, ); _shakeAnimation = Tween(begin: -5, end: 5).animate( CurvedAnimation( parent: _shakeAnimationController, curve: Curves.easeInOut, ), ); // 10秒后显示标签 Future.delayed(const Duration(seconds: 10), () { if (mounted) { setState(() { _showTags = true; }); } }); } @override void dispose() { _successAnimationController.dispose(); _shakeAnimationController.dispose(); _tagTimer?.cancel(); super.dispose(); } /// 初始化并加载题目 Future _initializeAndLoadQuestion() async { setState(() { _isLoading = true; _errorMessage = null; }); // 初始化题目列表(调用 fetch 和 refresh) final initResult = await _manager.initializeQuestions(); if (!mounted) return; if (!initResult.success) { setState(() { _errorMessage = initResult.message ?? '初始化题目失败,请重试'; _isLoading = false; }); // 如果需要下载,显示下载提示 if (initResult.needDownload) { _showDownloadPrompt(); } return; } // 显示加载模式提示 if (initResult.isOffline) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(initResult.message ?? '已加载离线缓存'), backgroundColor: AppConstants.primaryColor, duration: const Duration(seconds: 2), ), ); } // 加载第一题 await _loadQuestion(); } /// 显示下载提示 void _showDownloadPrompt() { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('提示'), content: const Text('当前无网络连接且无离线缓存数据,请先下载数据或检查网络设置。'), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text('取消'), ), TextButton( onPressed: () { Navigator.of(context).pop(); // 跳转到离线数据下载页面 Navigator.push( context, MaterialPageRoute(builder: (_) => const OfflineDataPage()), ); }, child: const Text('去下载'), ), ], ); }, ); } /// 加载题目 Future _loadQuestion() async { // 开始计时 _questionStartTime = DateTime.now(); final result = await _manager.loadQuestion(); if (!mounted) return; setState(() { if (result.success) { _currentQuestion = result.data; _isLoading = false; _errorMessage = null; // 重置标签显示状态 _showTags = false; // 取消之前的计时器 _tagTimer?.cancel(); // 10秒后显示标签 _tagTimer = Timer(const Duration(seconds: 10), () { if (mounted) { setState(() { _showTags = true; }); } }); } else { _errorMessage = result.message; _isLoading = false; } _selectedAnswer = null; _feedbackMessage = null; _showFeedback = false; _isAnswerCorrect = false; }); } /// 提交答案 Future _submitAnswer(int answer) async { if (_isSubmitting || _currentQuestion == null) return; setState(() { _isSubmitting = true; _selectedAnswer = answer; _showFeedback = false; }); final result = await _manager.submitAnswer(_manager.currentId, answer); if (!mounted) return; setState(() { if (result.success) { _isAnswerCorrect = result.isCorrect; if (result.message != null && result.message!.isNotEmpty) { _feedbackMessage = result.message; } else { _feedbackMessage = _isAnswerCorrect ? '🎉 回答正确!' : '😔 回答错误,再想想吧!'; } _showFeedback = true; // 计算答题时间 if (_questionStartTime != null) { final duration = DateTime.now().difference(_questionStartTime!); _totalTime += duration.inSeconds; } // 更新统计数据 _totalQuestions++; if (_isAnswerCorrect) { _correctAnswers++; _score++; _successAnimationController.forward().then((_) { _successAnimationController.reverse(); }); if (_autoLoadNext) { Future.delayed(const Duration(seconds: 2), () { if (mounted && _isAnswerCorrect) { _nextQuestion(); } }); } } else { _wrongAnswers++; _shakeAnimationController.forward().then((_) { _shakeAnimationController.reverse(); }); } // 保存答题记录 _saveAnswerRecord(isCorrect: _isAnswerCorrect); } else { _feedbackMessage = result.message; _showFeedback = true; } _isSubmitting = false; }); } /// 获取提示 Future _getHint() async { if (_isSubmitting || _currentQuestion == null) return; setState(() { _isSubmitting = true; }); final result = await _manager.getHint(_manager.currentId); if (!mounted) return; setState(() { if (result.success) { _feedbackMessage = result.message; _showFeedback = true; // 增加提示次数 _hintCount++; // 保存答题记录 _saveAnswerRecord(); } else { _feedbackMessage = result.message; _showFeedback = true; } _isSubmitting = false; }); } /// 下一题 void _nextQuestion() { // 增加跳过次数 _skipCount++; // 保存答题记录 _saveAnswerRecord(); _manager.nextQuestion(); _loadQuestion(); } /// 上一题 void _previousQuestion() { _manager.previousQuestion(); _loadQuestion(); } /// 保存答题记录到本地存储 Future _saveAnswerRecord({bool isCorrect = false}) async { try { // 保存统计数据 await SharedPreferencesStorageController.setInt( 'totalQuestions', _totalQuestions, ); await SharedPreferencesStorageController.setInt( 'correctAnswers', _correctAnswers, ); await SharedPreferencesStorageController.setInt( 'wrongAnswers', _wrongAnswers, ); await SharedPreferencesStorageController.setInt('totalTime', _totalTime); await SharedPreferencesStorageController.setInt('hintCount', _hintCount); await SharedPreferencesStorageController.setInt('skipCount', _skipCount); // 保存当前题目的详细记录 if (_currentQuestion != null) { // 构建标签列表 List tags = []; if (_currentQuestion!['type'] != null) { tags.add(_currentQuestion!['type'].toString()); } if (_currentQuestion!['grade'] != null) { tags.add(_currentQuestion!['grade'].toString()); } if (_currentQuestion!['dynasty'] != null) { tags.add(_currentQuestion!['dynasty'].toString()); } final record = { 'questionId': _manager.currentId, 'question': _currentQuestion!['question'] ?? '未知题目', 'author': _currentQuestion!['author'] ?? '未知作者', 'tags': tags, 'isCorrect': isCorrect, 'answerTime': DateTime.now().toIso8601String(), }; // 获取已有的记录列表 List records = await SharedPreferencesStorageController.getStringList( 'poetryAnswerRecords', defaultValue: [], ); // 添加新记录(JSON格式) records.add(jsonEncode(record)); // 保存更新后的列表 await SharedPreferencesStorageController.setStringList( 'poetryAnswerRecords', records, ); } } catch (e) { // 保存失败 } } /// 打开答题记录页面 void _openAnswerRecordPage() { Navigator.push( context, MaterialPageRoute(builder: (context) => const DistinguishPage()), ); } /// 构建选项布局 Widget _buildOptionsLayout() { if (_currentQuestion == null) { return const SizedBox(); } final options = _currentQuestion!['options'] as List?; if (options == null || options.isEmpty) { return const SizedBox(); } // 检查是否所有选项都少于等于4个字 bool allShortOptions = options.every((option) { final text = option['content'] ?? ''; return text.length <= 4; }); if (allShortOptions && options.length >= 4) { // 2*2布局 return Column( children: [ Row( children: [ Expanded(child: _buildOptionItem(options[0])), const SizedBox(width: 12), Expanded(child: _buildOptionItem(options[1])), ], ), const SizedBox(height: 12), Row( children: [ Expanded(child: _buildOptionItem(options[2])), const SizedBox(width: 12), Expanded(child: _buildOptionItem(options[3])), ], ), ], ); } else { // 1*4布局 final List optionWidgets = []; for (int i = 0; i < options.length; i++) { optionWidgets.add(_buildOptionItem(options[i])); if (i < options.length - 1) { optionWidgets.add(const SizedBox(height: 12)); } } return Column(children: optionWidgets); } } /// 构建标签 Widget _buildTag(String label, String value) { if (value.isEmpty) return const SizedBox(); return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppConstants.primaryColor.withAlpha(20), borderRadius: BorderRadius.circular(4), ), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( label, style: TextStyle( fontSize: 10, color: AppConstants.primaryColor, fontWeight: FontWeight.w600, ), ), Text( value, style: TextStyle( fontSize: 12, color: Colors.black87, fontWeight: FontWeight.w500, ), ), ], ), ); } /// 构建单个选项 Widget _buildOptionItem(dynamic option) { final optionNum = option['index'] ?? option['num'] ?? 0; final isSelected = _selectedAnswer == optionNum; final isCorrect = _showFeedback && _isAnswerCorrect && _selectedAnswer == optionNum; final isWrong = _showFeedback && !_isAnswerCorrect && _selectedAnswer == optionNum; return AnimatedContainer( duration: const Duration(milliseconds: 300), child: Container( decoration: BoxDecoration( gradient: isSelected ? LinearGradient( colors: isCorrect ? [Colors.green[400]!, Colors.green[300]!] : isWrong ? [Colors.red[400]!, Colors.red[300]!] : [ AppConstants.primaryColor, AppConstants.primaryColor.withAlpha(200), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ) : null, color: isSelected ? null : Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all( color: isSelected ? Colors.transparent : AppConstants.primaryColor.withAlpha(50), width: 2, ), boxShadow: isSelected ? [ BoxShadow( color: (isCorrect ? Colors.green : isWrong ? Colors.red : AppConstants.primaryColor) .withAlpha(80), blurRadius: 12, offset: const Offset(0, 4), ), ] : [ BoxShadow( color: Colors.black.withAlpha(5), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Material( color: Colors.transparent, child: InkWell( onTap: _isSubmitting || (_showFeedback && _isAnswerCorrect) ? null : () { if (_showFeedback) { // 重置状态,允许重新选择 setState(() { _showFeedback = false; _selectedAnswer = null; _feedbackMessage = null; }); } _submitAnswer(optionNum); }, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.all(16), child: Row( children: [ AnimatedContainer( duration: const Duration(milliseconds: 300), width: 32, height: 32, decoration: BoxDecoration( gradient: isSelected ? LinearGradient( colors: isCorrect ? [Colors.white, Colors.white.withAlpha(230)] : isWrong ? [Colors.white, Colors.white.withAlpha(230)] : [Colors.white, Colors.white.withAlpha(230)], begin: Alignment.topLeft, end: Alignment.bottomRight, ) : null, color: isSelected ? null : AppConstants.primaryColor.withAlpha(20), shape: BoxShape.circle, boxShadow: isSelected ? [ BoxShadow( color: Colors.black.withAlpha(20), blurRadius: 4, offset: const Offset(0, 2), ), ] : null, ), child: Center( child: Text( '$optionNum', style: TextStyle( color: isSelected ? (isCorrect ? Colors.green : isWrong ? Colors.red : AppConstants.primaryColor) : AppConstants.primaryColor, fontWeight: FontWeight.bold, fontSize: 16, ), ), ), ), const SizedBox(width: 16), Expanded( child: Text( option['content'] ?? option['text'] ?? '', style: TextStyle( fontSize: 17, fontWeight: FontWeight.w500, color: isSelected ? Colors.white : Colors.black87, ), ), ), if (isSelected) Icon( isCorrect ? Icons.check_circle : isWrong ? Icons.cancel : Icons.radio_button_checked, color: Colors.white, size: 28, ), ], ), ), ), ), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text( '诗词答题', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20), ), backgroundColor: AppConstants.primaryColor, foregroundColor: Colors.white, elevation: 0, flexibleSpace: Container( decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppConstants.primaryColor, AppConstants.primaryColor.withAlpha(180), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), ), actions: [ Padding( padding: const EdgeInsets.only(right: 16), child: Container( decoration: BoxDecoration( color: Colors.white.withAlpha(30), borderRadius: BorderRadius.circular(8), ), child: ElevatedButton( onPressed: _openAnswerRecordPage, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 8, ), ), child: const Text( '记录', style: TextStyle( color: Colors.white, fontSize: 14, fontWeight: FontWeight.w600, ), ), ), ), ), ], ), body: Container( color: Colors.white, child: SafeArea( child: Padding( padding: const EdgeInsets.only( left: 16.0, right: 16.0, top: 8.0, bottom: 16.0, ), child: Stack( children: [ Column( children: [ const SizedBox(height: 8), // 减少顶部空白 // 分数显示 AnimatedBuilder( animation: _successAnimationController, builder: (context, child) { return Transform.scale( scale: _isAnswerCorrect ? _scaleAnimation.value : 1.0, child: Container( padding: const EdgeInsets.symmetric( horizontal: 20, vertical: 12, ), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppConstants.primaryColor, AppConstants.primaryColor.withAlpha(200), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: AppConstants.primaryColor.withAlpha( 80, ), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.white.withAlpha(30), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.quiz_outlined, color: Colors.white, size: 20, ), ), const SizedBox(width: 12), Text( '题目: ${_manager.currentIndex + 1}/${_manager.total}', style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white, ), ), const SizedBox(width: 12), // 奖杯图标和分数 Row( children: [ Icon( Icons.emoji_events_outlined, color: Colors.amber[300], size: 24, ), const SizedBox(width: 8), Text( '$_score', style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), ], ), Row( children: [ // 开关按钮 Tooltip( message: _autoLoadNext ? '已开启自动下一题' : '已关闭自动下一题', child: Switch( value: _autoLoadNext, onChanged: (value) { setState(() { _autoLoadNext = value; }); }, activeColor: Colors.white, activeTrackColor: Colors.white .withAlpha(128), ), ), ], ), ], ), ), ); }, ), // 移除空白间距 const SizedBox(height: 10), // 加载状态 if (_isLoading) const Expanded( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( AppConstants.primaryColor, ), strokeWidth: 3, ), SizedBox(height: 20), Text( '加载题目中...', style: TextStyle( fontSize: 16, color: Colors.grey, ), ), ], ), ), ), // 错误状态 if (!_isLoading && _errorMessage != null) Expanded( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.red[50], shape: BoxShape.circle, ), child: Icon( Icons.error_outline, size: 64, color: Colors.red[400], ), ), const SizedBox(height: 24), Text( _errorMessage!, textAlign: TextAlign.center, style: const TextStyle( fontSize: 16, color: Colors.red, ), ), const SizedBox(height: 32), Container( decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppConstants.primaryColor, AppConstants.primaryColor.withAlpha(200), ], ), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: AppConstants.primaryColor .withAlpha(80), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: ElevatedButton( onPressed: () => _loadQuestion(), style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, padding: const EdgeInsets.symmetric( horizontal: 32, vertical: 16, ), ), child: const Text( '重新加载', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white, ), ), ), ), ], ), ), ), // 题目内容 if (!_isLoading && _currentQuestion != null) Expanded( child: Column( children: [ // 可滚动区域 Expanded( child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 题目信息 AnimatedBuilder( animation: _shakeAnimationController, builder: (context, child) { return Transform.translate( offset: Offset( _isAnswerCorrect ? 0 : _shakeAnimation.value, 0, ), child: Stack( children: [ // 流动边框 Positioned.fill( child: FlowingBorderContainer( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular( 16, ), color: Colors.white, ), ), color: AppConstants.primaryColor, width: 4, ), ), // 题目内容 Container( padding: const EdgeInsets.all( 16, ), decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.white, AppConstants.primaryColor .withAlpha(5), Colors.white, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), backgroundBlendMode: BlendMode.softLight, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 装饰元素 Row( children: [ Container( width: 4, height: 20, decoration: BoxDecoration( color: AppConstants .primaryColor, borderRadius: BorderRadius.circular( 2, ), ), ), const SizedBox( width: 12, ), Text( '诗词挑战', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: AppConstants .primaryColor, ), ), ], ), const SizedBox(height: 12), // 题目 Text( _currentQuestion!['question'] ?? '题目加载失败', style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, height: 1.5, color: Colors.black87, ), ), // 标签信息 if (_showTags) AnimatedOpacity( duration: const Duration( milliseconds: 500, ), opacity: 1, child: Container( margin: const EdgeInsets.only( top: 12, ), padding: const EdgeInsets.all( 12, ), decoration: BoxDecoration( color: AppConstants .primaryColor .withAlpha(10), borderRadius: BorderRadius.circular( 8, ), ), child: Row( mainAxisAlignment: MainAxisAlignment .spaceBetween, children: [ _buildTag( '作者', _currentQuestion!['author'] ?? '', ), _buildTag( '年代', _currentQuestion!['dynasty'] ?? '', ), _buildTag( '类型', _currentQuestion!['type'] ?? '', ), _buildTag( '阶段', _currentQuestion!['grade'] ?? '', ), ], ), ), ), ], ), ), ], ), ); }, ), const SizedBox(height: 10), // 选项 _buildOptionsLayout(), ], ), ), ), // 固定位置的操作按钮卡片(在底部固定,不随内容滚动) Container( width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(10), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: Column( children: [ // 操作按钮 - 改为一行显示 Row( children: [ // 上一题按钮 Expanded( child: Container( decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.white, Colors.grey[50]!, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular( 12, ), border: Border.all( color: AppConstants.primaryColor .withAlpha(50), width: 1, ), ), child: OutlinedButton( onPressed: _previousQuestion, style: OutlinedButton.styleFrom( side: BorderSide.none, padding: const EdgeInsets.symmetric( vertical: 14, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.arrow_back, color: AppConstants.primaryColor, size: 20, ), const SizedBox(width: 8), const Text( '上一题', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.black87, ), ), ], ), ), ), ), const SizedBox(width: 12), // 提示按钮 Expanded( child: Container( decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.white, Colors.grey[50]!, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular( 12, ), border: Border.all( color: AppConstants.primaryColor, width: 2, ), boxShadow: [ BoxShadow( color: AppConstants.primaryColor .withAlpha(30), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: ElevatedButton( onPressed: _getHint, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, padding: const EdgeInsets.symmetric( vertical: 14, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.lightbulb_outline, color: AppConstants.primaryColor, size: 20, ), const SizedBox(width: 8), const Text( '提示', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.black87, ), ), ], ), ), ), ), const SizedBox(width: 12), // 下一题按钮 Expanded( child: Container( decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppConstants.primaryColor, AppConstants.primaryColor .withAlpha(200), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular( 12, ), boxShadow: [ BoxShadow( color: AppConstants.primaryColor .withAlpha(80), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: ElevatedButton( onPressed: _nextQuestion, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, padding: const EdgeInsets.symmetric( vertical: 14, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( '下一题', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.white, ), ), const SizedBox(width: 8), Icon( Icons.arrow_forward, color: Colors.white, size: 20, ), ], ), ), ), ), ], ), ], ), ), ], ), ), ], ), // 反馈信息气泡(不占用布局) if (_showFeedback && _feedbackMessage != null) Positioned( top: 0, left: 16, right: 16, child: AnimatedContainer( duration: const Duration(milliseconds: 500), curve: Curves.easeOut, transform: Matrix4.translationValues(0, 0, 0), padding: const EdgeInsets.symmetric( horizontal: 20, vertical: 12, ), decoration: BoxDecoration( gradient: LinearGradient( colors: _isAnswerCorrect ? [Colors.green[400]!, Colors.green[300]!] : [Colors.orange[400]!, Colors.orange[300]!], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: (_isAnswerCorrect ? Colors.green : Colors.orange) .withAlpha(80), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: Row( children: [ Icon( _isAnswerCorrect ? Icons.celebration : Icons.lightbulb_outline, color: Colors.white, size: 24, ), const SizedBox(width: 12), Expanded( child: Text( _feedbackMessage!, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.white, ), ), ), ], ), ), ), ], ), ), ), ), ); } }