This commit is contained in:
Developer
2026-03-31 05:42:47 +08:00
parent 888363785b
commit d6ac0ed1e4
18 changed files with 751 additions and 170 deletions

View File

@@ -22,10 +22,12 @@ 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});
@@ -35,20 +37,35 @@ class ProfilePage extends StatefulWidget {
}
class _ProfilePageState extends State<ProfilePage>
with TickerProviderStateMixin {
with TickerProviderStateMixin, WidgetsBindingObserver {
late PageController _pageController;
late TabController _tabController;
int _currentPage = 1; // 默认显示第2页设置
bool _isCardExpanded = false; // 个人卡片展开状态
bool _isStatsHidden = false; // 统计数据隐藏状态
double _startY = 0.0;
// 历史记录相关
List<Map<String, dynamic>> _poetryHistory = [];
// PersonalCard 的 Key用于调用其刷新方法
final GlobalKey<PersonalCardState> _personalCardKey =
GlobalKey<PersonalCardState>();
// 答题统计数据
int _correctAnswers = 0;
int _todayQuestions = 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;
// 模拟用户数据
final Map<String, dynamic> _userData = {
'avatar': '👤', // 使用emoji代替网络图片
@@ -67,19 +84,41 @@ class _ProfilePageState extends State<ProfilePage>
@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;
@@ -146,6 +185,33 @@ class _ProfilePageState extends State<ProfilePage>
}
}
// === 加载统计数据 ===
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(
@@ -222,6 +288,7 @@ class _ProfilePageState extends State<ProfilePage>
Widget _buildProfileHeader() {
// === 个人信息头部:可收起/张开的个人卡片 ===
return PersonalCard(
key: _personalCardKey,
userData: _userData,
isExpanded: _isCardExpanded,
onExpandChanged: (value) {
@@ -277,97 +344,130 @@ class _ProfilePageState extends State<ProfilePage>
),
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),
// === 信息列表 ===
_buildInfoItem('用户ID', '123123'),
_buildInfoItem('注册时间', '2023-03-21'),
_buildInfoItem('会员等级', 'VIP会员'),
_buildInfoItem('积分余额', '2,580'),
_buildInfoItem('创作诗词', '156首'),
_buildInfoItem('获赞总数', '2,560'),
if (!_isStatsHidden) ...[
_buildInfoItem('今日浏览', '$_todayViews'),
_buildInfoItem('本周浏览', '$_weekViews'),
_buildInfoItem('天数', '$_useDays'),
_buildInfoItem('数据', _dataSize),
_buildInfoItem('笔记', '$_noteCount'),
_buildInfoItem('今日答题', '$_todayQuestions'),
_buildInfoItem('今日点赞', '$_todayLikes'),
] else
Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Text(
'数据已隐藏',
style: TextStyle(color: Colors.grey[500], fontSize: 14),
),
),
),
],
),
),
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.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),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildInteractionItem('今日答题', '$_todayQuestions'),
_buildInteractionItem('本周答题', '$_weekQuestions'),
_buildInteractionItem('答对次数', '$_correctAnswers'),
],
),
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)),
if (!_isStatsHidden)
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),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildInteractionItem('今日答题', '$_todayQuestions'),
_buildInteractionItem('本周答题', '$_weekQuestions'),
_buildInteractionItem('答对次数', '$_correctAnswers'),
],
),
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),
),
),
),
],
),
),
),
],
),
);
@@ -577,7 +677,7 @@ class _ProfilePageState extends State<ProfilePage>
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'标签',
label,
style: const TextStyle(
fontSize: 14,
color: Color(0xFF9E9E9E), // 使用具体颜色值代替Colors.grey[600]
@@ -768,80 +868,22 @@ class _ProfilePageState extends State<ProfilePage>
}
void _showMoreOptions() {
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
builder: (context) => Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 顶部拖拽条
Container(
width: 40,
height: 4,
margin: const EdgeInsets.only(top: 8),
decoration: BoxDecoration(
color: Colors.grey[300]!,
borderRadius: BorderRadius.circular(2),
),
),
// 选项列表
_buildBottomSheetItem(
'分享主页',
Icons.share,
() => _showSnackBar('分享主页'),
),
_buildBottomSheetItem(
'编辑资料',
Icons.edit,
() => _showSnackBar('编辑资料'),
),
_buildBottomSheetItem(
'扫描二维码',
Icons.qr_code_scanner,
() => _showSnackBar('扫描二维码'),
),
_buildBottomSheetItem(
'夜间模式',
Icons.dark_mode,
() => _showSnackBar('夜间模式'),
),
const SizedBox(height: 20),
_buildBottomSheetItem('设置', Icons.settings, () {
// 延迟执行,确保底部弹窗完全关闭
Future.delayed(const Duration(milliseconds: 100), () {
if (mounted && _pageController.hasClients) {
_pageController.animateToPage(
1,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
});
}),
],
),
),
);
}
Widget _buildBottomSheetItem(
String title,
IconData icon,
VoidCallback onTap,
) {
// === 底部弹窗选项项 ===
return ListTile(
leading: Icon(icon, color: AppConstants.primaryColor),
title: Text(title),
onTap: () {
Navigator.pop(context);
HapticFeedback.lightImpact();
onTap();
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,
);
}
});
},
);
}