📊 数据持久化阶段完成: - 完成4个数据模型的Hive集成(Book, Bookshelf, Bookmark, Highlight) - 实现4个Repository数据访问层 - 生成5个TypeAdapter自动序列化文件 - 完成所有模型的CRUD操作和测试验证 📚 项目文档更新: - 新增数据持久化阶段完成总结文档 - 更新CLAUDE.md项目主文档 - 完善项目结构说明和开发进度 🚀 UI开发阶段规划: - 定义产品定位:类似微信读书的Material Design电子书阅读器 - 制定4阶段开发计划:UI基础架构→顶部导航→首页内容→数据集成 - 明确页面结构:底部Tab导航(首页/书库/统计/我的) - 规划核心功能:搜索、导入、最近阅读、摘录列表 🎯 下一里程碑: - 开始UI基础架构搭建 - 实现底部Tab导航和Material Design主题系统 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
280 lines
7.7 KiB
Dart
280 lines
7.7 KiB
Dart
import 'package:hive/hive.dart';
|
||
|
||
part 'bookshelf.g.dart';
|
||
|
||
@HiveType(typeId: 3)
|
||
///书架类型
|
||
enum BookshelfType {
|
||
@HiveField(0)
|
||
system, //系统默认书架
|
||
@HiveField(1)
|
||
custom //用户自定义书架
|
||
}
|
||
|
||
@HiveType(typeId: 4)
|
||
/// 书架数据模型
|
||
class Bookshelf {
|
||
@HiveField(0)
|
||
final String id; // 唯一标识
|
||
|
||
@HiveField(1)
|
||
final String name; // 书架名称
|
||
|
||
@HiveField(2)
|
||
final String? description; // 书架描述
|
||
|
||
@HiveField(3)
|
||
final String? coverImagePath; // 书架封面
|
||
|
||
@HiveField(4)
|
||
final DateTime createdTime; // 创建时间
|
||
|
||
@HiveField(5)
|
||
final DateTime lastModifiedTime; // 最后修改时间
|
||
|
||
@HiveField(6)
|
||
final int bookCount; // 书籍数量
|
||
|
||
@HiveField(7)
|
||
final BookshelfType type; // 书架类型
|
||
|
||
@HiveField(8)
|
||
final bool isDefault; // 是否为默认书架
|
||
|
||
@HiveField(9)
|
||
final int sortOrder; // 排序顺序
|
||
|
||
// 构造函数
|
||
const Bookshelf(
|
||
{required this.id,
|
||
required this.name,
|
||
this.description,
|
||
this.coverImagePath,
|
||
required this.createdTime,
|
||
required this.lastModifiedTime,
|
||
required this.bookCount,
|
||
required this.type,
|
||
required this.isDefault,
|
||
required this.sortOrder});
|
||
|
||
// copyWith方法...
|
||
Bookshelf copyWith(
|
||
{String? id,
|
||
String? name,
|
||
String? description,
|
||
String? coverImagePath,
|
||
DateTime? createdTime,
|
||
DateTime? lastModifiedTime,
|
||
int? bookCount,
|
||
BookshelfType? type,
|
||
bool? isDefault,
|
||
int? sortOrder}) {
|
||
return Bookshelf(
|
||
id: id ?? this.id, // 如果id不为null就使用新值,否则保持原值
|
||
name: name ?? this.name,
|
||
description: description ?? this.description,
|
||
coverImagePath: coverImagePath ?? this.coverImagePath,
|
||
createdTime: createdTime ?? this.createdTime,
|
||
lastModifiedTime: lastModifiedTime ?? this.lastModifiedTime,
|
||
bookCount: bookCount ?? this.bookCount,
|
||
type: type ?? this.type,
|
||
isDefault: isDefault ?? this.isDefault,
|
||
sortOrder: sortOrder ?? this.sortOrder);
|
||
}
|
||
|
||
// toMap、fromMap、
|
||
/// toMap方法 - 将对象转换为Map
|
||
Map<String, dynamic> toMap() {
|
||
return {
|
||
'id': id,
|
||
'name': name,
|
||
'description': description,
|
||
'coverImagePath': coverImagePath,
|
||
'createdTime': createdTime.toIso8601String(),
|
||
'lastModifiedTime': lastModifiedTime.toIso8601String(),
|
||
'bookCount': bookCount,
|
||
'type': type.name,
|
||
'isDefault': isDefault,
|
||
'sortOrder': sortOrder
|
||
};
|
||
}
|
||
|
||
/// fromMap构造函数
|
||
factory Bookshelf.fromMap(Map<String, dynamic> map) {
|
||
return Bookshelf(
|
||
id: map['id'],
|
||
name: map['name'],
|
||
description: map['description'],
|
||
coverImagePath: map['coverImagePath'],
|
||
createdTime: DateTime.parse(map['createdTime']),
|
||
lastModifiedTime: DateTime.parse(map['lastModifiedTime']),
|
||
bookCount: map['bookCount'],
|
||
type: BookshelfType.values.firstWhere((e) => e.name == map['type']),
|
||
isDefault: map['isDefault'],
|
||
sortOrder: map['sortOrder']);
|
||
}
|
||
|
||
// 工厂方法
|
||
factory Bookshelf.create({
|
||
required String name,
|
||
BookshelfType type = BookshelfType.custom,
|
||
String? description,
|
||
}) {
|
||
return Bookshelf(
|
||
id: _generateId(),
|
||
name: name,
|
||
type: type,
|
||
createdTime: DateTime.now(),
|
||
lastModifiedTime: DateTime.now(),
|
||
bookCount: 0,
|
||
sortOrder: 0,
|
||
isDefault: false,
|
||
description: description,
|
||
);
|
||
}
|
||
|
||
// 创建系统书架的便利方法
|
||
factory Bookshelf.createSystem({
|
||
required String name,
|
||
String? description,
|
||
}) {
|
||
return Bookshelf(
|
||
id: _generateSystemId(name),
|
||
name: name,
|
||
type: BookshelfType.system,
|
||
isDefault: true,
|
||
createdTime: DateTime.now(),
|
||
lastModifiedTime: DateTime.now(),
|
||
bookCount: 0,
|
||
sortOrder: 0,
|
||
description: description,
|
||
);
|
||
}
|
||
|
||
/// 生成唯一ID的私有方法
|
||
/// 用于用户自定义书架
|
||
static String _generateId() {
|
||
return 'shelf_${DateTime.now().millisecondsSinceEpoch}_${DateTime.now().microsecond}';
|
||
}
|
||
|
||
/// 生成系统书架ID的私有方法
|
||
/// 基于书架名称生成可预测的ID,确保应用重启后ID保持一致
|
||
static String _generateSystemId(String name) {
|
||
// 清理名称:移除空格和特殊字符,保留中文、英文、数字
|
||
final cleanName = name
|
||
.replaceAll(RegExp(r'[^a-zA-Z0-9\u4e00-\u9fff]'), '') // 保留中文、英文、数字
|
||
.toLowerCase();
|
||
return 'system_$cleanName'; // 添加前缀区分系统书架
|
||
}
|
||
|
||
/// 重写equals和hashCode,用于对象比较
|
||
@override
|
||
bool operator ==(Object other) {
|
||
if (identical(this, other)) return true;
|
||
return other is Bookshelf && other.id == id;
|
||
}
|
||
|
||
@override
|
||
int get hashCode => id.hashCode;
|
||
|
||
/// 重写toString方法,便于调试
|
||
@override
|
||
String toString() {
|
||
final typeInfo = type == BookshelfType.system ? '[系统]' : '[自定义]';
|
||
return 'Bookshelf$typeInfo(id: $id, name: $name, books: $bookCount)';
|
||
}
|
||
|
||
/// 计算属性:检查是否为系统书架
|
||
bool get isSystemShelf => type == BookshelfType.system;
|
||
|
||
/// 计算属性:检查是否为用户自定义书架
|
||
bool get isCustomShelf => type == BookshelfType.custom;
|
||
|
||
/// 计算属性:检查是否有描述
|
||
bool get hasDescription => description != null && description!.isNotEmpty;
|
||
|
||
/// 计算属性:检查是否有封面图片
|
||
bool get hasCoverImage => coverImagePath != null && coverImagePath!.isNotEmpty;
|
||
|
||
/// 计算属性:检查书架是否为空
|
||
bool get isEmpty => bookCount == 0;
|
||
|
||
/// 计算属性:获取书籍数量的显示文本
|
||
String get bookCountDisplay {
|
||
if (bookCount == 0) return '暂无书籍';
|
||
if (bookCount == 1) return '1本书';
|
||
return '$bookCount本书';
|
||
}
|
||
|
||
/// 便利方法:更新书籍数量
|
||
/// 通常在添加或删除书籍时调用
|
||
Bookshelf updateBookCount(int newCount) {
|
||
return copyWith(
|
||
bookCount: newCount,
|
||
lastModifiedTime: DateTime.now(), // 更新修改时间
|
||
);
|
||
}
|
||
|
||
/// 便利方法:增加书籍数量
|
||
Bookshelf incrementBookCount({int increment = 1}) {
|
||
return copyWith(
|
||
bookCount: bookCount + increment,
|
||
lastModifiedTime: DateTime.now(),
|
||
);
|
||
}
|
||
|
||
/// 便利方法:减少书籍数量
|
||
Bookshelf decrementBookCount({int decrement = 1}) {
|
||
final newCount = (bookCount - decrement).clamp(0, bookCount);
|
||
return copyWith(
|
||
bookCount: newCount,
|
||
lastModifiedTime: DateTime.now(),
|
||
);
|
||
}
|
||
|
||
/// 便利方法:更新书架信息
|
||
Bookshelf updateInfo({
|
||
String? name,
|
||
String? description,
|
||
String? coverImagePath,
|
||
}) {
|
||
return copyWith(
|
||
name: name ?? this.name,
|
||
description: description ?? this.description,
|
||
coverImagePath: coverImagePath ?? this.coverImagePath,
|
||
lastModifiedTime: DateTime.now(),
|
||
);
|
||
}
|
||
|
||
/// 静态方法:创建默认的系统书架集合
|
||
/// 应用启动时调用,创建必要的系统书架
|
||
static List<Bookshelf> createDefaultSystemShelves() {
|
||
return [
|
||
Bookshelf.createSystem(
|
||
name: '全部书籍',
|
||
description: '包含所有导入的电子书',
|
||
),
|
||
Bookshelf.createSystem(
|
||
name: '最近阅读',
|
||
description: '最近打开过的书籍',
|
||
),
|
||
Bookshelf.createSystem(
|
||
name: '收藏',
|
||
description: '用户收藏的书籍',
|
||
),
|
||
Bookshelf.createSystem(
|
||
name: '阅读中',
|
||
description: '正在阅读的书籍',
|
||
),
|
||
Bookshelf.createSystem(
|
||
name: '已完成',
|
||
description: '已经读完的书籍',
|
||
),
|
||
Bookshelf.createSystem(
|
||
name: '待阅读',
|
||
description: '计划阅读的书籍',
|
||
),
|
||
];
|
||
}
|
||
}
|