Files
wushu/lib/views/profile/profile_page.dart
2026-03-30 07:32:12 +08:00

1175 lines
36 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// 时间: 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();
},
);
}
}