|
|
@@ -0,0 +1,680 @@
|
|
|
+/**
|
|
|
+ * 埋点管理器 - 负责游戏内事件追踪和数据上报
|
|
|
+ */
|
|
|
+// 事件属性类型定义
|
|
|
+export interface EventProperties {
|
|
|
+ [key: string]: string | number | boolean;
|
|
|
+}
|
|
|
+
|
|
|
+// 小程序生命周期事件属性
|
|
|
+export interface MPLifecycleProperties {
|
|
|
+ scene?: number; // 场景值
|
|
|
+ query?: string; // 启动参数
|
|
|
+ shareTicket?: string; // 分享票据
|
|
|
+ referrerInfo?: any; // 来源信息
|
|
|
+}
|
|
|
+// 场景加载事件属性
|
|
|
+export interface SceneLoadProperties {
|
|
|
+ scene_name: string; // 场景名称
|
|
|
+ load_time?: number; // 加载时长(ms)
|
|
|
+ success: boolean; // 是否成功
|
|
|
+ error_msg?: string; // 错误信息
|
|
|
+}
|
|
|
+// 游戏进度事件属性
|
|
|
+export interface GameProgressProperties {
|
|
|
+ level?: number; // 关卡等级
|
|
|
+ score?: number; // 分数
|
|
|
+ time_spent?: number; // 耗时(秒)
|
|
|
+ result?: string; // 结果
|
|
|
+}
|
|
|
+
|
|
|
+// 方块合成事件属性
|
|
|
+export interface BlockMergeProperties extends EventProperties {
|
|
|
+ merge_level: number; // 合成等级 (2, 3, 4)
|
|
|
+ weapon_type?: string; // 武器类型
|
|
|
+ shape_type?: string; // 形状类型
|
|
|
+ session_id?: string; // 会话ID
|
|
|
+}
|
|
|
+
|
|
|
+// 游戏失败事件属性
|
|
|
+export interface GameFailureProperties extends EventProperties {
|
|
|
+ $event_duration: number; // 停留时长(秒)
|
|
|
+ $section_id: number; // 关卡id
|
|
|
+ $section_name: string; // 关卡名称
|
|
|
+ $section_type: string; // 关卡类型 (0=主线关卡,1=活动关卡,2=挑战关卡,3=支线关卡)
|
|
|
+}
|
|
|
+
|
|
|
+// 商店打开事件属性
|
|
|
+export interface OpenShopProperties extends EventProperties {
|
|
|
+ shop_type?: string; // 商店类型
|
|
|
+ entry_point?: string; // 进入商店的入口点
|
|
|
+ user_level?: number; // 用户等级
|
|
|
+ user_money?: number; // 用户金币数量
|
|
|
+ user_diamonds?: number; // 用户钻石数量
|
|
|
+}
|
|
|
+
|
|
|
+// 小程序分享事件属性
|
|
|
+export interface MPShareProperties extends EventProperties {
|
|
|
+ share_type?: string; // 分享类型 (game_result, achievement, invite)
|
|
|
+ share_content?: string; // 分享内容描述
|
|
|
+ share_target?: string; // 分享目标 (friend, group, timeline)
|
|
|
+ level?: number; // 当前关卡
|
|
|
+ score?: number; // 当前分数
|
|
|
+ user_level?: number; // 用户等级
|
|
|
+}
|
|
|
+
|
|
|
+// 查看商城内容事件属性
|
|
|
+export interface ViewMallContentProperties extends EventProperties {
|
|
|
+ content_type?: string; // 内容类型 (weapon, skill, decoration)
|
|
|
+ content_id?: string; // 内容ID
|
|
|
+ content_name?: string; // 内容名称
|
|
|
+ price?: number; // 价格
|
|
|
+ currency_type?: string; // 货币类型 (coin, diamond)
|
|
|
+ user_money?: number; // 用户当前金币
|
|
|
+ user_diamonds?: number; // 用户当前钻石
|
|
|
+ view_duration?: number; // 查看时长(秒)
|
|
|
+}
|
|
|
+
|
|
|
+// 用户首次注册事件属性
|
|
|
+export interface UserFirstRegisterProperties extends EventProperties {
|
|
|
+ register_time?: number; // 注册时间戳
|
|
|
+ channel?: string; // 注册渠道(如 wechat_game, web)
|
|
|
+ scene?: number; // 启动场景值
|
|
|
+ query?: string; // 启动参数
|
|
|
+}
|
|
|
+
|
|
|
+// 小程序注册事件属性
|
|
|
+export interface MPRegisterProperties extends EventProperties {
|
|
|
+ register_time?: number; // 注册时间戳
|
|
|
+ scene?: number; // 启动场景值
|
|
|
+ query?: string; // 启动参数
|
|
|
+}
|
|
|
+
|
|
|
+// 小程序登录事件属性
|
|
|
+export interface MPLoginProperties extends EventProperties {
|
|
|
+ login_time?: number; // 登录时间戳
|
|
|
+ scene?: number; // 启动场景值
|
|
|
+ query?: string; // 启动参数
|
|
|
+}
|
|
|
+
|
|
|
+// 小程序登出事件属性
|
|
|
+export interface MPLogoutProperties extends EventProperties {
|
|
|
+ logout_time?: number; // 登出时间戳
|
|
|
+ scene?: number; // 场景值
|
|
|
+}
|
|
|
+
|
|
|
+// 创建角色事件属性
|
|
|
+export interface CreateRoleProperties extends EventProperties {
|
|
|
+ role_id: string; // 角色ID
|
|
|
+ role_name?: string; // 角色名称
|
|
|
+ role_class?: string; // 角色职业/类型
|
|
|
+ create_time?: number; // 创建时间戳
|
|
|
+ user_level?: number; // 用户等级
|
|
|
+}
|
|
|
+
|
|
|
+// 广告展示事件属性
|
|
|
+export interface AdShowProperties extends EventProperties {
|
|
|
+ ad_type?: string; // 广告类型 (rewarded_video, banner, interstitial)
|
|
|
+ ad_placement?: string; // 广告位置 (shop_reward, level_reward, extra_coins)
|
|
|
+ ad_source?: string; // 广告来源
|
|
|
+ reward_type?: string; // 奖励类型 (coins, diamonds, items)
|
|
|
+ reward_amount?: number; // 奖励数量
|
|
|
+ user_level?: number; // 用户等级
|
|
|
+ show_result?: string; // 展示结果 (success, failed, closed)
|
|
|
+}
|
|
|
+
|
|
|
+// 小程序添加收藏事件属性
|
|
|
+export interface MPAddFavoritesProperties extends EventProperties {
|
|
|
+ favorite_type?: string; // 收藏类型 (game, achievement, score)
|
|
|
+ trigger_point?: string; // 触发点 (game_end, achievement_unlock, manual)
|
|
|
+ user_level?: number; // 用户等级
|
|
|
+ game_progress?: number; // 游戏进度百分比
|
|
|
+}
|
|
|
+
|
|
|
+// 方块选择点击事件属性
|
|
|
+export interface BlockSelectionClickProperties extends EventProperties {
|
|
|
+ button_type: string; // 按钮类型 (add_ball, add_coin, refresh_block)
|
|
|
+ button_cost?: number; // 按钮费用
|
|
|
+ user_money?: number; // 用户当前金币数量
|
|
|
+ user_level?: number; // 用户等级
|
|
|
+ usage_count?: number; // 该按钮的使用次数
|
|
|
+ success: boolean; // 操作是否成功
|
|
|
+ failure_reason?: string; // 失败原因(如金币不足)
|
|
|
+}
|
|
|
+
|
|
|
+// 开始关卡事件属性
|
|
|
+export interface StartSectionProperties extends EventProperties {
|
|
|
+ $section_id: number; // 关卡ID
|
|
|
+ $section_name: string; // 关卡名称
|
|
|
+ $section_type: string; // 关卡类型 (0=主线关卡,1=活动关卡,2=挑战关卡,3=支线关卡)
|
|
|
+ total_waves?: number; // 总波次数
|
|
|
+ total_enemies?: number; // 总敌人数量
|
|
|
+ energy_max?: number; // 初始最大能量值
|
|
|
+ user_level?: number; // 用户等级
|
|
|
+ user_money?: number; // 用户当前金币数量
|
|
|
+ background_image?: string; // 背景图片
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 埋点管理器单例类
|
|
|
+ */
|
|
|
+export class AnalyticsManager {
|
|
|
+ private static instance: AnalyticsManager;
|
|
|
+ private isEnabled: boolean = true;
|
|
|
+ private sessionId: string;
|
|
|
+ private userId: string;
|
|
|
+ private deviceInfo: any = {};
|
|
|
+
|
|
|
+ private constructor() {
|
|
|
+ this.sessionId = this.generateSessionId();
|
|
|
+ this.userId = this.getUserId();
|
|
|
+ this.initDeviceInfo();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取单例实例
|
|
|
+ */
|
|
|
+ public static getInstance(): AnalyticsManager {
|
|
|
+ if (!AnalyticsManager.instance) {
|
|
|
+ AnalyticsManager.instance = new AnalyticsManager();
|
|
|
+ }
|
|
|
+ return AnalyticsManager.instance;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化埋点管理器
|
|
|
+ */
|
|
|
+ public init(): void {
|
|
|
+ console.log('[AnalyticsManager] 埋点管理器初始化完成');
|
|
|
+ console.log('[AnalyticsManager] SessionId:', this.sessionId);
|
|
|
+ console.log('[AnalyticsManager] UserId:', this.userId);
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 设置埋点开关
|
|
|
+ */
|
|
|
+ public setEnabled(enabled: boolean): void {
|
|
|
+ this.isEnabled = enabled;
|
|
|
+ console.log('[AnalyticsManager] 埋点功能', enabled ? '已启用' : '已禁用');
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 发送事件
|
|
|
+ */
|
|
|
+ public track(eventName: string, properties: EventProperties = {}): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const eventData = {
|
|
|
+ event_name: eventName,
|
|
|
+ timestamp: Date.now(),
|
|
|
+ session_id: this.sessionId,
|
|
|
+ user_id: this.userId,
|
|
|
+ device_info: this.deviceInfo,
|
|
|
+ properties: properties
|
|
|
+ };
|
|
|
+
|
|
|
+ // 输出到控制台(实际项目中应该发送到服务器)
|
|
|
+ console.log('[AnalyticsManager] 事件追踪:', JSON.stringify(eventData, null, 2));
|
|
|
+
|
|
|
+ // 这里可以集成第三方埋点SDK,如:
|
|
|
+ // - 微信小游戏数据助手
|
|
|
+ // - TalkingData
|
|
|
+ // - 友盟统计
|
|
|
+ // - 自定义服务器接口
|
|
|
+ this.sendToServer(eventData);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 小程序生命周期事件 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 小程序启动事件
|
|
|
+ */
|
|
|
+ public trackMPLaunch(properties: MPLifecycleProperties = {}): void {
|
|
|
+ this.track('$MPLaunch', {
|
|
|
+ scene: properties.scene || 0,
|
|
|
+ query: properties.query || '',
|
|
|
+ shareTicket: properties.shareTicket || '',
|
|
|
+ referrerInfo: JSON.stringify(properties.referrerInfo || {}),
|
|
|
+ ...properties
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 小程序显示事件
|
|
|
+ */
|
|
|
+ public trackMPShow(properties: MPLifecycleProperties = {}): void {
|
|
|
+ this.track('$MPShow', {
|
|
|
+ scene: properties.scene || 0,
|
|
|
+ query: properties.query || '',
|
|
|
+ ...properties
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 小程序隐藏事件
|
|
|
+ */
|
|
|
+ public trackMPHide(): void {
|
|
|
+ this.track('$MPHide', {
|
|
|
+ hide_time: Date.now()
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 场景加载事件 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 场景加载开始事件
|
|
|
+ */
|
|
|
+ public trackSceneLoadStart(sceneName: string): void {
|
|
|
+ this.track('$SceneLoadStart', {
|
|
|
+ scene_name: sceneName,
|
|
|
+ start_time: Date.now()
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 场景加载完成事件
|
|
|
+ */
|
|
|
+ public trackSceneLoaded(properties: SceneLoadProperties): void {
|
|
|
+ this.track('$SceneLoaded', {
|
|
|
+ scene_name: properties.scene_name,
|
|
|
+ load_time: properties.load_time || 0,
|
|
|
+ success: properties.success,
|
|
|
+ error_msg: properties.error_msg || '',
|
|
|
+ ...properties
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 场景卸载事件
|
|
|
+ */
|
|
|
+ public trackSceneUnloaded(sceneName: string): void {
|
|
|
+ this.track('$SceneUnloaded', {
|
|
|
+ scene_name: sceneName,
|
|
|
+ unload_time: Date.now()
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 游戏进度事件 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 完成关卡事件
|
|
|
+ */
|
|
|
+ public trackCompleteSection(properties: GameProgressProperties): void {
|
|
|
+ this.track('$CompleteSection', {
|
|
|
+ level: properties.level || 1,
|
|
|
+ score: properties.score || 0,
|
|
|
+ time_spent: properties.time_spent || 0,
|
|
|
+ result: properties.result || 'success',
|
|
|
+ ...properties
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 等级提升事件
|
|
|
+ */
|
|
|
+ public trackUpdateLevel(oldLevel: number, newLevel: number): void {
|
|
|
+ this.track('$UpdateLevel', {
|
|
|
+ old_level: oldLevel,
|
|
|
+ new_level: newLevel,
|
|
|
+ level_diff: newLevel - oldLevel
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 新手引导事件 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新手引导开始事件
|
|
|
+ */
|
|
|
+ public trackTutorialStart(): void {
|
|
|
+ this.track('$TutorialStart', {
|
|
|
+ start_time: Date.now()
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新手引导完成事件
|
|
|
+ */
|
|
|
+ public trackTutorialFinish(timeSpent: number): void {
|
|
|
+ this.track('$TutorialFinish', {
|
|
|
+ time_spent: timeSpent,
|
|
|
+ finish_time: Date.now()
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 方块合成事件 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪方块合成等级达成事件
|
|
|
+ * @param mergeLevel 合成等级 (2, 3, 4)
|
|
|
+ * @param weaponType 武器类型
|
|
|
+ * @param shapeType 形状类型
|
|
|
+ */
|
|
|
+ public trackBlockMergeLevel(mergeLevel: number, weaponType?: string, shapeType?: string): void {
|
|
|
+ if (mergeLevel < 2 || mergeLevel > 4) {
|
|
|
+ console.warn(`[Analytics] Invalid merge level: ${mergeLevel}. Only levels 2-4 are tracked.`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const properties: BlockMergeProperties = {
|
|
|
+ merge_level: mergeLevel,
|
|
|
+ session_id: this.sessionId
|
|
|
+ };
|
|
|
+
|
|
|
+ if (weaponType) {
|
|
|
+ properties.weapon_type = weaponType;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (shapeType) {
|
|
|
+ properties.shape_type = shapeType;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 上报合成等级达成事件
|
|
|
+ this.track('$block_merge', properties);
|
|
|
+
|
|
|
+ console.log(`[Analytics] Block merge level ${mergeLevel} achieved:`, properties);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪方块合成等级2达成
|
|
|
+ */
|
|
|
+ public trackMergeLevel2(weaponType?: string, shapeType?: string): void {
|
|
|
+ this.trackBlockMergeLevel(2, weaponType, shapeType);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪方块合成等级3达成
|
|
|
+ */
|
|
|
+ public trackMergeLevel3(weaponType?: string, shapeType?: string): void {
|
|
|
+ this.trackBlockMergeLevel(3, weaponType, shapeType);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪方块合成等级4达成
|
|
|
+ */
|
|
|
+ public trackMergeLevel4(weaponType?: string, shapeType?: string): void {
|
|
|
+ this.trackBlockMergeLevel(4, weaponType, shapeType);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪游戏失败事件(墙体摧毁)
|
|
|
+ */
|
|
|
+ public trackGameFailure(properties: GameFailureProperties): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $GameFailure 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪游戏失败事件:', properties);
|
|
|
+ this.track('$GameFailure', properties);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪商店打开事件
|
|
|
+ */
|
|
|
+ public trackOpenShop(properties: OpenShopProperties = {}): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $OpenShop 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪商店打开事件:', properties);
|
|
|
+ this.track('$OpenShop', properties);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪方块选择点击事件
|
|
|
+ */
|
|
|
+ public trackBlockSelectionClick(properties: BlockSelectionClickProperties): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $block_selection_click 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪方块选择点击事件:', properties);
|
|
|
+ this.track('$block_selection_click', properties);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪开始关卡事件
|
|
|
+ */
|
|
|
+ public trackStartSection(properties: StartSectionProperties): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $StartSection 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪开始关卡事件:', properties);
|
|
|
+ this.track('$StartSection', properties);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 小程序分享事件 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪小程序分享事件
|
|
|
+ */
|
|
|
+ public trackMPShare(properties: MPShareProperties = {}): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $MPShare 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪小程序分享事件:', properties);
|
|
|
+ this.track('$MPShare', properties);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 商城内容查看事件 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪查看商城内容事件
|
|
|
+ */
|
|
|
+ public trackViewMallContent(properties: ViewMallContentProperties = {}): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $ViewMallContent 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪查看商城内容事件:', properties);
|
|
|
+ this.track('$ViewMallContent', properties);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 广告展示事件 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪广告展示事件
|
|
|
+ */
|
|
|
+ public trackAdShow(properties: AdShowProperties = {}): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $AdShow 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪广告展示事件:', properties);
|
|
|
+ this.track('$AdShow', properties);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 小程序添加收藏事件 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪小程序添加收藏事件
|
|
|
+ */
|
|
|
+ public trackMPAddFavorites(properties: MPAddFavoritesProperties = {}): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $MPAddFavorites 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪小程序添加收藏事件:', properties);
|
|
|
+ this.track('$MPAddFavorites', properties);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 用户注册与账号事件 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪用户首次注册事件
|
|
|
+ */
|
|
|
+ public trackUserFirstRegister(properties: UserFirstRegisterProperties = {}): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $UserFirstRegister 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const payload = {
|
|
|
+ register_time: properties.register_time || Date.now(),
|
|
|
+ channel: properties.channel || (typeof wx !== 'undefined' ? 'wechat_game' : 'web'),
|
|
|
+ scene: properties.scene || 0,
|
|
|
+ query: properties.query || '',
|
|
|
+ ...properties
|
|
|
+ };
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪用户首次注册事件:', payload);
|
|
|
+ this.track('$UserFirstRegister', payload);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪小程序注册事件
|
|
|
+ */
|
|
|
+ public trackMPRegister(properties: MPRegisterProperties = {}): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $MPRegister 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const payload = {
|
|
|
+ register_time: properties.register_time || Date.now(),
|
|
|
+ scene: properties.scene || 0,
|
|
|
+ query: properties.query || '',
|
|
|
+ ...properties
|
|
|
+ };
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪小程序注册事件:', payload);
|
|
|
+ this.track('$MPRegister', payload);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪小程序登录事件
|
|
|
+ */
|
|
|
+ public trackMPLogin(properties: MPLoginProperties = {}): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $MPLogin 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const payload = {
|
|
|
+ login_time: properties.login_time || Date.now(),
|
|
|
+ scene: properties.scene || 0,
|
|
|
+ query: properties.query || '',
|
|
|
+ ...properties
|
|
|
+ };
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪小程序登录事件:', payload);
|
|
|
+ this.track('$MPLogin', payload);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪小程序登出事件
|
|
|
+ */
|
|
|
+ public trackMPLogout(properties: MPLogoutProperties = {}): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $MPLogout 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const payload = {
|
|
|
+ logout_time: properties.logout_time || Date.now(),
|
|
|
+ scene: properties.scene || 0,
|
|
|
+ ...properties
|
|
|
+ };
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪小程序登出事件:', payload);
|
|
|
+ this.track('$MPLogout', payload);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 追踪创建角色事件
|
|
|
+ */
|
|
|
+ public trackCreateRole(properties: CreateRoleProperties): void {
|
|
|
+ if (!this.isEnabled) {
|
|
|
+ console.log('[AnalyticsManager] 埋点已禁用,跳过 $CreateRole 事件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const payload = {
|
|
|
+ role_id: properties.role_id,
|
|
|
+ role_name: properties.role_name || '',
|
|
|
+ role_class: properties.role_class || '',
|
|
|
+ create_time: properties.create_time || Date.now(),
|
|
|
+ user_level: properties.user_level || 1,
|
|
|
+ ...properties
|
|
|
+ };
|
|
|
+
|
|
|
+ console.log('[AnalyticsManager] 追踪创建角色事件:', payload);
|
|
|
+ this.track('$CreateRole', payload);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 私有方法 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成会话ID
|
|
|
+ */
|
|
|
+ private generateSessionId(): string {
|
|
|
+ return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户ID
|
|
|
+ */
|
|
|
+ private getUserId(): string {
|
|
|
+ // 尝试从本地存储获取用户ID,如果没有则生成新的
|
|
|
+ let userId = localStorage.getItem('analytics_user_id');
|
|
|
+ if (!userId) {
|
|
|
+ userId = 'user_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
|
|
+ localStorage.setItem('analytics_user_id', userId);
|
|
|
+ }
|
|
|
+ return userId;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化设备信息
|
|
|
+ */
|
|
|
+ private initDeviceInfo(): void {
|
|
|
+ this.deviceInfo = {
|
|
|
+ platform: 'web',
|
|
|
+ user_agent: navigator.userAgent,
|
|
|
+ screen_width: screen.width,
|
|
|
+ screen_height: screen.height,
|
|
|
+ language: navigator.language,
|
|
|
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
|
+ };
|
|
|
+
|
|
|
+ // 如果是微信小游戏环境,获取更多信息
|
|
|
+ if (typeof wx !== 'undefined') {
|
|
|
+ this.deviceInfo.platform = 'wechat_game';
|
|
|
+ // 可以调用wx.getSystemInfo等API获取更详细的设备信息
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 发送数据到服务器
|
|
|
+ */
|
|
|
+ private sendToServer(eventData: any): void {
|
|
|
+ // 实际项目中应该发送到服务器
|
|
|
+ // 这里只是模拟发送过程
|
|
|
+
|
|
|
+ // 示例:使用fetch发送到服务器
|
|
|
+ /*
|
|
|
+ fetch('/api/analytics/track', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ },
|
|
|
+ body: JSON.stringify(eventData)
|
|
|
+ }).catch(error => {
|
|
|
+ console.error('[AnalyticsManager] 发送埋点数据失败:', error);
|
|
|
+ });
|
|
|
+ */
|
|
|
+
|
|
|
+ // 或者集成第三方SDK
|
|
|
+ // 例如:wx.reportAnalytics(eventName, eventData);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 导出单例实例,方便全局使用
|
|
|
+export const Analytics = AnalyticsManager.getInstance();
|