generated from dellevin/template
691 lines
19 KiB
Dart
691 lines
19 KiB
Dart
import 'dart:io';
|
||
import 'dart:convert';
|
||
|
||
/// 用于区分 copyWith 中"未传参数"和"传了 null"的标记
|
||
class _CopyWithNullSentinel {
|
||
const _CopyWithNullSentinel();
|
||
}
|
||
const _copyWithNull = _CopyWithNullSentinel();
|
||
|
||
/// 影视条目模型
|
||
class Movie {
|
||
final String id;
|
||
final String title; // 影视名称
|
||
final String? posterPath; // 本地海报路径
|
||
final DateTime? releaseDate; // 上映时间
|
||
final List<String> directors; // 导演列表
|
||
final List<String> writers; // 编剧列表
|
||
final List<String> actors; // 主演列表
|
||
final List<String> genres; // 类型
|
||
final List<String> alternateTitles; // 别名
|
||
final String? summary; // 剧情简介
|
||
final double? rating; // 评分 1-10
|
||
final String status; // watched/want_to_watch/watching
|
||
final DateTime? watchDate; // 观看日期
|
||
final DateTime createdAt;
|
||
final DateTime updatedAt;
|
||
final bool isDeleted;
|
||
|
||
Movie({
|
||
required this.id,
|
||
required this.title,
|
||
this.posterPath,
|
||
this.releaseDate,
|
||
this.directors = const [],
|
||
this.writers = const [],
|
||
this.actors = const [],
|
||
this.genres = const [],
|
||
this.alternateTitles = const [],
|
||
this.summary,
|
||
this.rating,
|
||
required this.status,
|
||
this.watchDate,
|
||
required this.createdAt,
|
||
required this.updatedAt,
|
||
this.isDeleted = false,
|
||
});
|
||
|
||
factory Movie.fromJson(Map<String, dynamic> json) {
|
||
return Movie(
|
||
id: json['id'] ?? '',
|
||
title: json['title'] ?? '',
|
||
posterPath: json['poster_path'],
|
||
releaseDate: json['release_date'] != null
|
||
? DateTime.parse(json['release_date'])
|
||
: null,
|
||
directors: _parseStringList(json['directors']),
|
||
writers: _parseStringList(json['writers']),
|
||
actors: _parseStringList(json['actors']),
|
||
genres: _parseStringList(json['genres']),
|
||
alternateTitles: _parseStringList(json['alternate_titles']),
|
||
summary: json['summary'],
|
||
rating: json['rating']?.toDouble(),
|
||
status: json['status'] ?? 'want_to_watch',
|
||
watchDate: json['watch_date'] != null
|
||
? DateTime.parse(json['watch_date'])
|
||
: null,
|
||
createdAt: json['created_at'] != null
|
||
? DateTime.parse(json['created_at'])
|
||
: DateTime.now(),
|
||
updatedAt: json['updated_at'] != null
|
||
? DateTime.parse(json['updated_at'])
|
||
: DateTime.now(),
|
||
isDeleted: json['is_deleted'] == 1 || json['is_deleted'] == true,
|
||
);
|
||
}
|
||
|
||
Map<String, dynamic> toJson() {
|
||
return {
|
||
'id': id,
|
||
'title': title,
|
||
'poster_path': posterPath,
|
||
'release_date': releaseDate?.toUtc().toIso8601String(),
|
||
'directors': jsonEncode(directors),
|
||
'writers': jsonEncode(writers),
|
||
'actors': jsonEncode(actors),
|
||
'genres': jsonEncode(genres),
|
||
'alternate_titles': jsonEncode(alternateTitles),
|
||
'summary': summary,
|
||
'rating': rating,
|
||
'status': status,
|
||
'watch_date': watchDate?.toUtc().toIso8601String(),
|
||
'created_at': createdAt.toUtc().toIso8601String(),
|
||
'updated_at': updatedAt.toUtc().toIso8601String(),
|
||
'is_deleted': isDeleted ? 1 : 0,
|
||
};
|
||
}
|
||
|
||
/// 获取封面文件
|
||
File? get posterFile {
|
||
if (posterPath == null || posterPath!.isEmpty) return null;
|
||
return File(posterPath!);
|
||
}
|
||
|
||
/// 解析字符串列表(公共静态方法,供Book使用)
|
||
static List<String> parseStringList(dynamic data) {
|
||
if (data == null) return [];
|
||
if (data is List) {
|
||
return data.map((e) => e.toString()).toList();
|
||
}
|
||
if (data is String) {
|
||
try {
|
||
// 尝试解析JSON字符串
|
||
final decoded = jsonDecode(data);
|
||
if (decoded is List) {
|
||
return decoded.map((e) => e.toString()).toList();
|
||
}
|
||
} catch (e) {
|
||
// 如果解析失败,按逗号分割
|
||
return data.split(',').map((s) => s.trim()).where((s) => s.isNotEmpty).toList();
|
||
}
|
||
}
|
||
return [];
|
||
}
|
||
|
||
/// 解析字符串列表(私有别名,保持兼容性)
|
||
static List<String> _parseStringList(dynamic data) => parseStringList(data);
|
||
|
||
/// 复制并修改
|
||
Movie copyWith({
|
||
String? id,
|
||
String? title,
|
||
Object? posterPath = _copyWithNull,
|
||
DateTime? releaseDate,
|
||
List<String>? directors,
|
||
List<String>? writers,
|
||
List<String>? actors,
|
||
List<String>? genres,
|
||
List<String>? alternateTitles,
|
||
Object? summary = _copyWithNull,
|
||
double? rating,
|
||
String? status,
|
||
DateTime? watchDate,
|
||
DateTime? createdAt,
|
||
DateTime? updatedAt,
|
||
bool? isDeleted,
|
||
}) {
|
||
return Movie(
|
||
id: id ?? this.id,
|
||
title: title ?? this.title,
|
||
posterPath: posterPath is _CopyWithNullSentinel ? this.posterPath : (posterPath as String?),
|
||
releaseDate: releaseDate ?? this.releaseDate,
|
||
directors: directors ?? this.directors,
|
||
writers: writers ?? this.writers,
|
||
actors: actors ?? this.actors,
|
||
genres: genres ?? this.genres,
|
||
alternateTitles: alternateTitles ?? this.alternateTitles,
|
||
summary: summary is _CopyWithNullSentinel ? this.summary : (summary as String?),
|
||
rating: rating ?? this.rating,
|
||
status: status ?? this.status,
|
||
watchDate: watchDate ?? this.watchDate,
|
||
createdAt: createdAt ?? this.createdAt,
|
||
updatedAt: updatedAt ?? this.updatedAt,
|
||
isDeleted: isDeleted ?? this.isDeleted,
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 书籍条目模型
|
||
class Book {
|
||
final String id;
|
||
final String title; // 书籍名称
|
||
final String? coverPath; // 本地封面路径
|
||
final List<String> authors; // 作者列表
|
||
final List<String> alternateTitles; // 别名
|
||
final String? publisher; // 出版社
|
||
final List<String> genres; // 类型
|
||
final String? summary; // 书籍简介
|
||
final double? rating; // 评分 1-10
|
||
final String status; // read/reading/want_to_read
|
||
final String? isbn; // ISBN编号
|
||
final DateTime? publishDate; // 出版时间
|
||
final DateTime createdAt;
|
||
final DateTime updatedAt;
|
||
final bool isDeleted;
|
||
|
||
Book({
|
||
required this.id,
|
||
required this.title,
|
||
this.coverPath,
|
||
this.authors = const [],
|
||
this.alternateTitles = const [],
|
||
this.publisher,
|
||
this.genres = const [],
|
||
this.summary,
|
||
this.rating,
|
||
required this.status,
|
||
this.isbn,
|
||
this.publishDate,
|
||
required this.createdAt,
|
||
required this.updatedAt,
|
||
this.isDeleted = false,
|
||
});
|
||
|
||
factory Book.fromJson(Map<String, dynamic> json) {
|
||
return Book(
|
||
id: json['id'] ?? '',
|
||
title: json['title'] ?? '',
|
||
coverPath: json['cover_path'],
|
||
authors: Movie.parseStringList(json['authors']),
|
||
alternateTitles: Movie.parseStringList(json['alternate_titles']),
|
||
publisher: json['publisher'],
|
||
genres: Movie.parseStringList(json['genres']),
|
||
summary: json['summary'],
|
||
rating: json['rating']?.toDouble(),
|
||
status: json['status'] ?? 'want_to_read',
|
||
isbn: json['isbn'],
|
||
publishDate: json['publish_date'] != null
|
||
? DateTime.parse(json['publish_date'])
|
||
: null,
|
||
createdAt: json['created_at'] != null
|
||
? DateTime.parse(json['created_at'])
|
||
: DateTime.now(),
|
||
updatedAt: json['updated_at'] != null
|
||
? DateTime.parse(json['updated_at'])
|
||
: DateTime.now(),
|
||
isDeleted: json['is_deleted'] == 1 || json['is_deleted'] == true,
|
||
);
|
||
}
|
||
|
||
Map<String, dynamic> toJson() {
|
||
return {
|
||
'id': id,
|
||
'title': title,
|
||
'cover_path': coverPath,
|
||
'authors': jsonEncode(authors),
|
||
'alternate_titles': jsonEncode(alternateTitles),
|
||
'publisher': publisher,
|
||
'genres': jsonEncode(genres),
|
||
'summary': summary,
|
||
'rating': rating,
|
||
'status': status,
|
||
'isbn': isbn,
|
||
'publish_date': publishDate?.toUtc().toIso8601String(),
|
||
'created_at': createdAt.toUtc().toIso8601String(),
|
||
'updated_at': updatedAt.toUtc().toIso8601String(),
|
||
'is_deleted': isDeleted ? 1 : 0,
|
||
};
|
||
}
|
||
|
||
/// 获取封面文件
|
||
File? get coverFile {
|
||
if (coverPath == null || coverPath!.isEmpty) return null;
|
||
return File(coverPath!);
|
||
}
|
||
|
||
/// 复制并修改
|
||
Book copyWith({
|
||
String? id,
|
||
String? title,
|
||
Object? coverPath = _copyWithNull,
|
||
List<String>? authors,
|
||
List<String>? alternateTitles,
|
||
String? publisher,
|
||
List<String>? genres,
|
||
Object? summary = _copyWithNull,
|
||
double? rating,
|
||
String? status,
|
||
Object? isbn = _copyWithNull,
|
||
DateTime? publishDate,
|
||
DateTime? createdAt,
|
||
DateTime? updatedAt,
|
||
bool? isDeleted,
|
||
}) {
|
||
return Book(
|
||
id: id ?? this.id,
|
||
title: title ?? this.title,
|
||
coverPath: coverPath is _CopyWithNullSentinel ? this.coverPath : (coverPath as String?),
|
||
authors: authors ?? this.authors,
|
||
alternateTitles: alternateTitles ?? this.alternateTitles,
|
||
publisher: publisher ?? this.publisher,
|
||
genres: genres ?? this.genres,
|
||
summary: summary is _CopyWithNullSentinel ? this.summary : (summary as String?),
|
||
rating: rating ?? this.rating,
|
||
status: status ?? this.status,
|
||
isbn: isbn is _CopyWithNullSentinel ? this.isbn : (isbn as String?),
|
||
publishDate: publishDate ?? this.publishDate,
|
||
createdAt: createdAt ?? this.createdAt,
|
||
updatedAt: updatedAt ?? this.updatedAt,
|
||
isDeleted: isDeleted ?? this.isDeleted,
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 笔记模型
|
||
class Note {
|
||
final String id;
|
||
final String title;
|
||
final String content;
|
||
final String contentType; // 内容类型(markdown)
|
||
final List<String> tags;
|
||
final List<String> images; // 图片路径列表
|
||
final DateTime createdAt;
|
||
final DateTime updatedAt;
|
||
final bool isDeleted;
|
||
|
||
Note({
|
||
required this.id,
|
||
required this.title,
|
||
required this.content,
|
||
this.contentType = 'markdown',
|
||
this.tags = const [],
|
||
this.images = const [],
|
||
required this.createdAt,
|
||
required this.updatedAt,
|
||
this.isDeleted = false,
|
||
});
|
||
|
||
factory Note.fromJson(Map<String, dynamic> json) {
|
||
return Note(
|
||
id: json['id']?.toString() ?? '',
|
||
title: json['title'] ?? '',
|
||
content: json['content'] ?? '',
|
||
contentType: json['content_type'] ?? 'markdown',
|
||
tags: Movie.parseStringList(json['tags']),
|
||
images: Movie.parseStringList(json['images']),
|
||
createdAt: json['created_at'] != null
|
||
? DateTime.parse(json['created_at'])
|
||
: DateTime.now(),
|
||
updatedAt: json['updated_at'] != null
|
||
? DateTime.parse(json['updated_at'])
|
||
: DateTime.now(),
|
||
isDeleted: json['is_deleted'] == 1 || json['is_deleted'] == true,
|
||
);
|
||
}
|
||
|
||
Map<String, dynamic> toJson() {
|
||
return {
|
||
'id': id,
|
||
'title': title,
|
||
'content': content,
|
||
'content_type': contentType,
|
||
'tags': jsonEncode(tags),
|
||
'images': jsonEncode(images),
|
||
'created_at': createdAt.toUtc().toIso8601String(),
|
||
'updated_at': updatedAt.toUtc().toIso8601String(),
|
||
'is_deleted': isDeleted ? 1 : 0,
|
||
};
|
||
}
|
||
|
||
/// 复制并修改
|
||
Note copyWith({
|
||
String? id,
|
||
String? title,
|
||
String? content,
|
||
String? contentType,
|
||
List<String>? tags,
|
||
List<String>? images,
|
||
DateTime? createdAt,
|
||
DateTime? updatedAt,
|
||
bool? isDeleted,
|
||
}) {
|
||
return Note(
|
||
id: id ?? this.id,
|
||
title: title ?? this.title,
|
||
content: content ?? this.content,
|
||
contentType: contentType ?? this.contentType,
|
||
tags: tags ?? this.tags,
|
||
images: images ?? this.images,
|
||
createdAt: createdAt ?? this.createdAt,
|
||
updatedAt: updatedAt ?? this.updatedAt,
|
||
isDeleted: isDeleted ?? this.isDeleted,
|
||
);
|
||
}
|
||
|
||
/// 获取内容摘要(前100字)
|
||
String get summary {
|
||
if (content.length <= 100) return content;
|
||
return '${content.substring(0, 100)}...';
|
||
}
|
||
}
|
||
|
||
/// 影评模型
|
||
class MovieReview {
|
||
final String id;
|
||
final String movieId;
|
||
final String content;
|
||
final String reviewer;
|
||
final String source;
|
||
final int reviewType; // 1: 短评, 2: 长评
|
||
final bool isDeleted;
|
||
final DateTime createdAt;
|
||
final DateTime updatedAt;
|
||
|
||
MovieReview({
|
||
required this.id,
|
||
required this.movieId,
|
||
required this.content,
|
||
this.reviewer = '',
|
||
this.source = '',
|
||
this.reviewType = 1,
|
||
this.isDeleted = false,
|
||
required this.createdAt,
|
||
required this.updatedAt,
|
||
});
|
||
|
||
factory MovieReview.fromJson(Map<String, dynamic> json) {
|
||
return MovieReview(
|
||
id: json['id']?.toString() ?? '',
|
||
movieId: json['movie_id']?.toString() ?? '',
|
||
content: json['content'] ?? '',
|
||
reviewer: json['reviewer'] ?? '',
|
||
source: json['source'] ?? '',
|
||
reviewType: json['review_type'] ?? 1,
|
||
isDeleted: json['is_deleted'] == 1 || json['is_deleted'] == true,
|
||
createdAt: json['created_at'] != null
|
||
? DateTime.parse(json['created_at'])
|
||
: DateTime.now(),
|
||
updatedAt: json['updated_at'] != null
|
||
? DateTime.parse(json['updated_at'])
|
||
: DateTime.now(),
|
||
);
|
||
}
|
||
|
||
Map<String, dynamic> toJson() {
|
||
return {
|
||
'id': id,
|
||
'movie_id': movieId,
|
||
'content': content,
|
||
'reviewer': reviewer,
|
||
'source': source,
|
||
'review_type': reviewType,
|
||
'is_deleted': isDeleted ? 1 : 0,
|
||
'created_at': createdAt.toUtc().toIso8601String(),
|
||
'updated_at': updatedAt.toUtc().toIso8601String(),
|
||
};
|
||
}
|
||
|
||
/// 复制并修改
|
||
MovieReview copyWith({
|
||
String? id,
|
||
String? movieId,
|
||
String? content,
|
||
String? reviewer,
|
||
String? source,
|
||
int? reviewType,
|
||
bool? isDeleted,
|
||
DateTime? createdAt,
|
||
DateTime? updatedAt,
|
||
}) {
|
||
return MovieReview(
|
||
id: id ?? this.id,
|
||
movieId: movieId ?? this.movieId,
|
||
content: content ?? this.content,
|
||
reviewer: reviewer ?? this.reviewer,
|
||
source: source ?? this.source,
|
||
reviewType: reviewType ?? this.reviewType,
|
||
isDeleted: isDeleted ?? this.isDeleted,
|
||
createdAt: createdAt ?? this.createdAt,
|
||
updatedAt: updatedAt ?? this.updatedAt,
|
||
);
|
||
}
|
||
|
||
/// 获取评论摘要
|
||
String get summary {
|
||
if (content.length <= 50) return content;
|
||
return '${content.substring(0, 50)}...';
|
||
}
|
||
|
||
/// 评论类型文本
|
||
String get typeText => reviewType == 1 ? '短评' : '长评';
|
||
}
|
||
|
||
/// 影视海报墙模型
|
||
class MoviePoster {
|
||
final String id;
|
||
final String movieId;
|
||
final String posterPath;
|
||
final bool isDeleted;
|
||
final DateTime createdAt;
|
||
|
||
MoviePoster({
|
||
required this.id,
|
||
required this.movieId,
|
||
required this.posterPath,
|
||
this.isDeleted = false,
|
||
required this.createdAt,
|
||
});
|
||
|
||
factory MoviePoster.fromJson(Map<String, dynamic> json) {
|
||
return MoviePoster(
|
||
id: json['id']?.toString() ?? '',
|
||
movieId: json['movie_id']?.toString() ?? '',
|
||
posterPath: json['poster_path'] ?? '',
|
||
isDeleted: json['is_deleted'] == 1 || json['is_deleted'] == true,
|
||
createdAt: json['created_at'] != null
|
||
? DateTime.parse(json['created_at'])
|
||
: DateTime.now(),
|
||
);
|
||
}
|
||
|
||
Map<String, dynamic> toJson() {
|
||
return {
|
||
'id': id,
|
||
'movie_id': movieId,
|
||
'poster_path': posterPath,
|
||
'is_deleted': isDeleted ? 1 : 0,
|
||
'created_at': createdAt.toUtc().toIso8601String(),
|
||
};
|
||
}
|
||
|
||
/// 获取海报文件
|
||
File? get posterFile {
|
||
if (posterPath.isEmpty) return null;
|
||
return File(posterPath);
|
||
}
|
||
}
|
||
|
||
/// 书评模型
|
||
class BookReview {
|
||
final String id;
|
||
final String bookId;
|
||
final String content;
|
||
final String reviewer;
|
||
final String source;
|
||
final int reviewType; // 1: 短评, 2: 长评
|
||
final bool isDeleted;
|
||
final DateTime createdAt;
|
||
final DateTime updatedAt;
|
||
|
||
BookReview({
|
||
required this.id,
|
||
required this.bookId,
|
||
required this.content,
|
||
this.reviewer = '',
|
||
this.source = '',
|
||
this.reviewType = 1,
|
||
this.isDeleted = false,
|
||
required this.createdAt,
|
||
required this.updatedAt,
|
||
});
|
||
|
||
factory BookReview.fromJson(Map<String, dynamic> json) {
|
||
return BookReview(
|
||
id: json['id']?.toString() ?? '',
|
||
bookId: json['book_id']?.toString() ?? '',
|
||
content: json['content'] ?? '',
|
||
reviewer: json['reviewer'] ?? '',
|
||
source: json['source'] ?? '',
|
||
reviewType: json['review_type'] ?? 1,
|
||
isDeleted: json['is_deleted'] == 1 || json['is_deleted'] == true,
|
||
createdAt: json['created_at'] != null
|
||
? DateTime.parse(json['created_at'])
|
||
: DateTime.now(),
|
||
updatedAt: json['updated_at'] != null
|
||
? DateTime.parse(json['updated_at'])
|
||
: DateTime.now(),
|
||
);
|
||
}
|
||
|
||
Map<String, dynamic> toJson() {
|
||
return {
|
||
'id': id,
|
||
'book_id': bookId,
|
||
'content': content,
|
||
'reviewer': reviewer,
|
||
'source': source,
|
||
'review_type': reviewType,
|
||
'is_deleted': isDeleted ? 1 : 0,
|
||
'created_at': createdAt.toUtc().toIso8601String(),
|
||
'updated_at': updatedAt.toUtc().toIso8601String(),
|
||
};
|
||
}
|
||
|
||
/// 复制并修改
|
||
BookReview copyWith({
|
||
String? id,
|
||
String? bookId,
|
||
String? content,
|
||
String? reviewer,
|
||
String? source,
|
||
int? reviewType,
|
||
bool? isDeleted,
|
||
DateTime? createdAt,
|
||
DateTime? updatedAt,
|
||
}) {
|
||
return BookReview(
|
||
id: id ?? this.id,
|
||
bookId: bookId ?? this.bookId,
|
||
content: content ?? this.content,
|
||
reviewer: reviewer ?? this.reviewer,
|
||
source: source ?? this.source,
|
||
reviewType: reviewType ?? this.reviewType,
|
||
isDeleted: isDeleted ?? this.isDeleted,
|
||
createdAt: createdAt ?? this.createdAt,
|
||
updatedAt: updatedAt ?? this.updatedAt,
|
||
);
|
||
}
|
||
|
||
/// 获取评论摘要
|
||
String get summary {
|
||
if (content.length <= 50) return content;
|
||
return '${content.substring(0, 50)}...';
|
||
}
|
||
|
||
/// 评论类型文本
|
||
String get typeText => reviewType == 1 ? '短评' : '长评';
|
||
}
|
||
|
||
/// 书籍摘抄模型
|
||
class BookExcerpt {
|
||
final String id;
|
||
final String bookId;
|
||
final String chapter; // 章节
|
||
final String content; // 摘抄内容
|
||
final String comment; // 摘抄的评论/感悟
|
||
final bool isDeleted;
|
||
final DateTime createdAt;
|
||
final DateTime updatedAt;
|
||
|
||
BookExcerpt({
|
||
required this.id,
|
||
required this.bookId,
|
||
this.chapter = '',
|
||
required this.content,
|
||
this.comment = '',
|
||
this.isDeleted = false,
|
||
required this.createdAt,
|
||
required this.updatedAt,
|
||
});
|
||
|
||
factory BookExcerpt.fromJson(Map<String, dynamic> json) {
|
||
return BookExcerpt(
|
||
id: json['id']?.toString() ?? '',
|
||
bookId: json['book_id']?.toString() ?? '',
|
||
chapter: json['chapter'] ?? '',
|
||
content: json['content'] ?? '',
|
||
comment: json['comment'] ?? '',
|
||
isDeleted: json['is_deleted'] == 1 || json['is_deleted'] == true,
|
||
createdAt: json['created_at'] != null
|
||
? DateTime.parse(json['created_at'])
|
||
: DateTime.now(),
|
||
updatedAt: json['updated_at'] != null
|
||
? DateTime.parse(json['updated_at'])
|
||
: DateTime.now(),
|
||
);
|
||
}
|
||
|
||
Map<String, dynamic> toJson() {
|
||
return {
|
||
'id': id,
|
||
'book_id': bookId,
|
||
'chapter': chapter,
|
||
'content': content,
|
||
'comment': comment,
|
||
'is_deleted': isDeleted ? 1 : 0,
|
||
'created_at': createdAt.toUtc().toIso8601String(),
|
||
'updated_at': updatedAt.toUtc().toIso8601String(),
|
||
};
|
||
}
|
||
|
||
/// 复制并修改
|
||
BookExcerpt copyWith({
|
||
String? id,
|
||
String? bookId,
|
||
String? chapter,
|
||
String? content,
|
||
String? comment,
|
||
bool? isDeleted,
|
||
DateTime? createdAt,
|
||
DateTime? updatedAt,
|
||
}) {
|
||
return BookExcerpt(
|
||
id: id ?? this.id,
|
||
bookId: bookId ?? this.bookId,
|
||
chapter: chapter ?? this.chapter,
|
||
content: content ?? this.content,
|
||
comment: comment ?? this.comment,
|
||
isDeleted: isDeleted ?? this.isDeleted,
|
||
createdAt: createdAt ?? this.createdAt,
|
||
updatedAt: updatedAt ?? this.updatedAt,
|
||
);
|
||
}
|
||
|
||
/// 获取摘抄摘要
|
||
String get summary {
|
||
if (content.length <= 50) return content;
|
||
return '${content.substring(0, 50)}...';
|
||
}
|
||
}
|
||
|