feat: 添加用户行为分析功能

This commit is contained in:
qzl
2026-04-01 18:35:32 +08:00
parent 24eda6ff51
commit 2cdf075e92
25 changed files with 1321 additions and 5 deletions
@@ -0,0 +1,111 @@
import 'package:equatable/equatable.dart';
class AnalyticsContext extends Equatable {
final String? networkType;
final String? osVersion;
final String? deviceModel;
final String? locale;
final String? timezone;
const AnalyticsContext({
this.networkType,
this.osVersion,
this.deviceModel,
this.locale,
this.timezone,
});
Map<String, dynamic> toJson() => {
'network_type': networkType,
'os_version': osVersion,
'device_model': deviceModel,
'locale': locale,
'timezone': timezone,
};
@override
List<Object?> get props => [
networkType,
osVersion,
deviceModel,
locale,
timezone,
];
}
class BaseAnalyticsEvent extends Equatable {
final String eventId;
final String eventType;
final DateTime timestamp;
final String userId;
final String deviceId;
final String sessionId;
final String platform;
final String appVersion;
final String? appBuild;
final String env;
final String? pageName;
final String? traceId;
final String? requestId;
final Map<String, dynamic> attributes;
final Map<String, num> metrics;
final AnalyticsContext? context;
const BaseAnalyticsEvent({
required this.eventId,
required this.eventType,
required this.timestamp,
required this.userId,
required this.deviceId,
required this.sessionId,
required this.platform,
required this.appVersion,
this.appBuild,
required this.env,
this.pageName,
this.traceId,
this.requestId,
this.attributes = const {},
this.metrics = const {},
this.context,
});
Map<String, dynamic> toJson() => {
'event_id': eventId,
'event_type': eventType,
'timestamp': timestamp.toUtc().toIso8601String(),
'user_id': userId,
'device_id': deviceId,
'session_id': sessionId,
'platform': platform,
'app_version': appVersion,
'app_build': appBuild,
'env': env,
'page_name': pageName,
'trace_id': traceId,
'request_id': requestId,
'attributes': attributes,
'metrics': metrics,
'context': context?.toJson(),
};
@override
List<Object?> get props => [
eventId,
eventType,
timestamp,
userId,
deviceId,
sessionId,
platform,
appVersion,
appBuild,
env,
pageName,
traceId,
requestId,
attributes,
metrics,
context,
];
}
@@ -0,0 +1,27 @@
import 'base_event.dart';
class UiClickEvent extends BaseAnalyticsEvent {
UiClickEvent({
required super.eventId,
required super.timestamp,
required super.userId,
required super.deviceId,
required super.sessionId,
required super.platform,
required super.appVersion,
super.appBuild,
required super.env,
required super.pageName,
super.traceId,
super.requestId,
required String elementId,
String? elementType,
super.context,
}) : super(
eventType: 'ui.click',
attributes: {
'element_id': elementId,
if (elementType != null) 'element_type': elementType,
},
);
}
@@ -0,0 +1,34 @@
import 'base_event.dart';
class AgentChatCompletedEvent extends BaseAnalyticsEvent {
AgentChatCompletedEvent({
required super.eventId,
required super.timestamp,
required super.userId,
required super.deviceId,
required super.sessionId,
required super.platform,
required super.appVersion,
super.appBuild,
required super.env,
super.pageName,
super.traceId,
super.requestId,
required String conversationId,
String? scenario,
int? messageCount,
int? responseTimeMs,
AnalyticsContext? context,
}) : super(
eventType: 'agent.chat_completed',
attributes: {
'conversation_id': conversationId,
if (scenario != null) 'scenario': scenario,
},
metrics: {
if (messageCount != null) 'message_count': messageCount,
if (responseTimeMs != null) 'response_time_ms': responseTimeMs,
},
context: context,
);
}
@@ -0,0 +1,6 @@
export 'base_event.dart';
export 'login_event.dart';
export 'logout_event.dart';
export 'conversation_event.dart';
export 'page_view_event.dart';
export 'click_event.dart';
@@ -0,0 +1,24 @@
import 'base_event.dart';
class SessionLoginEvent extends BaseAnalyticsEvent {
SessionLoginEvent({
required super.eventId,
required super.timestamp,
required super.userId,
required super.deviceId,
required super.sessionId,
required super.platform,
required super.appVersion,
super.appBuild,
required super.env,
super.pageName,
super.traceId,
super.requestId,
required String method,
AnalyticsContext? context,
}) : super(
eventType: 'session.login',
attributes: {'method': method},
context: context,
);
}
@@ -0,0 +1,28 @@
import 'base_event.dart';
class SessionLogoutEvent extends BaseAnalyticsEvent {
SessionLogoutEvent({
required super.eventId,
required super.timestamp,
required super.userId,
required super.deviceId,
required super.sessionId,
required super.platform,
required super.appVersion,
super.appBuild,
required super.env,
super.pageName,
super.traceId,
super.requestId,
String? reason,
int? sessionDurationS,
AnalyticsContext? context,
}) : super(
eventType: 'session.logout',
attributes: reason != null ? {'reason': reason} : const {},
metrics: sessionDurationS != null
? {'session_duration_s': sessionDurationS}
: const {},
context: context,
);
}
@@ -0,0 +1,29 @@
import 'base_event.dart';
class PageViewEvent extends BaseAnalyticsEvent {
PageViewEvent({
required super.eventId,
required super.timestamp,
required super.userId,
required super.deviceId,
required super.sessionId,
required super.platform,
required super.appVersion,
super.appBuild,
required super.env,
required super.pageName,
super.traceId,
super.requestId,
String? pageFrom,
int? stayDurationMs,
int? clickCount,
super.context,
}) : super(
eventType: 'page.view',
attributes: pageFrom != null ? {'page_from': pageFrom} : const {},
metrics: {
if (stayDurationMs != null) 'stay_duration_ms': stayDurationMs,
if (clickCount != null) 'click_count': clickCount,
},
);
}