refactor(apps): 重构数据层目录结构并新增启动预热编排器
This commit is contained in:
@@ -1,182 +0,0 @@
|
||||
class ReminderPayload {
|
||||
final String eventId;
|
||||
final String title;
|
||||
final DateTime startAt;
|
||||
final DateTime? endAt;
|
||||
final String timezone;
|
||||
final String? location;
|
||||
final String? notes;
|
||||
final String? color;
|
||||
final ReminderPayloadMode mode;
|
||||
final List<String> aggregateIds;
|
||||
final int? fireTimeBucket;
|
||||
final int version;
|
||||
|
||||
const ReminderPayload({
|
||||
required this.eventId,
|
||||
required this.title,
|
||||
required this.startAt,
|
||||
required this.timezone,
|
||||
this.endAt,
|
||||
this.location,
|
||||
this.notes,
|
||||
this.color,
|
||||
this.mode = ReminderPayloadMode.single,
|
||||
this.aggregateIds = const [],
|
||||
this.fireTimeBucket,
|
||||
this.version = 1,
|
||||
});
|
||||
|
||||
ReminderPayload copyWith({
|
||||
String? eventId,
|
||||
String? title,
|
||||
DateTime? startAt,
|
||||
DateTime? endAt,
|
||||
String? timezone,
|
||||
String? location,
|
||||
String? notes,
|
||||
String? color,
|
||||
ReminderPayloadMode? mode,
|
||||
List<String>? aggregateIds,
|
||||
int? fireTimeBucket,
|
||||
int? version,
|
||||
}) {
|
||||
return ReminderPayload(
|
||||
eventId: eventId ?? this.eventId,
|
||||
title: title ?? this.title,
|
||||
startAt: startAt ?? this.startAt,
|
||||
endAt: endAt ?? this.endAt,
|
||||
timezone: timezone ?? this.timezone,
|
||||
location: location ?? this.location,
|
||||
notes: notes ?? this.notes,
|
||||
color: color ?? this.color,
|
||||
mode: mode ?? this.mode,
|
||||
aggregateIds: aggregateIds ?? this.aggregateIds,
|
||||
fireTimeBucket: fireTimeBucket ?? this.fireTimeBucket,
|
||||
version: version ?? this.version,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'eventId': eventId,
|
||||
'title': title,
|
||||
'startAt': startAt.toIso8601String(),
|
||||
'endAt': endAt?.toIso8601String(),
|
||||
'timezone': timezone,
|
||||
'location': location,
|
||||
'notes': notes,
|
||||
'color': color,
|
||||
'mode': mode.value,
|
||||
'aggregateIds': aggregateIds,
|
||||
'fireTimeBucket': fireTimeBucket,
|
||||
'version': version,
|
||||
};
|
||||
}
|
||||
|
||||
factory ReminderPayload.fromJson(Map<String, dynamic> json) {
|
||||
final eventId = (json['eventId'] as String?) ?? '';
|
||||
if (eventId.isEmpty) {
|
||||
throw const FormatException('eventId is required');
|
||||
}
|
||||
|
||||
final startAtRaw = json['startAt'] as String?;
|
||||
if (startAtRaw == null || startAtRaw.isEmpty) {
|
||||
throw const FormatException('startAt is required');
|
||||
}
|
||||
final parsedStartAt = DateTime.parse(startAtRaw);
|
||||
|
||||
final mode = ReminderPayloadMode.fromValue(
|
||||
(json['mode'] as String?) ?? 'single',
|
||||
);
|
||||
final aggregateIds = (json['aggregateIds'] as List<dynamic>? ?? const [])
|
||||
.map((item) => item.toString())
|
||||
.toList();
|
||||
if (mode == ReminderPayloadMode.aggregate && aggregateIds.length < 2) {
|
||||
throw const FormatException('aggregateIds must contain at least 2 items');
|
||||
}
|
||||
|
||||
return ReminderPayload(
|
||||
eventId: eventId,
|
||||
title: (json['title'] as String?) ?? '',
|
||||
startAt: parsedStartAt,
|
||||
endAt: json['endAt'] != null
|
||||
? DateTime.parse(json['endAt'] as String)
|
||||
: null,
|
||||
timezone: (json['timezone'] as String?) ?? 'UTC',
|
||||
location: json['location'] as String?,
|
||||
notes: json['notes'] as String?,
|
||||
color: json['color'] as String?,
|
||||
mode: mode,
|
||||
aggregateIds: aggregateIds,
|
||||
fireTimeBucket: json['fireTimeBucket'] as int?,
|
||||
version: (json['version'] as int?) ?? 1,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
return other is ReminderPayload &&
|
||||
other.eventId == eventId &&
|
||||
other.title == title &&
|
||||
other.startAt == startAt &&
|
||||
other.endAt == endAt &&
|
||||
other.timezone == timezone &&
|
||||
other.location == location &&
|
||||
other.notes == notes &&
|
||||
other.color == color &&
|
||||
other.mode == mode &&
|
||||
_listEquals(other.aggregateIds, aggregateIds) &&
|
||||
other.fireTimeBucket == fireTimeBucket &&
|
||||
other.version == version;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return Object.hash(
|
||||
eventId,
|
||||
title,
|
||||
startAt,
|
||||
endAt,
|
||||
timezone,
|
||||
location,
|
||||
notes,
|
||||
color,
|
||||
mode,
|
||||
Object.hashAll(aggregateIds),
|
||||
fireTimeBucket,
|
||||
version,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum ReminderPayloadMode {
|
||||
single('single'),
|
||||
aggregate('aggregate');
|
||||
|
||||
const ReminderPayloadMode(this.value);
|
||||
|
||||
final String value;
|
||||
|
||||
static ReminderPayloadMode fromValue(String raw) {
|
||||
return ReminderPayloadMode.values.firstWhere(
|
||||
(item) => item.value == raw,
|
||||
orElse: () => ReminderPayloadMode.single,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool _listEquals(List<String> left, List<String> right) {
|
||||
if (left.length != right.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < left.length; i++) {
|
||||
if (left[i] != right[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
class UserProfile {
|
||||
final String id;
|
||||
final String username;
|
||||
final String? phone;
|
||||
final String? avatarUrl;
|
||||
final String? bio;
|
||||
|
||||
const UserProfile({
|
||||
required this.id,
|
||||
required this.username,
|
||||
this.phone,
|
||||
this.avatarUrl,
|
||||
this.bio,
|
||||
});
|
||||
|
||||
factory UserProfile.fromJson(Map<String, dynamic> json) {
|
||||
return UserProfile(
|
||||
id: json['id'] as String,
|
||||
username: json['username'] as String,
|
||||
phone: json['phone'] as String?,
|
||||
avatarUrl: json['avatar_url'] as String?,
|
||||
bio: json['bio'] as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UserUpdateRequest {
|
||||
final String? username;
|
||||
final String? avatarUrl;
|
||||
final String? bio;
|
||||
|
||||
const UserUpdateRequest({this.username, this.avatarUrl, this.bio});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
if (username != null) 'username': username,
|
||||
if (avatarUrl != null) 'avatar_url': avatarUrl,
|
||||
if (bio != null) 'bio': bio,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user