1175 lines
36 KiB
Dart
1175 lines
36 KiB
Dart
/// 时间: 2025.03.21
|
||
/// 功能: 个人页面(类似朋友圈布局)
|
||
/// 介绍: 展示用户头像、个性签名、昵称、统计信息和设置列表,支持左右滑动切换页面
|
||
/// 最新变化: 重新设计布局,实现朋友圈风格的个人页面
|
||
|
||
import 'dart:convert';
|
||
import 'dart:ui';
|
||
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:intl/intl.dart';
|
||
|
||
import '../../constants/app_constants.dart';
|
||
import '../../controllers/history_controller.dart';
|
||
import '../../controllers/sqlite_storage_controller.dart';
|
||
import '../../utils/flutter_compatibility_fix.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/sp-guide.dart';
|
||
import 'guide/permission.dart';
|
||
import 'guide/app-data.dart';
|
||
import 'theme/app-diy.dart';
|
||
import 'expand/vote.dart';
|
||
import 'expand/manu-script.dart';
|
||
|
||
class ProfilePage extends StatefulWidget {
|
||
const ProfilePage({super.key});
|
||
|
||
@override
|
||
State<ProfilePage> createState() => _ProfilePageState();
|
||
}
|
||
|
||
class _ProfilePageState extends State<ProfilePage>
|
||
with TickerProviderStateMixin {
|
||
late PageController _pageController;
|
||
late TabController _tabController;
|
||
int _currentPage = 1; // 默认显示第2页(设置)
|
||
bool _isCardExpanded = false; // 个人卡片展开状态
|
||
double _startY = 0.0;
|
||
// 历史记录相关
|
||
List<Map<String, dynamic>> _poetryHistory = [];
|
||
final String _historyKey = 'poetry_history';
|
||
|
||
// 答题统计数据
|
||
int _totalQuestions = 0;
|
||
int _correctAnswers = 0;
|
||
int _todayQuestions = 0;
|
||
int _weekQuestions = 0;
|
||
|
||
// 模拟用户数据
|
||
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,
|
||
};
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_pageController = PageController(initialPage: 1);
|
||
_tabController = TabController(length: 3, vsync: this);
|
||
_loadPoetryHistory();
|
||
_loadPoetryStatistics();
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_pageController.dispose();
|
||
_tabController.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
void _handleScroll() {
|
||
// 这个方法现在由手势检测处理
|
||
}
|
||
|
||
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> _savePoetryToHistory(Map<String, dynamic> poetryData) async {
|
||
try {
|
||
final success = await HistoryController.addToHistory(poetryData);
|
||
|
||
if (success) {
|
||
_showSnackBar('已添加到历史记录');
|
||
} else {
|
||
_showSnackBar('该诗词已在历史记录中');
|
||
}
|
||
} catch (e) {
|
||
_showSnackBar('保存失败');
|
||
}
|
||
}
|
||
|
||
Future<void> _clearPoetryHistory() async {
|
||
try {
|
||
final success = await HistoryController.clearHistory();
|
||
|
||
if (success) {
|
||
setState(() {
|
||
_poetryHistory.clear();
|
||
});
|
||
_showSnackBar('历史记录已清空');
|
||
} else {
|
||
_showSnackBar('清空失败');
|
||
}
|
||
} catch (e) {
|
||
_showSnackBar('清空失败');
|
||
}
|
||
}
|
||
|
||
// === 答题统计相关方法 ===
|
||
Future<void> _loadPoetryStatistics() async {
|
||
try {
|
||
// 加载总体统计
|
||
_totalQuestions = await SQLiteStorageController.getInt(
|
||
'totalQuestions',
|
||
defaultValue: 0,
|
||
);
|
||
_correctAnswers = await SQLiteStorageController.getInt(
|
||
'correctAnswers',
|
||
defaultValue: 0,
|
||
);
|
||
|
||
// 加载答题记录列表来计算今日和本周答题数
|
||
List<String> records = await SQLiteStorageController.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) {
|
||
print('加载答题统计失败: $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(
|
||
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,
|
||
);
|
||
}
|
||
},
|
||
);
|
||
}
|
||
|
||
Widget _buildStatCard(String label, String value, IconData icon) {
|
||
// === 单个统计卡片:显示统计数据和图标 ===
|
||
return Expanded(
|
||
child: Container(
|
||
padding: const EdgeInsets.all(12),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(12),
|
||
boxShadow: [
|
||
BoxShadow(
|
||
color: Colors.black.withValues(alpha: 0.05),
|
||
blurRadius: 5,
|
||
offset: const Offset(0, 1),
|
||
),
|
||
],
|
||
),
|
||
child: Column(
|
||
children: [
|
||
Icon(icon, color: AppConstants.primaryColor, size: 24),
|
||
const SizedBox(height: 8),
|
||
Text(
|
||
value,
|
||
style: const TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
color: Colors.black87,
|
||
),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
const SizedBox(height: 4),
|
||
Text(
|
||
label,
|
||
style: const TextStyle(fontSize: 12, color: Colors.grey),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildTabBar() {
|
||
// === 页面切换标签栏:显示当前页面指示器 ===
|
||
return GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onVerticalDragStart: (_) {},
|
||
onVerticalDragUpdate: (_) {},
|
||
onVerticalDragEnd: (_) {},
|
||
child: Container(
|
||
decoration: BoxDecoration(
|
||
gradient: LinearGradient(
|
||
colors: [
|
||
AppConstants.primaryColor.withValues(alpha: 0.85),
|
||
AppConstants.primaryColor.withValues(alpha: 0.8),
|
||
],
|
||
begin: Alignment.topCenter,
|
||
end: Alignment.bottomCenter,
|
||
),
|
||
),
|
||
child: Container(
|
||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||
child: Row(
|
||
children: [
|
||
// 页面指示器
|
||
Expanded(
|
||
child: Container(
|
||
height: 3,
|
||
margin: const EdgeInsets.symmetric(horizontal: 20),
|
||
decoration: BoxDecoration(
|
||
color: Colors.white.withValues(alpha: 0.3),
|
||
borderRadius: BorderRadius.circular(2),
|
||
),
|
||
child: Stack(
|
||
children: [
|
||
// 背景条
|
||
Container(
|
||
height: 3,
|
||
decoration: BoxDecoration(
|
||
color: Colors.white.withValues(alpha: 0.3),
|
||
borderRadius: BorderRadius.circular(2),
|
||
),
|
||
),
|
||
// 滑动指示器
|
||
AnimatedContainer(
|
||
duration: const Duration(milliseconds: 300),
|
||
width: MediaQuery.of(context).size.width / 3 - 40,
|
||
height: 3,
|
||
decoration: BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.circular(2),
|
||
),
|
||
margin: EdgeInsets.only(
|
||
left:
|
||
(MediaQuery.of(context).size.width / 3 - 40) *
|
||
_currentPage,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
// 页面标签
|
||
Container(
|
||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||
decoration: BoxDecoration(
|
||
color: Colors.black.withValues(alpha: 0.1),
|
||
borderRadius: BorderRadius.circular(12),
|
||
),
|
||
child: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
_buildTabLabel(0, '卡片'),
|
||
_buildTabLabel(1, '设置'),
|
||
_buildTabLabel(2, '更多'),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildTabLabel(int index, String label) {
|
||
// === 单个页面标签:可点击切换到对应页面 ===
|
||
final isSelected = _currentPage == index;
|
||
return GestureDetector(
|
||
onTap: () {
|
||
// 添加 mounted 和 hasClients 检查,避免 dispose 后调用导致黑屏
|
||
if (mounted && _pageController.hasClients) {
|
||
_pageController.animateToPage(
|
||
index,
|
||
duration: const Duration(milliseconds: 300),
|
||
curve: Curves.easeInOut,
|
||
);
|
||
}
|
||
},
|
||
child: Container(
|
||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||
child: Text(
|
||
label,
|
||
style: TextStyle(
|
||
color: isSelected ? Colors.white : Colors.white70,
|
||
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
||
fontSize: 14,
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
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.person_outline,
|
||
color: AppConstants.primaryColor,
|
||
size: 20,
|
||
),
|
||
const SizedBox(width: 8),
|
||
Text(
|
||
'统计*隐藏',
|
||
style: TextStyle(
|
||
color: AppConstants.primaryColor,
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
// === 信息列表 ===
|
||
_buildInfoItem('用户ID', '123123'),
|
||
_buildInfoItem('注册时间', '2023-03-21'),
|
||
_buildInfoItem('会员等级', 'VIP会员'),
|
||
_buildInfoItem('积分余额', '2,580'),
|
||
_buildInfoItem('创作诗词', '156首'),
|
||
_buildInfoItem('获赞总数', '2,560'),
|
||
],
|
||
),
|
||
),
|
||
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)),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildPage2() {
|
||
// === 第2页:设置列表 ===
|
||
return ListView(
|
||
padding: const EdgeInsets.all(16),
|
||
children: [
|
||
// === 账户设置组 ===
|
||
_buildSettingsGroup('软件设置', [
|
||
_buildSettingsItem(
|
||
'离线使用',
|
||
Icons.volunteer_activism,
|
||
() => _navigateToOfflineDataPage(),
|
||
),
|
||
_buildSettingsItem(
|
||
'历史记录',
|
||
Icons.history,
|
||
() => _navigateToHistoryPage(),
|
||
),
|
||
_buildSettingsItem(
|
||
'功能设置',
|
||
Icons.verified_user,
|
||
() => _navigateToAppFunSettings(),
|
||
),
|
||
_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(
|
||
'商务合作',
|
||
Icons.cleaning_services,
|
||
() => _showSnackBar('商务合作'),
|
||
),
|
||
_buildSettingsItem(
|
||
'关闭退出',
|
||
Icons.palette,
|
||
() => _showSnackBar('重启 关闭?'),
|
||
),
|
||
]),
|
||
],
|
||
);
|
||
}
|
||
|
||
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(
|
||
'标签',
|
||
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 _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 _navigateToSpGuidePage() {
|
||
Navigator.push(
|
||
context,
|
||
MaterialPageRoute(
|
||
builder: (context) => const SpGuidePage(fromSettings: true),
|
||
),
|
||
);
|
||
}
|
||
|
||
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 _showHistoryDialog() {
|
||
showDialog(
|
||
context: context,
|
||
builder: (context) => Dialog(
|
||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||
child: Container(
|
||
width: MediaQuery.of(context).size.width * 0.9,
|
||
height: MediaQuery.of(context).size.height * 0.7,
|
||
padding: const EdgeInsets.all(20),
|
||
child: Column(
|
||
children: [
|
||
// 对话框标题
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
Text(
|
||
'历史记录',
|
||
style: TextStyle(
|
||
fontSize: 18,
|
||
fontWeight: FontWeight.bold,
|
||
color: AppConstants.primaryColor,
|
||
),
|
||
),
|
||
Row(
|
||
children: [
|
||
TextButton(
|
||
onPressed: _poetryHistory.isEmpty
|
||
? null
|
||
: () {
|
||
Navigator.pop(context);
|
||
_clearPoetryHistory();
|
||
},
|
||
child: const Text('清空'),
|
||
),
|
||
IconButton(
|
||
onPressed: () => Navigator.pop(context),
|
||
icon: const Icon(Icons.close),
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
// 历史记录列表
|
||
Expanded(
|
||
child: _poetryHistory.isEmpty
|
||
? Center(
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Icon(
|
||
Icons.history,
|
||
size: 64,
|
||
color: Colors.grey[400],
|
||
),
|
||
const SizedBox(height: 16),
|
||
Text(
|
||
'暂无历史记录',
|
||
style: TextStyle(
|
||
fontSize: 16,
|
||
color: Colors.grey[600],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
)
|
||
: ListView.builder(
|
||
itemCount: _poetryHistory.length,
|
||
itemBuilder: (context, index) {
|
||
final poetry = _poetryHistory[index];
|
||
return Card(
|
||
margin: const EdgeInsets.only(bottom: 8),
|
||
child: ListTile(
|
||
leading: CircleAvatar(
|
||
radius: 20,
|
||
backgroundColor: AppConstants.primaryColor
|
||
.withValues(alpha: 0.1),
|
||
child: Text(
|
||
'${index + 1}',
|
||
style: TextStyle(
|
||
fontSize: 12,
|
||
color: AppConstants.primaryColor,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
),
|
||
title: Text(
|
||
poetry['name'] ?? '未知诗词',
|
||
style: const TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.w500,
|
||
),
|
||
maxLines: 2,
|
||
overflow: TextOverflow.ellipsis,
|
||
),
|
||
subtitle: Text(
|
||
'${poetry['alias'] ?? '未知朝代'} • ${poetry['date'] ?? ''}',
|
||
style: const TextStyle(
|
||
fontSize: 12,
|
||
color: Colors.grey,
|
||
),
|
||
),
|
||
trailing: IconButton(
|
||
icon: const Icon(Icons.favorite_border),
|
||
onPressed: () {
|
||
Navigator.pop(context);
|
||
_showSnackBar('已添加到收藏');
|
||
},
|
||
),
|
||
),
|
||
);
|
||
},
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget? _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();
|
||
},
|
||
);
|
||
}
|
||
}
|