Files
ai_english/client/lib/features/writing/screens/writing_detail_screen.dart
2025-11-17 13:39:05 +08:00

439 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/writing_task.dart';
import 'writing_exercise_screen.dart';
import '../providers/writing_provider.dart';
/// 写作练习详情页面
class WritingDetailScreen extends ConsumerWidget {
final WritingTask task;
const WritingDetailScreen({
super.key,
required this.task,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
backgroundColor: const Color(0xFFF5F5F5),
appBar: AppBar(
title: const Text('写作详情'),
backgroundColor: Colors.white,
foregroundColor: Colors.black,
elevation: 0,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildTaskHeader(),
const SizedBox(height: 20),
_buildTaskInfo(),
const SizedBox(height: 20),
_buildPrompt(),
const SizedBox(height: 20),
_buildRequirements(),
if (task.keywords.isNotEmpty) ...[
const SizedBox(height: 20),
_buildKeywords(),
],
const SizedBox(height: 30),
_buildStartButton(context, ref),
],
),
),
);
}
Widget _buildTaskHeader() {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
task.title,
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: _getDifficultyColor(task.difficulty),
borderRadius: BorderRadius.circular(16),
),
child: Text(
task.difficulty.displayName,
style: const TextStyle(
fontSize: 14,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
],
),
const SizedBox(height: 12),
Text(
task.description,
style: const TextStyle(
fontSize: 16,
color: Colors.grey,
height: 1.5,
),
),
],
),
);
}
Widget _buildTaskInfo() {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'任务信息',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: _buildInfoItem(
Icons.category,
'类型',
task.type.displayName,
const Color(0xFF2196F3),
),
),
Expanded(
child: _buildInfoItem(
Icons.timer,
'时间限制',
'${task.timeLimit}分钟',
const Color(0xFF4CAF50),
),
),
],
),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: _buildInfoItem(
Icons.text_fields,
'字数要求',
'${task.wordLimit}',
const Color(0xFFFF9800),
),
),
Expanded(
child: _buildInfoItem(
Icons.star,
'难度等级',
'${task.difficulty.level}',
_getDifficultyColor(task.difficulty),
),
),
],
),
],
),
);
}
Widget _buildInfoItem(IconData icon, String label, String value, Color color) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Icon(
icon,
color: color,
size: 24,
),
const SizedBox(height: 8),
Text(
label,
style: const TextStyle(
fontSize: 12,
color: Colors.grey,
),
),
const SizedBox(height: 4),
Text(
value,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: color,
),
),
],
),
);
}
Widget _buildPrompt() {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'写作提示',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 12),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFF2196F3).withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: const Color(0xFF2196F3).withOpacity(0.3),
),
),
child: Text(
task.prompt ?? '暂无写作提示',
style: const TextStyle(
fontSize: 16,
height: 1.6,
),
),
),
],
),
);
}
Widget _buildRequirements() {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'写作要求',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 12),
...task.requirements.map((requirement) => Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Icon(
Icons.check_circle,
color: Color(0xFF4CAF50),
size: 20,
),
const SizedBox(width: 8),
Expanded(
child: Text(
requirement,
style: const TextStyle(
fontSize: 14,
height: 1.5,
),
),
),
],
),
)).toList(),
],
),
);
}
Widget _buildKeywords() {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'关键词提示',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 12),
Wrap(
spacing: 8,
runSpacing: 8,
children: task.keywords.map((keyword) => Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: const Color(0xFFFF9800).withOpacity(0.1),
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: const Color(0xFFFF9800).withOpacity(0.3),
),
),
child: Text(
keyword,
style: const TextStyle(
fontSize: 14,
color: Color(0xFFFF9800),
fontWeight: FontWeight.w500,
),
),
)).toList(),
),
],
),
);
}
Widget _buildStartButton(BuildContext context, WidgetRef ref) {
return SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton(
onPressed: () async {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => const Center(child: CircularProgressIndicator()),
);
try {
final service = ref.read(writingServiceProvider);
final freshTask = await service.getWritingTask(task.id);
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => WritingExerciseScreen(task: freshTask),
),
);
} catch (e) {
Navigator.pop(context);
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('加载失败'),
content: const Text('无法获取最新任务,稍后重试'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('确定'),
),
],
),
);
}
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF2196F3),
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 0,
),
child: const Text(
'开始写作',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
);
}
Color _getDifficultyColor(WritingDifficulty difficulty) {
switch (difficulty) {
case WritingDifficulty.beginner:
return const Color(0xFF4CAF50);
case WritingDifficulty.elementary:
return const Color(0xFF8BC34A);
case WritingDifficulty.intermediate:
return const Color(0xFFFF9800);
case WritingDifficulty.upperIntermediate:
return const Color(0xFFFF5722);
case WritingDifficulty.advanced:
return const Color(0xFFF44336);
}
}
}