Files
MookNote/lib/models/data_models.dart
2026-03-06 13:49:13 +08:00

336 lines
9.5 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:io';
import 'dart:convert';
/// 影视条目模型
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 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,
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',
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?.toIso8601String(),
'directors': jsonEncode(directors),
'writers': jsonEncode(writers),
'actors': jsonEncode(actors),
'genres': jsonEncode(genres),
'alternate_titles': jsonEncode(alternateTitles),
'summary': summary,
'rating': rating,
'status': status,
'created_at': createdAt.toIso8601String(),
'updated_at': updatedAt.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,
String? posterPath,
DateTime? releaseDate,
List<String>? directors,
List<String>? writers,
List<String>? actors,
List<String>? genres,
List<String>? alternateTitles,
String? summary,
double? rating,
String? status,
DateTime? createdAt,
DateTime? updatedAt,
bool? isDeleted,
}) {
return Movie(
id: id ?? this.id,
title: title ?? this.title,
posterPath: posterPath ?? this.posterPath,
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 ?? this.summary,
rating: rating ?? this.rating,
status: status ?? this.status,
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 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,
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',
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,
'created_at': createdAt.toIso8601String(),
'updated_at': updatedAt.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,
String? coverPath,
List<String>? authors,
List<String>? alternateTitles,
String? publisher,
List<String>? genres,
String? summary,
double? rating,
String? status,
DateTime? createdAt,
DateTime? updatedAt,
bool? isDeleted,
}) {
return Book(
id: id ?? this.id,
title: title ?? this.title,
coverPath: coverPath ?? this.coverPath,
authors: authors ?? this.authors,
alternateTitles: alternateTitles ?? this.alternateTitles,
publisher: publisher ?? this.publisher,
genres: genres ?? this.genres,
summary: summary ?? this.summary,
rating: rating ?? this.rating,
status: status ?? this.status,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
isDeleted: isDeleted ?? this.isDeleted,
);
}
}
/// 笔记模型
class Note {
final String id;
final String content;
final String contentType; // markdown / rich_text
final List<String> tags;
final DateTime createdAt;
final DateTime updatedAt;
Note({
required this.id,
required this.content,
this.contentType = 'markdown',
this.tags = const [],
required this.createdAt,
required this.updatedAt,
});
factory Note.fromJson(Map<String, dynamic> json) {
return Note(
id: json['id']?.toString() ?? '',
content: json['content'] ?? '',
contentType: json['content_type'] ?? 'markdown',
tags: Movie.parseStringList(json['tags']),
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,
'content': content,
'content_type': contentType,
'tags': jsonEncode(tags),
'created_at': createdAt.toIso8601String(),
'updated_at': updatedAt.toIso8601String(),
};
}
/// 复制并修改
Note copyWith({
String? id,
String? content,
String? contentType,
List<String>? tags,
DateTime? createdAt,
DateTime? updatedAt,
}) {
return Note(
id: id ?? this.id,
content: content ?? this.content,
contentType: contentType ?? this.contentType,
tags: tags ?? this.tags,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
/// 获取内容摘要前100字
String get summary {
if (content.length <= 100) return content;
return '${content.substring(0, 100)}...';
}
}