MPLifecycleManager.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /**
  2. * 小程序生命周期管理器
  3. * 负责监听小程序的显示、隐藏等生命周期事件,并触发相应的埋点
  4. */
  5. import { Analytics } from './AnalyticsManager';
  6. export class MPLifecycleManager {
  7. private static instance: MPLifecycleManager;
  8. private isInitialized: boolean = false;
  9. private showTime: number = 0;
  10. private hideTime: number = 0;
  11. private constructor() {}
  12. /**
  13. * 获取单例实例
  14. */
  15. public static getInstance(): MPLifecycleManager {
  16. if (!MPLifecycleManager.instance) {
  17. MPLifecycleManager.instance = new MPLifecycleManager();
  18. }
  19. return MPLifecycleManager.instance;
  20. }
  21. /**
  22. * 初始化小程序生命周期监听
  23. */
  24. public init(): void {
  25. if (this.isInitialized) {
  26. return;
  27. }
  28. console.log('[MPLifecycleManager] 初始化小程序生命周期监听');
  29. // 如果是微信小游戏环境,注册生命周期监听
  30. if (typeof wx !== 'undefined') {
  31. this.setupWechatListeners();
  32. } else {
  33. // Web环境下监听页面可见性变化
  34. this.setupWebListeners();
  35. }
  36. this.isInitialized = true;
  37. }
  38. /**
  39. * 设置微信小游戏生命周期监听
  40. */
  41. private setupWechatListeners(): void {
  42. // 监听小程序显示事件
  43. if (wx.onShow) {
  44. wx.onShow((options: any) => {
  45. console.log('[MPLifecycleManager] 小程序显示', options);
  46. this.showTime = Date.now();
  47. // 计算后台时长
  48. const backgroundTime = this.hideTime > 0 ? this.showTime - this.hideTime : 0;
  49. // 追踪显示事件
  50. Analytics.trackMPShow({
  51. scene: options.scene || 0,
  52. query: JSON.stringify(options.query || {}),
  53. shareTicket: options.shareTicket || '',
  54. referrerInfo: options.referrerInfo || {}
  55. });
  56. // 检测是否通过分享进入,如果是则追踪分享事件
  57. if (options.shareTicket) {
  58. this.trackMPShareFromShow(options);
  59. }
  60. // 单独记录后台时长
  61. if (backgroundTime > 0) {
  62. Analytics.track('$MPBackgroundTime', {
  63. background_time: backgroundTime
  64. });
  65. }
  66. });
  67. }
  68. // 监听小程序隐藏事件
  69. if (wx.onHide) {
  70. wx.onHide(() => {
  71. console.log('[MPLifecycleManager] 小程序隐藏');
  72. this.hideTime = Date.now();
  73. // 计算前台时长
  74. const foregroundTime = this.showTime > 0 ? this.hideTime - this.showTime : 0;
  75. Analytics.trackMPHide();
  76. // 可以添加额外的隐藏事件属性
  77. Analytics.track('$MPHide', {
  78. hide_time: this.hideTime,
  79. foreground_time: foregroundTime
  80. });
  81. });
  82. }
  83. }
  84. /**
  85. * 追踪通过分享进入的事件
  86. */
  87. private trackMPShareFromShow(options: any): void {
  88. try {
  89. Analytics.trackMPShare({
  90. share_type: 'show_from_share', // 分享类型:从分享显示
  91. share_target: 'unknown', // 分享目标:未知(显示时无法确定)
  92. share_content: options.shareTicket || '', // 分享内容:shareTicket
  93. share_time: Date.now(), // 分享时间戳
  94. scene: options.scene || 0, // 显示场景
  95. query: JSON.stringify(options.query || {}) // 显示参数
  96. });
  97. console.log('[MPLifecycleManager] $MPShare 事件已上报(从分享显示):', options);
  98. } catch (error) {
  99. console.error('[MPLifecycleManager] 追踪分享显示事件时出错:', error);
  100. }
  101. }
  102. /**
  103. * 设置Web环境生命周期监听
  104. */
  105. private setupWebListeners(): void {
  106. // 监听页面可见性变化
  107. document.addEventListener('visibilitychange', () => {
  108. if (document.hidden) {
  109. // 页面隐藏
  110. console.log('[MPLifecycleManager] 页面隐藏');
  111. this.hideTime = Date.now();
  112. const foregroundTime = this.showTime > 0 ? this.hideTime - this.showTime : 0;
  113. Analytics.track('$MPHide', {
  114. hide_time: this.hideTime,
  115. foreground_time: foregroundTime,
  116. platform: 'web'
  117. });
  118. } else {
  119. // 页面显示
  120. console.log('[MPLifecycleManager] 页面显示');
  121. this.showTime = Date.now();
  122. const backgroundTime = this.hideTime > 0 ? this.showTime - this.hideTime : 0;
  123. Analytics.track('$MPShow', {
  124. show_time: this.showTime,
  125. background_time: backgroundTime,
  126. platform: 'web'
  127. });
  128. }
  129. });
  130. // 监听页面加载完成
  131. window.addEventListener('load', () => {
  132. console.log('[MPLifecycleManager] 页面加载完成');
  133. this.showTime = Date.now();
  134. Analytics.track('$MPShow', {
  135. show_time: this.showTime,
  136. platform: 'web',
  137. event_type: 'page_load'
  138. });
  139. });
  140. // 监听页面卸载
  141. window.addEventListener('beforeunload', () => {
  142. console.log('[MPLifecycleManager] 页面即将卸载');
  143. this.hideTime = Date.now();
  144. const foregroundTime = this.showTime > 0 ? this.hideTime - this.showTime : 0;
  145. Analytics.track('$MPHide', {
  146. hide_time: this.hideTime,
  147. foreground_time: foregroundTime,
  148. platform: 'web',
  149. event_type: 'page_unload'
  150. });
  151. });
  152. }
  153. /**
  154. * 获取当前会话时长
  155. */
  156. public getSessionDuration(): number {
  157. if (this.showTime === 0) {
  158. return 0;
  159. }
  160. const currentTime = Date.now();
  161. return currentTime - this.showTime;
  162. }
  163. /**
  164. * 手动触发显示事件(用于特殊场景)
  165. */
  166. public triggerShow(options: any = {}): void {
  167. this.showTime = Date.now();
  168. Analytics.trackMPShow(options);
  169. }
  170. /**
  171. * 手动触发隐藏事件(用于特殊场景)
  172. */
  173. public triggerHide(): void {
  174. this.hideTime = Date.now();
  175. Analytics.trackMPHide();
  176. }
  177. }
  178. // 导出单例实例
  179. export const MPLifecycle = MPLifecycleManager.getInstance();