yx_tracking_flutter/lib/src/model/event.dart

216 lines
5.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:convert';
import 'package:yx_tracking_flutter/src/model/device_info.dart';
import 'package:yx_tracking_flutter/src/model/user_info.dart';
/// 统一事件模型。
class Event {
/// 创建事件实例。
const Event({
required this.systemCode,
required this.eventType,
required this.userInfo,
required this.clientType,
required this.clientTimestamp,
required this.timestamp,
required this.deviceInfo,
required this.eventParams,
required this.customTags,
required this.createTime,
this.retryCount = 0,
});
/// 从序列化 payload 恢复事件。
factory Event.fromPayload(
String payload, {
required DateTime createTime,
required int retryCount,
}) {
final decoded = jsonDecode(payload);
if (decoded is! Map<String, dynamic>) {
throw const FormatException('事件 payload 不是合法的 JSON 对象');
}
return Event.fromJson(
decoded,
createTime: createTime,
retryCount: retryCount,
);
}
/// 从 JSON 恢复事件。
factory Event.fromJson(
Map<String, dynamic> json, {
required DateTime createTime,
required int retryCount,
}) {
final userJson = json['userInfo'];
final deviceJson = json['deviceInfo'];
if (deviceJson is! Map) {
throw const FormatException('deviceInfo 缺失或格式错误');
}
return Event(
systemCode: (json['system_code'] ?? '').toString(),
eventType: (json['eventType'] ?? '').toString(),
userInfo: userJson is Map
? UserInfo(
userId: _toInt(userJson['userId']),
userName: userJson['userName']?.toString(),
account: userJson['account']?.toString(),
)
: null,
clientType: _toInt(json['clientType']) ?? 0,
clientTimestamp: _toInt(json['clientTimestamp']) ?? 0,
timestamp: (json['timestamp'] ?? '').toString(),
deviceInfo: DeviceInfo(
os: deviceJson['os']?.toString() ?? 'unknown',
model: deviceJson['model']?.toString() ?? 'unknown',
screenResolution:
deviceJson['screenResolution']?.toString() ?? 'unknown',
),
eventParams: _toMap(json['eventParams']),
customTags: _toMap(json['customTags']),
createTime: createTime,
retryCount: retryCount,
);
}
/// 系统编码system_code
final String systemCode;
/// 事件类型。
final String eventType;
/// 用户信息。
final UserInfo? userInfo;
/// 客户端类型client_type
final int clientType;
/// 客户端时间戳(秒)。
final int clientTimestamp;
/// 业务时间戳字符串。
final String timestamp;
/// 设备信息。
final DeviceInfo deviceInfo;
/// 事件参数。
final Map<String, dynamic>? eventParams;
/// 自定义标签。
final Map<String, dynamic>? customTags;
/// 事件创建时间。
final DateTime createTime;
/// 当前重试次数。
final int retryCount;
/// 复制事件并覆盖部分字段。
Event copyWith({
UserInfo? userInfo,
DeviceInfo? deviceInfo,
Map<String, dynamic>? eventParams,
Map<String, dynamic>? customTags,
DateTime? createTime,
int? retryCount,
}) =>
Event(
systemCode: systemCode,
eventType: eventType,
userInfo: userInfo ?? this.userInfo,
clientType: clientType,
clientTimestamp: clientTimestamp,
timestamp: timestamp,
deviceInfo: deviceInfo ?? this.deviceInfo,
eventParams: eventParams ?? this.eventParams,
customTags: customTags ?? this.customTags,
createTime: createTime ?? this.createTime,
retryCount: retryCount ?? this.retryCount,
);
/// 转换为可序列化的 JSON。
Map<String, dynamic> toJson() => <String, dynamic>{
'system_code': systemCode,
'eventType': eventType,
'userInfo': userInfo?.toJson(),
'clientType': clientType,
'clientTimestamp': clientTimestamp,
'timestamp': timestamp,
'deviceInfo': deviceInfo.toJson(),
'eventParams': eventParams,
'customTags': customTags,
};
/// 转换为 payload 字符串。
String toPayload() => jsonEncode(toJson());
static int? _toInt(dynamic value) {
if (value is int) {
return value;
}
if (value is num) {
return value.toInt();
}
if (value is String) {
return int.tryParse(value);
}
return null;
}
static Map<String, dynamic>? _toMap(dynamic value) {
if (value == null) {
return null;
}
if (value is Map<String, dynamic>) {
return value;
}
if (value is Map) {
return value.map(
(key, val) => MapEntry(key.toString(), val),
);
}
return null;
}
}
/// 带本地存储元数据的事件。
class StoredEvent {
/// 创建带存储元数据的事件实例。
const StoredEvent({
required this.id,
required this.event,
required this.retryCount,
required this.createTime,
});
/// 存储中的自增 ID。
final int id;
/// 事件本体。
final Event event;
/// 当前重试次数。
final int retryCount;
/// 事件创建时间。
final DateTime createTime;
/// 复制对象并覆盖部分字段。
StoredEvent copyWith({
int? id,
Event? event,
int? retryCount,
DateTime? createTime,
}) =>
StoredEvent(
id: id ?? this.id,
event: event ?? this.event,
retryCount: retryCount ?? this.retryCount,
createTime: createTime ?? this.createTime,
);
}