Files
wushu/lib/views/profile/guide/beginner_page.dart
2026-04-01 18:40:21 +08:00

861 lines
26 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 '../../../constants/app_constants.dart';
import 'sp-guide.dart';
class BeginnerPage extends StatefulWidget {
const BeginnerPage({super.key});
@override
State<BeginnerPage> createState() => _BeginnerPageState();
}
class _BeginnerPageState extends State<BeginnerPage>
with TickerProviderStateMixin {
final ScrollController _scrollController = ScrollController();
late AnimationController _fadeController;
late Animation<double> _fadeAnimation;
double _progress = 0.0;
final List<Map<String, dynamic>> _tutorialSections = [
{
'title': '首页功能',
'icon': Icons.home,
'emoji': '🏠',
'color': AppConstants.primaryColor,
'features': [
'精美卡片展示',
'智能推荐:根据时间和情景推荐合适的诗词',
'诗词详情:显示标题、作者、朝代、正文、注释和赏析',
'精选诗句:突出显示经典名句',
'下拉刷新:刷新诗词内容',
],
},
{
'title': '发现页面',
'icon': Icons.explore,
'emoji': '🔍',
'color': const Color(0xFF00BCD4),
'features': [
'分类浏览:按朝代、作者、主题等分类浏览',
'热门诗词:查看最受欢迎的诗词',
'活跃排行:查看活跃度最高的诗词',
'搜索功能:通过关键词搜索诗词',
'Tab切换分类、热门、搜索标签页',
],
},
{
'title': '足迹页面',
'icon': Icons.history,
'emoji': '📚',
'color': const Color(0xFFFF9800),
'features': [
'收藏管理:查看和管理所有收藏的诗词',
'笔记功能:创建和管理诗词笔记',
'分类展示:全部、点赞、笔记等分类',
'搜索功能:搜索收藏内容',
'视图切换:网格和列表视图',
],
},
{
'title': '个人中心',
'icon': Icons.person,
'emoji': '👤',
'color': const Color(0xFF4CAF50),
'features': [
'个人信息:编辑昵称、头像等',
'统计数据:今日浏览、累计浏览、今日点赞等',
'数据隐藏:可隐藏统计和答题数据',
'用户计划:加入用户体验计划',
'功能入口:设置、了解我们、权限管理等',
],
},
{
'title': '诗词阅读',
'icon': Icons.menu_book,
'emoji': '📖',
'color': const Color(0xFF9C27B0),
'features': [
'加载诗词:点击卡片任意区域加载下一条',
'查看详情:显示完整诗词信息',
'点赞诗词:点击心形图标',
'切换诗词:上一条/下一条按钮',
'长按复制:长按复制诗词内容',
],
},
{
'title': '收藏功能',
'icon': Icons.favorite,
'emoji': '❤️',
'color': const Color(0xFFE91E63),
'features': [
'一键收藏:点击收藏图标',
'收藏列表:在足迹页查看',
'取消收藏:再次点击收藏图标',
'收藏统计:显示收藏数量',
'创建笔记:从诗词创建笔记',
],
},
{
'title': '搜索功能',
'icon': Icons.search,
'emoji': '🔎',
'color': const Color(0xFF009688),
'features': [
'关键词搜索:输入关键词搜索',
'分类筛选:按分类筛选结果',
'热门搜索:查看热门搜索词',
'搜索历史:保留搜索记录',
'实时搜索:输入即时搜索',
],
},
{
'title': '答题挑战',
'icon': Icons.quiz,
'emoji': '🎮',
'color': const Color(0xFFFF5722),
'features': [
'答题挑战:参与诗词答题',
'题目随机化使用Fisher-Yates算法',
'答题记录:记录历史和成绩',
'答题统计:正确率等数据',
'提示功能:遇到困难可获取提示',
],
},
{
'title': '离线模式',
'icon': Icons.wifi_off,
'emoji': '📴',
'color': const Color(0xFF607D8B),
'features': [
'离线数据下载:支持下载诗词和答题',
'下载选项20/30/60/100条可选',
'后台下载:返回上一页继续下载',
'缓存管理:清空缓存可选择内容',
'自动切换:无网络自动切换',
],
},
{
'title': '个性化设置',
'icon': Icons.palette,
'emoji': '🎨',
'color': const Color(0xFF3F51B5),
'features': [
'主题切换:浅色/深色主题',
'卡片样式:三种样式可选',
'颜色自定义:主题色和背景色',
'圆角调整:卡片圆角大小',
'字体大小:调整字体大小',
],
},
{
'title': '投稿功能',
'icon': Icons.send,
'emoji': '📝',
'color': const Color(0xFF00BCD4),
'features': [
'诗词投稿:向软件投稿诗词',
'投稿表单:填写诗词信息',
'投稿记录:查看历史投稿',
'相似度检测:防止重复投稿',
'清空记录:清空投稿历史',
],
},
{
'title': '投票功能',
'icon': Icons.how_to_vote,
'emoji': '🗳️',
'color': const Color(0xFF795548),
'features': [
'用户投票:参与功能投票',
'投票结果:查看统计',
'登录注册:用户身份',
'自动注册:简化流程',
'投票详情:查看选项',
],
},
{
'title': '桌面卡片',
'icon': Icons.wb_sunny,
'emoji': '🌤️',
'color': const Color(0xFFFFC107),
'features': [
'天气显示:显示当前天气',
'城市显示:所在城市',
'十二时辰:中国传统计时',
'时间标签:子丑寅卯辰巳午未申酉戌亥',
'智能更新:自动更新时间',
],
},
{
'title': '图片分享',
'icon': Icons.share,
'emoji': '📸',
'color': const Color(0xFF03A9F4),
'features': [
'诗词分享:生成图片分享',
'软件分享:分享给朋友',
'复制功能:复制内容',
'高清图片:生成高质量图片',
'跨平台:支持多平台分享',
],
},
{
'title': '数据管理',
'icon': Icons.storage,
'emoji': '💾',
'color': const Color(0xFF8BC34A),
'features': [
'数据统计:显示数据占用',
'清空数据:清空应用数据',
'数据备份:备份数据',
'缓存管理:管理缓存',
'离线数据:管理离线数据',
],
},
{
'title': '帮助与反馈',
'icon': Icons.help,
'emoji': '',
'color': const Color(0xFF9E9E9E),
'features': [
'使用指南:查看使用说明',
'常见问题FAQ解答',
'用户反馈:反馈问题',
'功能建议:提交建议',
'已知Bug查看Bug列表',
],
},
];
@override
void initState() {
super.initState();
_scrollController.addListener(_onScroll);
_fadeController = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
);
_fadeAnimation = CurvedAnimation(
parent: _fadeController,
curve: Curves.easeIn,
);
_fadeController.forward();
}
@override
void dispose() {
_scrollController.removeListener(_onScroll);
_scrollController.dispose();
_fadeController.dispose();
super.dispose();
}
void _onScroll() {
if (_scrollController.hasClients) {
final maxScroll = _scrollController.position.maxScrollExtent;
final currentScroll = _scrollController.position.pixels;
final progress = maxScroll > 0 ? currentScroll / maxScroll : 0.0;
if (mounted) {
setState(() {
_progress = progress;
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[50],
body: Stack(
children: [
FadeTransition(
opacity: _fadeAnimation,
child: CustomScrollView(
controller: _scrollController,
slivers: [
SliverAppBar(
title: const Text(
'软件功能',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17,
color: AppConstants.primaryColor,
),
),
backgroundColor: Colors.white,
foregroundColor: AppConstants.primaryColor,
elevation: 0,
centerTitle: true,
floating: true,
snap: true,
pinned: false,
actions: [
IconButton(
icon: const Icon(Icons.help_outline),
color: AppConstants.primaryColor,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const SpGuidePage(fromSettings: true),
),
);
},
),
],
),
SliverPadding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 100),
sliver: SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return _buildSectionCard(_tutorialSections[index], index);
}, childCount: _tutorialSections.length),
),
),
],
),
),
_buildProgressIndicator(),
],
),
);
}
Widget _buildSectionCard(Map<String, dynamic> section, int index) {
return TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
duration: Duration(milliseconds: 300 + (index * 50)),
curve: Curves.easeOut,
builder: (context, value, child) {
return Transform.translate(
offset: Offset(0, 20 * (1 - value)),
child: Opacity(opacity: value, child: child),
);
},
child: Container(
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
blurRadius: 12,
offset: const Offset(0, 2),
),
],
),
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: (section['color'] as Color).withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(14),
),
child: Center(
child: Text(
section['emoji'],
style: const TextStyle(fontSize: 24),
),
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
section['title'],
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.black87,
letterSpacing: -0.3,
),
),
const SizedBox(height: 4),
Text(
'${index + 1} 部分',
style: TextStyle(
fontSize: 13,
color: Colors.grey[500],
fontWeight: FontWeight.w400,
),
),
],
),
),
],
),
const SizedBox(height: 20),
_buildSectionContent(section['features'], section['color']),
const SizedBox(height: 16),
if (index < 4) ...[
const Divider(height: 1, color: Color(0xFFF5F5F5)),
const SizedBox(height: 16),
_buildPreviewSection(section['title']),
],
],
),
),
),
);
}
Widget _buildSectionContent(List<String> features, Color color) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: features.map((feature) {
return Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 6,
height: 6,
margin: const EdgeInsets.only(top: 8, right: 12),
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
),
Expanded(
child: Text(
feature,
style: TextStyle(
fontSize: 15,
color: Colors.grey[700],
height: 1.5,
fontWeight: FontWeight.w400,
),
),
),
],
),
);
}).toList(),
);
}
Widget _buildPreviewSection(String title) {
Widget preview;
switch (title) {
case '首页功能':
preview = _buildHomePreview();
break;
case '发现页面':
preview = _buildDiscoverPreview();
break;
case '足迹页面':
preview = _buildFootprintPreview();
break;
case '个人中心':
preview = _buildProfilePreview();
break;
default:
preview = const SizedBox.shrink();
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.visibility_outlined,
size: 16,
color: AppConstants.primaryColor,
),
const SizedBox(width: 6),
Text(
'界面预览',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w600,
color: AppConstants.primaryColor,
),
),
],
),
const SizedBox(height: 12),
preview,
],
);
}
Widget _buildHomePreview() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: AppConstants.primaryColor.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(
Icons.book,
size: 18,
color: AppConstants.primaryColor,
),
),
const SizedBox(width: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'静夜思',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.grey[800],
),
),
Text(
'唐·李白',
style: TextStyle(fontSize: 12, color: Colors.grey[500]),
),
],
),
],
),
const SizedBox(height: 12),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Text(
'床前明月光,疑是地上霜。\n举头望明月,低头思故乡。',
style: TextStyle(
fontSize: 14,
color: Colors.grey[700],
height: 1.6,
),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildPreviewAction(Icons.favorite_border, '点赞'),
_buildPreviewAction(Icons.bookmark_border, '收藏'),
_buildPreviewAction(Icons.share_outlined, '分享'),
],
),
],
),
);
}
Widget _buildDiscoverPreview() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: Row(
children: [
Icon(Icons.search, size: 18, color: Colors.grey[400]),
const SizedBox(width: 8),
Text(
'搜索诗词...',
style: TextStyle(fontSize: 14, color: Colors.grey[400]),
),
],
),
),
const SizedBox(height: 12),
Row(
children: [
_buildPreviewTag('唐诗'),
const SizedBox(width: 8),
_buildPreviewTag('宋词'),
const SizedBox(width: 8),
_buildPreviewTag('元曲'),
],
),
const SizedBox(height: 12),
_buildPreviewListItem('将进酒', '李白'),
const SizedBox(height: 8),
_buildPreviewListItem('水调歌头', '苏轼'),
],
),
);
}
Widget _buildFootprintPreview() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildPreviewStat('128', '收藏'),
_buildPreviewStat('45', '笔记'),
_buildPreviewStat('89', '点赞'),
],
),
const SizedBox(height: 12),
_buildPreviewListItem('静夜思', '已收藏'),
const SizedBox(height: 8),
_buildPreviewListItem('春晓', '有笔记'),
],
),
);
}
Widget _buildProfilePreview() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Row(
children: [
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: AppConstants.primaryColor.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(24),
),
child: const Center(
child: Text('👤', style: TextStyle(fontSize: 24)),
),
),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'诗词爱好者',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.grey[800],
),
),
Text(
'Lv.12 · 诗意生活',
style: TextStyle(fontSize: 12, color: Colors.grey[500]),
),
],
),
],
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildPreviewStat('156', '浏览'),
_buildPreviewStat('89', '点赞'),
_buildPreviewStat('45', '答题'),
],
),
],
),
);
}
Widget _buildPreviewAction(IconData icon, String label) {
return Column(
children: [
Icon(icon, size: 20, color: Colors.grey[600]),
const SizedBox(height: 4),
Text(label, style: TextStyle(fontSize: 11, color: Colors.grey[600])),
],
);
}
Widget _buildPreviewTag(String text) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: AppConstants.primaryColor.withValues(alpha: 0.3),
),
),
child: Text(
text,
style: TextStyle(
fontSize: 12,
color: AppConstants.primaryColor,
fontWeight: FontWeight.w500,
),
),
);
}
Widget _buildPreviewListItem(String title, String subtitle) {
return Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: TextStyle(
fontSize: 14,
color: Colors.grey[700],
fontWeight: FontWeight.w500,
),
),
Text(
subtitle,
style: TextStyle(fontSize: 12, color: Colors.grey[500]),
),
],
),
);
}
Widget _buildPreviewStat(String value, String label) {
return Column(
children: [
Text(
value,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppConstants.primaryColor,
),
),
const SizedBox(height: 2),
Text(label, style: TextStyle(fontSize: 11, color: Colors.grey[500])),
],
);
}
Widget _buildProgressIndicator() {
return Positioned(
left: 0,
top: 0,
bottom: 0,
child: Container(
width: 60,
padding: const EdgeInsets.symmetric(vertical: 20),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Colors.white.withValues(alpha: 0.95),
Colors.white.withValues(alpha: 0.85),
Colors.white.withValues(alpha: 0.0),
],
stops: const [0.0, 0.7, 1.0],
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 8,
height: 200,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(4),
),
child: Stack(
children: [
AnimatedPositioned(
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
top: _progress * 160,
child: Container(
width: 8,
height: 40,
decoration: BoxDecoration(
color: AppConstants.primaryColor,
borderRadius: BorderRadius.circular(4),
boxShadow: [
BoxShadow(
color: AppConstants.primaryColor.withValues(
alpha: 0.3,
),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
),
),
],
),
),
const SizedBox(height: 12),
AnimatedContainer(
duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: AppConstants.primaryColor,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: AppConstants.primaryColor.withValues(alpha: 0.2),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: Text(
'${(_progress * 100).toInt()}%',
style: const TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.w600,
letterSpacing: -0.2,
),
),
),
],
),
),
);
}
}