深色模式、首页设置页面和功能优化

This commit is contained in:
Developer
2026-04-02 07:06:55 +08:00
parent f0a62ed68b
commit 954d173329
88 changed files with 12157 additions and 7578 deletions

View File

@@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../constants/app_constants.dart';
import '../../../services/get/theme_controller.dart';
import 'sp-guide.dart';
class BeginnerPage extends StatefulWidget {
@@ -12,6 +14,7 @@ class BeginnerPage extends StatefulWidget {
class _BeginnerPageState extends State<BeginnerPage>
with TickerProviderStateMixin {
final ScrollController _scrollController = ScrollController();
final ThemeController _themeController = Get.find<ThemeController>();
late AnimationController _fadeController;
late Animation<double> _fadeAnimation;
double _progress = 0.0;
@@ -266,65 +269,78 @@ class _BeginnerPageState extends State<BeginnerPage>
@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,
return Obx(() {
final isDark = _themeController.isDarkMode;
return Scaffold(
backgroundColor: isDark ? const Color(0xFF1A1A1A) : Colors.grey[50],
body: Stack(
children: [
FadeTransition(
opacity: _fadeAnimation,
child: CustomScrollView(
controller: _scrollController,
slivers: [
SliverAppBar(
title: Text(
'软件功能',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17,
color: AppConstants.primaryColor,
),
),
backgroundColor: isDark
? const Color(0xFF2A2A2A)
: 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),
),
);
},
),
],
),
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,
isDark,
);
},
}, childCount: _tutorialSections.length),
),
],
),
SliverPadding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 100),
sliver: SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return _buildSectionCard(_tutorialSections[index], index);
}, childCount: _tutorialSections.length),
),
),
],
],
),
),
),
_buildProgressIndicator(),
],
),
);
_buildProgressIndicator(isDark),
],
),
);
});
}
Widget _buildSectionCard(Map<String, dynamic> section, int index) {
Widget _buildSectionCard(
Map<String, dynamic> section,
int index,
bool isDark,
) {
return TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
duration: Duration(milliseconds: 300 + (index * 50)),
@@ -338,11 +354,13 @@ class _BeginnerPageState extends State<BeginnerPage>
child: Container(
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
color: isDark
? Colors.black.withValues(alpha: 0.3)
: Colors.black.withValues(alpha: 0.05),
blurRadius: 12,
offset: const Offset(0, 2),
),
@@ -376,10 +394,10 @@ class _BeginnerPageState extends State<BeginnerPage>
children: [
Text(
section['title'],
style: const TextStyle(
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.black87,
color: isDark ? Colors.white : Colors.black87,
letterSpacing: -0.3,
),
),
@@ -388,7 +406,7 @@ class _BeginnerPageState extends State<BeginnerPage>
'${index + 1} 部分',
style: TextStyle(
fontSize: 13,
color: Colors.grey[500],
color: isDark ? Colors.grey[400] : Colors.grey[500],
fontWeight: FontWeight.w400,
),
),
@@ -398,12 +416,19 @@ class _BeginnerPageState extends State<BeginnerPage>
],
),
const SizedBox(height: 20),
_buildSectionContent(section['features'], section['color']),
_buildSectionContent(
section['features'],
section['color'],
isDark,
),
const SizedBox(height: 16),
if (index < 4) ...[
const Divider(height: 1, color: Color(0xFFF5F5F5)),
Divider(
height: 1,
color: isDark ? Colors.grey[700] : const Color(0xFFF5F5F5),
),
const SizedBox(height: 16),
_buildPreviewSection(section['title']),
_buildPreviewSection(section['title'], isDark),
],
],
),
@@ -412,7 +437,7 @@ class _BeginnerPageState extends State<BeginnerPage>
);
}
Widget _buildSectionContent(List<String> features, Color color) {
Widget _buildSectionContent(List<String> features, Color color, bool isDark) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: features.map((feature) {
@@ -432,7 +457,7 @@ class _BeginnerPageState extends State<BeginnerPage>
feature,
style: TextStyle(
fontSize: 15,
color: Colors.grey[700],
color: isDark ? Colors.grey[300] : Colors.grey[700],
height: 1.5,
fontWeight: FontWeight.w400,
),
@@ -445,20 +470,20 @@ class _BeginnerPageState extends State<BeginnerPage>
);
}
Widget _buildPreviewSection(String title) {
Widget _buildPreviewSection(String title, bool isDark) {
Widget preview;
switch (title) {
case '首页功能':
preview = _buildHomePreview();
preview = _buildHomePreview(isDark);
break;
case '发现页面':
preview = _buildDiscoverPreview();
preview = _buildDiscoverPreview(isDark);
break;
case '足迹页面':
preview = _buildFootprintPreview();
preview = _buildFootprintPreview(isDark);
break;
case '个人中心':
preview = _buildProfilePreview();
preview = _buildProfilePreview(isDark);
break;
default:
preview = const SizedBox.shrink();
@@ -491,11 +516,11 @@ class _BeginnerPageState extends State<BeginnerPage>
);
}
Widget _buildHomePreview() {
Widget _buildHomePreview(bool isDark) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[100],
color: isDark ? const Color(0xFF3A3A3A) : Colors.grey[100],
borderRadius: BorderRadius.circular(12),
),
child: Column(
@@ -525,12 +550,15 @@ class _BeginnerPageState extends State<BeginnerPage>
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.grey[800],
color: isDark ? Colors.white : Colors.grey[800],
),
),
Text(
'唐·李白',
style: TextStyle(fontSize: 12, color: Colors.grey[500]),
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey[500],
),
),
],
),
@@ -540,14 +568,14 @@ class _BeginnerPageState extends State<BeginnerPage>
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Text(
'床前明月光,疑是地上霜。\n举头望明月,低头思故乡。',
style: TextStyle(
fontSize: 14,
color: Colors.grey[700],
color: isDark ? Colors.grey[300] : Colors.grey[700],
height: 1.6,
),
textAlign: TextAlign.center,
@@ -557,9 +585,9 @@ class _BeginnerPageState extends State<BeginnerPage>
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildPreviewAction(Icons.favorite_border, '点赞'),
_buildPreviewAction(Icons.bookmark_border, '收藏'),
_buildPreviewAction(Icons.share_outlined, '分享'),
_buildPreviewAction(Icons.favorite_border, '点赞', isDark),
_buildPreviewAction(Icons.bookmark_border, '收藏', isDark),
_buildPreviewAction(Icons.share_outlined, '分享', isDark),
],
),
],
@@ -567,11 +595,11 @@ class _BeginnerPageState extends State<BeginnerPage>
);
}
Widget _buildDiscoverPreview() {
Widget _buildDiscoverPreview(bool isDark) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[100],
color: isDark ? const Color(0xFF3A3A3A) : Colors.grey[100],
borderRadius: BorderRadius.circular(12),
),
child: Column(
@@ -580,16 +608,23 @@ class _BeginnerPageState extends State<BeginnerPage>
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: Row(
children: [
Icon(Icons.search, size: 18, color: Colors.grey[400]),
Icon(
Icons.search,
size: 18,
color: isDark ? Colors.grey[500] : Colors.grey[400],
),
const SizedBox(width: 8),
Text(
'搜索诗词...',
style: TextStyle(fontSize: 14, color: Colors.grey[400]),
style: TextStyle(
fontSize: 14,
color: isDark ? Colors.grey[500] : Colors.grey[400],
),
),
],
),
@@ -597,27 +632,27 @@ class _BeginnerPageState extends State<BeginnerPage>
const SizedBox(height: 12),
Row(
children: [
_buildPreviewTag('唐诗'),
_buildPreviewTag('唐诗', isDark),
const SizedBox(width: 8),
_buildPreviewTag('宋词'),
_buildPreviewTag('宋词', isDark),
const SizedBox(width: 8),
_buildPreviewTag('元曲'),
_buildPreviewTag('元曲', isDark),
],
),
const SizedBox(height: 12),
_buildPreviewListItem('将进酒', '李白'),
_buildPreviewListItem('将进酒', '李白', isDark),
const SizedBox(height: 8),
_buildPreviewListItem('水调歌头', '苏轼'),
_buildPreviewListItem('水调歌头', '苏轼', isDark),
],
),
);
}
Widget _buildFootprintPreview() {
Widget _buildFootprintPreview(bool isDark) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[100],
color: isDark ? const Color(0xFF3A3A3A) : Colors.grey[100],
borderRadius: BorderRadius.circular(12),
),
child: Column(
@@ -625,25 +660,25 @@ class _BeginnerPageState extends State<BeginnerPage>
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildPreviewStat('128', '收藏'),
_buildPreviewStat('45', '笔记'),
_buildPreviewStat('89', '点赞'),
_buildPreviewStat('128', '收藏', isDark),
_buildPreviewStat('45', '笔记', isDark),
_buildPreviewStat('89', '点赞', isDark),
],
),
const SizedBox(height: 12),
_buildPreviewListItem('静夜思', '已收藏'),
_buildPreviewListItem('静夜思', '已收藏', isDark),
const SizedBox(height: 8),
_buildPreviewListItem('春晓', '有笔记'),
_buildPreviewListItem('春晓', '有笔记', isDark),
],
),
);
}
Widget _buildProfilePreview() {
Widget _buildProfilePreview(bool isDark) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey[100],
color: isDark ? const Color(0xFF3A3A3A) : Colors.grey[100],
borderRadius: BorderRadius.circular(12),
),
child: Column(
@@ -670,12 +705,15 @@ class _BeginnerPageState extends State<BeginnerPage>
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.grey[800],
color: isDark ? Colors.white : Colors.grey[800],
),
),
Text(
'Lv.12 · 诗意生活',
style: TextStyle(fontSize: 12, color: Colors.grey[500]),
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey[500],
),
),
],
),
@@ -685,9 +723,9 @@ class _BeginnerPageState extends State<BeginnerPage>
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildPreviewStat('156', '浏览'),
_buildPreviewStat('89', '点赞'),
_buildPreviewStat('45', '答题'),
_buildPreviewStat('156', '浏览', isDark),
_buildPreviewStat('89', '点赞', isDark),
_buildPreviewStat('45', '答题', isDark),
],
),
],
@@ -695,21 +733,31 @@ class _BeginnerPageState extends State<BeginnerPage>
);
}
Widget _buildPreviewAction(IconData icon, String label) {
Widget _buildPreviewAction(IconData icon, String label, bool isDark) {
return Column(
children: [
Icon(icon, size: 20, color: Colors.grey[600]),
Icon(
icon,
size: 20,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
const SizedBox(height: 4),
Text(label, style: TextStyle(fontSize: 11, color: Colors.grey[600])),
Text(
label,
style: TextStyle(
fontSize: 11,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
],
);
}
Widget _buildPreviewTag(String text) {
Widget _buildPreviewTag(String text, bool isDark) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: AppConstants.primaryColor.withValues(alpha: 0.3),
@@ -726,11 +774,11 @@ class _BeginnerPageState extends State<BeginnerPage>
);
}
Widget _buildPreviewListItem(String title, String subtitle) {
Widget _buildPreviewListItem(String title, String subtitle, bool isDark) {
return Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Row(
@@ -740,20 +788,23 @@ class _BeginnerPageState extends State<BeginnerPage>
title,
style: TextStyle(
fontSize: 14,
color: Colors.grey[700],
color: isDark ? Colors.grey[300] : Colors.grey[700],
fontWeight: FontWeight.w500,
),
),
Text(
subtitle,
style: TextStyle(fontSize: 12, color: Colors.grey[500]),
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey[500],
),
),
],
),
);
}
Widget _buildPreviewStat(String value, String label) {
Widget _buildPreviewStat(String value, String label, bool isDark) {
return Column(
children: [
Text(
@@ -765,12 +816,18 @@ class _BeginnerPageState extends State<BeginnerPage>
),
),
const SizedBox(height: 2),
Text(label, style: TextStyle(fontSize: 11, color: Colors.grey[500])),
Text(
label,
style: TextStyle(
fontSize: 11,
color: isDark ? Colors.grey[400] : Colors.grey[500],
),
),
],
);
}
Widget _buildProgressIndicator() {
Widget _buildProgressIndicator(bool isDark) {
return Positioned(
left: 0,
top: 0,
@@ -783,9 +840,15 @@ class _BeginnerPageState extends State<BeginnerPage>
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),
(isDark ? const Color(0xFF1A1A1A) : Colors.white).withValues(
alpha: 0.95,
),
(isDark ? const Color(0xFF1A1A1A) : Colors.white).withValues(
alpha: 0.85,
),
(isDark ? const Color(0xFF1A1A1A) : Colors.white).withValues(
alpha: 0.0,
),
],
stops: const [0.0, 0.7, 1.0],
),

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../constants/app_constants.dart';
import '../../../services/get/theme_controller.dart';
/// 时间: 2026-03-27
/// 功能: 权限管理页面
@@ -15,6 +17,7 @@ class PermissionPage extends StatefulWidget {
}
class _PermissionPageState extends State<PermissionPage> {
final ThemeController _themeController = Get.find<ThemeController>();
bool _vibrationEnabled = true;
bool _networkEnabled = true;
bool _clipboardEnabled = true;
@@ -36,98 +39,114 @@ class _PermissionPageState extends State<PermissionPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF5F5F5),
appBar: AppBar(
title: Text(
'权限管理',
style: TextStyle(
color: AppConstants.primaryColor,
fontWeight: FontWeight.bold,
),
),
backgroundColor: Colors.white,
elevation: 0,
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: AppConstants.primaryColor),
onPressed: () => Navigator.pop(context),
),
actions: [
IconButton(
icon: Icon(Icons.info_outline, color: AppConstants.primaryColor),
onPressed: _showPermissionInfoDialog,
),
],
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
_buildPermissionGroup('权限列表', [
_buildPermissionItem(
'网络访问',
'访问网络获取诗词内容和数据',
Icons.wifi,
_networkEnabled,
null,
return Obx(() {
final isDark = _themeController.isDarkMode;
return Scaffold(
backgroundColor: isDark
? const Color(0xFF1A1A1A)
: const Color(0xFFF5F5F5),
appBar: AppBar(
title: Text(
'权限管理',
style: TextStyle(
color: isDark ? Colors.white : AppConstants.primaryColor,
fontWeight: FontWeight.bold,
),
_buildPermissionItem(
'震动反馈',
'操作时的震动反馈,提升交互体验',
Icons.vibration,
_vibrationEnabled,
null,
),
backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white,
elevation: 0,
centerTitle: true,
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: isDark ? Colors.white : AppConstants.primaryColor,
),
onPressed: () => Navigator.pop(context),
),
actions: [
IconButton(
icon: Icon(
Icons.info_outline,
color: isDark ? Colors.white : AppConstants.primaryColor,
),
onPressed: _showPermissionInfoDialog,
),
],
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
_buildPermissionGroup('权限列表', [
_buildPermissionItem(
'网络访问',
'访问网络获取诗词内容和数据',
Icons.wifi,
_networkEnabled,
null,
isDark,
),
_buildPermissionItem(
'震动反馈',
'操作时的震动反馈,提升交互体验',
Icons.vibration,
_vibrationEnabled,
null,
isDark,
),
_buildPermissionItem(
'剪切板',
'复制诗词内容到剪切板',
Icons.content_copy,
_clipboardEnabled,
null,
),
_buildPermissionItem(
'播放声音',
'播放内置提示',
Icons.audio_file,
_clipboardEnabled,
null,
),
_buildPermissionItem(
'分享能力',
'调用系统分享接口',
Icons.share,
_clipboardEnabled,
null,
),
]),
const SizedBox(height: 16),
_buildPermissionGroup('权限说明', [
_buildInfoItem('震动反馈', '用于点赞、收藏等操作的触觉反馈,提升用户体验。'),
_buildInfoItem('网络访问', '用于获取诗词内容、排行榜数据、用户信息等。'),
_buildInfoItem('剪切板', '用于复制诗词内容,方便用户分享和记录。'),
_buildInfoItem('播放声音', '用于主页点击提示音,提升用户体验。'),
_buildInfoItem('分享能力', '用于分享诗词内容到社交媒体平台。'),
]),
const SizedBox(height: 16),
_buildSandboxInfoCard(),
const SizedBox(height: 16),
_buildProjectSupplement(),
const SizedBox(height: 24),
_buildBottomTip(),
],
),
);
_buildPermissionItem(
'剪切板',
'复制诗词内容到剪切板',
Icons.content_copy,
_clipboardEnabled,
null,
isDark,
),
_buildPermissionItem(
'播放',
'播放内置提示音',
Icons.audio_file,
_clipboardEnabled,
null,
isDark,
),
_buildPermissionItem(
'分享能力',
'调用系统分享接口',
Icons.share,
_clipboardEnabled,
null,
isDark,
),
], isDark),
const SizedBox(height: 16),
_buildPermissionGroup('权限说明', [
_buildInfoItem('震动反馈', '用于点赞、收藏等操作的触觉反馈,提升用户体验。', isDark),
_buildInfoItem('网络访问', '用于获取诗词内容、排行榜数据、用户信息等。', isDark),
_buildInfoItem('剪切板', '用于复制诗词内容,方便用户分享和记录。', isDark),
_buildInfoItem('播放声音', '用于主页点击提示音,提升用户体验。', isDark),
_buildInfoItem('分享能力', '用于分享诗词内容到社交媒体平台。', isDark),
], isDark),
const SizedBox(height: 16),
_buildSandboxInfoCard(isDark),
const SizedBox(height: 16),
_buildProjectSupplement(isDark),
const SizedBox(height: 24),
_buildBottomTip(isDark),
],
),
);
});
}
Widget _buildPermissionGroup(String title, List<Widget> items) {
Widget _buildPermissionGroup(String title, List<Widget> items, bool isDark) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
@@ -157,7 +176,7 @@ class _PermissionPageState extends State<PermissionPage> {
],
),
),
const Divider(height: 1),
Divider(height: 1, color: isDark ? Colors.grey[700] : null),
...items,
],
),
@@ -170,6 +189,7 @@ class _PermissionPageState extends State<PermissionPage> {
IconData icon,
bool enabled,
Function(bool)? onToggle,
bool isDark,
) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
@@ -193,9 +213,10 @@ class _PermissionPageState extends State<PermissionPage> {
children: [
Text(
title,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : Colors.black87,
),
),
const SizedBox(width: 8),
@@ -205,12 +226,15 @@ class _PermissionPageState extends State<PermissionPage> {
vertical: 2,
),
decoration: BoxDecoration(
color: Colors.grey[200],
color: isDark ? Colors.grey[700] : Colors.grey[200],
borderRadius: BorderRadius.circular(4),
),
child: Text(
'已开启',
style: TextStyle(fontSize: 10, color: Colors.grey[600]),
style: TextStyle(
fontSize: 10,
color: isDark ? Colors.grey[300] : Colors.grey[600],
),
),
),
],
@@ -218,18 +242,25 @@ class _PermissionPageState extends State<PermissionPage> {
const SizedBox(height: 2),
Text(
description,
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
],
),
),
Icon(Icons.lock, color: Colors.grey[400], size: 20),
Icon(
Icons.lock,
color: isDark ? Colors.grey[500] : Colors.grey[400],
size: 20,
),
],
),
);
}
Widget _buildInfoItem(String title, String description) {
Widget _buildInfoItem(String title, String description, bool isDark) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
@@ -251,9 +282,10 @@ class _PermissionPageState extends State<PermissionPage> {
children: [
Text(
title,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : Colors.black87,
),
),
// const SizedBox(height: 4),
@@ -261,7 +293,7 @@ class _PermissionPageState extends State<PermissionPage> {
description,
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
color: isDark ? Colors.grey[400] : Colors.grey[600],
height: 1.5,
),
),
@@ -273,14 +305,14 @@ class _PermissionPageState extends State<PermissionPage> {
);
}
Widget _buildProjectSupplement() {
Widget _buildProjectSupplement(bool isDark) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
@@ -306,30 +338,34 @@ class _PermissionPageState extends State<PermissionPage> {
],
),
),
const Divider(height: 1),
Divider(height: 1, color: isDark ? Colors.grey[700] : null),
_buildSupplementItem(
'用户反馈',
'帮助我们改进产品',
Icons.feedback,
() => _showFeedbackDialog(),
isDark,
),
_buildSupplementItem(
'功能建议',
'提出您希望的功能',
Icons.lightbulb,
() => _showSuggestionDialog(),
isDark,
),
// _buildSupplementItem(
// 'Bug报告',
// '报告遇到的问题',
// Icons.bug_report,
// () => _showBugReportDialog(),
// isDark,
// ),
// _buildSupplementItem(
// '参与开发',
// '成为贡献者',
// Icons.code,
// () => _showContributionDialog(),
// isDark,
// ),
],
),
@@ -341,6 +377,7 @@ class _PermissionPageState extends State<PermissionPage> {
String description,
IconData icon,
VoidCallback onTap,
bool isDark,
) {
return InkWell(
onTap: onTap,
@@ -364,20 +401,27 @@ class _PermissionPageState extends State<PermissionPage> {
children: [
Text(
title,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : Colors.black87,
),
),
const SizedBox(height: 2),
Text(
description,
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
],
),
),
Icon(Icons.chevron_right, color: Colors.grey[400]),
Icon(
Icons.chevron_right,
color: isDark ? Colors.grey[500] : Colors.grey[400],
),
],
),
),
@@ -533,15 +577,15 @@ class _PermissionPageState extends State<PermissionPage> {
);
}
Widget _buildSandboxInfoCard() {
Widget _buildSandboxInfoCard(bool isDark) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
@@ -576,30 +620,34 @@ class _PermissionPageState extends State<PermissionPage> {
],
),
const SizedBox(height: 12),
const Divider(height: 1),
Divider(height: 1, color: isDark ? Colors.grey[700] : null),
const SizedBox(height: 12),
Text(
'本软件严格遵循移动平台沙盒机制运行,确保您的数据安全:',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.grey[800],
color: isDark ? Colors.grey[300] : Colors.grey[800],
),
),
const SizedBox(height: 12),
_buildSandboxItem('📱 沙盒隔离', '软件在独立沙盒环境中运行,无法访问系统其他应用数据'),
_buildSandboxItem('📱 沙盒隔离', '软件在独立沙盒环境中运行,无法访问系统其他应用数据', isDark),
const SizedBox(height: 8),
_buildSandboxItem('📄 无文件创建', '不会在设备上创建额外文件,所有数据通过网络获取'),
_buildSandboxItem('📄 无文件创建', '不会在设备上创建额外文件,所有数据通过网络获取', isDark),
const SizedBox(height: 8),
_buildSandboxItem('🔒 权限透明', '仅使用必要权限,此类权限均为基础权限'),
_buildSandboxItem('🔒 权限透明', '仅使用必要权限,此类权限均为基础权限', isDark),
const SizedBox(height: 8),
_buildSandboxItem('💾 本地存储', '仅使用 SharedPreferences 存储少量用户偏好设置'),
_buildSandboxItem(
'💾 本地存储',
'仅使用 SharedPreferences 存储少量用户偏好设置',
isDark,
),
],
),
);
}
Widget _buildSandboxItem(String title, String description) {
Widget _buildSandboxItem(String title, String description, bool isDark) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -622,7 +670,7 @@ class _PermissionPageState extends State<PermissionPage> {
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.grey[800],
color: isDark ? Colors.white : Colors.grey[800],
),
),
const SizedBox(height: 4),
@@ -630,7 +678,7 @@ class _PermissionPageState extends State<PermissionPage> {
description,
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
color: isDark ? Colors.grey[400] : Colors.grey[600],
height: 1.5,
),
),
@@ -641,7 +689,7 @@ class _PermissionPageState extends State<PermissionPage> {
);
}
Widget _buildBottomTip() {
Widget _buildBottomTip(bool isDark) {
return Center(
child: Padding(
padding: const EdgeInsets.only(bottom: 32),
@@ -649,7 +697,7 @@ class _PermissionPageState extends State<PermissionPage> {
'到底了',
style: TextStyle(
fontSize: 14,
color: Colors.grey[400],
color: isDark ? Colors.grey[500] : Colors.grey[400],
fontWeight: FontWeight.w500,
),
),

View File

@@ -1,8 +1,10 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../constants/app_constants.dart';
import '../../../config/app_config.dart';
import '../../../services/get/theme_controller.dart';
import '../settings/privacy.dart';
import '../settings/user-plan.dart';
import 'permission.dart';
@@ -24,6 +26,7 @@ class SpGuidePage extends StatefulWidget {
class _SpGuidePageState extends State<SpGuidePage>
with TickerProviderStateMixin {
final PageController _pageController = PageController();
final ThemeController _themeController = Get.find<ThemeController>();
TabController? _tabController;
int _currentPage = 0;
bool _firstLaunch = true;
@@ -31,7 +34,6 @@ class _SpGuidePageState extends State<SpGuidePage>
bool _agreementAccepted = false;
bool _userPlanJoined = false;
// 协议焦点状态
bool _isAgreementFocused = false;
final int _totalPages = 3;
@@ -217,58 +219,55 @@ class _SpGuidePageState extends State<SpGuidePage>
@override
Widget build(BuildContext context) {
return WillPopScope(
// 拦截返回按钮,如果不是从设置页面进入,则阻止返回
onWillPop: () async {
if (widget.fromSettings) {
return true; // 允许返回
}
// 首次启动时,阻止返回,必须完成引导流程
return false;
},
child: Scaffold(
backgroundColor: Colors.white,
appBar: _buildAppBar(),
body: Stack(
children: [
PageView(
controller: _pageController,
scrollDirection: Axis.vertical,
physics: const PageScrollPhysics(),
onPageChanged: (index) {
setState(() {
_currentPage = index;
});
},
children: [
_buildWelcomePage(),
_buildPrivacyPage(),
_buildFeaturePage(),
],
),
_buildPageIndicator(),
_buildBottomNavigation(),
],
return Obx(() {
final isDark = _themeController.isDarkMode;
return WillPopScope(
onWillPop: () async {
if (widget.fromSettings) {
return true;
}
return false;
},
child: Scaffold(
backgroundColor: isDark ? const Color(0xFF1A1A1A) : Colors.white,
appBar: _buildAppBar(isDark),
body: Stack(
children: [
PageView(
controller: _pageController,
scrollDirection: Axis.vertical,
physics: const PageScrollPhysics(),
onPageChanged: (index) {
setState(() {
_currentPage = index;
});
},
children: [
_buildWelcomePage(isDark),
_buildPrivacyPage(isDark),
_buildFeaturePage(isDark),
],
),
_buildPageIndicator(isDark),
_buildBottomNavigation(isDark),
],
),
),
),
);
);
});
}
Widget _buildPageIndicator() {
// 根据当前页面计算进度条位置
// 第1页屏幕上方靠近顶部
// 第2页屏幕中间不变
// 第3页屏幕下方靠近底部
Widget _buildPageIndicator(bool isDark) {
double alignmentY;
switch (_currentPage) {
case 0:
alignmentY = -0.7; // 上方靠近顶部
alignmentY = -0.7;
break;
case 1:
alignmentY = 0.0; // 中间
alignmentY = 0.0;
break;
case 2:
alignmentY = 0.7; // 下方靠近底部
alignmentY = 0.7;
break;
default:
alignmentY = 0.0;
@@ -283,11 +282,15 @@ class _SpGuidePageState extends State<SpGuidePage>
child: Container(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.9),
color: (isDark ? const Color(0xFF2A2A2A) : Colors.white).withValues(
alpha: 0.9,
),
borderRadius: BorderRadius.circular(24),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
color: isDark
? Colors.black.withValues(alpha: 0.3)
: Colors.black.withValues(alpha: 0.1),
blurRadius: 8,
offset: const Offset(2, 0),
),
@@ -318,7 +321,7 @@ class _SpGuidePageState extends State<SpGuidePage>
? AppConstants.primaryColor
: isCompleted
? AppConstants.primaryColor.withValues(alpha: 0.5)
: Colors.grey[300],
: (isDark ? Colors.grey[600] : Colors.grey[300]),
border: isActive
? Border.all(color: AppConstants.primaryColor, width: 3)
: null,
@@ -343,7 +346,7 @@ class _SpGuidePageState extends State<SpGuidePage>
);
}
PreferredSizeWidget _buildAppBar() {
PreferredSizeWidget _buildAppBar(bool isDark) {
return AppBar(
title: Text(
_pageTitles[_currentPage],
@@ -352,7 +355,7 @@ class _SpGuidePageState extends State<SpGuidePage>
fontWeight: FontWeight.bold,
),
),
backgroundColor: Colors.white,
backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white,
elevation: 0,
centerTitle: true,
leading: widget.fromSettings
@@ -365,7 +368,7 @@ class _SpGuidePageState extends State<SpGuidePage>
);
}
Widget _buildWelcomePage() {
Widget _buildWelcomePage(bool isDark) {
return Container(
padding: const EdgeInsets.all(32),
child: Column(
@@ -388,12 +391,12 @@ class _SpGuidePageState extends State<SpGuidePage>
),
),
const SizedBox(height: 40),
const Text(
Text(
'欢迎使用',
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
color: Colors.black87,
color: isDark ? Colors.white : Colors.black87,
),
),
const SizedBox(height: 16),
@@ -409,18 +412,18 @@ class _SpGuidePageState extends State<SpGuidePage>
Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
decoration: BoxDecoration(
color: Colors.grey[50],
color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[50],
borderRadius: BorderRadius.circular(16),
),
child: Column(
children: [
_buildWelcomeItem('🌟', '在诗词里旅行,在文化中生长'),
_buildWelcomeItem('🌟', '在诗词里旅行,在文化中生长', isDark),
const SizedBox(height: 16),
_buildWelcomeItem('📚', '海量诗词,随心阅读'),
_buildWelcomeItem('📚', '海量诗词,随心阅读', isDark),
const SizedBox(height: 16),
_buildWelcomeItem('❤️', '收藏喜爱,记录感悟'),
_buildWelcomeItem('❤️', '收藏喜爱,记录感悟', isDark),
const SizedBox(height: 16),
_buildWelcomeItem('🌙', '每日推荐,发现美好'),
_buildWelcomeItem('🌙', '每日推荐,发现美好', isDark),
],
),
),
@@ -429,12 +432,15 @@ class _SpGuidePageState extends State<SpGuidePage>
margin: const EdgeInsets.only(left: 16),
height: 1,
width: double.infinity,
color: Colors.grey[300],
color: isDark ? Colors.grey[700] : Colors.grey[300],
),
const SizedBox(height: 16),
Text(
'向上滑动继续 ↓',
style: TextStyle(fontSize: 14, color: Colors.grey[400]),
style: TextStyle(
fontSize: 14,
color: isDark ? Colors.grey[500] : Colors.grey[400],
),
),
const SizedBox(height: 16),
Row(
@@ -475,7 +481,6 @@ class _SpGuidePageState extends State<SpGuidePage>
),
),
const SizedBox(width: 8),
// _buildShowGuideCheckbox(),
],
),
],
@@ -483,7 +488,7 @@ class _SpGuidePageState extends State<SpGuidePage>
);
}
Widget _buildWelcomeItem(String emoji, String text) {
Widget _buildWelcomeItem(String emoji, String text, bool isDark) {
return Row(
children: [
Text(emoji, style: const TextStyle(fontSize: 20)),
@@ -491,44 +496,17 @@ class _SpGuidePageState extends State<SpGuidePage>
Expanded(
child: Text(
text,
style: const TextStyle(fontSize: 15, color: Colors.black87),
style: TextStyle(
fontSize: 15,
color: isDark ? Colors.white : Colors.black87,
),
),
),
],
);
}
Widget _buildShowGuideCheckbox() {
return GestureDetector(
onTap: () {
_toggleShowGuide(!_showGuideOnStartup);
_showGuideStatusPopup();
},
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Icon(
_showGuideOnStartup ? Icons.check_box : Icons.check_box_outline_blank,
color: _showGuideOnStartup
? AppConstants.primaryColor
: Colors.grey[400],
size: 24,
),
),
);
}
void _showGuideStatusPopup() {
void _showGuideStatusPopup(bool isDark) {
showDialog(
context: context,
builder: (context) => Dialog(
@@ -536,11 +514,13 @@ class _SpGuidePageState extends State<SpGuidePage>
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF1A1A1A) : Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.15),
color: isDark
? Colors.black.withValues(alpha: 0.3)
: Colors.black.withValues(alpha: 0.15),
blurRadius: 20,
offset: const Offset(0, 4),
),
@@ -557,13 +537,17 @@ class _SpGuidePageState extends State<SpGuidePage>
: Icons.info_outline,
color: _showGuideOnStartup
? AppConstants.primaryColor
: Colors.grey[600],
: (isDark ? Colors.grey[400] : Colors.grey[600]),
size: 24,
),
const SizedBox(width: 8),
const Text(
Text(
'通知设置',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: isDark ? Colors.white : Colors.black87,
),
),
],
),
@@ -573,7 +557,7 @@ class _SpGuidePageState extends State<SpGuidePage>
decoration: BoxDecoration(
color: _showGuideOnStartup
? AppConstants.primaryColor.withValues(alpha: 0.1)
: Colors.grey[50],
: (isDark ? const Color(0xFF2A2A2A) : Colors.grey[50]),
borderRadius: BorderRadius.circular(12),
),
child: Column(
@@ -584,7 +568,7 @@ class _SpGuidePageState extends State<SpGuidePage>
: Icons.notifications_off,
color: _showGuideOnStartup
? AppConstants.primaryColor
: Colors.grey[500],
: (isDark ? Colors.grey[400] : Colors.grey[500]),
size: 40,
),
const SizedBox(height: 12),
@@ -595,13 +579,16 @@ class _SpGuidePageState extends State<SpGuidePage>
fontWeight: FontWeight.w600,
color: _showGuideOnStartup
? AppConstants.primaryColor
: Colors.grey[700],
: (isDark ? Colors.white : Colors.grey[700]),
),
),
const SizedBox(height: 8),
Text(
_showGuideOnStartup ? '下次启动时将显示欢迎页' : '下次启动时将不显示欢迎页',
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
style: TextStyle(
fontSize: 14,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
textAlign: TextAlign.center,
),
],
@@ -630,18 +617,20 @@ class _SpGuidePageState extends State<SpGuidePage>
);
}
Widget _buildPrivacyPage() {
Widget _buildPrivacyPage(bool isDark) {
_initTabController();
return Stack(
children: [
Column(
children: [
Container(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
child: TabBar(
controller: _tabController!,
labelColor: AppConstants.primaryColor,
unselectedLabelColor: Colors.grey[600],
unselectedLabelColor: isDark
? Colors.grey[400]
: Colors.grey[600],
indicatorColor: AppConstants.primaryColor,
indicatorWeight: 2,
tabs: const [
@@ -653,19 +642,16 @@ class _SpGuidePageState extends State<SpGuidePage>
Expanded(
child: Stack(
children: [
// 协议内容区域
TabBarView(
controller: _tabController!,
physics: _isAgreementFocused
? const AlwaysScrollableScrollPhysics()
: const NeverScrollableScrollPhysics(),
children: [
// 隐私政策 - 使用 NotificationListener 监听滚动
NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification is ScrollEndNotification) {
final metrics = notification.metrics;
// 只有在到达顶部或底部时才取消焦点
if (metrics.pixels <= metrics.minScrollExtent ||
metrics.pixels >= metrics.maxScrollExtent) {
setState(() {
@@ -691,12 +677,10 @@ class _SpGuidePageState extends State<SpGuidePage>
),
),
),
// 用户协议 - 使用 NotificationListener 监听滚动
NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification is ScrollEndNotification) {
final metrics = notification.metrics;
// 只有在到达顶部或底部时才取消焦点
if (metrics.pixels <= metrics.minScrollExtent ||
metrics.pixels >= metrics.maxScrollExtent) {
setState(() {
@@ -724,7 +708,6 @@ class _SpGuidePageState extends State<SpGuidePage>
),
],
),
// 左右焦点竖线
if (_isAgreementFocused)
Positioned(
left: 0,
@@ -750,7 +733,6 @@ class _SpGuidePageState extends State<SpGuidePage>
),
],
),
// 底部按钮区域 - 点击时取消协议焦点
Positioned(
left: 0,
right: 0,
@@ -766,10 +748,12 @@ class _SpGuidePageState extends State<SpGuidePage>
child: Container(
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.05),
color: isDark
? Colors.black.withValues(alpha: 0.3)
: Colors.black.withValues(alpha: 0.05),
blurRadius: 10,
offset: const Offset(0, -2),
),
@@ -781,7 +765,7 @@ class _SpGuidePageState extends State<SpGuidePage>
Container(
height: 1,
width: double.infinity,
color: Colors.grey[300],
color: isDark ? Colors.grey[700] : Colors.grey[300],
),
const SizedBox(height: 16),
Row(
@@ -812,7 +796,9 @@ class _SpGuidePageState extends State<SpGuidePage>
fontSize: 14,
color: _agreementAccepted
? AppConstants.primaryColor
: Colors.grey[700],
: (isDark
? Colors.grey[300]
: Colors.grey[700]),
),
),
),
@@ -829,9 +815,11 @@ class _SpGuidePageState extends State<SpGuidePage>
style: ElevatedButton.styleFrom(
backgroundColor: _agreementAccepted
? AppConstants.primaryColor
: Colors.grey[600],
: (isDark ? Colors.grey[700] : Colors.grey[600]),
foregroundColor: Colors.white,
disabledBackgroundColor: Colors.grey[300],
disabledBackgroundColor: isDark
? Colors.grey[800]
: Colors.grey[300],
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
@@ -855,41 +843,19 @@ class _SpGuidePageState extends State<SpGuidePage>
);
}
Widget _buildFeaturePage() {
Widget _buildFeaturePage(bool isDark) {
return Padding(
padding: const EdgeInsets.fromLTRB(24, 16, 24, 100),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Center(
// child: Container(
// width: 80,
// height: 80,
// decoration: BoxDecoration(
// color: Colors.purple.withValues(alpha: 0.1),
// borderRadius: BorderRadius.circular(20),
// ),
// child: const Center(
// child: Text('✨', style: TextStyle(fontSize: 40)),
// ),
// ),
// ),
// const SizedBox(height: 24),
// const Center(
// child: Text(
// '功能介绍',
// style: TextStyle(
// fontSize: 26,
// fontWeight: FontWeight.bold,
// color: Colors.black87,
// ),
// ),
// ),
// const SizedBox(height: 8),
Center(
child: Text(
'探索丰富的诗词世界',
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
style: TextStyle(
fontSize: 14,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
),
const SizedBox(height: 16),
@@ -903,6 +869,7 @@ class _SpGuidePageState extends State<SpGuidePage>
'每日推荐精选诗词',
Icons.home,
Colors.blue,
isDark,
),
),
const SizedBox(width: 8),
@@ -912,6 +879,7 @@ class _SpGuidePageState extends State<SpGuidePage>
'浏览排行榜、分类',
Icons.explore,
Colors.green,
isDark,
),
),
],
@@ -925,6 +893,7 @@ class _SpGuidePageState extends State<SpGuidePage>
'点赞收藏、记笔记',
Icons.favorite,
Colors.red,
isDark,
),
),
const SizedBox(width: 8),
@@ -934,6 +903,7 @@ class _SpGuidePageState extends State<SpGuidePage>
'管理数据、设置',
Icons.person,
Colors.purple,
isDark,
),
),
],
@@ -945,7 +915,7 @@ class _SpGuidePageState extends State<SpGuidePage>
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
decoration: BoxDecoration(
color: Colors.grey[50],
color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[50],
borderRadius: BorderRadius.circular(12),
),
child: Row(
@@ -993,7 +963,7 @@ class _SpGuidePageState extends State<SpGuidePage>
Switch(
value: _userPlanJoined,
onChanged: _toggleUserPlan,
activeColor: AppConstants.primaryColor,
activeThumbColor: AppConstants.primaryColor,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
],
@@ -1099,16 +1069,23 @@ class _SpGuidePageState extends State<SpGuidePage>
String desc,
IconData icon,
Color color,
bool isDark,
) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.withValues(alpha: 0.2)),
border: Border.all(
color: isDark
? Colors.grey[700]!
: Colors.grey.withValues(alpha: 0.2),
),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.03),
color: isDark
? Colors.black.withValues(alpha: 0.2)
: Colors.black.withValues(alpha: 0.03),
blurRadius: 8,
offset: const Offset(0, 2),
),
@@ -1130,14 +1107,18 @@ class _SpGuidePageState extends State<SpGuidePage>
const SizedBox(height: 8),
Text(
title,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: isDark ? Colors.white : Colors.black87,
),
),
const SizedBox(height: 2),
Text(
desc,
style: TextStyle(
fontSize: 11,
color: Colors.grey[600],
color: isDark ? Colors.grey[400] : Colors.grey[600],
height: 1.3,
),
),
@@ -1146,7 +1127,7 @@ class _SpGuidePageState extends State<SpGuidePage>
);
}
Widget _buildBottomNavigation() {
Widget _buildBottomNavigation(bool isDark) {
return Positioned(
bottom: 0,
left: 0,
@@ -1161,6 +1142,7 @@ class _SpGuidePageState extends State<SpGuidePage>
icon: Icons.arrow_back_ios,
label: '上一页',
onPressed: _previousPage,
isDark: isDark,
)
: const SizedBox(width: 100),
_currentPage < _totalPages - 1
@@ -1170,11 +1152,13 @@ class _SpGuidePageState extends State<SpGuidePage>
onPressed: _currentPage == 1 && !_agreementAccepted
? null
: _nextPage,
isDark: isDark,
)
: _buildNavButton(
icon: Icons.check,
label: '完成',
onPressed: _agreementAccepted ? _finishGuide : null,
isDark: isDark,
),
],
),
@@ -1186,10 +1170,13 @@ class _SpGuidePageState extends State<SpGuidePage>
required IconData icon,
required String label,
VoidCallback? onPressed,
required bool isDark,
}) {
return Container(
decoration: BoxDecoration(
color: onPressed != null ? AppConstants.primaryColor : Colors.grey[300],
color: onPressed != null
? AppConstants.primaryColor
: (isDark ? Colors.grey[700] : Colors.grey[300]),
borderRadius: BorderRadius.circular(12),
boxShadow: onPressed != null
? [
@@ -1213,14 +1200,18 @@ class _SpGuidePageState extends State<SpGuidePage>
children: [
Icon(
icon,
color: onPressed != null ? Colors.white : Colors.grey[500],
color: onPressed != null
? Colors.white
: (isDark ? Colors.grey[400] : Colors.grey[500]),
size: 20,
),
const SizedBox(width: 8),
Text(
label,
style: TextStyle(
color: onPressed != null ? Colors.white : Colors.grey[500],
color: onPressed != null
? Colors.white
: (isDark ? Colors.grey[400] : Colors.grey[500]),
fontSize: 14,
fontWeight: FontWeight.w500,
),