重构
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import '../../../constants/app_constants.dart';
|
||||
|
||||
class PopMenu extends StatelessWidget {
|
||||
final VoidCallback? onRefresh;
|
||||
final VoidCallback? onEdit;
|
||||
final VoidCallback? onScanQr;
|
||||
final VoidCallback? onDarkMode;
|
||||
final VoidCallback? onSettings;
|
||||
|
||||
const PopMenu({
|
||||
super.key,
|
||||
this.onRefresh,
|
||||
this.onEdit,
|
||||
this.onScanQr,
|
||||
this.onDarkMode,
|
||||
this.onSettings,
|
||||
});
|
||||
|
||||
static Future<void> shareApp(BuildContext context) async {
|
||||
try {
|
||||
const String shareText = '诗词学习App - 一款优雅的诗词学习应用,包含丰富的诗词内容和答题功能';
|
||||
|
||||
final result = await Share.shareWithResult(shareText, subject: '诗词学习App');
|
||||
|
||||
if (result.status == ShareResultStatus.success) {
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('分享成功!')));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('该平台暂不支持分享功能')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void show(
|
||||
BuildContext context, {
|
||||
VoidCallback? onRefresh,
|
||||
VoidCallback? onEdit,
|
||||
VoidCallback? onScanQr,
|
||||
VoidCallback? onDarkMode,
|
||||
VoidCallback? onSettings,
|
||||
}) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (context) => PopMenu(
|
||||
onRefresh: onRefresh,
|
||||
onEdit: onEdit,
|
||||
onScanQr: onScanQr,
|
||||
onDarkMode: onDarkMode,
|
||||
onSettings: onSettings,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return 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(context, '刷新数据', Icons.refresh, onRefresh),
|
||||
_buildBottomSheetItem(context, '分享软件', Icons.share, () {
|
||||
shareApp(context);
|
||||
}),
|
||||
_buildBottomSheetItem(
|
||||
context,
|
||||
'扫描二维码',
|
||||
Icons.qr_code_scanner,
|
||||
onScanQr,
|
||||
),
|
||||
_buildBottomSheetItem(context, '夜间模式', Icons.dark_mode, onDarkMode),
|
||||
const SizedBox(height: 20),
|
||||
_buildBottomSheetItem(context, '设置', Icons.settings, onSettings),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBottomSheetItem(
|
||||
BuildContext context,
|
||||
String title,
|
||||
IconData icon,
|
||||
VoidCallback? onTap,
|
||||
) {
|
||||
return ListTile(
|
||||
leading: Icon(icon, color: AppConstants.primaryColor),
|
||||
title: Text(title),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
HapticFeedback.lightImpact();
|
||||
if (onTap != null) {
|
||||
onTap();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/// 时间: 2026-03-31
|
||||
/// 功能: 统计数据管理
|
||||
/// 介绍: 管理应用的各种统计数据,包括浏览次数、答题次数、点赞数等
|
||||
/// 最新变化: 新建文件
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class StatisticsManager {
|
||||
static const String _todayViewsKey = 'today_views';
|
||||
static const String _weekViewsKey = 'week_views';
|
||||
static const String _firstUseTimeKey = 'first_use_time';
|
||||
static const String _todayLikesKey = 'today_likes';
|
||||
static const String _todayQuestionsKey = 'today_questions';
|
||||
static const String _lastViewDateKey = 'last_view_date';
|
||||
static const String _lastWeekKey = 'last_week_start';
|
||||
static const String _lastQuestionDateKey = 'last_question_date';
|
||||
|
||||
static StatisticsManager? _instance;
|
||||
|
||||
StatisticsManager._internal();
|
||||
|
||||
factory StatisticsManager() {
|
||||
_instance ??= StatisticsManager._internal();
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
/// 记录一次浏览
|
||||
Future<void> recordView() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final now = DateTime.now();
|
||||
final today = _formatDate(now);
|
||||
final weekStart = _getWeekStart(now);
|
||||
|
||||
final lastViewDate = prefs.getString(_lastViewDateKey);
|
||||
final lastWeekStart = prefs.getString(_lastWeekKey);
|
||||
|
||||
if (lastViewDate != today) {
|
||||
await prefs.setInt(_todayViewsKey, 0);
|
||||
await prefs.setString(_lastViewDateKey, today);
|
||||
}
|
||||
|
||||
if (lastWeekStart != weekStart) {
|
||||
await prefs.setInt(_weekViewsKey, 0);
|
||||
await prefs.setString(_lastWeekKey, weekStart);
|
||||
}
|
||||
|
||||
final todayViews = prefs.getInt(_todayViewsKey) ?? 0;
|
||||
final weekViews = prefs.getInt(_weekViewsKey) ?? 0;
|
||||
|
||||
await prefs.setInt(_todayViewsKey, todayViews + 1);
|
||||
await prefs.setInt(_weekViewsKey, weekViews + 1);
|
||||
}
|
||||
|
||||
/// 获取今日浏览次数
|
||||
Future<int> getTodayViews() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final today = _formatDate(DateTime.now());
|
||||
final lastViewDate = prefs.getString(_lastViewDateKey);
|
||||
|
||||
if (lastViewDate != today) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return prefs.getInt(_todayViewsKey) ?? 0;
|
||||
}
|
||||
|
||||
/// 获取本周浏览次数
|
||||
Future<int> getWeekViews() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final now = DateTime.now();
|
||||
final weekStart = _getWeekStart(now);
|
||||
final lastWeekStart = prefs.getString(_lastWeekKey);
|
||||
|
||||
if (lastWeekStart != weekStart) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return prefs.getInt(_weekViewsKey) ?? 0;
|
||||
}
|
||||
|
||||
/// 记录首次使用时间
|
||||
Future<void> recordFirstUse() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
if (!prefs.containsKey(_firstUseTimeKey)) {
|
||||
await prefs.setString(_firstUseTimeKey, DateTime.now().toIso8601String());
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取首次使用时间
|
||||
Future<String> getFirstUseTime() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final timeStr = prefs.getString(_firstUseTimeKey);
|
||||
if (timeStr == null) {
|
||||
return '未记录';
|
||||
}
|
||||
final date = DateTime.parse(timeStr);
|
||||
return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
/// 记录今日点赞
|
||||
Future<void> recordTodayLike() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final now = DateTime.now();
|
||||
final today = _formatDate(now);
|
||||
final lastLikeDate = prefs.getString('last_like_date');
|
||||
|
||||
if (lastLikeDate != today) {
|
||||
await prefs.setInt(_todayLikesKey, 0);
|
||||
await prefs.setString('last_like_date', today);
|
||||
}
|
||||
|
||||
final todayLikes = prefs.getInt(_todayLikesKey) ?? 0;
|
||||
await prefs.setInt(_todayLikesKey, todayLikes + 1);
|
||||
}
|
||||
|
||||
/// 获取今日点赞数
|
||||
Future<int> getTodayLikes() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final today = _formatDate(DateTime.now());
|
||||
final lastLikeDate = prefs.getString('last_like_date');
|
||||
|
||||
if (lastLikeDate != today) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return prefs.getInt(_todayLikesKey) ?? 0;
|
||||
}
|
||||
|
||||
/// 获取数据占用空间
|
||||
Future<String> getDataSize() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final keys = prefs.getKeys();
|
||||
int totalBytes = 0;
|
||||
|
||||
for (final key in keys) {
|
||||
final value = prefs.get(key);
|
||||
if (value != null) {
|
||||
totalBytes += value.toString().length * 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalBytes < 1024) {
|
||||
return '$totalBytes B';
|
||||
} else if (totalBytes < 1024 * 1024) {
|
||||
return '${(totalBytes / 1024).toStringAsFixed(1)} KB';
|
||||
} else {
|
||||
return '${(totalBytes / (1024 * 1024)).toStringAsFixed(1)} MB';
|
||||
}
|
||||
} catch (e) {
|
||||
return '计算失败';
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取累计浏览数
|
||||
Future<int> getTotalViews() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getInt('total_views') ?? 0;
|
||||
}
|
||||
|
||||
/// 记录累计浏览
|
||||
Future<void> recordTotalView() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final totalViews = prefs.getInt('total_views') ?? 0;
|
||||
await prefs.setInt('total_views', totalViews + 1);
|
||||
}
|
||||
|
||||
/// 获取累计点赞数
|
||||
Future<int> getTotalLikes() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getInt('total_likes') ?? 0;
|
||||
}
|
||||
|
||||
/// 记录累计点赞
|
||||
Future<void> recordTotalLike() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final totalLikes = prefs.getInt('total_likes') ?? 0;
|
||||
await prefs.setInt('total_likes', totalLikes + 1);
|
||||
}
|
||||
|
||||
/// 获取累计答题数
|
||||
Future<int> getTotalQuestions() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getInt('totalQuestions') ?? 0;
|
||||
}
|
||||
|
||||
/// 记录今日答题
|
||||
Future<void> recordTodayQuestion() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final now = DateTime.now();
|
||||
final today = _formatDate(now);
|
||||
final lastQuestionDate = prefs.getString(_lastQuestionDateKey);
|
||||
|
||||
if (lastQuestionDate != today) {
|
||||
await prefs.setInt(_todayQuestionsKey, 0);
|
||||
await prefs.setString(_lastQuestionDateKey, today);
|
||||
}
|
||||
|
||||
final todayQuestions = prefs.getInt(_todayQuestionsKey) ?? 0;
|
||||
await prefs.setInt(_todayQuestionsKey, todayQuestions + 1);
|
||||
}
|
||||
|
||||
/// 获取今日答题数
|
||||
Future<int> getTodayQuestions() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final today = _formatDate(DateTime.now());
|
||||
final lastQuestionDate = prefs.getString(_lastQuestionDateKey);
|
||||
|
||||
if (lastQuestionDate != today) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return prefs.getInt(_todayQuestionsKey) ?? 0;
|
||||
}
|
||||
|
||||
/// 获取使用天数
|
||||
Future<int> getUseDays() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final timeStr = prefs.getString(_firstUseTimeKey);
|
||||
if (timeStr == null) {
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
final firstUseDate = DateTime.parse(timeStr);
|
||||
final today = DateTime.now();
|
||||
final difference = today.difference(firstUseDate);
|
||||
return difference.inDays + 1;
|
||||
} catch (e) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// 格式化日期为 YYYY-MM-DD
|
||||
String _formatDate(DateTime date) {
|
||||
return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
/// 获取本周开始日期(周一)
|
||||
String _getWeekStart(DateTime date) {
|
||||
final monday = date.subtract(Duration(days: date.weekday - 1));
|
||||
return _formatDate(monday);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../constants/app_constants.dart';
|
||||
import '../../../controllers/shared_preferences_storage_controller.dart';
|
||||
import '../guide/tongji.dart';
|
||||
import 'level-jilu.dart';
|
||||
import 'flow-anim.dart';
|
||||
import 'distinguish.dart';
|
||||
@@ -231,6 +232,13 @@ class _PoetryLevelPageState extends State<PoetryLevelPage>
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
// 记录今日答题
|
||||
try {
|
||||
await StatisticsManager().recordTodayQuestion();
|
||||
} catch (e) {
|
||||
// 忽略错误
|
||||
}
|
||||
|
||||
setState(() {
|
||||
if (result.success) {
|
||||
_isAnswerCorrect = result.isCorrect;
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../constants/app_constants.dart';
|
||||
import '../../services/network_listener_service.dart';
|
||||
import 'guide/tongji.dart';
|
||||
|
||||
/// 时间: 2026-03-25
|
||||
/// 功能: 个人信息卡片组件
|
||||
@@ -28,20 +29,42 @@ class PersonalCard extends StatefulWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
State<PersonalCard> createState() => _PersonalCardState();
|
||||
State<PersonalCard> createState() => PersonalCardState();
|
||||
}
|
||||
|
||||
class _PersonalCardState extends State<PersonalCard> {
|
||||
class PersonalCardState extends State<PersonalCard> {
|
||||
late bool _isExpanded;
|
||||
late String _currentTip;
|
||||
bool _isOnline = true;
|
||||
|
||||
// 累计数据
|
||||
int _totalViews = 0;
|
||||
int _totalLikes = 0;
|
||||
int _totalQuestions = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_isExpanded = widget.isExpanded ?? false;
|
||||
_currentTip = _getRandomTip();
|
||||
_loadOnlineStatus();
|
||||
_loadTotalStats();
|
||||
}
|
||||
|
||||
Future<void> _loadTotalStats() async {
|
||||
final views = await StatisticsManager().getTotalViews();
|
||||
final likes = await StatisticsManager().getTotalLikes();
|
||||
final questions = await StatisticsManager().getTotalQuestions();
|
||||
setState(() {
|
||||
_totalViews = views;
|
||||
_totalLikes = likes;
|
||||
_totalQuestions = questions;
|
||||
});
|
||||
}
|
||||
|
||||
// 刷新数据(公共方法,供外部调用)
|
||||
Future<void> refreshData() async {
|
||||
await _loadTotalStats();
|
||||
}
|
||||
|
||||
Future<void> _loadOnlineStatus() async {
|
||||
@@ -378,15 +401,38 @@ class _PersonalCardState extends State<PersonalCard> {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
// 统计信息
|
||||
Row(
|
||||
children: [
|
||||
_buildStatItem('收藏', widget.userData['favorites'] ?? 0),
|
||||
const SizedBox(width: 12),
|
||||
_buildStatItem('点赞', widget.userData['likes'] ?? 0),
|
||||
const SizedBox(width: 12),
|
||||
_buildStatItem('浏览', widget.userData['views'] ?? 0),
|
||||
],
|
||||
// 累计统计卡片
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 10,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'累计',
|
||||
style: const TextStyle(
|
||||
color: Colors.white70,
|
||||
fontSize: 11,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildStatItem('浏览', _totalViews),
|
||||
const SizedBox(width: 16),
|
||||
_buildStatItem('点赞', _totalLikes),
|
||||
const SizedBox(width: 16),
|
||||
_buildStatItem('答题', _totalQuestions),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user