From bd9b82f6e14d8cfd648d3954ec69abe1f2cdf438 Mon Sep 17 00:00:00 2001 From: DelLevin-Home Date: Fri, 13 Mar 2026 16:18:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A4=87=E4=BB=BD=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E8=BF=9E=E5=90=8C=E5=A4=B4=E5=83=8F=E4=B8=80?= =?UTF-8?q?=E8=B5=B7=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/book/book_tab_page.dart | 54 +++++++++++++++++-------- lib/pages/movies/movie_tab_page.dart | 40 +++++++++++++----- lib/pages/note/note_tab_page.dart | 10 +---- lib/pages/profile_page.dart | 5 ++- lib/pages/sync/backup_page.dart | 2 +- lib/utils/sync/auto_backup_service.dart | 4 +- lib/utils/sync/backup_service.dart | 54 +++++++++++++++++++++++++ lib/widgets/book_list_item.dart | 39 +++++++++++++++--- lib/widgets/movie_list_item.dart | 39 +++++++++++++++--- 9 files changed, 197 insertions(+), 50 deletions(-) diff --git a/lib/pages/book/book_tab_page.dart b/lib/pages/book/book_tab_page.dart index 08cb9a3..898bf42 100644 --- a/lib/pages/book/book_tab_page.dart +++ b/lib/pages/book/book_tab_page.dart @@ -65,29 +65,36 @@ class BookTabPage extends StatelessWidget { /// 构建空状态提示 Widget _buildEmptyState(BuildContext context, int statusIndex) { - final statusText = ['读完', '在读', '准备读'][statusIndex]; + final statusText = ['已读', '在读', '想读'][statusIndex]; return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - Icons.menu_book_outlined, - size: 80, - color: Theme.of(context).colorScheme.onSurfaceVariant.withValues(alpha: 0.3), - ), - const SizedBox(height: 16), - Text( - '暂无$statusText的书籍', - style: Theme.of(context).textTheme.titleMedium?.copyWith( - color: Theme.of(context).colorScheme.onSurfaceVariant, + Container( + width: 80, + height: 80, + decoration: BoxDecoration( + color: const Color(0xFFF5F5F5), + borderRadius: BorderRadius.circular(20), + ), + child: const Icon( + Icons.menu_book_outlined, + size: 40, + color: Color(0xFFCCCCCC), ), ), - const SizedBox(height: 8), - ElevatedButton.icon( - icon: const Icon(Icons.add), - label: const Text('添加记录'), - onPressed: () { + const SizedBox(height: 20), + Text( + '暂无$statusText的书籍', + style: const TextStyle( + fontSize: 16, + color: Color(0xFF999999), + ), + ), + const SizedBox(height: 24), + InkWell( + onTap: () { final statusMap = { 0: 'read', 1: 'reading', @@ -100,6 +107,21 @@ class BookTabPage extends StatelessWidget { arguments: {'initialStatus': currentStatus}, ); }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + decoration: BoxDecoration( + color: const Color(0xFF1A1A1A), + borderRadius: BorderRadius.circular(8), + ), + child: const Text( + '添加记录', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), + ), ), ], ), diff --git a/lib/pages/movies/movie_tab_page.dart b/lib/pages/movies/movie_tab_page.dart index 117ab9d..fd6cac4 100644 --- a/lib/pages/movies/movie_tab_page.dart +++ b/lib/pages/movies/movie_tab_page.dart @@ -71,22 +71,30 @@ class MovieTabPage extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon( - Icons.movie_outlined, - size: 48, - color: Color(0xFFCCCCCC), + Container( + width: 80, + height: 80, + decoration: BoxDecoration( + color: const Color(0xFFF5F5F5), + borderRadius: BorderRadius.circular(20), + ), + child: const Icon( + Icons.movie_outlined, + size: 40, + color: Color(0xFFCCCCCC), + ), ), - const SizedBox(height: 16), + const SizedBox(height: 20), Text( '暂无$statusText的影片', style: const TextStyle( - fontSize: 15, + fontSize: 16, color: Color(0xFF999999), ), ), const SizedBox(height: 24), - TextButton( - onPressed: () { + InkWell( + onTap: () { final statusMap = { 0: 'watched', 1: 'watching', @@ -99,7 +107,21 @@ class MovieTabPage extends StatelessWidget { arguments: {'initialStatus': currentStatus}, ); }, - child: const Text('添加记录'), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + decoration: BoxDecoration( + color: const Color(0xFF1A1A1A), + borderRadius: BorderRadius.circular(8), + ), + child: const Text( + '添加记录', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), + ), ), ], ), diff --git a/lib/pages/note/note_tab_page.dart b/lib/pages/note/note_tab_page.dart index 9916137..5ea3378 100644 --- a/lib/pages/note/note_tab_page.dart +++ b/lib/pages/note/note_tab_page.dart @@ -213,14 +213,6 @@ class _NoteTabPageState extends State { color: Color(0xFF999999), ), ), - const SizedBox(height: 8), - const Text( - '记录你的想法和灵感', - style: TextStyle( - fontSize: 13, - color: Color(0xFFBBBBBB), - ), - ), const SizedBox(height: 24), InkWell( onTap: () { @@ -233,7 +225,7 @@ class _NoteTabPageState extends State { borderRadius: BorderRadius.circular(8), ), child: const Text( - '添加笔记', + '添加记录', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, diff --git a/lib/pages/profile_page.dart b/lib/pages/profile_page.dart index a31b986..141f9c8 100644 --- a/lib/pages/profile_page.dart +++ b/lib/pages/profile_page.dart @@ -438,7 +438,10 @@ class _ProfilePageState extends State { Navigator.push( context, MaterialPageRoute(builder: (context) => const BackupPage()), - ); + ).then((_) { + // 返回时刷新用户数据 + _loadUserData(); + }); }, ), const Divider(height: 1, indent: 72, endIndent: 16, color: Color(0xFFE8E8E8)), diff --git a/lib/pages/sync/backup_page.dart b/lib/pages/sync/backup_page.dart index f0eb98c..a3a4633 100644 --- a/lib/pages/sync/backup_page.dart +++ b/lib/pages/sync/backup_page.dart @@ -477,7 +477,7 @@ class _BackupPageState extends State { ), SizedBox(height: 4), Text( - '每2分钟自动备份,保留最近10个备份', + '每2分钟自动备份,保留最近5个备份', style: TextStyle( fontSize: 13, color: Color(0xFF666666), diff --git a/lib/utils/sync/auto_backup_service.dart b/lib/utils/sync/auto_backup_service.dart index ea1f0b5..7662032 100644 --- a/lib/utils/sync/auto_backup_service.dart +++ b/lib/utils/sync/auto_backup_service.dart @@ -16,8 +16,8 @@ class AutoBackupService { static const String _prefsKey = 'auto_backup_enabled'; static const String _backupDirName = 'mooknote'; - static const int _maxBackups = 10; - static const Duration _backupInterval = Duration(minutes: 2); + static const int _maxBackups = 5; + static const Duration _backupInterval = Duration(minutes: 5); /// 是否正在运行 bool get isRunning => _isRunning; diff --git a/lib/utils/sync/backup_service.dart b/lib/utils/sync/backup_service.dart index 133477a..aff3b08 100644 --- a/lib/utils/sync/backup_service.dart +++ b/lib/utils/sync/backup_service.dart @@ -8,6 +8,7 @@ import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as path; import 'package:share_plus/share_plus.dart'; import '../database_helper.dart'; +import '../user_prefs.dart'; /// 数据备份服务 - 支持导出和导入数据(包含图片) class BackupService { @@ -71,12 +72,27 @@ class BackupService { } } + // 获取用户个人信息 + final userPrefs = UserPrefs(); + final userInfo = { + 'nickname': userPrefs.nickname, + 'motto': userPrefs.motto, + 'avatarPath': userPrefs.avatarPath, + }; + + // 如果有头像,添加到图片路径 + final avatarPath = userPrefs.avatarPath; + if (avatarPath != null && avatarPath.isNotEmpty) { + imagePaths.add(avatarPath); + } + // 构建备份数据 final backupData = { 'version': 2, 'exportTime': DateTime.now().toIso8601String(), 'appName': 'MookNote', 'hasImages': true, + 'userInfo': userInfo, 'data': { 'movies': movies, 'books': books, @@ -238,12 +254,27 @@ class BackupService { } } + // 获取用户个人信息 + final userPrefs = UserPrefs(); + final userInfo = { + 'nickname': userPrefs.nickname, + 'motto': userPrefs.motto, + 'avatarPath': userPrefs.avatarPath, + }; + + // 如果有头像,添加到图片路径 + final avatarPath = userPrefs.avatarPath; + if (avatarPath != null && avatarPath.isNotEmpty) { + imagePaths.add(avatarPath); + } + // 构建备份数据 final backupData = { 'version': 2, 'exportTime': DateTime.now().toIso8601String(), 'appName': 'MookNote', 'hasImages': true, + 'userInfo': userInfo, 'data': { 'movies': movies, 'books': books, @@ -443,6 +474,29 @@ class BackupService { } }); + // 恢复用户个人信息 + if (backupData.containsKey('userInfo')) { + final userInfo = backupData['userInfo'] as Map; + final userPrefs = UserPrefs(); + + if (userInfo.containsKey('nickname')) { + await userPrefs.setNickname(userInfo['nickname'] as String); + } + if (userInfo.containsKey('motto')) { + await userPrefs.setMotto(userInfo['motto'] as String); + } + if (userInfo.containsKey('avatarPath')) { + final avatarPath = userInfo['avatarPath'] as String?; + if (avatarPath != null && avatarPath.isNotEmpty) { + // 更新头像路径为新的路径 + final fileName = path.basename(avatarPath); + if (imagePathMap.containsKey(fileName)) { + await userPrefs.setAvatarPath(imagePathMap[fileName]!); + } + } + } + } + // 统计导入数量 final stats = {}; if (data.containsKey('movies')) { diff --git a/lib/widgets/book_list_item.dart b/lib/widgets/book_list_item.dart index c654888..08b2e7b 100644 --- a/lib/widgets/book_list_item.dart +++ b/lib/widgets/book_list_item.dart @@ -133,23 +133,50 @@ class BookListItem extends StatelessWidget { builder: (context) => AlertDialog( backgroundColor: Colors.white, elevation: 0, - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), - title: const Text('确认删除'), - content: Text('确定要删除《${book.title}》吗?'), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + title: const Text( + '确认删除', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + content: Text( + '确定要删除《${book.title}》吗?删除后可在回收站恢复。', + style: const TextStyle( + fontSize: 14, + color: Color(0xFF666666), + height: 1.5, + ), + ), actions: [ TextButton( onPressed: () => Navigator.pop(context), - child: const Text('取消', style: TextStyle(color: Color(0xFF666666))), + style: TextButton.styleFrom( + foregroundColor: const Color(0xFF666666), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + ), + child: const Text('取消'), ), - TextButton( + ElevatedButton( onPressed: () async { await context.read().removeBook(book.id); Navigator.pop(context); ToastUtil.show(context, '已删除'); }, - child: const Text('删除', style: TextStyle(color: Colors.red)), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + foregroundColor: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + ), + child: const Text('删除'), ), ], + actionsPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), ), ); } diff --git a/lib/widgets/movie_list_item.dart b/lib/widgets/movie_list_item.dart index ed66687..2c8186d 100644 --- a/lib/widgets/movie_list_item.dart +++ b/lib/widgets/movie_list_item.dart @@ -133,23 +133,50 @@ class MovieListItem extends StatelessWidget { builder: (context) => AlertDialog( backgroundColor: Colors.white, elevation: 0, - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero), - title: const Text('确认删除'), - content: Text('确定要删除《${movie.title}》吗?'), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + title: const Text( + '确认删除', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + content: Text( + '确定要删除《${movie.title}》吗?删除后可在回收站恢复。', + style: const TextStyle( + fontSize: 14, + color: Color(0xFF666666), + height: 1.5, + ), + ), actions: [ TextButton( onPressed: () => Navigator.pop(context), - child: const Text('取消', style: TextStyle(color: Color(0xFF666666))), + style: TextButton.styleFrom( + foregroundColor: const Color(0xFF666666), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + ), + child: const Text('取消'), ), - TextButton( + ElevatedButton( onPressed: () async { await context.read().removeMovie(movie.id); Navigator.pop(context); ToastUtil.show(context, '已删除'); }, - child: const Text('删除', style: TextStyle(color: Colors.red)), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, + foregroundColor: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + ), + child: const Text('删除'), ), ], + actionsPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), ), ); }