Files
ai_english/client/lib/features/vocabulary/screens/ai_recommendation_screen.dart
2025-11-17 14:09:17 +08:00

519 lines
16 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/utils/responsive_utils.dart';
import '../../../shared/widgets/custom_app_bar.dart';
import '../../../shared/widgets/loading_widget.dart';
class AIRecommendationScreen extends ConsumerStatefulWidget {
const AIRecommendationScreen({super.key});
@override
ConsumerState<AIRecommendationScreen> createState() => _AIRecommendationScreenState();
}
class _AIRecommendationScreenState extends ConsumerState<AIRecommendationScreen> {
bool _isLoading = false;
List<RecommendationItem> _recommendations = [];
@override
void initState() {
super.initState();
_loadRecommendations();
}
Future<void> _loadRecommendations() async {
setState(() {
_isLoading = true;
});
// 模拟AI推荐数据加载
await Future.delayed(const Duration(milliseconds: 1000));
setState(() {
_recommendations = _generateRecommendations();
_isLoading = false;
});
}
List<RecommendationItem> _generateRecommendations() {
return [
RecommendationItem(
type: RecommendationType.vocabulary,
title: '商务英语词汇强化',
description: '基于您的学习历史,建议加强商务场景词汇学习',
priority: 'high',
estimatedTime: '15分钟',
icon: Icons.business_center,
color: Colors.blue,
action: '开始学习',
details: [
'包含50个高频商务词汇',
'涵盖会议、谈判、报告等场景',
'配有真实商务对话示例',
],
),
RecommendationItem(
type: RecommendationType.review,
title: '复习昨日学习内容',
description: '您有8个单词需要复习趁热打铁效果更佳',
priority: 'high',
estimatedTime: '10分钟',
icon: Icons.refresh,
color: Colors.orange,
action: '立即复习',
details: [
'8个单词待复习',
'基于遗忘曲线算法推荐',
'巩固记忆效果显著',
],
),
RecommendationItem(
type: RecommendationType.test,
title: '词汇测试挑战',
description: '测试您的词汇掌握程度,发现薄弱环节',
priority: 'medium',
estimatedTime: '20分钟',
icon: Icons.quiz,
color: Colors.green,
action: '开始测试',
details: [
'30道精选测试题',
'多种题型组合',
'即时反馈和解析',
],
),
RecommendationItem(
type: RecommendationType.plan,
title: '制定本周学习计划',
description: '为您量身定制的学习计划,提高学习效率',
priority: 'medium',
estimatedTime: '5分钟',
icon: Icons.schedule,
color: Colors.purple,
action: '查看计划',
details: [
'个性化学习路径',
'合理安排学习时间',
'目标导向的学习方案',
],
),
RecommendationItem(
type: RecommendationType.weakness,
title: '语法薄弱点强化',
description: '针对您在时态方面的薄弱点进行专项训练',
priority: 'low',
estimatedTime: '25分钟',
icon: Icons.trending_up,
color: Colors.red,
action: '开始训练',
details: [
'时态专项练习',
'常见错误纠正',
'实用例句训练',
],
),
];
}
@override
Widget build(BuildContext context) {
final isMobile = ResponsiveUtils.isMobile(context);
return Scaffold(
appBar: CustomAppBar(
title: 'AI助手推荐',
),
body: _isLoading
? const LoadingWidget()
: _buildContent(context, isMobile),
);
}
Widget _buildContent(BuildContext context, bool isMobile) {
return RefreshIndicator(
onRefresh: _loadRecommendations,
child: SingleChildScrollView(
padding: EdgeInsets.all(isMobile ? 16.0 : 24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(context, isMobile),
const SizedBox(height: 24),
_buildRecommendationsList(context, isMobile),
],
),
),
);
}
Widget _buildHeader(BuildContext context, bool isMobile) {
return Container(
padding: EdgeInsets.all(isMobile ? 20.0 : 24.0),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.purple.shade400, Colors.blue.shade500],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.purple.withOpacity(0.3),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
Icons.psychology,
color: Colors.white,
size: isMobile ? 28 : 32,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'AI智能推荐',
style: TextStyle(
color: Colors.white,
fontSize: isMobile ? 20 : 24,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
'基于您的学习数据智能分析',
style: TextStyle(
color: Colors.white.withOpacity(0.9),
fontSize: isMobile ? 14 : 16,
),
),
],
),
),
],
),
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(
Icons.lightbulb,
color: Colors.yellow.shade300,
size: 20,
),
const SizedBox(width: 8),
Expanded(
child: Text(
'今日为您推荐了 ${_recommendations.length} 项学习内容',
style: TextStyle(
color: Colors.white,
fontSize: isMobile ? 13 : 15,
),
),
),
],
),
),
],
),
);
}
Widget _buildRecommendationsList(BuildContext context, bool isMobile) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'推荐内容',
style: TextStyle(
fontSize: isMobile ? 18 : 20,
fontWeight: FontWeight.bold,
color: Colors.grey[800],
),
),
const SizedBox(height: 16),
ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: _recommendations.length,
separatorBuilder: (context, index) => const SizedBox(height: 16),
itemBuilder: (context, index) {
return _buildRecommendationCard(
context,
_recommendations[index],
isMobile,
);
},
),
],
);
}
Widget _buildRecommendationCard(
BuildContext context,
RecommendationItem item,
bool isMobile,
) {
return Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
child: InkWell(
onTap: () => _handleRecommendationTap(item),
borderRadius: BorderRadius.circular(16),
child: Padding(
padding: EdgeInsets.all(isMobile ? 16.0 : 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: item.color.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
item.icon,
color: item.color,
size: isMobile ? 24 : 28,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
item.title,
style: TextStyle(
fontSize: isMobile ? 16 : 18,
fontWeight: FontWeight.bold,
color: Colors.grey[800],
),
),
),
_buildPriorityBadge(item.priority),
],
),
const SizedBox(height: 4),
Row(
children: [
Icon(
Icons.access_time,
size: 16,
color: Colors.grey[600],
),
const SizedBox(width: 4),
Text(
item.estimatedTime,
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
),
],
),
],
),
),
],
),
const SizedBox(height: 16),
Text(
item.description,
style: TextStyle(
fontSize: isMobile ? 14 : 16,
color: Colors.grey[700],
height: 1.4,
),
),
const SizedBox(height: 16),
ExpansionTile(
title: const Text(
'查看详情',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
tilePadding: EdgeInsets.zero,
childrenPadding: const EdgeInsets.only(top: 8),
children: [
...item.details.map((detail) => Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(top: 6),
width: 4,
height: 4,
decoration: BoxDecoration(
color: item.color,
shape: BoxShape.circle,
),
),
const SizedBox(width: 8),
Expanded(
child: Text(
detail,
style: TextStyle(
fontSize: 13,
color: Colors.grey[600],
),
),
),
],
),
)),
],
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () => _handleRecommendationTap(item),
style: ElevatedButton.styleFrom(
backgroundColor: item.color,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(
vertical: isMobile ? 12 : 16,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: Text(
item.action,
style: TextStyle(
fontSize: isMobile ? 14 : 16,
fontWeight: FontWeight.w600,
),
),
),
),
],
),
),
),
);
}
Widget _buildPriorityBadge(String priority) {
Color color;
String text;
switch (priority) {
case 'high':
color = Colors.red;
text = '高优先级';
break;
case 'medium':
color = Colors.orange;
text = '中优先级';
break;
case 'low':
color = Colors.green;
text = '低优先级';
break;
default:
color = Colors.grey;
text = '普通';
}
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: color, width: 1),
),
child: Text(
text,
style: TextStyle(
fontSize: 12,
color: color,
fontWeight: FontWeight.w500,
),
),
);
}
void _handleRecommendationTap(RecommendationItem item) {
switch (item.type) {
case RecommendationType.vocabulary:
Navigator.of(context).pushNamed('/vocabulary/daily-words');
break;
case RecommendationType.review:
Navigator.of(context).pushNamed('/vocabulary/review');
break;
case RecommendationType.test:
Navigator.of(context).pushNamed('/vocabulary/test');
break;
case RecommendationType.plan:
Navigator.of(context).pushNamed('/vocabulary/study-plan');
break;
case RecommendationType.weakness:
// 处理薄弱点强化
break;
}
}
}
enum RecommendationType {
vocabulary,
review,
test,
plan,
weakness,
}
class RecommendationItem {
final RecommendationType type;
final String title;
final String description;
final String priority;
final String estimatedTime;
final IconData icon;
final Color color;
final String action;
final List<String> details;
const RecommendationItem({
required this.type,
required this.title,
required this.description,
required this.priority,
required this.estimatedTime,
required this.icon,
required this.color,
required this.action,
required this.details,
});
}