Files
ai_english/client/lib/features/profile/screens/help_feedback_screen.dart

708 lines
22 KiB
Dart
Raw Normal View History

2025-11-17 14:09:17 +08:00
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../../core/theme/app_colors.dart';
import '../../../shared/widgets/custom_app_bar.dart';
/// 帮助与反馈页面
class HelpFeedbackScreen extends StatefulWidget {
const HelpFeedbackScreen({super.key});
@override
State<HelpFeedbackScreen> createState() => _HelpFeedbackScreenState();
}
class _HelpFeedbackScreenState extends State<HelpFeedbackScreen>
with SingleTickerProviderStateMixin {
late TabController _tabController;
final TextEditingController _feedbackController = TextEditingController();
String _selectedFeedbackType = '功能建议';
String _contactEmail = '';
bool _isSubmitting = false;
final List<String> _feedbackTypes = [
'功能建议',
'问题反馈',
'内容错误',
'性能问题',
'其他'
];
final List<Map<String, dynamic>> _faqList = [
{
'question': '如何开始学习?',
'answer': '点击首页的"开始学习"按钮,选择适合您的学习模式。我们提供单词学习、语法练习、听力训练等多种学习方式。',
'category': '学习指导'
},
{
'question': '如何设置学习目标?',
'answer': '进入个人中心 > 设置 > 学习设置,您可以设置每日单词目标和学习时长目标。系统会根据您的目标提供个性化的学习计划。',
'category': '学习指导'
},
{
'question': '如何查看学习进度?',
'answer': '在个人中心可以查看详细的学习统计,包括学习天数、掌握单词数、学习时长等数据。',
'category': '学习指导'
},
{
'question': '忘记密码怎么办?',
'answer': '在登录页面点击"忘记密码",输入您的邮箱地址,我们会发送重置密码的链接到您的邮箱。',
'category': '账户问题'
},
{
'question': '如何修改个人信息?',
'answer': '进入个人中心 > 个人信息,您可以修改头像、用户名、邮箱等个人信息。',
'category': '账户问题'
},
{
'question': '如何开启/关闭通知?',
'answer': '进入个人中心 > 设置 > 通知设置,您可以自定义各种通知的开启状态和提醒时间。',
'category': '设置问题'
},
{
'question': '音频播放不了怎么办?',
'answer': '请检查网络连接和设备音量设置。如果问题持续存在,可以尝试重启应用或清除缓存。',
'category': '技术问题'
},
{
'question': '应用运行缓慢怎么办?',
'answer': '建议清除应用缓存,关闭其他后台应用,确保设备有足够的存储空间。如果问题持续,请联系客服。',
'category': '技术问题'
},
{
'question': '学习数据会丢失吗?',
'answer': '您的学习数据会自动同步到云端,即使更换设备也不会丢失。建议保持网络连接以确保数据及时同步。',
'category': '数据安全'
},
{
'question': '如何导出学习记录?',
'answer': '目前暂不支持导出功能,但您可以在学习统计页面查看详细的学习数据和进度图表。',
'category': '数据安全'
},
];
@override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
@override
void dispose() {
_tabController.dispose();
_feedbackController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.surface,
appBar: CustomAppBar(
title: '帮助与反馈',
bottom: TabBar(
controller: _tabController,
labelColor: AppColors.primary,
unselectedLabelColor: AppColors.onSurfaceVariant,
indicatorColor: AppColors.primary,
tabs: const [
Tab(text: '常见问题'),
Tab(text: '意见反馈'),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
_buildFAQTab(),
_buildFeedbackTab(),
],
),
);
}
/// 构建常见问题标签页
Widget _buildFAQTab() {
final categories = _faqList.map((faq) => faq['category'] as String).toSet().toList();
return SingleChildScrollView(
child: Column(
children: [
// 搜索框
Container(
margin: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: TextField(
decoration: InputDecoration(
hintText: '搜索问题...',
prefixIcon: Icon(Icons.search, color: AppColors.onSurfaceVariant),
border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 12,
),
),
onChanged: (value) {
// TODO: 实现搜索功能
},
),
),
// 快速入口
Container(
margin: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'快速入口',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
),
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: _buildQuickActionCard(
icon: Icons.school,
title: '学习指南',
subtitle: '新手入门教程',
onTap: () => _showLearningGuide(),
),
),
const SizedBox(width: 12),
Expanded(
child: _buildQuickActionCard(
icon: Icons.contact_support,
title: '在线客服',
subtitle: '实时帮助支持',
onTap: () => _contactCustomerService(),
),
),
],
),
],
),
),
const SizedBox(height: 24),
// 分类问题列表
...categories.map((category) => _buildFAQCategory(category)),
const SizedBox(height: 32),
],
),
);
}
/// 构建意见反馈标签页
Widget _buildFeedbackTab() {
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 反馈类型选择
Text(
'反馈类型',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
),
),
const SizedBox(height: 12),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: DropdownButtonFormField<String>(
value: _selectedFeedbackType,
decoration: const InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(
horizontal: 16,
vertical: 12,
),
),
items: _feedbackTypes.map((type) {
return DropdownMenuItem<String>(
value: type,
child: Text(type),
);
}).toList(),
onChanged: (value) {
setState(() {
_selectedFeedbackType = value!;
});
},
),
),
const SizedBox(height: 24),
// 反馈内容
Text(
'反馈内容',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
),
),
const SizedBox(height: 12),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: TextField(
controller: _feedbackController,
maxLines: 6,
decoration: const InputDecoration(
hintText: '请详细描述您遇到的问题或建议...',
border: InputBorder.none,
contentPadding: EdgeInsets.all(16),
),
),
),
const SizedBox(height: 24),
// 联系邮箱
Text(
'联系邮箱(可选)',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
),
),
const SizedBox(height: 12),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: TextField(
onChanged: (value) {
_contactEmail = value;
},
decoration: const InputDecoration(
hintText: '请输入您的邮箱地址',
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(
horizontal: 16,
vertical: 12,
),
),
),
),
const SizedBox(height: 32),
// 提交按钮
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _isSubmitting ? null : _submitFeedback,
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primary,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: _isSubmitting
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: const Text(
'提交反馈',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
),
const SizedBox(height: 16),
// 提示信息
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Icon(
Icons.info_outline,
color: AppColors.primary,
size: 20,
),
const SizedBox(width: 12),
Expanded(
child: Text(
'我们会认真对待每一条反馈并在24小时内回复您的问题。',
style: TextStyle(
fontSize: 14,
color: AppColors.primary,
),
),
),
],
),
),
],
),
),
);
}
/// 构建快速操作卡片
Widget _buildQuickActionCard({
required IconData icon,
required String title,
required String subtitle,
required VoidCallback onTap,
}) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
children: [
Icon(
icon,
color: AppColors.primary,
size: 32,
),
const SizedBox(height: 8),
Text(
title,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.onSurface,
),
),
const SizedBox(height: 4),
Text(
subtitle,
style: TextStyle(
fontSize: 12,
color: AppColors.onSurfaceVariant,
),
textAlign: TextAlign.center,
),
],
),
),
);
}
/// 构建FAQ分类
Widget _buildFAQCategory(String category) {
final categoryFAQs = _faqList.where((faq) => faq['category'] == category).toList();
return Container(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Text(
category,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: AppColors.onSurface,
),
),
),
...categoryFAQs.map((faq) => _buildFAQItem(faq)),
],
),
);
}
/// 构建FAQ项目
Widget _buildFAQItem(Map<String, dynamic> faq) {
return ExpansionTile(
title: Text(
faq['question'],
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppColors.onSurface,
),
),
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Text(
faq['answer'],
style: TextStyle(
fontSize: 14,
color: AppColors.onSurfaceVariant,
height: 1.5,
),
),
),
],
);
}
/// 显示学习指南
void _showLearningGuide() {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('学习指南'),
content: const SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'1. 注册并完善个人信息',
style: TextStyle(fontWeight: FontWeight.w600),
),
SizedBox(height: 8),
Text('创建账户后,请完善您的英语水平、学习目标等信息,以便为您提供个性化的学习内容。'),
SizedBox(height: 16),
Text(
'2. 设置学习目标',
style: TextStyle(fontWeight: FontWeight.w600),
),
SizedBox(height: 8),
Text('在设置中制定每日学习目标,包括单词数量和学习时长,系统会帮助您跟踪进度。'),
SizedBox(height: 16),
Text(
'3. 选择学习模式',
style: TextStyle(fontWeight: FontWeight.w600),
),
SizedBox(height: 8),
Text('根据您的需求选择单词学习、语法练习、听力训练等不同的学习模式。'),
SizedBox(height: 16),
Text(
'4. 坚持每日学习',
style: TextStyle(fontWeight: FontWeight.w600),
),
SizedBox(height: 8),
Text('保持每日学习习惯,利用碎片时间进行学习,积少成多提升英语水平。'),
],
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('知道了'),
),
],
);
},
);
}
/// 联系客服
void _contactCustomerService() {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('联系客服'),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('您可以通过以下方式联系我们:'),
const SizedBox(height: 16),
Row(
children: [
const Icon(Icons.email, size: 20),
const SizedBox(width: 8),
const Text('邮箱:'),
GestureDetector(
onTap: () {
Clipboard.setData(const ClipboardData(text: 'support@aienglish.com'));
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('邮箱地址已复制')),
);
},
child: Text(
'support@aienglish.com',
style: TextStyle(
color: AppColors.primary,
decoration: TextDecoration.underline,
),
),
),
],
),
const SizedBox(height: 8),
Row(
children: [
const Icon(Icons.phone, size: 20),
const SizedBox(width: 8),
const Text('电话:'),
GestureDetector(
onTap: () {
Clipboard.setData(const ClipboardData(text: '400-123-4567'));
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('电话号码已复制')),
);
},
child: Text(
'400-123-4567',
style: TextStyle(
color: AppColors.primary,
decoration: TextDecoration.underline,
),
),
),
],
),
const SizedBox(height: 8),
const Row(
children: [
Icon(Icons.access_time, size: 20),
SizedBox(width: 8),
Text('服务时间9:00-18:00工作日'),
],
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('确定'),
),
],
);
},
);
}
/// 提交反馈
Future<void> _submitFeedback() async {
if (_feedbackController.text.trim().isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('请输入反馈内容'),
backgroundColor: Colors.red,
),
);
return;
}
setState(() {
_isSubmitting = true;
});
try {
// TODO: 实现提交反馈的API调用
await Future.delayed(const Duration(seconds: 2)); // 模拟网络请求
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('反馈提交成功,感谢您的建议!'),
backgroundColor: Colors.green,
),
);
// 清空表单
_feedbackController.clear();
_contactEmail = '';
setState(() {
_selectedFeedbackType = '功能建议';
});
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('提交失败:$e'),
backgroundColor: Colors.red,
),
);
}
} finally {
if (mounted) {
setState(() {
_isSubmitting = false;
});
}
}
}
}