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

708 lines
22 KiB
Dart
Raw 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/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;
});
}
}
}
}