import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as p; /// 图片路径管理助手 - 按分类和ID组织图片存储 /// /// 存储结构: /// images/movies/{movieId}/xxxx.jpg - 影视海报 /// images/movies/{movieId}/posterimgs/xxxx.jpg - 影视海报墙图片 /// images/books/{bookId}/xxxx.jpg - 书籍封面 /// images/notes/{noteId}/xxxx.jpg - 笔记图片 /// images/games/{gameId}/xxxx.jpg - 游戏封面 /// images/games/{gameId}/screenshots/xxxx.jpg - 游戏截图 /// images/people/{personId}/xxxx.jpg - 人物图片 class ImagePathHelper { static final ImagePathHelper instance = ImagePathHelper._init(); ImagePathHelper._init(); static String? _appDirPath; /// 获取应用数据根目录(Windows 下统一到 mooknote 子目录) /// 所有需要访问 images/、epub_books/ 等目录的代码都应使用此方法 static Future getAppDir() async { if (_appDirPath != null) return _appDirPath!; final appDir = await getApplicationDocumentsDirectory(); if (Platform.isWindows) { _appDirPath = p.join(appDir.path, 'mooknote'); } else { _appDirPath = appDir.path; } return _appDirPath!; } /// 获取图片根目录 Future get imagesRoot async { final appDir = await getAppDir(); return p.join(appDir, 'images'); } // ==================== 影视相关路径 ==================== /// 获取影视图片目录 /// 路径: images/movies/{movieId}/ Future getMovieImagesDir(String movieId) async { final root = await imagesRoot; return p.join(root, 'movies', movieId); } /// 获取影视海报路径 /// 路径: images/movies/{movieId}/{fileName} Future getMoviePosterPath(String movieId, String fileName) async { final dir = await getMovieImagesDir(movieId); return p.join(dir, fileName); } /// 获取影视海报墙目录 /// 路径: images/movies/{movieId}/posterimgs/ Future getMoviePosterImgsDir(String movieId) async { final dir = await getMovieImagesDir(movieId); return p.join(dir, 'posterimgs'); } /// 获取影视海报墙图片路径 /// 路径: images/movies/{movieId}/posterimgs/{fileName} Future getMoviePosterImgPath(String movieId, String fileName) async { final dir = await getMoviePosterImgsDir(movieId); return p.join(dir, fileName); } // ==================== 书籍相关路径 ==================== /// 获取书籍图片目录 /// 路径: images/books/{bookId}/ Future getBookImagesDir(String bookId) async { final root = await imagesRoot; return p.join(root, 'books', bookId); } /// 获取书籍封面路径 /// 路径: images/books/{bookId}/{fileName} Future getBookCoverPath(String bookId, String fileName) async { final dir = await getBookImagesDir(bookId); return p.join(dir, fileName); } // ==================== 笔记相关路径 ==================== /// 获取笔记图片目录 /// 路径: images/notes/{noteId}/ Future getNoteImagesDir(String noteId) async { final root = await imagesRoot; return p.join(root, 'notes', noteId); } /// 获取笔记图片路径 /// 路径: images/notes/{noteId}/{fileName} Future getNoteImagePath(String noteId, String fileName) async { final dir = await getNoteImagesDir(noteId); return p.join(dir, fileName); } // ==================== 游戏相关路径 ==================== /// 获取游戏图片目录 /// 路径: images/games/{gameId}/ Future getGameImagesDir(String gameId) async { final root = await imagesRoot; return p.join(root, 'games', gameId); } /// 获取游戏封面路径 /// 路径: images/games/{gameId}/{fileName} Future getGameCoverPath(String gameId, String fileName) async { final dir = await getGameImagesDir(gameId); return p.join(dir, fileName); } /// 获取游戏截图目录 /// 路径: images/games/{gameId}/screenshots/ Future getGameScreenshotImgsDir(String gameId) async { final dir = await getGameImagesDir(gameId); return p.join(dir, 'screenshots'); } /// 获取游戏截图图片路径 /// 路径: images/games/{gameId}/screenshots/{fileName} Future getGameScreenshotImgPath(String gameId, String fileName) async { final dir = await getGameScreenshotImgsDir(gameId); return p.join(dir, fileName); } // ==================== 人物相关路径 ==================== /// 获取人物图片目录 /// 路径: images/people/{personId}/ Future getPersonImagesDir(String personId) async { final root = await imagesRoot; return p.join(root, 'people', personId); } /// 获取人物图片路径 /// 路径: images/people/{personId}/{fileName} Future getPersonPhotoPath(String personId, String fileName) async { final dir = await getPersonImagesDir(personId); return p.join(dir, fileName); } // ==================== 目录操作 ==================== /// 确保目录存在 Future ensureDirExists(String dirPath) async { try { final dir = Directory(dirPath); if (!await dir.exists()) { await dir.create(recursive: true); } } catch (e) { debugPrint('[ImagePathHelper] ensureDirExists($dirPath) error: $e'); rethrow; } } /// 删除影视图片目录(包括海报和海报墙) /// 删除路径: images/movies/{movieId}/ Future deleteMovieImages(String movieId) async { final dirPath = await getMovieImagesDir(movieId); await _deleteDirectory(dirPath); } /// 删除书籍图片目录 /// 删除路径: images/books/{bookId}/ Future deleteBookImages(String bookId) async { final dirPath = await getBookImagesDir(bookId); await _deleteDirectory(dirPath); } /// 删除笔记图片目录 /// 删除路径: images/notes/{noteId}/ Future deleteNoteImages(String noteId) async { final dirPath = await getNoteImagesDir(noteId); await _deleteDirectory(dirPath); } /// 删除游戏图片目录 /// 删除路径: images/games/{gameId}/ Future deleteGameImages(String gameId) async { final dirPath = await getGameImagesDir(gameId); await _deleteDirectory(dirPath); } /// 删除人物图片目录 /// 删除路径: images/people/{personId}/ Future deletePersonImages(String personId) async { final dirPath = await getPersonImagesDir(personId); await _deleteDirectory(dirPath); } /// 删除目录及其内容 Future _deleteDirectory(String dirPath) async { try { final dir = Directory(dirPath); if (await dir.exists()) { await dir.delete(recursive: true); } } catch (e) { debugPrint('[ImagePathHelper] deleteDirectory($dirPath) error: $e'); rethrow; } } /// 移动文件到新位置 Future moveFile(String sourcePath, String targetDir, String fileName) async { try { await ensureDirExists(targetDir); final targetPath = p.join(targetDir, fileName); final sourceFile = File(sourcePath); if (await sourceFile.exists()) { await sourceFile.rename(targetPath); } return targetPath; } catch (e) { debugPrint('[ImagePathHelper] moveFile($sourcePath) error: $e'); rethrow; } } /// 复制文件到新位置 Future copyFile(String sourcePath, String targetDir, String fileName) async { try { await ensureDirExists(targetDir); final targetPath = p.join(targetDir, fileName); final sourceFile = File(sourcePath); if (await sourceFile.exists()) { await sourceFile.copy(targetPath); } return targetPath; } catch (e) { debugPrint('[ImagePathHelper] copyFile($sourcePath) error: $e'); rethrow; } } /// 删除单个文件 Future deleteFile(String filePath) async { try { final file = File(filePath); if (await file.exists()) { await file.delete(); } } catch (e) { debugPrint('[ImagePathHelper] deleteFile($filePath) error: $e'); rethrow; } } }