1116 lines
33 KiB
Dart
1116 lines
33 KiB
Dart
/// 时间: 2025.03.21
|
||
/// 功能: 个人页面(类似朋友圈布局)
|
||
/// 介绍: 展示用户头像、个性签名、昵称、统计信息和设置列表,支持左右滑动切换页面
|
||
/// 最新变化: 重新设计布局,实现朋友圈风格的个人页面
|
||
|
||
import 'dart:convert';
|
||
import 'dart:math' show Random;
|
||
import 'dart:io' as io;
|
||
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||
|
||
import '../../constants/app_constants.dart';
|
||
import '../../controllers/history_controller.dart';
|
||
import '../../controllers/shared_preferences_storage_controller.dart';
|
||
import '../../services/wakelock_service.dart';
|
||
import 'history_page.dart';
|
||
import 'per_card.dart';
|
||
import 'settings/app_fun.dart';
|
||
import 'settings/user-plan.dart';
|
||
import 'settings/offline-data.dart';
|
||
import 'settings/privacy.dart';
|
||
import 'settings/learn-us.dart';
|
||
import 'app-info.dart';
|
||
import 'level/poetry.dart';
|
||
import 'guide/permission.dart';
|
||
import 'guide/app-data.dart';
|
||
import 'guide/tongji.dart';
|
||
import 'theme/app-diy.dart';
|
||
import 'expand/vote.dart';
|
||
import 'expand/manu-script.dart';
|
||
import 'components/bug_list_page.dart';
|
||
import 'components/pop-menu.dart';
|
||
|
||
class ProfilePage extends StatefulWidget {
|
||
const ProfilePage({super.key});
|
||
|
||
@override
|
||
State<ProfilePage> createState() => _ProfilePageState();
|
||
}
|
||
|
||
class _ProfilePageState extends State<ProfilePage>
|
||
with TickerProviderStateMixin, WidgetsBindingObserver {
|
||
late PageController _pageController;
|
||
late TabController _tabController;
|
||
int _currentPage = 1; // 默认显示第2页(设置)
|
||
bool _isCardExpanded = false; // 个人卡片展开状态
|
||
bool _isStatsHidden = false; // 统计数据隐藏状态
|
||
bool _isScreenWakeEnabled = false; // 屏幕常亮状态
|
||
double _startY = 0.0;
|
||
// 历史记录相关
|
||
List<Map<String, dynamic>> _poetryHistory = [];
|
||
|
||
// PersonalCard 的 Key,用于调用其刷新方法
|
||
final GlobalKey<PersonalCardState> _personalCardKey =
|
||
GlobalKey<PersonalCardState>();
|
||
|
||
// 答题统计数据
|
||
int _correctAnswers = 0;
|
||
int _weekQuestions = 0;
|
||
|
||
// 统计数据
|
||
int _todayViews = 0;
|
||
int _weekViews = 0;
|
||
String _firstUseTime = '未记录';
|
||
int _useDays = 1;
|
||
String _dataSize = '0 B';
|
||
int _noteCount = 0;
|
||
int _totalQuestions = 0;
|
||
int _todayQuestions = 0;
|
||
int _todayLikes = 0;
|
||
|
||
// 可爱的emoji列表
|
||
final List<String> _avatars = [
|
||
'👤',
|
||
'😊',
|
||
'🎉',
|
||
'🌟',
|
||
'🔥',
|
||
'💎',
|
||
'🌈',
|
||
'🦋',
|
||
'🌸',
|
||
'🐱',
|
||
'🐶',
|
||
'🐼',
|
||
'🐨',
|
||
'🐵',
|
||
'🦄',
|
||
'🐸',
|
||
'🐹',
|
||
'🐰',
|
||
'🦊',
|
||
'🐻',
|
||
];
|
||
|
||
// 模拟用户数据
|
||
final Map<String, dynamic> _userData = {
|
||
'avatar': '👤', // 使用emoji代替网络图片
|
||
'nickname': '诗词爱好者',
|
||
'signature': '人生如诗,岁月如歌',
|
||
'level': 'Lv.12',
|
||
'vip': true,
|
||
'posts': 156,
|
||
'followers': 1280,
|
||
'following': 89,
|
||
'likes': 2560,
|
||
'favorites': 128,
|
||
'views': 3560,
|
||
};
|
||
|
||
// 更换头像
|
||
void _changeAvatar() {
|
||
final random = Random();
|
||
setState(() {
|
||
_userData['avatar'] = _avatars[random.nextInt(_avatars.length)];
|
||
});
|
||
}
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
WidgetsBinding.instance.addObserver(this);
|
||
_pageController = PageController(initialPage: 1);
|
||
_tabController = TabController(length: 3, vsync: this);
|
||
_loadPoetryHistory();
|
||
_loadPoetryStatistics();
|
||
_loadStatistics();
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
WidgetsBinding.instance.removeObserver(this);
|
||
_pageController.dispose();
|
||
_tabController.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||
if (state == AppLifecycleState.resumed) {
|
||
// 应用恢复时刷新数据
|
||
refreshData();
|
||
}
|
||
}
|
||
|
||
// 刷新所有数据(公共方法,供外部调用)
|
||
Future<void> refreshData() async {
|
||
await _loadPoetryStatistics();
|
||
await _loadStatistics();
|
||
// 同时刷新个人卡片的数据
|
||
final personalCardState = _personalCardKey.currentState;
|
||
if (personalCardState != null && personalCardState.mounted) {
|
||
await personalCardState.refreshData();
|
||
}
|
||
}
|
||
|
||
void _onPageChanged(int page) {
|
||
setState(() {
|
||
_currentPage = page;
|
||
});
|
||
HapticFeedback.lightImpact();
|
||
}
|
||
|
||
// === 历史记录相关方法 ===
|
||
Future<void> _loadPoetryHistory() async {
|
||
try {
|
||
final history = await HistoryController.getHistory();
|
||
setState(() {
|
||
_poetryHistory = history;
|
||
});
|
||
} catch (e) {}
|
||
}
|
||
|
||
// === 答题统计相关方法 ===
|
||
Future<void> _loadPoetryStatistics() async {
|
||
try {
|
||
// 加载总体统计
|
||
_correctAnswers = await SharedPreferencesStorageController.getInt(
|
||
'correctAnswers',
|
||
defaultValue: 0,
|
||
);
|
||
|
||
// 加载答题记录列表来计算今日和本周答题数
|
||
List<String> records =
|
||
await SharedPreferencesStorageController.getStringList(
|
||
'poetryAnswerRecords',
|
||
defaultValue: [],
|
||
);
|
||
|
||
final now = DateTime.now();
|
||
final todayStart = DateTime(now.year, now.month, now.day);
|
||
final weekStart = todayStart.subtract(
|
||
Duration(days: todayStart.weekday - 1),
|
||
);
|
||
|
||
_todayQuestions = 0;
|
||
_weekQuestions = 0;
|
||
|
||
for (String recordStr in records) {
|
||
try {
|
||
final record = jsonDecode(recordStr) as Map<String, dynamic>;
|
||
final answerTime = record['answerTime'];
|
||
if (answerTime != null) {
|
||
final time = DateTime.parse(answerTime);
|
||
if (time.isAfter(todayStart)) {
|
||
_todayQuestions++;
|
||
}
|
||
if (time.isAfter(weekStart)) {
|
||
_weekQuestions++;
|
||
}
|
||
}
|
||
} catch (e) {
|
||
continue;
|
||
}
|
||
}
|
||
|
||
setState(() {});
|
||
} catch (e) {
|
||
// 加载失败
|
||
}
|
||
}
|
||
|
||
// === 加载统计数据 ===
|
||
Future<void> _loadStatistics() async {
|
||
try {
|
||
// 加载浏览统计
|
||
_todayViews = await StatisticsManager().getTodayViews();
|
||
_weekViews = await StatisticsManager().getWeekViews();
|
||
_firstUseTime = await StatisticsManager().getFirstUseTime();
|
||
_useDays = await StatisticsManager().getUseDays();
|
||
_dataSize = await StatisticsManager().getDataSize();
|
||
_todayLikes = await StatisticsManager().getTodayLikes();
|
||
_todayQuestions = await StatisticsManager().getTodayQuestions();
|
||
|
||
// 加载笔记总数
|
||
_noteCount = await HistoryController.getNotesCount();
|
||
|
||
// 加载累计答题数
|
||
_totalQuestions = await SharedPreferencesStorageController.getInt(
|
||
'totalQuestions',
|
||
defaultValue: 0,
|
||
);
|
||
|
||
setState(() {});
|
||
} catch (e) {
|
||
// 加载失败
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
backgroundColor: const Color(0xFFF5F5F5),
|
||
appBar: _buildAppBar(),
|
||
body: GestureDetector(
|
||
behavior: HitTestBehavior.opaque, // 确保手势检测能够捕获整个区域的事件
|
||
onVerticalDragStart: (details) {
|
||
_startY = details.globalPosition.dy;
|
||
},
|
||
onVerticalDragUpdate: (details) {
|
||
double currentY = details.globalPosition.dy;
|
||
double deltaY = currentY - _startY;
|
||
|
||
if (deltaY > 20) {
|
||
// 下拉超过20像素,张开卡片(降低阈值提高灵敏度)
|
||
if (!_isCardExpanded) {
|
||
setState(() {
|
||
_isCardExpanded = true;
|
||
});
|
||
}
|
||
} else if (deltaY < -60) {
|
||
// 上滑超过60像素,收起卡片(降低阈值提高灵敏度)
|
||
if (_isCardExpanded) {
|
||
setState(() {
|
||
_isCardExpanded = false;
|
||
});
|
||
}
|
||
}
|
||
},
|
||
child: Column(
|
||
children: [
|
||
_buildProfileHeader(),
|
||
Expanded(
|
||
child: PageView(
|
||
controller: _pageController,
|
||
onPageChanged: _onPageChanged,
|
||
children: [
|
||
_buildPage1(), // 个人信息卡片
|
||
_buildPage2(), // 设置列表
|
||
_buildPage3(), // 其他功能
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
PreferredSizeWidget _buildAppBar() {
|
||
// === 顶部导航栏:显示页面标题 ===
|
||
return AppBar(
|
||
title: Text(
|
||
'个人',
|
||
style: TextStyle(
|
||
color: AppConstants.primaryColor,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
backgroundColor: Colors.white,
|
||
elevation: 0,
|
||
centerTitle: true,
|
||
actions: [
|
||
// 右上角更多按钮
|
||
IconButton(
|
||
icon: Icon(Icons.more_horiz, color: AppConstants.primaryColor),
|
||
onPressed: _showMoreOptions,
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
Widget _buildProfileHeader() {
|
||
// === 个人信息头部:可收起/张开的个人卡片 ===
|
||
return PersonalCard(
|
||
key: _personalCardKey,
|
||
userData: _userData,
|
||
isExpanded: _isCardExpanded,
|
||
onExpandChanged: (value) {
|
||
setState(() {
|
||
_isCardExpanded = value;
|
||
});
|
||
},
|
||
currentPage: _currentPage,
|
||
onPageChanged: (page) {
|
||
// 添加 mounted 和 hasClients 检查,避免 dispose 后调用导致黑屏
|
||
if (mounted && _pageController.hasClients) {
|
||
_pageController.animateToPage(
|
||
page,
|
||
duration: const Duration(milliseconds: 300),
|
||
curve: Curves.easeInOut,
|
||
);
|
||
}
|
||
},
|
||
onAvatarTap: _changeAvatar,
|
||
);
|
||
}
|
||
|
||
Widget _buildPage1() {
|
||
// === 第1页:个人信息卡片展示 ===
|
||
return SingleChildScrollView(
|
||
padding: const EdgeInsets.all(16),
|
||
child: Column(
|
||
children: [
|
||
// === 互动统计卡片 ===
|
||
Container(
|
||
width: double.infinity,
|
||
padding: const EdgeInsets.all(20),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(16),
|
||
boxShadow: [
|
||
BoxShadow(
|
||
color: Colors.black.withValues(alpha: 0.08),
|
||
blurRadius: 10,
|
||
offset: const Offset(0, 2),
|
||
),
|
||
],
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: [
|
||
Icon(
|
||
Icons.analytics_outlined,
|
||
color: AppConstants.primaryColor,
|
||
size: 20,
|
||
),
|
||
const SizedBox(width: 8),
|
||
Text(
|
||
'诗词挑战',
|
||
style: TextStyle(
|
||
color: AppConstants.primaryColor,
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
if (!_isStatsHidden)
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||
children: [
|
||
_buildInteractionItem('今日答题', '$_todayQuestions'),
|
||
_buildInteractionItem('本周答题', '$_weekQuestions'),
|
||
_buildInteractionItem('答对次数', '$_correctAnswers'),
|
||
],
|
||
)
|
||
else
|
||
Center(
|
||
child: Padding(
|
||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||
child: Text(
|
||
'数据已隐藏',
|
||
style: TextStyle(color: Colors.grey[500], fontSize: 14),
|
||
),
|
||
),
|
||
),
|
||
const SizedBox(height: 16),
|
||
SizedBox(
|
||
width: double.infinity,
|
||
child: ElevatedButton(
|
||
onPressed: () {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(
|
||
builder: (_) => const PoetryLevelPage(),
|
||
),
|
||
);
|
||
},
|
||
style: ElevatedButton.styleFrom(
|
||
backgroundColor: AppConstants.primaryColor,
|
||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(8),
|
||
),
|
||
),
|
||
child: const Text('开始诗词答题', style: TextStyle(fontSize: 16)),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
const SizedBox(height: 16),
|
||
// 个人信息卡片
|
||
Container(
|
||
width: double.infinity,
|
||
padding: const EdgeInsets.all(20),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(16),
|
||
boxShadow: [
|
||
BoxShadow(
|
||
color: Colors.black.withValues(alpha: 0.08),
|
||
blurRadius: 10,
|
||
offset: const Offset(0, 2),
|
||
),
|
||
],
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
// === 卡片标题 ===
|
||
Row(
|
||
children: [
|
||
Icon(
|
||
Icons.person_outline,
|
||
color: AppConstants.primaryColor,
|
||
size: 20,
|
||
),
|
||
const SizedBox(width: 8),
|
||
Text(
|
||
'统计',
|
||
style: TextStyle(
|
||
color: AppConstants.primaryColor,
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
const Spacer(),
|
||
IconButton(
|
||
icon: Icon(
|
||
_isStatsHidden
|
||
? Icons.visibility_off_outlined
|
||
: Icons.visibility_outlined,
|
||
color: Colors.grey[600],
|
||
size: 20,
|
||
),
|
||
onPressed: () {
|
||
setState(() {
|
||
_isStatsHidden = !_isStatsHidden;
|
||
});
|
||
HapticFeedback.lightImpact();
|
||
},
|
||
tooltip: _isStatsHidden ? '显示数据' : '隐藏数据',
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
// === 信息列表 ===
|
||
if (!_isStatsHidden) ...[
|
||
_buildInfoItem('今日浏览', '$_todayViews 条'),
|
||
_buildInfoItem('今日点赞', '$_todayLikes 个'),
|
||
_buildInfoItem('今日答题', '$_todayQuestions 题'),
|
||
_buildInfoItem('本周浏览', '$_weekViews 条'),
|
||
_buildInfoItem('数据', _dataSize),
|
||
_buildInfoItem('笔记', '$_noteCount 个'),
|
||
_buildInfoItem('已用', '$_useDays 天'),
|
||
] else
|
||
Center(
|
||
child: Padding(
|
||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||
child: Text(
|
||
'数据已隐藏',
|
||
style: TextStyle(color: Colors.grey[500], fontSize: 14),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildPage2() {
|
||
// === 第2页:设置列表 ===
|
||
return ListView(
|
||
padding: const EdgeInsets.all(16),
|
||
children: [
|
||
// === 账户设置组 ===
|
||
_buildSettingsGroup('软件设置', [
|
||
_buildSettingsItem(
|
||
'功能设置',
|
||
Icons.verified_user,
|
||
() => _navigateToAppFunSettings(),
|
||
),
|
||
|
||
_buildSettingsItem(
|
||
'离线使用',
|
||
Icons.volunteer_activism,
|
||
() => _navigateToOfflineDataPage(),
|
||
),
|
||
_buildSettingsItem(
|
||
'历史记录',
|
||
Icons.history,
|
||
() => _navigateToHistoryPage(),
|
||
),
|
||
|
||
_buildSettingsItem(
|
||
'主题风格',
|
||
Icons.palette,
|
||
() => _navigateToAppDiyPage(),
|
||
),
|
||
]),
|
||
const SizedBox(height: 16),
|
||
// === 隐私设置组 ===
|
||
_buildSettingsGroup('隐私设置', [
|
||
_buildSettingsItem(
|
||
'权限管理',
|
||
Icons.block,
|
||
() => _navigateToPermissionPage(),
|
||
),
|
||
_buildSettingsItem(
|
||
'应用数据',
|
||
Icons.security,
|
||
() => _navigateToAppDataPage(),
|
||
),
|
||
//撤回同意
|
||
_buildSettingsItem(
|
||
'软件协议',
|
||
Icons.description,
|
||
() => _navigateToPrivacyPage(),
|
||
),
|
||
]),
|
||
const SizedBox(height: 16),
|
||
// === 通用设置组 ===
|
||
_buildSettingsGroup('软件信息', [
|
||
_buildSettingsItem(
|
||
'应用信息',
|
||
Icons.phone_android,
|
||
() => _navigateToAppInfoPage(),
|
||
),
|
||
_buildSettingsItem(
|
||
'了解我们',
|
||
Icons.info,
|
||
() => _navigateToLearnUsPage(),
|
||
),
|
||
_buildSettingsItem(
|
||
'已知bug',
|
||
Icons.cleaning_services,
|
||
() => showBugListBottomSheet(context),
|
||
),
|
||
_buildScreenWakeItem(),
|
||
]),
|
||
],
|
||
);
|
||
}
|
||
|
||
Widget _buildPage3() {
|
||
// === 第3页:其他功能列表 ===
|
||
return ListView(
|
||
padding: const EdgeInsets.all(16),
|
||
children: [
|
||
// === 功能服务组 ===
|
||
_buildSettingsGroup('用户体验计划(限免)', [
|
||
_buildSettingsItem(
|
||
'加入体验',
|
||
Icons.edit,
|
||
() => _navigateToUserPlanPage(),
|
||
),
|
||
_buildSettingsItem(
|
||
'参与投票',
|
||
Icons.how_to_vote,
|
||
() => _navigateToVotePage(),
|
||
),
|
||
_buildSettingsItem(
|
||
'查看全站统计',
|
||
Icons.history,
|
||
() => _showSnackBar('查看全站统计'),
|
||
),
|
||
_buildSettingsItem(
|
||
'开发计划',
|
||
Icons.analytics,
|
||
() => _showSnackBar('软件开发进度'),
|
||
),
|
||
_buildSettingsItem('去投稿', Icons.edit_note, () {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const ManuscriptPage()),
|
||
);
|
||
}),
|
||
]),
|
||
const SizedBox(height: 16),
|
||
// === 帮助支持组 ===
|
||
// _buildSettingsGroup('帮助支持', [
|
||
// _buildSettingsItem(
|
||
// '使用教程',
|
||
// Icons.help_outline,
|
||
// () => _navigateToSpGuidePage(),
|
||
// ),
|
||
// _buildSettingsItem(
|
||
// '意见反馈',
|
||
// Icons.feedback,
|
||
// () => _showSnackBar('意见反馈'),
|
||
// ),
|
||
// _buildSettingsItem(
|
||
// '联系客服',
|
||
// Icons.support_agent,
|
||
// () => _showSnackBar('联系客服'),
|
||
// ),
|
||
// _buildSettingsItem(
|
||
// '商务合作',
|
||
// Icons.info_outline,
|
||
// () => _showSnackBar('商务合作'),
|
||
// ),
|
||
// ]),
|
||
// const SizedBox(height: 16),
|
||
// === 关于信息组 ===
|
||
Container(
|
||
padding: const EdgeInsets.all(20),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(16),
|
||
boxShadow: [
|
||
BoxShadow(
|
||
color: Colors.black.withValues(alpha: 0.08),
|
||
blurRadius: 10,
|
||
offset: const Offset(0, 2),
|
||
),
|
||
],
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: [
|
||
Icon(Icons.info, color: AppConstants.primaryColor, size: 20),
|
||
const SizedBox(width: 8),
|
||
Text(
|
||
'关于应用',
|
||
style: TextStyle(
|
||
color: AppConstants.primaryColor,
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
Text(
|
||
AppConstants.appName,
|
||
style: const TextStyle(
|
||
fontSize: 18,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
const SizedBox(height: 8),
|
||
Text(
|
||
'版本 ${AppConstants.appVersion}',
|
||
style: const TextStyle(fontSize: 14, color: Colors.grey),
|
||
),
|
||
const SizedBox(height: 16),
|
||
const Text(
|
||
'基于Flutter开发的现代化诗词应用,致力于为用户提供优质的诗词阅读和创作体验。',
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
color: Colors.black87,
|
||
height: 1.5,
|
||
),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
Widget _buildInfoItem(String label, String value) {
|
||
// === 信息项:显示标签和值 ===
|
||
return Padding(
|
||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
Text(
|
||
label,
|
||
style: const TextStyle(
|
||
fontSize: 14,
|
||
color: Color(0xFF9E9E9E), // 使用具体颜色值代替Colors.grey[600]
|
||
),
|
||
),
|
||
Text(
|
||
value,
|
||
style: const TextStyle(
|
||
fontSize: 14,
|
||
color: Colors.black87,
|
||
fontWeight: FontWeight.w500,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildSettingsGroup(String title, List<Widget> items) {
|
||
// === 设置组:显示组标题和设置项列表 ===
|
||
return Container(
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(16),
|
||
boxShadow: [
|
||
BoxShadow(
|
||
color: Colors.black.withValues(alpha: 0.08),
|
||
blurRadius: 10,
|
||
offset: const Offset(0, 2),
|
||
),
|
||
],
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
// 组标题
|
||
Padding(
|
||
padding: const EdgeInsets.all(16),
|
||
child: Row(
|
||
children: [
|
||
Icon(
|
||
Icons.settings_outlined,
|
||
color: AppConstants.primaryColor,
|
||
size: 20,
|
||
),
|
||
const SizedBox(width: 8),
|
||
Text(
|
||
title,
|
||
style: TextStyle(
|
||
color: AppConstants.primaryColor,
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
const Divider(height: 1),
|
||
// 设置项列表
|
||
...items,
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildSettingsItem(String title, IconData icon, VoidCallback onTap) {
|
||
// === 设置项:显示图标、标题和箭头 ===
|
||
return ListTile(
|
||
leading: Icon(icon, color: AppConstants.primaryColor, size: 20),
|
||
title: Text(
|
||
title,
|
||
style: const TextStyle(fontSize: 14, color: Colors.black87),
|
||
),
|
||
trailing: const Icon(Icons.chevron_right, color: Colors.grey, size: 20),
|
||
onTap: () {
|
||
HapticFeedback.lightImpact();
|
||
onTap();
|
||
},
|
||
);
|
||
}
|
||
|
||
Widget _buildScreenWakeItem() {
|
||
// Web 平台不支持屏幕常亮功能,不显示该项
|
||
if (kIsWeb) {
|
||
return const SizedBox.shrink();
|
||
}
|
||
|
||
// === 屏幕常亮设置项:显示图标、标题和开关 ===
|
||
return ListTile(
|
||
leading: Icon(
|
||
Icons.screen_lock_rotation,
|
||
color: AppConstants.primaryColor,
|
||
size: 20,
|
||
),
|
||
title: Text(
|
||
'屏幕常亮',
|
||
style: const TextStyle(fontSize: 14, color: Colors.black87),
|
||
),
|
||
trailing: Switch(
|
||
value: _isScreenWakeEnabled,
|
||
onChanged: (value) async {
|
||
if (value) {
|
||
// 显示提示对话框
|
||
showDialog(
|
||
context: context,
|
||
builder: (context) => AlertDialog(
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(16),
|
||
),
|
||
title: Row(
|
||
children: [
|
||
Icon(
|
||
Icons.info_outline,
|
||
color: AppConstants.primaryColor,
|
||
size: 20,
|
||
),
|
||
const SizedBox(width: 8),
|
||
const Text(
|
||
'屏幕常亮提示',
|
||
style: TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
content: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
const SizedBox(height: 8),
|
||
Text(
|
||
'⚠️ 注意事项',
|
||
style: TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.w500,
|
||
color: Colors.orange[600],
|
||
),
|
||
),
|
||
const SizedBox(height: 8),
|
||
Text(
|
||
'• OLED屏幕长时间显示相同内容可能会造成不可逆老化',
|
||
style: const TextStyle(
|
||
fontSize: 14,
|
||
color: Colors.black87,
|
||
),
|
||
),
|
||
const SizedBox(height: 6),
|
||
Text(
|
||
'• 开启常亮后,配合自动刷新内容的设置,实现常亮自动加载诗句',
|
||
style: const TextStyle(
|
||
fontSize: 14,
|
||
color: Colors.black87,
|
||
),
|
||
),
|
||
const SizedBox(height: 6),
|
||
Text(
|
||
'• 挂起常亮后,需保持该软件在屏幕中显示,记得关闭常亮哦!',
|
||
style: const TextStyle(
|
||
fontSize: 14,
|
||
color: Colors.black87,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
actions: [
|
||
TextButton(
|
||
onPressed: () => Navigator.pop(context),
|
||
style: TextButton.styleFrom(
|
||
foregroundColor: Colors.grey[600],
|
||
),
|
||
child: const Text('取消'),
|
||
),
|
||
TextButton(
|
||
onPressed: () async {
|
||
Navigator.pop(context);
|
||
await _toggleScreenWake(true);
|
||
},
|
||
style: TextButton.styleFrom(
|
||
foregroundColor: AppConstants.primaryColor,
|
||
textStyle: const TextStyle(fontWeight: FontWeight.bold),
|
||
),
|
||
child: const Text('确定'),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
} else {
|
||
await _toggleScreenWake(false);
|
||
}
|
||
},
|
||
activeColor: AppConstants.primaryColor,
|
||
),
|
||
);
|
||
}
|
||
|
||
Future<void> _toggleScreenWake(bool enable) async {
|
||
// Web 平台不支持 wakelock_plus
|
||
if (kIsWeb) {
|
||
if (mounted) {
|
||
ScaffoldMessenger.of(
|
||
context,
|
||
).showSnackBar(const SnackBar(content: Text('Web 平台不支持屏幕常亮功能')));
|
||
}
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// 使用 io.Platform 检测平台
|
||
final String osName = io.Platform.operatingSystem;
|
||
final String osVersion = io.Platform.operatingSystemVersion;
|
||
print('Current platform: $osName, version: $osVersion');
|
||
|
||
if (enable) {
|
||
await WakelockService.instance.enable();
|
||
if (mounted) {
|
||
ScaffoldMessenger.of(
|
||
context,
|
||
).showSnackBar(const SnackBar(content: Text('屏幕常亮已开启')));
|
||
}
|
||
} else {
|
||
await WakelockService.instance.disable();
|
||
if (mounted) {
|
||
ScaffoldMessenger.of(
|
||
context,
|
||
).showSnackBar(const SnackBar(content: Text('屏幕常亮已关闭')));
|
||
}
|
||
}
|
||
|
||
setState(() {
|
||
_isScreenWakeEnabled = enable;
|
||
});
|
||
} catch (e, stackTrace) {
|
||
print('WakelockService error: $e');
|
||
print('Stack trace: $stackTrace');
|
||
if (mounted) {
|
||
// 检查错误类型,判断是否是设备不支持
|
||
String errorMessage;
|
||
if (e.toString().contains('not supported') ||
|
||
e.toString().contains('unsupported') ||
|
||
e.toString().contains('不支持')) {
|
||
errorMessage = '该设备不支持屏幕常亮功能';
|
||
} else {
|
||
errorMessage = '屏幕常亮功能异常: $e';
|
||
}
|
||
|
||
showDialog(
|
||
context: context,
|
||
builder: (context) => AlertDialog(
|
||
title: const Text('提示'),
|
||
content: Text(errorMessage),
|
||
actions: [
|
||
TextButton(
|
||
onPressed: () => Navigator.pop(context),
|
||
child: const Text('确定'),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
Widget _buildInteractionItem(String label, String value) {
|
||
// === 互动统计项:显示标签和数值 ===
|
||
return Expanded(
|
||
child: Column(
|
||
children: [
|
||
Text(
|
||
value,
|
||
style: const TextStyle(
|
||
fontSize: 20,
|
||
fontWeight: FontWeight.bold,
|
||
color: AppConstants.primaryColor,
|
||
),
|
||
),
|
||
const SizedBox(height: 4),
|
||
Text(label, style: const TextStyle(fontSize: 12, color: Colors.grey)),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
void _showSnackBar(String message) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(
|
||
content: Text(message),
|
||
backgroundColor: AppConstants.primaryColor,
|
||
duration: const Duration(seconds: 2),
|
||
),
|
||
);
|
||
}
|
||
|
||
// === 导航到历史记录页面 ===
|
||
void _navigateToHistoryPage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const HistoryPage()),
|
||
);
|
||
}
|
||
|
||
void _navigateToAppFunSettings() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const AppFunSettingsPage()),
|
||
);
|
||
}
|
||
|
||
void _navigateToUserPlanPage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (_) => const UserPlanPage()),
|
||
);
|
||
}
|
||
|
||
void _navigateToOfflineDataPage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (_) => const OfflineDataPage()),
|
||
);
|
||
}
|
||
|
||
void _navigateToPermissionPage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const PermissionPage()),
|
||
);
|
||
}
|
||
|
||
void _navigateToAppDataPage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const AppDataPage()),
|
||
);
|
||
}
|
||
|
||
void _navigateToPrivacyPage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const PrivacyPage()),
|
||
);
|
||
}
|
||
|
||
void _navigateToLearnUsPage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const LearnUsPage()),
|
||
);
|
||
}
|
||
|
||
void _navigateToAppInfoPage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const AppInfoPage()),
|
||
);
|
||
}
|
||
|
||
void _navigateToAppDiyPage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const AppDiyPage()),
|
||
);
|
||
}
|
||
|
||
void _navigateToVotePage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const VotePage()),
|
||
);
|
||
}
|
||
|
||
void _showMoreOptions() {
|
||
PopMenu.show(
|
||
context,
|
||
onRefresh: () => refreshData(),
|
||
onEdit: () => _showSnackBar('编辑资料'),
|
||
onScanQr: () => _showSnackBar('了解软件功能'),
|
||
onDarkMode: () => _showSnackBar('夜间模式'),
|
||
onSettings: () {
|
||
Future.delayed(const Duration(milliseconds: 100), () {
|
||
if (mounted && _pageController.hasClients) {
|
||
_pageController.animateToPage(
|
||
1,
|
||
duration: const Duration(milliseconds: 300),
|
||
curve: Curves.easeInOut,
|
||
);
|
||
}
|
||
});
|
||
},
|
||
);
|
||
}
|
||
}
|