import 'package:hive/hive.dart'; part 'book.g.dart'; // 电子书数据模型 // 这是Flutter中数据模型的标准写法,后续其他模型都可以参考这个结构 /// 书籍文件格式枚举 /// 使用enum提供类型安全的枚举值 @HiveType(typeId: 0) enum BookFormat { @HiveField(0) epub, // EPUB格式电子书 @HiveField(1) mobi, // Kindle MOBI格式 @HiveField(2) txt, // 纯文本格式 @HiveField(3) pdf // PDF格式 } /// 阅读状态枚举 @HiveType(typeId: 1) enum ReadingStatus { @HiveField(0) reading, // 阅读中 @HiveField(1) completed, // 已完成 @HiveField(2) pending // 待阅读 } /// 书籍数据模型 /// /// 设计原则: /// 1. 所有字段都是final(不可变性) /// 2. 提供copyWith方法创建新对象 /// 3. 提供序列化和反序列化方法 /// 4. 使用空值安全语法 @HiveType(typeId: 2) class Book { /// 唯一标识符 - 使用UUID确保全局唯一 @HiveField(0) final String id; /// 书名 - 必需字段 @HiveField(1) final String title; /// 作者 - 可为null(因为有些书籍可能没有作者信息) @HiveField(2) final String? author; /// 出版社 - 可选字段 @HiveField(3) final String? publisher; /// 书籍简介 - 可选字段 @HiveField(4) final String? description; /// 封面图片路径 - 可选字段 @HiveField(5) final String? coverImagePath; /// 文件路径 - 必需字段,指向实际的电子书文件 @HiveField(6) final String filePath; /// 文件格式 - 必需字段 @HiveField(7) final BookFormat format; /// 文件大小(字节)- 必需字段 @HiveField(8) final int fileSize; /// 添加到书架的时间 - 必需字段 @HiveField(9) final DateTime addedDate; /// 阅读状态 - 必需字段 @HiveField(10) final ReadingStatus status; /// 评分(1-5星)- 可选字段 @HiveField(11) final double? rating; /// 标签列表 - 使用空列表作为默认值,避免null指针 @HiveField(12) final List tags; /// 总页数 - 必需字段 @HiveField(13) final int totalPages; /// 构造函数 /// /// 使用required关键字标记必需字段,这是Flutter的空值安全特性 const Book({ required this.id, // 必需 required this.title, // 必需 this.author, // 可选 this.publisher, // 可选 this.description, // 可选 this.coverImagePath, // 可选 required this.filePath, // 必需 required this.format, // 必需 required this.fileSize, // 必需 required this.addedDate, // 必需 required this.status, // 必需 this.rating, // 可选 this.tags = const [], // 默认空列表,避免null required this.totalPages, // 必需 }); /// copyWith方法 - 创建对象的副本 /// /// 这是Flutter中不可变对象的标准模式 /// 当需要修改对象时,不是直接修改原对象,而是创建一个新对象 /// /// 使用示例: /// ```dart /// final newBook = book.copyWith( /// title: "新书名", /// status: ReadingStatus.completed, /// ); /// ``` Book copyWith({ String? id, String? title, String? author, String? publisher, String? description, String? coverImagePath, String? filePath, BookFormat? format, int? fileSize, DateTime? addedDate, ReadingStatus? status, double? rating, List? tags, int? totalPages, }) { return Book( id: id ?? this.id, // 如果id不为null就使用新值,否则保持原值 title: title ?? this.title, author: author ?? this.author, publisher: publisher ?? this.publisher, description: description ?? this.description, coverImagePath: coverImagePath ?? this.coverImagePath, filePath: filePath ?? this.filePath, format: format ?? this.format, fileSize: fileSize ?? this.fileSize, addedDate: addedDate ?? this.addedDate, status: status ?? this.status, rating: rating ?? this.rating, tags: tags ?? this.tags, totalPages: totalPages ?? this.totalPages, ); } /// toMap方法 - 将对象转换为Map /// /// 这个方法用于: /// 1. 本地存储(如Hive数据库) /// 2. 网络传输(转换为JSON) /// 3. 状态保存 Map toMap() { return { 'id': id, 'title': title, 'author': author, 'publisher': publisher, 'description': description, 'coverImagePath': coverImagePath, 'filePath': filePath, 'format': format.name, // 枚举值转换为字符串 'fileSize': fileSize, 'addedDate': addedDate.toIso8601String(), // DateTime转换为字符串 'status': status.name, 'rating': rating, 'tags': tags, // List直接存储 'totalPages': totalPages, }; } /// fromMap构造函数 - 从Map创建Book对象 /// /// 这是toMap的逆操作,用于: /// 1. 从本地存储中读取数据 /// 2. 从网络请求中解析数据 /// 3. 从保存的状态中恢复对象 factory Book.fromMap(Map map) { return Book( id: map['id'], title: map['title'], author: map['author'], publisher: map['publisher'], description: map['description'], coverImagePath: map['coverImagePath'], filePath: map['filePath'], format: BookFormat.values.firstWhere( // 字符串转换回枚举 (e) => e.name == map['format'], ), fileSize: map['fileSize'], addedDate: DateTime.parse(map['addedDate']), status: ReadingStatus.values.firstWhere( (e) => e.name == map['status'], ), rating: map['rating'], tags: List.from(map['tags'] ?? []), // 确保返回List totalPages: map['totalPages'], ); } /// 创建一个新Book实例的工厂方法 /// /// 这是一个便利方法,用于创建基本的Book对象 /// 通常在用户导入新书籍时使用 factory Book.create({ required String title, required String filePath, required BookFormat format, required int fileSize, String? author, int totalPages = 0, }) { return Book( id: _generateId(), // 生成唯一ID title: title, author: author, filePath: filePath, format: format, fileSize: fileSize, totalPages: totalPages, addedDate: DateTime.now(), // 当前时间作为添加时间 status: ReadingStatus.pending, // 默认状态为待阅读 ); } /// 生成唯一ID的私有方法 static String _generateId() { return '${DateTime.now().millisecondsSinceEpoch}_${(DateTime.now().microsecond).toString()}'; } /// 重写toString方法,便于调试 @override String toString() { return 'Book(id: $id, title: $title, author: $author, format: $format)'; } /// 重写equals和hashCode,用于对象比较 @override bool operator ==(Object other) { if (identical(this, other)) return true; return other is Book && other.id == id; } @override int get hashCode => id.hashCode; }