📊 数据持久化阶段完成: - 完成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>
258 lines
6.9 KiB
Dart
258 lines
6.9 KiB
Dart
import 'package:hive/hive.dart';
|
||
|
||
part 'highlight.g.dart';
|
||
|
||
///高亮模型
|
||
|
||
/// 不同颜色的高亮
|
||
@HiveType(typeId: 6)
|
||
enum HighlightColor {
|
||
@HiveField(0)
|
||
yellow, // 黄色 - 默认高亮
|
||
|
||
@HiveField(1)
|
||
orange, // 橙色 - 重要内容
|
||
|
||
@HiveField(2)
|
||
green, // 绿色 - 已理解内容
|
||
|
||
@HiveField(3)
|
||
blue, // 蓝色 - 需要复习
|
||
|
||
@HiveField(4)
|
||
pink // 粉色 - 个人感想
|
||
}
|
||
|
||
/// 批注类型枚举
|
||
/// 用于分类不同类型的批注内容
|
||
@HiveType(typeId: 7)
|
||
enum AnnotationType {
|
||
@HiveField(0)
|
||
note, // 笔记 - 记录知识点
|
||
|
||
@HiveField(1)
|
||
thought, // 感想 - 个人想法
|
||
|
||
@HiveField(2)
|
||
summary, // 摘要 - 内容总结
|
||
|
||
@HiveField(3)
|
||
question // 问题 - 疑问记录
|
||
}
|
||
|
||
///高亮模型
|
||
// 关联书籍和章节
|
||
// 记录选中的文本范围
|
||
// 支持不同颜色的高亮
|
||
// 记录创建时间
|
||
@HiveType(typeId: 8)
|
||
class Highlight {
|
||
//唯一标识符 - 使用UUID确保全局唯一
|
||
@HiveField(0)
|
||
final String id;
|
||
|
||
//对应的书籍id
|
||
@HiveField(1)
|
||
final String bookId;
|
||
|
||
// 对应章节id
|
||
@HiveField(2)
|
||
final String? chapterId;
|
||
|
||
// 选中文本
|
||
@HiveField(3)
|
||
final String selectedText;
|
||
|
||
// 开始索引
|
||
@HiveField(4)
|
||
final int startIndex;
|
||
|
||
// 结尾索引
|
||
@HiveField(5)
|
||
final int endIndex;
|
||
|
||
// 高亮颜色
|
||
@HiveField(6)
|
||
final HighlightColor color;
|
||
|
||
// 创建时间
|
||
@HiveField(7)
|
||
final DateTime createdTime;
|
||
|
||
/// 批注内容 - 可选字段,用于存储用户对高亮的注释
|
||
@HiveField(8)
|
||
final String? annotation;
|
||
|
||
/// 批注类型 - 可选字段,用于分类批注
|
||
@HiveField(9)
|
||
final AnnotationType? annotationType;
|
||
|
||
/// 批注添加时间 - 可选字段,记录批注的最后修改时间
|
||
@HiveField(10)
|
||
final DateTime? annotationTime;
|
||
|
||
const Highlight({
|
||
required this.id,
|
||
required this.bookId,
|
||
this.chapterId,
|
||
required this.selectedText,
|
||
required this.startIndex,
|
||
required this.endIndex,
|
||
required this.color,
|
||
required this.createdTime,
|
||
this.annotation, // 批注内容
|
||
this.annotationType, // 批注类型
|
||
this.annotationTime, // 批注时间
|
||
});
|
||
|
||
/// copyWith方法 - 创建对象的副本
|
||
Highlight copyWith({
|
||
String? id,
|
||
String? bookId,
|
||
String? chapterId,
|
||
String? selectedText,
|
||
int? startIndex,
|
||
int? endIndex,
|
||
HighlightColor? color,
|
||
DateTime? createdTime,
|
||
String? annotation,
|
||
AnnotationType? annotationType,
|
||
DateTime? annotationTime,
|
||
}) {
|
||
return Highlight(
|
||
id: id ?? this.id,
|
||
bookId: bookId ?? this.bookId,
|
||
chapterId: chapterId ?? this.chapterId,
|
||
selectedText: selectedText ?? this.selectedText,
|
||
startIndex: startIndex ?? this.startIndex,
|
||
endIndex: endIndex ?? this.endIndex,
|
||
color: color ?? this.color,
|
||
createdTime: createdTime ?? this.createdTime,
|
||
annotation: annotation ?? this.annotation,
|
||
annotationType: annotationType ?? this.annotationType,
|
||
annotationTime: annotationTime ?? this.annotationTime,
|
||
);
|
||
}
|
||
|
||
/// toMap方法 - 将对象转换为Map
|
||
Map<String, dynamic> toMap() {
|
||
return {
|
||
'id': id,
|
||
'bookId': bookId,
|
||
'chapterId': chapterId,
|
||
'selectedText': selectedText,
|
||
'startIndex': startIndex,
|
||
'endIndex': endIndex,
|
||
'color': color.name, // 枚举值转换为字符串
|
||
'createdTime': createdTime.toIso8601String(), // DateTime转换为字符串
|
||
'annotation': annotation,
|
||
'annotationType': annotationType?.name, // 枚举转换为字符串,注意可能是null
|
||
'annotationTime':
|
||
annotationTime?.toIso8601String(), // DateTime转换为字符串,注意可能是null
|
||
};
|
||
}
|
||
|
||
/// fromMap构造函数 - 从Map创建Highlight对象
|
||
factory Highlight.fromMap(Map<String, dynamic> map) {
|
||
return Highlight(
|
||
id: map['id'],
|
||
bookId: map['bookId'],
|
||
chapterId: map['chapterId'],
|
||
selectedText: map['selectedText'],
|
||
startIndex: map['startIndex'],
|
||
endIndex: map['endIndex'],
|
||
color: HighlightColor.values.firstWhere((e) => e.name == map['color']),
|
||
createdTime: DateTime.parse(map['createdTime']),
|
||
annotation: map['annotation'], // 批注内容直接取值
|
||
annotationType: map['annotationType'] != null
|
||
? AnnotationType.values
|
||
.firstWhere((e) => e.name == map['annotationType'])
|
||
: null, // 处理可选的枚举字段
|
||
annotationTime: map['annotationTime'] != null
|
||
? DateTime.parse(map['annotationTime'])
|
||
: null, // 处理可选的DateTime字段
|
||
);
|
||
}
|
||
|
||
/// 创建一个新Highlight实例的工厂方法
|
||
/// 这是一个便利方法,用于创建基本的高亮对象
|
||
/// 通常在用户选中文本时使用
|
||
factory Highlight.create({
|
||
required String bookId,
|
||
required String selectedText,
|
||
required int startIndex,
|
||
required int endIndex,
|
||
HighlightColor color = HighlightColor.yellow, // 默认颜色
|
||
String? chapterId,
|
||
}) {
|
||
return Highlight(
|
||
id: _generateId(), // 生成唯一ID
|
||
bookId: bookId,
|
||
chapterId: chapterId,
|
||
selectedText: selectedText,
|
||
startIndex: startIndex,
|
||
endIndex: endIndex,
|
||
color: color,
|
||
createdTime: DateTime.now(), // 当前时间作为创建时间
|
||
);
|
||
}
|
||
|
||
/// 生成唯一ID的私有方法
|
||
static String _generateId() {
|
||
return '${DateTime.now().millisecondsSinceEpoch}_${(DateTime.now().microsecond).toString()}';
|
||
}
|
||
|
||
/// 重写equals和hashCode,用于对象比较
|
||
@override
|
||
bool operator ==(Object other) {
|
||
if (identical(this, other)) return true;
|
||
return other is Highlight && other.id == id;
|
||
}
|
||
|
||
@override
|
||
int get hashCode => id.hashCode;
|
||
|
||
/// 计算属性:检查是否有批注
|
||
bool get hasAnnotation => annotation != null && annotation!.isNotEmpty;
|
||
|
||
/// 计算属性:获取批注文本长度
|
||
int get annotationLength => annotation?.length ?? 0;
|
||
|
||
/// 添加批注的方法
|
||
/// 返回一个新的Highlight对象,包含指定的批注内容
|
||
Highlight addAnnotation(String content, AnnotationType type) {
|
||
return copyWith(
|
||
annotation: content,
|
||
annotationType: type,
|
||
annotationTime: DateTime.now(), // 设置当前时间为批注时间
|
||
);
|
||
}
|
||
|
||
/// 更新批注内容的方法
|
||
/// 返回一个新的Highlight对象,包含更新的批注内容
|
||
Highlight updateAnnotation(String content, AnnotationType type) {
|
||
return copyWith(
|
||
annotation: content,
|
||
annotationType: type,
|
||
annotationTime: DateTime.now(), // 更新批注时间
|
||
);
|
||
}
|
||
|
||
/// 移除批注的方法
|
||
/// 返回一个新的Highlight对象,移除所有批注相关字段
|
||
Highlight removeAnnotation() {
|
||
return copyWith(
|
||
annotation: null,
|
||
annotationType: null,
|
||
annotationTime: null,
|
||
);
|
||
}
|
||
|
||
/// 重写toString方法,增加批注信息显示
|
||
@override
|
||
String toString() {
|
||
final annotationInfo = hasAnnotation ? ' [批注: $annotation]' : '';
|
||
return 'Highlight(id: $id, bookId: $bookId, text: "$selectedText"$annotationInfo)';
|
||
}
|
||
}
|