/** * 埋点服务 * 提供分享和下载打印事件的上报功能 */ import { getAppUUID } from './uuid'; // 格式化时间为 yyyy-MM-dd HH:mm function formatTime(date: Date = new Date()): string { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); return `${year}-${month}-${day} ${hours}:${minutes}`; } /** * 获取今天的日期字符串(yyyy-MM-dd) */ function getTodayString(): string { const date = new Date(); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } /** * 获取事件计数(当天该事件上报的次数) * 使用本地存储持久化,每天重置计数 */ function getEventCount(eventName: string): number { try { const storageKey = `tracker_count_${eventName}`; const dateKey = `tracker_date_${eventName}`; const today = getTodayString(); // 获取上次记录的日期 const lastDate = wx.getStorageSync(dateKey); let currentCount = 0; // 如果是今天,获取上次的计数;否则重置为0 if (lastDate === today) { currentCount = wx.getStorageSync(storageKey) || 0; } // 递增计数 const newCount = currentCount + 1; // 保存计数和日期 wx.setStorageSync(storageKey, newCount); wx.setStorageSync(dateKey, today); return newCount; } catch (error) { console.error('获取事件计数失败:', error); return 1; // 如果存储失败,返回 1 } } /** * 埋点追踪器(单例模式) */ class Tracker { private static instance: Tracker | null = null; private openLog: boolean; private constructor() { this.openLog = true; } /** * 获取 Tracker 单例实例 */ public static getInstance(): Tracker { if (!Tracker.instance) { Tracker.instance = new Tracker(); } return Tracker.instance; } printLog(tip: string, message?: string | object): void { if (this.openLog) { if (message) { if (typeof message === 'object') { console.log(tip, ':', JSON.stringify(message, null, 2)); } else { console.log(tip, ':', message as string); } } else { console.log(tip); } } } /** * 生成公共埋点属性 * @param eventName 事件名称 * @param pageName 页面名称 * @param extraParams 额外的参数对象 * @returns 包含公共属性和额外参数的埋点参数对象 */ private getCommonEventParams( eventName: string, pageName: string, extraParams?: Record, ): Record { return { count: getEventCount(eventName), date_time: formatTime(), uuid: getAppUUID(), page_name: pageName, ...extraParams, }; } /** * 上报分享点击事件 * @param pageName 页面名称 */ reportShare(pageName: string): void { try { const params = this.getCommonEventParams('share_click', pageName); this.sendEvent('share_click', params); } catch (error) { console.error('上报分享事件失败:', error); } } /** * 上报下载打印事件 * @param pageName 页面名称 * @param mode 模式(可选) */ reportDownload(pageName: string, mode?: string): void { try { const params = this.getCommonEventParams('download', pageName, { ...(mode && { mode }), }); this.sendEvent('download', params); } catch (error) { console.error('上报下载事件失败:', error); } } /** * 发送事件(仅在线上环境上报) * @param eventName 事件名称 * @param params 事件参数 */ sendEvent(eventName: string, params: Record): void { try { // 获取当前环境,只在 release 环境下上报 const accountInfo = wx.getAccountInfoSync(); const env = accountInfo.miniProgram.envVersion || 'release'; if (env === 'release') { this.printLog(`[${env}] 事件上报`, { eventName, params }); wx.reportEvent(eventName, params); } else { // 非线上环境,只打印日志,不上报 this.printLog(`[${env}] 事件上报已跳过`, { eventName, params }); } } catch (error) { console.error('获取环境信息失败:', error); // 如果获取环境信息失败,为了安全起见不上报 } } } // 导出 Tracker 单例实例 const tracker = Tracker.getInstance(); export default tracker;