feat: 诗词答题页面主题色支持与代码重构
- 创建 poetry-page.dart,提取 UI 组件(PoetryOptionItem、PoetryOptionsLayout、PoetryTag) - 修改 poetry.dart,使用新组件,添加主题色支持 - 修改 flow-anim.dart,添加主题色支持 - 修改 distinguish.dart,添加主题色支持 - 支持动态主题色切换 - 支持深色模式 - 保持页面布局不变
This commit is contained in:
@@ -1,25 +1,34 @@
|
||||
/// 时间: 2026-03-28
|
||||
/// 功能: 诗词答题页面
|
||||
/// 介绍: 基于 API 接口实现的诗词答题系统,支持获取题目、提交答案、获取提示
|
||||
/// 最新变化: 添加自动加载下一题开关,隐藏提示标签,使用独立逻辑管理器,支持主题色设置
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.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 '../../../services/get/theme_controller.dart';
|
||||
import '../../../models/colors/theme_colors.dart';
|
||||
import '../guide/tongji.dart';
|
||||
import 'level-jilu.dart';
|
||||
import 'flow-anim.dart';
|
||||
import 'distinguish.dart';
|
||||
import 'poetry-page.dart';
|
||||
import '../settings/offline-data.dart';
|
||||
|
||||
/// 时间: 2026-03-28
|
||||
/// 功能: 诗词答题页面
|
||||
/// 介绍: 基于 API 接口实现的诗词答题系统,支持获取题目、提交答案、获取提示
|
||||
/// 最新变化: 添加自动加载下一题开关,隐藏提示标签,使用独立逻辑管理器
|
||||
|
||||
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
|
||||
State<PoetryLevelPage> createState() => _PoetryLevelPageState();
|
||||
@@ -137,7 +146,9 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(initResult.message ?? '已加载离线缓存'),
|
||||
backgroundColor: AppColors.primary,
|
||||
backgroundColor: ThemeColors.getThemeColor(
|
||||
_themeController.themeColorIndexRx.value,
|
||||
),
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
@@ -153,15 +164,14 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
backgroundColor: AppColors.surface,
|
||||
title: Text('提示', style: TextStyle(color: AppColors.primaryText)),
|
||||
content: Text('当前无网络连接且无离线缓存数据,请先下载数据或检查网络设置。', style: TextStyle(color: AppColors.secondaryText)),
|
||||
title: const Text('提示'),
|
||||
content: const Text('当前无网络连接且无离线缓存数据,请先下载数据或检查网络设置。'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text('取消', style: TextStyle(color: AppColors.primary)),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
@@ -172,7 +182,7 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
MaterialPageRoute(builder: (_) => const OfflineDataPage()),
|
||||
);
|
||||
},
|
||||
child: Text('去下载', style: TextStyle(color: AppColors.primary)),
|
||||
child: const Text('去下载'),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -407,317 +417,78 @@ 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;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
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),
|
||||
final isDark = _themeController.isDarkModeRx.value;
|
||||
final primaryColor = ThemeColors.getThemeColor(
|
||||
_themeController.themeColorIndexRx.value,
|
||||
);
|
||||
return Scaffold(
|
||||
appBar: widget.showAppBar
|
||||
? AppBar(
|
||||
title: Text(
|
||||
'诗词答题',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
backgroundColor: primaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
leading: widget.showBackButton ? null : const SizedBox.shrink(),
|
||||
flexibleSpace: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [primaryColor, primaryColor.withAlpha(180)],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
]
|
||||
: [
|
||||
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,
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 16),
|
||||
child: Container(
|
||||
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,
|
||||
color: Colors.white.withAlpha(30),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'$optionNum',
|
||||
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: isSelected
|
||||
? (isCorrect
|
||||
? AppColors.iosGreen
|
||||
: isWrong
|
||||
? AppColors.iosRed
|
||||
: AppColors.primary)
|
||||
: AppColors.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
return Obx(() {
|
||||
final isDark = _themeController.isDarkMode;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
'诗词答题',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
backgroundColor: AppColors.primary,
|
||||
foregroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
flexibleSpace: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColors.primary,
|
||||
AppColors.primary.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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: null,
|
||||
body: Container(
|
||||
color: AppColors.background,
|
||||
color: isDark ? const Color(0xFF1A1A1A) : Colors.white,
|
||||
child: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
padding: EdgeInsets.only(
|
||||
left: 16.0,
|
||||
right: 16.0,
|
||||
top: 8.0,
|
||||
bottom: 16.0,
|
||||
bottom: widget.showAppBar ? 16.0 : 100.0, // 关怀模式下增加底部padding
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
@@ -740,8 +511,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColors.primary,
|
||||
AppColors.primary.withAlpha(200),
|
||||
primaryColor,
|
||||
primaryColor.withAlpha(200),
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
@@ -749,9 +520,7 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColors.primary.withAlpha(
|
||||
80,
|
||||
),
|
||||
color: primaryColor.withAlpha(80),
|
||||
blurRadius: 12,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
@@ -844,7 +613,7 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
children: [
|
||||
CircularProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
AppColors.primary,
|
||||
primaryColor,
|
||||
),
|
||||
strokeWidth: 3,
|
||||
),
|
||||
@@ -853,7 +622,9 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
'加载题目中...',
|
||||
style: TextStyle(
|
||||
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),
|
||||
decoration: BoxDecoration(
|
||||
color: isDark
|
||||
? AppColors.iosRed.withAlpha(30)
|
||||
: AppColors.iosRed.withAlpha(10),
|
||||
? Colors.red[900]!.withAlpha(30)
|
||||
: Colors.red[50],
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.error_outline,
|
||||
size: 64,
|
||||
color: AppColors.iosRed,
|
||||
color: Colors.red[400],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
@@ -887,7 +658,9 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: AppColors.iosRed,
|
||||
color: isDark
|
||||
? Colors.red[300]
|
||||
: Colors.red,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
@@ -895,17 +668,14 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColors.primary,
|
||||
AppColors.primary.withAlpha(
|
||||
200,
|
||||
),
|
||||
primaryColor,
|
||||
primaryColor.withAlpha(200),
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColors.primary
|
||||
.withAlpha(80),
|
||||
color: primaryColor.withAlpha(80),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
@@ -966,9 +736,15 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
BorderRadius.circular(
|
||||
16,
|
||||
),
|
||||
color: AppColors.surface,
|
||||
color: isDark
|
||||
? const Color(
|
||||
0xFF2A2A2A,
|
||||
)
|
||||
: Colors.white,
|
||||
),
|
||||
),
|
||||
color: AppConstants
|
||||
.primaryColor,
|
||||
width: 4,
|
||||
),
|
||||
),
|
||||
@@ -979,10 +755,19 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColors.surface,
|
||||
AppColors.primary
|
||||
isDark
|
||||
? const Color(
|
||||
0xFF2A2A2A,
|
||||
)
|
||||
: Colors.white,
|
||||
AppConstants
|
||||
.primaryColor
|
||||
.withAlpha(5),
|
||||
AppColors.surface,
|
||||
isDark
|
||||
? const Color(
|
||||
0xFF2A2A2A,
|
||||
)
|
||||
: Colors.white,
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end:
|
||||
@@ -1007,8 +792,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
width: 4,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors
|
||||
.primary,
|
||||
color: AppConstants
|
||||
.primaryColor,
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
2,
|
||||
@@ -1025,8 +810,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
fontWeight:
|
||||
FontWeight
|
||||
.w600,
|
||||
color: AppColors
|
||||
.primary,
|
||||
color: AppConstants
|
||||
.primaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -1042,7 +827,9 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
fontWeight:
|
||||
FontWeight.bold,
|
||||
height: 1.5,
|
||||
color: AppColors.primaryText,
|
||||
color: isDark
|
||||
? Colors.white
|
||||
: Colors.black87,
|
||||
),
|
||||
),
|
||||
// 标签信息
|
||||
@@ -1064,8 +851,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
12,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors
|
||||
.primary
|
||||
color: AppConstants
|
||||
.primaryColor
|
||||
.withAlpha(
|
||||
10,
|
||||
),
|
||||
@@ -1079,24 +866,28 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
_buildTag(
|
||||
'作者',
|
||||
_currentQuestion!['author'] ??
|
||||
PoetryTag(
|
||||
label: '作者',
|
||||
value:
|
||||
_currentQuestion!['author'] ??
|
||||
'',
|
||||
),
|
||||
_buildTag(
|
||||
'年代',
|
||||
_currentQuestion!['dynasty'] ??
|
||||
PoetryTag(
|
||||
label: '年代',
|
||||
value:
|
||||
_currentQuestion!['dynasty'] ??
|
||||
'',
|
||||
),
|
||||
_buildTag(
|
||||
'类型',
|
||||
_currentQuestion!['type'] ??
|
||||
PoetryTag(
|
||||
label: '类型',
|
||||
value:
|
||||
_currentQuestion!['type'] ??
|
||||
'',
|
||||
),
|
||||
_buildTag(
|
||||
'阶段',
|
||||
_currentQuestion!['grade'] ??
|
||||
PoetryTag(
|
||||
label: '阶段',
|
||||
value:
|
||||
_currentQuestion!['grade'] ??
|
||||
'',
|
||||
),
|
||||
],
|
||||
@@ -1113,7 +904,27 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
),
|
||||
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,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.surface,
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
@@ -1144,8 +955,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColors.surface,
|
||||
AppColors.background,
|
||||
Colors.white,
|
||||
Colors.grey[50]!,
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
@@ -1153,8 +964,9 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
borderRadius:
|
||||
BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: AppColors.primary
|
||||
.withAlpha(50),
|
||||
color: primaryColor.withAlpha(
|
||||
50,
|
||||
),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
@@ -1177,18 +989,18 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
children: [
|
||||
Icon(
|
||||
Icons.arrow_back,
|
||||
color: AppColors
|
||||
.primary,
|
||||
color: AppConstants
|
||||
.primaryColor,
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
const Text(
|
||||
'上一题',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight:
|
||||
FontWeight.w500,
|
||||
color: AppColors.primaryText,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -1203,20 +1015,23 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColors.primary,
|
||||
AppColors.primary.withAlpha(
|
||||
200,
|
||||
),
|
||||
Colors.white,
|
||||
Colors.grey[50]!,
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: primaryColor,
|
||||
width: 2,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColors.primary
|
||||
.withAlpha(80),
|
||||
color: primaryColor.withAlpha(
|
||||
30,
|
||||
),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
@@ -1225,7 +1040,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
child: ElevatedButton(
|
||||
onPressed: _getHint,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.transparent,
|
||||
backgroundColor:
|
||||
Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
@@ -1240,9 +1056,10 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icon(
|
||||
Icons.lightbulb_outline,
|
||||
color: Colors.white,
|
||||
color: AppConstants
|
||||
.primaryColor,
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -1251,8 +1068,8 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight:
|
||||
FontWeight.w500,
|
||||
color: Colors.white,
|
||||
FontWeight.w600,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -1267,24 +1084,30 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColors.surface,
|
||||
AppColors.background,
|
||||
primaryColor,
|
||||
primaryColor.withAlpha(200),
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: AppColors.primary
|
||||
.withAlpha(50),
|
||||
width: 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppConstants
|
||||
.primaryColor
|
||||
.withAlpha(80),
|
||||
blurRadius: 12,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: OutlinedButton(
|
||||
child: ElevatedButton(
|
||||
onPressed: _nextQuestion,
|
||||
style: OutlinedButton.styleFrom(
|
||||
side: BorderSide.none,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor:
|
||||
Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
vertical: 14,
|
||||
@@ -1298,20 +1121,19 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
const Text(
|
||||
'下一题',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight:
|
||||
FontWeight.w500,
|
||||
color: AppColors.primaryText,
|
||||
FontWeight.w600,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Icon(
|
||||
Icons.arrow_forward,
|
||||
color: AppColors
|
||||
.primary,
|
||||
color: Colors.white,
|
||||
size: 20,
|
||||
),
|
||||
],
|
||||
@@ -1321,38 +1143,6 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
),
|
||||
],
|
||||
),
|
||||
if (_showFeedback && _feedbackMessage != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: _isAnswerCorrect
|
||||
? AppColors.iosGreen
|
||||
.withAlpha(20)
|
||||
: AppColors.iosRed
|
||||
.withAlpha(20),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: _isAnswerCorrect
|
||||
? AppColors.iosGreen
|
||||
: AppColors.iosRed,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
_feedbackMessage!,
|
||||
style: TextStyle(
|
||||
color: _isAnswerCorrect
|
||||
? AppColors.iosGreen
|
||||
: AppColors.iosRed,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -1361,6 +1151,65 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
),
|
||||
],
|
||||
),
|
||||
// 反馈信息气泡(不占用布局)
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user