| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715 |
- /**
- * 埋点管理器 - 负责游戏内事件追踪和数据上报
- */
- // 事件属性类型定义
- 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 {
- const storage: any = (globalThis as any).localStorage;
- const wxAny: any = (globalThis as any).wx;
- let userId: string | null = null;
- try {
- if (storage && typeof storage.getItem === 'function') {
- userId = storage.getItem('analytics_user_id');
- } else if (wxAny && typeof wxAny.getStorageSync === 'function') {
- userId = wxAny.getStorageSync('analytics_user_id') || null;
- }
- } catch {
- // ignore storage errors
- }
- if (!userId) {
- userId = 'user_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
- try {
- if (storage && typeof storage.setItem === 'function') {
- storage.setItem('analytics_user_id', userId);
- } else if (wxAny && typeof wxAny.setStorageSync === 'function') {
- wxAny.setStorageSync('analytics_user_id', userId);
- }
- } catch {
- // ignore storage errors
- }
- }
- return userId;
- }
- /**
- * 初始化设备信息
- */
- private initDeviceInfo(): void {
- const safeNavigator: any = (globalThis as any).navigator || {};
- const safeScreen: any = (globalThis as any).screen || {};
- const wxAny: any = (globalThis as any).wx;
- // 优先使用微信小游戏的系统信息,无需时区字段
- if (wxAny && typeof wxAny.getSystemInfoSync === 'function') {
- const sys = wxAny.getSystemInfoSync();
- this.deviceInfo = {
- platform: 'wechat_game',
- user_agent: safeNavigator.userAgent || 'wechat_game',
- screen_width: sys.screenWidth ?? safeScreen.width ?? 0,
- screen_height: sys.screenHeight ?? safeScreen.height ?? 0,
- language: sys.language || safeNavigator.language || 'zh_CN',
- brand: sys.brand,
- model: sys.model,
- system: sys.system,
- version: sys.version,
- pixelRatio: sys.pixelRatio
- };
- } else {
- // Web 环境的基础设备信息,移除时区字段以避免 Intl 依赖
- this.deviceInfo = {
- platform: 'web',
- user_agent: safeNavigator.userAgent || 'unknown',
- screen_width: safeScreen.width || 0,
- screen_height: safeScreen.height || 0,
- language: safeNavigator.language || 'en'
- };
- }
- }
- /**
- * 发送数据到服务器
- */
- 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();
|