// 日记条目数据模型 — 手写不可变类(避免 build_runner 依赖) import 'package:uuid/uuid.dart'; /// 心情枚举 — 对应日记心情选择器 enum Mood { happy('happy'), calm('calm'), sad('sad'), angry('angry'), thinking('thinking'); const Mood(this.value); final String value; } /// 天气枚举 — 对应日记天气标签 enum Weather { sunny('sunny'), cloudy('cloudy'), rainy('rainy'), snowy('snowy'), windy('windy'); const Weather(this.value); final String value; } /// 日记条目 — 核心数据模型 /// /// 每篇日记包含标题、日期、心情、天气、标签等元信息。 /// 日记的具体内容(文字/图片/手写/贴纸)通过 [JournalElement] 管理。 class JournalEntry { final String id; final String authorId; final String? classId; final String title; final DateTime date; final Mood mood; final Weather weather; final List tags; final bool isPrivate; final bool sharedToClass; final String? assignedTopicId; final int version; final DateTime createdAt; final DateTime updatedAt; const JournalEntry({ required this.id, required this.authorId, this.classId, required this.title, required this.date, this.mood = Mood.calm, this.weather = Weather.sunny, this.tags = const [], this.isPrivate = true, this.sharedToClass = false, this.assignedTopicId, this.version = 1, required this.createdAt, required this.updatedAt, }); JournalEntry copyWith({ String? id, String? authorId, String? classId, bool clearClassId = false, String? title, DateTime? date, Mood? mood, Weather? weather, List? tags, bool? isPrivate, bool? sharedToClass, String? assignedTopicId, bool clearAssignedTopicId = false, int? version, DateTime? createdAt, DateTime? updatedAt, }) => JournalEntry( id: id ?? this.id, authorId: authorId ?? this.authorId, classId: clearClassId ? null : (classId ?? this.classId), title: title ?? this.title, date: date ?? this.date, mood: mood ?? this.mood, weather: weather ?? this.weather, tags: tags ?? this.tags, isPrivate: isPrivate ?? this.isPrivate, sharedToClass: sharedToClass ?? this.sharedToClass, assignedTopicId: clearAssignedTopicId ? null : (assignedTopicId ?? this.assignedTopicId), version: version ?? this.version, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, ); Map toJson() => { 'id': id, 'author_id': authorId, 'class_id': classId, 'title': title, 'date': date.toIso8601String(), 'mood': mood.value, 'weather': weather.value, 'tags': tags, 'is_private': isPrivate, 'shared_to_class': sharedToClass, 'assigned_topic_id': assignedTopicId, 'version': version, 'created_at': createdAt.toIso8601String(), 'updated_at': updatedAt.toIso8601String(), }; factory JournalEntry.fromJson(Map json) => JournalEntry( id: json['id'] as String, authorId: json['author_id'] as String, classId: json['class_id'] as String?, title: json['title'] as String, date: DateTime.parse(json['date'] as String), mood: Mood.values.firstWhere( (m) => m.value == json['mood'], orElse: () => Mood.calm, ), weather: Weather.values.firstWhere( (w) => w.value == json['weather'], orElse: () => Weather.sunny, ), tags: List.from(json['tags'] as List? ?? []), isPrivate: (json['is_private'] as bool?) ?? true, sharedToClass: (json['shared_to_class'] as bool?) ?? false, assignedTopicId: json['assigned_topic_id'] as String?, version: (json['version'] as int?) ?? 1, createdAt: DateTime.parse(json['created_at'] as String), updatedAt: DateTime.parse(json['updated_at'] as String), ); /// 创建新日记的工厂方法 — 自动生成 id 和时间戳 factory JournalEntry.create({ required String authorId, required String title, required DateTime date, String? classId, Mood mood = Mood.calm, Weather weather = Weather.sunny, List tags = const [], bool isPrivate = true, String? assignedTopicId, }) { final now = DateTime.now(); return JournalEntry( id: const Uuid().v4(), authorId: authorId, classId: classId, title: title, date: date, mood: mood, weather: weather, tags: tags, isPrivate: isPrivate, sharedToClass: false, assignedTopicId: assignedTopicId, version: 1, createdAt: now, updatedAt: now, ); } }