feat: 诗词答题页面主题色支持与代码重构
- 创建 poetry-page.dart,提取 UI 组件(PoetryOptionItem、PoetryOptionsLayout、PoetryTag) - 修改 poetry.dart,使用新组件,添加主题色支持 - 修改 flow-anim.dart,添加主题色支持 - 修改 distinguish.dart,添加主题色支持 - 支持动态主题色切换 - 支持深色模式 - 保持页面布局不变
This commit is contained in:
@@ -11,6 +11,7 @@ import 'package:get/get.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
import '../../../models/colors/app_colors.dart';
|
import '../../../models/colors/app_colors.dart';
|
||||||
|
import '../../../models/colors/theme_colors.dart';
|
||||||
import '../../../controllers/shared_preferences_storage_controller.dart';
|
import '../../../controllers/shared_preferences_storage_controller.dart';
|
||||||
import '../../../controllers/history_controller.dart';
|
import '../../../controllers/history_controller.dart';
|
||||||
import '../../../services/network_listener_service.dart';
|
import '../../../services/network_listener_service.dart';
|
||||||
@@ -262,16 +263,8 @@ class _DistinguishPageState extends State<DistinguishPage> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
_buildStatRow('已答题', '$_totalQuestions 题'),
|
_buildStatRow('已答题', '$_totalQuestions 题'),
|
||||||
_buildStatRow(
|
_buildStatRow('正确', '$_correctAnswers 题', isGreen: true),
|
||||||
'正确',
|
_buildStatRow('错误', '$_wrongAnswers 题', isRed: true),
|
||||||
'$_correctAnswers 题',
|
|
||||||
isGreen: true,
|
|
||||||
),
|
|
||||||
_buildStatRow(
|
|
||||||
'错误',
|
|
||||||
'$_wrongAnswers 题',
|
|
||||||
isRed: true,
|
|
||||||
),
|
|
||||||
_buildStatRow(
|
_buildStatRow(
|
||||||
'正确率',
|
'正确率',
|
||||||
'${_correctRate.toStringAsFixed(1)}%',
|
'${_correctRate.toStringAsFixed(1)}%',
|
||||||
@@ -288,15 +281,8 @@ class _DistinguishPageState extends State<DistinguishPage> {
|
|||||||
),
|
),
|
||||||
_buildStatRow('提示次数', '$_hintCount 次'),
|
_buildStatRow('提示次数', '$_hintCount 次'),
|
||||||
_buildStatRow('跳过次数', '$_skipCount 次'),
|
_buildStatRow('跳过次数', '$_skipCount 次'),
|
||||||
Divider(
|
Divider(height: 24, color: AppColors.divider),
|
||||||
height: 24,
|
_buildStatRow('诗词水平', _poetryLevel, isHighlight: true),
|
||||||
color: AppColors.divider,
|
|
||||||
),
|
|
||||||
_buildStatRow(
|
|
||||||
'诗词水平',
|
|
||||||
_poetryLevel,
|
|
||||||
isHighlight: true,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -378,10 +364,7 @@ class _DistinguishPageState extends State<DistinguishPage> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style: TextStyle(
|
style: TextStyle(fontSize: 15, color: AppColors.secondaryText),
|
||||||
fontSize: 15,
|
|
||||||
color: AppColors.secondaryText,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
value,
|
value,
|
||||||
@@ -453,7 +436,10 @@ $_poetryLevel
|
|||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
backgroundColor: AppColors.surface,
|
backgroundColor: AppColors.surface,
|
||||||
title: Text('确认清空', style: TextStyle(color: AppColors.primaryText)),
|
title: Text('确认清空', style: TextStyle(color: AppColors.primaryText)),
|
||||||
content: Text('确定要清空所有答题记录吗?此操作不可恢复。', style: TextStyle(color: AppColors.secondaryText)),
|
content: Text(
|
||||||
|
'确定要清空所有答题记录吗?此操作不可恢复。',
|
||||||
|
style: TextStyle(color: AppColors.secondaryText),
|
||||||
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context, false),
|
onPressed: () => Navigator.pop(context, false),
|
||||||
@@ -500,6 +486,9 @@ $_poetryLevel
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Obx(() {
|
return Obx(() {
|
||||||
final isDark = _themeController.isDarkMode;
|
final isDark = _themeController.isDarkMode;
|
||||||
|
final primaryColor = ThemeColors.getThemeColor(
|
||||||
|
_themeController.themeColorIndexRx.value,
|
||||||
|
);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(
|
title: Text(
|
||||||
@@ -510,16 +499,13 @@ $_poetryLevel
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
backgroundColor: AppColors.primary,
|
backgroundColor: primaryColor,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
flexibleSpace: Container(
|
flexibleSpace: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [
|
colors: [primaryColor, primaryColor.withAlpha(180)],
|
||||||
AppColors.primary,
|
|
||||||
AppColors.primary.withAlpha(180),
|
|
||||||
],
|
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
),
|
),
|
||||||
@@ -540,7 +526,7 @@ $_poetryLevel
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: Container(
|
body: Container(
|
||||||
color: AppColors.background,
|
color: isDark ? const Color(0xFF1A1A1A) : AppColors.background,
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: _isLoading
|
child: _isLoading
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
@@ -577,10 +563,7 @@ $_poetryLevel
|
|||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
'快去答题吧!',
|
'快去答题吧!',
|
||||||
style: TextStyle(
|
style: TextStyle(fontSize: 14, color: AppColors.tertiaryText),
|
||||||
fontSize: 14,
|
|
||||||
color: AppColors.tertiaryText,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -591,30 +574,36 @@ $_poetryLevel
|
|||||||
Widget _buildRecordList() {
|
Widget _buildRecordList() {
|
||||||
return Obx(() {
|
return Obx(() {
|
||||||
final isDark = _themeController.isDarkMode;
|
final isDark = _themeController.isDarkMode;
|
||||||
|
final primaryColor = ThemeColors.getThemeColor(
|
||||||
|
_themeController.themeColorIndexRx.value,
|
||||||
|
);
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
itemCount: _answerRecords.length,
|
itemCount: _answerRecords.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final record = _answerRecords[index];
|
final record = _answerRecords[index];
|
||||||
return _buildRecordCard(record, index);
|
return _buildRecordCard(record, index, primaryColor, isDark);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildRecordCard(Map<String, dynamic> record, int index) {
|
Widget _buildRecordCard(
|
||||||
|
Map<String, dynamic> record,
|
||||||
|
int index,
|
||||||
|
Color primaryColor,
|
||||||
|
bool isDark,
|
||||||
|
) {
|
||||||
final question = record['question'] ?? '未知题目';
|
final question = record['question'] ?? '未知题目';
|
||||||
final author = record['author'] ?? '未知作者';
|
final author = record['author'] ?? '未知作者';
|
||||||
final tags = (record['tags'] as List<dynamic>?)?.cast<String>() ?? [];
|
final tags = (record['tags'] as List<dynamic>?)?.cast<String>() ?? [];
|
||||||
final isCorrect = record['isCorrect'] ?? false;
|
final isCorrect = record['isCorrect'] ?? false;
|
||||||
final answerTime = _formatTime(record['answerTime']);
|
final answerTime = _formatTime(record['answerTime']);
|
||||||
|
|
||||||
return Obx(() {
|
|
||||||
final isDark = _themeController.isDarkMode;
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.surface,
|
color: isDark ? const Color(0xFF2A2A2A) : AppColors.surface,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
@@ -636,7 +625,7 @@ $_poetryLevel
|
|||||||
width: 28,
|
width: 28,
|
||||||
height: 28,
|
height: 28,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.primary.withAlpha(20),
|
color: primaryColor.withAlpha(20),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
@@ -645,7 +634,7 @@ $_poetryLevel
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: AppColors.primary,
|
color: primaryColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -660,7 +649,9 @@ $_poetryLevel
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: AppColors.primaryText,
|
color: isDark
|
||||||
|
? Colors.grey[300]
|
||||||
|
: AppColors.primaryText,
|
||||||
),
|
),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
@@ -670,7 +661,9 @@ $_poetryLevel
|
|||||||
'—— $author',
|
'—— $author',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: AppColors.secondaryText,
|
color: isDark
|
||||||
|
? Colors.grey[500]
|
||||||
|
: AppColors.secondaryText,
|
||||||
fontStyle: FontStyle.italic,
|
fontStyle: FontStyle.italic,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -695,7 +688,9 @@ $_poetryLevel
|
|||||||
Icon(
|
Icon(
|
||||||
isCorrect ? Icons.check_circle : Icons.cancel,
|
isCorrect ? Icons.check_circle : Icons.cancel,
|
||||||
size: 14,
|
size: 14,
|
||||||
color: isCorrect ? AppColors.iosGreen : AppColors.iosRed,
|
color: isCorrect
|
||||||
|
? AppColors.iosGreen
|
||||||
|
: AppColors.iosRed,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
@@ -703,7 +698,9 @@ $_poetryLevel
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: isCorrect ? AppColors.iosGreen : AppColors.iosRed,
|
color: isCorrect
|
||||||
|
? AppColors.iosGreen
|
||||||
|
: AppColors.iosRed,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -726,12 +723,10 @@ $_poetryLevel
|
|||||||
vertical: 3,
|
vertical: 3,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.primary.withAlpha(15),
|
color: primaryColor.withAlpha(15),
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: AppColors.primary.withAlpha(
|
color: primaryColor.withAlpha(50),
|
||||||
50,
|
|
||||||
),
|
|
||||||
width: 0.5,
|
width: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -739,7 +734,7 @@ $_poetryLevel
|
|||||||
tag,
|
tag,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
color: AppColors.primary,
|
color: primaryColor,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -750,7 +745,9 @@ $_poetryLevel
|
|||||||
'暂无标签',
|
'暂无标签',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: AppColors.tertiaryText,
|
color: isDark
|
||||||
|
? Colors.grey[500]
|
||||||
|
: AppColors.tertiaryText,
|
||||||
fontStyle: FontStyle.italic,
|
fontStyle: FontStyle.italic,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -761,14 +758,16 @@ $_poetryLevel
|
|||||||
Icon(
|
Icon(
|
||||||
Icons.access_time,
|
Icons.access_time,
|
||||||
size: 12,
|
size: 12,
|
||||||
color: AppColors.tertiaryText,
|
color: isDark ? Colors.grey[500] : AppColors.tertiaryText,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
answerTime,
|
answerTime,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: AppColors.secondaryText,
|
color: isDark
|
||||||
|
? Colors.grey[400]
|
||||||
|
: AppColors.secondaryText,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -779,7 +778,6 @@ $_poetryLevel
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 写入统计数据到笔记
|
// 写入统计数据到笔记
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
import '../../../services/get/theme_controller.dart';
|
import '../../../services/get/theme_controller.dart';
|
||||||
|
import '../../../models/colors/theme_colors.dart';
|
||||||
|
|
||||||
/// 流动边框装饰器
|
/// 流动边框装饰器
|
||||||
class FlowingBorderDecoration extends Decoration {
|
class FlowingBorderDecoration extends Decoration {
|
||||||
@@ -108,7 +109,10 @@ class _FlowingBorderContainerState extends State<FlowingBorderContainer>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Obx(() {
|
return Obx(() {
|
||||||
final color = widget.color ?? _themeController.currentThemeColor;
|
final color =
|
||||||
|
widget.color ??
|
||||||
|
ThemeColors.getThemeColor(_themeController.themeColorIndexRx.value);
|
||||||
|
|
||||||
return AnimatedBuilder(
|
return AnimatedBuilder(
|
||||||
animation: _animation,
|
animation: _animation,
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
|
|||||||
327
lib/views/profile/level/poetry-page.dart
Normal file
327
lib/views/profile/level/poetry-page.dart
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
/// 诗词答题页面组件
|
||||||
|
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<ThemeController>();
|
||||||
|
|
||||||
|
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<dynamic> 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<Widget> 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<ThemeController>();
|
||||||
|
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,34 @@
|
|||||||
/// 时间: 2026-03-28
|
|
||||||
/// 功能: 诗词答题页面
|
|
||||||
/// 介绍: 基于 API 接口实现的诗词答题系统,支持获取题目、提交答案、获取提示
|
|
||||||
/// 最新变化: 添加自动加载下一题开关,隐藏提示标签,使用独立逻辑管理器,支持主题色设置
|
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
import '../../../models/colors/app_colors.dart';
|
import '../../../constants/app_constants.dart';
|
||||||
import '../../../controllers/shared_preferences_storage_controller.dart';
|
import '../../../controllers/shared_preferences_storage_controller.dart';
|
||||||
import '../../../services/get/theme_controller.dart';
|
import '../../../services/get/theme_controller.dart';
|
||||||
|
import '../../../models/colors/theme_colors.dart';
|
||||||
import '../guide/tongji.dart';
|
import '../guide/tongji.dart';
|
||||||
import 'level-jilu.dart';
|
import 'level-jilu.dart';
|
||||||
import 'flow-anim.dart';
|
import 'flow-anim.dart';
|
||||||
import 'distinguish.dart';
|
import 'distinguish.dart';
|
||||||
|
import 'poetry-page.dart';
|
||||||
import '../settings/offline-data.dart';
|
import '../settings/offline-data.dart';
|
||||||
|
|
||||||
|
/// 时间: 2026-03-28
|
||||||
|
/// 功能: 诗词答题页面
|
||||||
|
/// 介绍: 基于 API 接口实现的诗词答题系统,支持获取题目、提交答案、获取提示
|
||||||
|
/// 最新变化: 添加自动加载下一题开关,隐藏提示标签,使用独立逻辑管理器
|
||||||
|
|
||||||
class PoetryLevelPage extends StatefulWidget {
|
class PoetryLevelPage extends StatefulWidget {
|
||||||
const PoetryLevelPage({super.key});
|
final bool showBackButton;
|
||||||
|
final bool showAppBar;
|
||||||
|
|
||||||
|
const PoetryLevelPage({
|
||||||
|
super.key,
|
||||||
|
this.showBackButton = true,
|
||||||
|
this.showAppBar = true,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PoetryLevelPage> createState() => _PoetryLevelPageState();
|
State<PoetryLevelPage> createState() => _PoetryLevelPageState();
|
||||||
@@ -137,7 +146,9 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(initResult.message ?? '已加载离线缓存'),
|
content: Text(initResult.message ?? '已加载离线缓存'),
|
||||||
backgroundColor: AppColors.primary,
|
backgroundColor: ThemeColors.getThemeColor(
|
||||||
|
_themeController.themeColorIndexRx.value,
|
||||||
|
),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -153,15 +164,14 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
backgroundColor: AppColors.surface,
|
title: const Text('提示'),
|
||||||
title: Text('提示', style: TextStyle(color: AppColors.primaryText)),
|
content: const Text('当前无网络连接且无离线缓存数据,请先下载数据或检查网络设置。'),
|
||||||
content: Text('当前无网络连接且无离线缓存数据,请先下载数据或检查网络设置。', style: TextStyle(color: AppColors.secondaryText)),
|
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
child: Text('取消', style: TextStyle(color: AppColors.primary)),
|
child: const Text('取消'),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -172,7 +182,7 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
MaterialPageRoute(builder: (_) => const OfflineDataPage()),
|
MaterialPageRoute(builder: (_) => const OfflineDataPage()),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text('去下载', style: TextStyle(color: AppColors.primary)),
|
child: const Text('去下载'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -407,254 +417,16 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 构建选项布局
|
|
||||||
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<Widget> 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: AppColors.primary.withAlpha(20),
|
|
||||||
borderRadius: BorderRadius.circular(4),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
label,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10,
|
|
||||||
color: AppColors.primary,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
value,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: AppColors.primaryText,
|
|
||||||
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 Obx(() {
|
|
||||||
final isDark = _themeController.isDarkMode;
|
|
||||||
return AnimatedContainer(
|
|
||||||
duration: const Duration(milliseconds: 300),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
gradient: isSelected
|
|
||||||
? LinearGradient(
|
|
||||||
colors: isCorrect
|
|
||||||
? [AppColors.iosGreen, AppColors.iosGreen.withAlpha(200)]
|
|
||||||
: isWrong
|
|
||||||
? [AppColors.iosRed, AppColors.iosRed.withAlpha(200)]
|
|
||||||
: [
|
|
||||||
AppColors.primary,
|
|
||||||
AppColors.primary.withAlpha(200),
|
|
||||||
],
|
|
||||||
begin: Alignment.topLeft,
|
|
||||||
end: Alignment.bottomRight,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
color: isSelected ? null : AppColors.surface,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
border: Border.all(
|
|
||||||
color: isSelected
|
|
||||||
? Colors.transparent
|
|
||||||
: AppColors.primary.withAlpha(50),
|
|
||||||
width: 2,
|
|
||||||
),
|
|
||||||
boxShadow: isSelected
|
|
||||||
? [
|
|
||||||
BoxShadow(
|
|
||||||
color: (isCorrect
|
|
||||||
? AppColors.iosGreen
|
|
||||||
: isWrong
|
|
||||||
? AppColors.iosRed
|
|
||||||
: AppColors.primary)
|
|
||||||
.withAlpha(80),
|
|
||||||
blurRadius: 12,
|
|
||||||
offset: const Offset(0, 4),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withAlpha(isDark ? 10 : 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
|
|
||||||
: AppColors.primary.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
|
|
||||||
? AppColors.iosGreen
|
|
||||||
: isWrong
|
|
||||||
? AppColors.iosRed
|
|
||||||
: AppColors.primary)
|
|
||||||
: AppColors.primary,
|
|
||||||
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 : AppColors.primaryText,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (isSelected)
|
|
||||||
Icon(
|
|
||||||
isCorrect
|
|
||||||
? Icons.check_circle
|
|
||||||
: isWrong
|
|
||||||
? Icons.cancel
|
|
||||||
: Icons.radio_button_checked,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 28,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Obx(() {
|
return Obx(() {
|
||||||
final isDark = _themeController.isDarkMode;
|
final isDark = _themeController.isDarkModeRx.value;
|
||||||
|
final primaryColor = ThemeColors.getThemeColor(
|
||||||
|
_themeController.themeColorIndexRx.value,
|
||||||
|
);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: widget.showAppBar
|
||||||
|
? AppBar(
|
||||||
title: Text(
|
title: Text(
|
||||||
'诗词答题',
|
'诗词答题',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -663,16 +435,14 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
backgroundColor: AppColors.primary,
|
backgroundColor: primaryColor,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
|
leading: widget.showBackButton ? null : const SizedBox.shrink(),
|
||||||
flexibleSpace: Container(
|
flexibleSpace: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [
|
colors: [primaryColor, primaryColor.withAlpha(180)],
|
||||||
AppColors.primary,
|
|
||||||
AppColors.primary.withAlpha(180),
|
|
||||||
],
|
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
),
|
),
|
||||||
@@ -708,16 +478,17 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
)
|
||||||
|
: null,
|
||||||
body: Container(
|
body: Container(
|
||||||
color: AppColors.background,
|
color: isDark ? const Color(0xFF1A1A1A) : Colors.white,
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: 16.0,
|
left: 16.0,
|
||||||
right: 16.0,
|
right: 16.0,
|
||||||
top: 8.0,
|
top: 8.0,
|
||||||
bottom: 16.0,
|
bottom: widget.showAppBar ? 16.0 : 100.0, // 关怀模式下增加底部padding
|
||||||
),
|
),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
@@ -740,8 +511,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
AppColors.primary,
|
primaryColor,
|
||||||
AppColors.primary.withAlpha(200),
|
primaryColor.withAlpha(200),
|
||||||
],
|
],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
@@ -749,9 +520,7 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: AppColors.primary.withAlpha(
|
color: primaryColor.withAlpha(80),
|
||||||
80,
|
|
||||||
),
|
|
||||||
blurRadius: 12,
|
blurRadius: 12,
|
||||||
offset: const Offset(0, 4),
|
offset: const Offset(0, 4),
|
||||||
),
|
),
|
||||||
@@ -844,7 +613,7 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
children: [
|
children: [
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
valueColor: AlwaysStoppedAnimation<Color>(
|
valueColor: AlwaysStoppedAnimation<Color>(
|
||||||
AppColors.primary,
|
primaryColor,
|
||||||
),
|
),
|
||||||
strokeWidth: 3,
|
strokeWidth: 3,
|
||||||
),
|
),
|
||||||
@@ -853,7 +622,9 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
'加载题目中...',
|
'加载题目中...',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: AppColors.tertiaryText,
|
color: isDark
|
||||||
|
? Colors.grey[400]
|
||||||
|
: Colors.grey,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -871,14 +642,14 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isDark
|
color: isDark
|
||||||
? AppColors.iosRed.withAlpha(30)
|
? Colors.red[900]!.withAlpha(30)
|
||||||
: AppColors.iosRed.withAlpha(10),
|
: Colors.red[50],
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.error_outline,
|
Icons.error_outline,
|
||||||
size: 64,
|
size: 64,
|
||||||
color: AppColors.iosRed,
|
color: Colors.red[400],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
@@ -887,7 +658,9 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: AppColors.iosRed,
|
color: isDark
|
||||||
|
? Colors.red[300]
|
||||||
|
: Colors.red,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
@@ -895,17 +668,14 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
AppColors.primary,
|
primaryColor,
|
||||||
AppColors.primary.withAlpha(
|
primaryColor.withAlpha(200),
|
||||||
200,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: AppColors.primary
|
color: primaryColor.withAlpha(80),
|
||||||
.withAlpha(80),
|
|
||||||
blurRadius: 8,
|
blurRadius: 8,
|
||||||
offset: const Offset(0, 4),
|
offset: const Offset(0, 4),
|
||||||
),
|
),
|
||||||
@@ -966,9 +736,15 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
BorderRadius.circular(
|
BorderRadius.circular(
|
||||||
16,
|
16,
|
||||||
),
|
),
|
||||||
color: AppColors.surface,
|
color: isDark
|
||||||
|
? const Color(
|
||||||
|
0xFF2A2A2A,
|
||||||
|
)
|
||||||
|
: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
color: AppConstants
|
||||||
|
.primaryColor,
|
||||||
width: 4,
|
width: 4,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -979,10 +755,19 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
AppColors.surface,
|
isDark
|
||||||
AppColors.primary
|
? const Color(
|
||||||
|
0xFF2A2A2A,
|
||||||
|
)
|
||||||
|
: Colors.white,
|
||||||
|
AppConstants
|
||||||
|
.primaryColor
|
||||||
.withAlpha(5),
|
.withAlpha(5),
|
||||||
AppColors.surface,
|
isDark
|
||||||
|
? const Color(
|
||||||
|
0xFF2A2A2A,
|
||||||
|
)
|
||||||
|
: Colors.white,
|
||||||
],
|
],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end:
|
end:
|
||||||
@@ -1007,8 +792,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
width: 4,
|
width: 4,
|
||||||
height: 20,
|
height: 20,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors
|
color: AppConstants
|
||||||
.primary,
|
.primaryColor,
|
||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.circular(
|
BorderRadius.circular(
|
||||||
2,
|
2,
|
||||||
@@ -1025,8 +810,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
fontWeight:
|
fontWeight:
|
||||||
FontWeight
|
FontWeight
|
||||||
.w600,
|
.w600,
|
||||||
color: AppColors
|
color: AppConstants
|
||||||
.primary,
|
.primaryColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -1042,7 +827,9 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
fontWeight:
|
fontWeight:
|
||||||
FontWeight.bold,
|
FontWeight.bold,
|
||||||
height: 1.5,
|
height: 1.5,
|
||||||
color: AppColors.primaryText,
|
color: isDark
|
||||||
|
? Colors.white
|
||||||
|
: Colors.black87,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// 标签信息
|
// 标签信息
|
||||||
@@ -1064,8 +851,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
12,
|
12,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors
|
color: AppConstants
|
||||||
.primary
|
.primaryColor
|
||||||
.withAlpha(
|
.withAlpha(
|
||||||
10,
|
10,
|
||||||
),
|
),
|
||||||
@@ -1079,23 +866,27 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
MainAxisAlignment
|
MainAxisAlignment
|
||||||
.spaceBetween,
|
.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
_buildTag(
|
PoetryTag(
|
||||||
'作者',
|
label: '作者',
|
||||||
|
value:
|
||||||
_currentQuestion!['author'] ??
|
_currentQuestion!['author'] ??
|
||||||
'',
|
'',
|
||||||
),
|
),
|
||||||
_buildTag(
|
PoetryTag(
|
||||||
'年代',
|
label: '年代',
|
||||||
|
value:
|
||||||
_currentQuestion!['dynasty'] ??
|
_currentQuestion!['dynasty'] ??
|
||||||
'',
|
'',
|
||||||
),
|
),
|
||||||
_buildTag(
|
PoetryTag(
|
||||||
'类型',
|
label: '类型',
|
||||||
|
value:
|
||||||
_currentQuestion!['type'] ??
|
_currentQuestion!['type'] ??
|
||||||
'',
|
'',
|
||||||
),
|
),
|
||||||
_buildTag(
|
PoetryTag(
|
||||||
'阶段',
|
label: '阶段',
|
||||||
|
value:
|
||||||
_currentQuestion!['grade'] ??
|
_currentQuestion!['grade'] ??
|
||||||
'',
|
'',
|
||||||
),
|
),
|
||||||
@@ -1113,7 +904,27 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
// 选项
|
// 选项
|
||||||
_buildOptionsLayout(),
|
PoetryOptionsLayout(
|
||||||
|
options:
|
||||||
|
_currentQuestion!['options']
|
||||||
|
as List,
|
||||||
|
selectedAnswer: _selectedAnswer,
|
||||||
|
showFeedback: _showFeedback,
|
||||||
|
isAnswerCorrect: _isAnswerCorrect,
|
||||||
|
isSubmitting: _isSubmitting,
|
||||||
|
onTap: (optionNum) {
|
||||||
|
if (optionNum == -1) {
|
||||||
|
// 重置状态
|
||||||
|
setState(() {
|
||||||
|
_showFeedback = false;
|
||||||
|
_selectedAnswer = null;
|
||||||
|
_feedbackMessage = null;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_submitAnswer(optionNum);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1123,7 +934,7 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.surface,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
@@ -1144,8 +955,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
AppColors.surface,
|
Colors.white,
|
||||||
AppColors.background,
|
Colors.grey[50]!,
|
||||||
],
|
],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
@@ -1153,8 +964,9 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.circular(12),
|
BorderRadius.circular(12),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: AppColors.primary
|
color: primaryColor.withAlpha(
|
||||||
.withAlpha(50),
|
50,
|
||||||
|
),
|
||||||
width: 1,
|
width: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1177,18 +989,18 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
Icons.arrow_back,
|
Icons.arrow_back,
|
||||||
color: AppColors
|
color: AppConstants
|
||||||
.primary,
|
.primaryColor,
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
const Text(
|
||||||
'上一题',
|
'上一题',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight:
|
fontWeight:
|
||||||
FontWeight.w500,
|
FontWeight.w500,
|
||||||
color: AppColors.primaryText,
|
color: Colors.black87,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -1203,20 +1015,23 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
AppColors.primary,
|
Colors.white,
|
||||||
AppColors.primary.withAlpha(
|
Colors.grey[50]!,
|
||||||
200,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
),
|
),
|
||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.circular(12),
|
BorderRadius.circular(12),
|
||||||
|
border: Border.all(
|
||||||
|
color: primaryColor,
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: AppColors.primary
|
color: primaryColor.withAlpha(
|
||||||
.withAlpha(80),
|
30,
|
||||||
|
),
|
||||||
blurRadius: 8,
|
blurRadius: 8,
|
||||||
offset: const Offset(0, 4),
|
offset: const Offset(0, 4),
|
||||||
),
|
),
|
||||||
@@ -1225,7 +1040,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: _getHint,
|
onPressed: _getHint,
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor:
|
||||||
|
Colors.transparent,
|
||||||
shadowColor: Colors.transparent,
|
shadowColor: Colors.transparent,
|
||||||
padding:
|
padding:
|
||||||
const EdgeInsets.symmetric(
|
const EdgeInsets.symmetric(
|
||||||
@@ -1240,9 +1056,10 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
MainAxisAlignment.center,
|
MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Icon(
|
Icon(
|
||||||
Icons.lightbulb_outline,
|
Icons.lightbulb_outline,
|
||||||
color: Colors.white,
|
color: AppConstants
|
||||||
|
.primaryColor,
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
@@ -1251,8 +1068,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight:
|
fontWeight:
|
||||||
FontWeight.w500,
|
FontWeight.w600,
|
||||||
color: Colors.white,
|
color: Colors.black87,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -1267,24 +1084,30 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
AppColors.surface,
|
primaryColor,
|
||||||
AppColors.background,
|
primaryColor.withAlpha(200),
|
||||||
],
|
],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
),
|
),
|
||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.circular(12),
|
BorderRadius.circular(12),
|
||||||
border: Border.all(
|
boxShadow: [
|
||||||
color: AppColors.primary
|
BoxShadow(
|
||||||
.withAlpha(50),
|
color: AppConstants
|
||||||
width: 1,
|
.primaryColor
|
||||||
|
.withAlpha(80),
|
||||||
|
blurRadius: 12,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
child: OutlinedButton(
|
child: ElevatedButton(
|
||||||
onPressed: _nextQuestion,
|
onPressed: _nextQuestion,
|
||||||
style: OutlinedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
side: BorderSide.none,
|
backgroundColor:
|
||||||
|
Colors.transparent,
|
||||||
|
shadowColor: Colors.transparent,
|
||||||
padding:
|
padding:
|
||||||
const EdgeInsets.symmetric(
|
const EdgeInsets.symmetric(
|
||||||
vertical: 14,
|
vertical: 14,
|
||||||
@@ -1298,20 +1121,19 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
MainAxisAlignment.center,
|
MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
const Text(
|
||||||
'下一题',
|
'下一题',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight:
|
fontWeight:
|
||||||
FontWeight.w500,
|
FontWeight.w600,
|
||||||
color: AppColors.primaryText,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Icon(
|
Icon(
|
||||||
Icons.arrow_forward,
|
Icons.arrow_forward,
|
||||||
color: AppColors
|
color: Colors.white,
|
||||||
.primary,
|
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -1321,45 +1143,72 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// 反馈信息气泡(不占用布局)
|
||||||
if (_showFeedback && _feedbackMessage != null)
|
if (_showFeedback && _feedbackMessage != null)
|
||||||
Padding(
|
Positioned(
|
||||||
padding: const EdgeInsets.only(top: 16),
|
top: 0,
|
||||||
child: Container(
|
left: 16,
|
||||||
padding: const EdgeInsets.all(12),
|
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(
|
decoration: BoxDecoration(
|
||||||
color: _isAnswerCorrect
|
gradient: LinearGradient(
|
||||||
? AppColors.iosGreen
|
colors: _isAnswerCorrect
|
||||||
.withAlpha(20)
|
? [Colors.green[400]!, Colors.green[300]!]
|
||||||
: AppColors.iosRed
|
: [Colors.orange[400]!, Colors.orange[300]!],
|
||||||
.withAlpha(20),
|
begin: Alignment.topLeft,
|
||||||
borderRadius: BorderRadius.circular(8),
|
end: Alignment.bottomRight,
|
||||||
border: Border.all(
|
|
||||||
color: _isAnswerCorrect
|
|
||||||
? AppColors.iosGreen
|
|
||||||
: AppColors.iosRed,
|
|
||||||
width: 1,
|
|
||||||
),
|
),
|
||||||
|
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(
|
child: Text(
|
||||||
_feedbackMessage!,
|
_feedbackMessage!,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
color: _isAnswerCorrect
|
|
||||||
? AppColors.iosGreen
|
|
||||||
: AppColors.iosRed,
|
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
color: Colors.white,
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user