/// 诗词答题页面组件 library; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../services/get/theme_controller.dart'; import '../../../models/colors/theme_colors.dart'; /// 单个选项组件 class PoetryOptionItem extends StatelessWidget { final dynamic option; final bool isSelected; final bool isCorrect; final bool isWrong; final bool isSubmitting; final bool showFeedback; final bool isAnswerCorrect; final Function(int) onTap; const PoetryOptionItem({ super.key, required this.option, required this.isSelected, required this.isCorrect, required this.isWrong, required this.isSubmitting, required this.showFeedback, required this.isAnswerCorrect, required this.onTap, }); @override Widget build(BuildContext context) { final themeController = Get.find(); return Obx(() { final isDark = themeController.isDarkModeRx.value; final primaryColor = ThemeColors.getThemeColor( themeController.themeColorIndexRx.value, ); final optionNum = option['index'] ?? option['num'] ?? 0; 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]!] : [primaryColor, primaryColor.withAlpha(200)], begin: Alignment.topLeft, end: Alignment.bottomRight, ) : null, color: isSelected ? null : isDark ? const Color(0xFF2A2A2A) : Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all( color: isSelected ? Colors.transparent : primaryColor.withAlpha(50), width: 2, ), boxShadow: isSelected ? [ BoxShadow( color: (isCorrect ? Colors.green : isWrong ? Colors.red : primaryColor) .withAlpha(80), blurRadius: 12, offset: const Offset(0, 4), ), ] : [ BoxShadow( color: isDark ? Colors.white.withAlpha(5) : 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) { onTap(-1); // -1 表示重置状态 } else { onTap(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: [ Colors.white, Colors.white.withAlpha(230), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ) : null, color: isSelected ? null : 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 : primaryColor) : 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 : isDark ? Colors.grey[300] : Colors.black87, ), ), ), if (isSelected) Icon( isCorrect ? Icons.check_circle : isWrong ? Icons.cancel : Icons.radio_button_checked, color: Colors.white, size: 28, ), ], ), ), ), ), ), ); }); } } /// 选项布局组件 class PoetryOptionsLayout extends StatelessWidget { final List options; final int? selectedAnswer; final bool showFeedback; final bool isAnswerCorrect; final bool isSubmitting; final Function(int) onTap; const PoetryOptionsLayout({ super.key, required this.options, required this.selectedAnswer, required this.showFeedback, required this.isAnswerCorrect, required this.isSubmitting, required this.onTap, }); @override Widget build(BuildContext context) { if (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 _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 PoetryOptionItem( option: option, isSelected: isSelected, isCorrect: isCorrect, isWrong: isWrong, isSubmitting: isSubmitting, showFeedback: showFeedback, isAnswerCorrect: isAnswerCorrect, onTap: onTap, ); } } /// 标签组件 class PoetryTag extends StatelessWidget { final String label; final String value; const PoetryTag({super.key, required this.label, required this.value}); @override Widget build(BuildContext context) { if (value.isEmpty) return const SizedBox(); final themeController = Get.find(); return Obx(() { final isDark = themeController.isDarkModeRx.value; final primaryColor = ThemeColors.getThemeColor( themeController.themeColorIndexRx.value, ); return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: primaryColor.withAlpha(20), borderRadius: BorderRadius.circular(4), ), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( label, style: TextStyle( fontSize: 10, color: primaryColor, fontWeight: FontWeight.w600, ), ), Text( value, style: TextStyle( fontSize: 12, color: isDark ? Colors.grey[300] : Colors.black87, fontWeight: FontWeight.w500, ), ), ], ), ); }); } }