gio-miniprogram-sdk 4.3.2 → 4.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.github/workflows/publish.yml +3 -3
  2. package/dist/alipay.js +1 -1
  3. package/dist/baidu.js +1 -1
  4. package/dist/bytedance.js +1 -1
  5. package/dist/jingdong.js +1 -1
  6. package/dist/kuaishou.js +1 -1
  7. package/dist/plugins/gioABTest.js +1 -1
  8. package/dist/plugins/gioCompress.js +1 -1
  9. package/dist/plugins/gioEventAutoTracking.js +1 -1
  10. package/dist/plugins/gioImpressionTracking.js +1 -1
  11. package/dist/plugins/gioMultipleInstances.js +1 -1
  12. package/dist/plugins/gioPerformance.js +1 -0
  13. package/dist/qq.js +1 -1
  14. package/dist/quickapp.js +1 -1
  15. package/dist/taobao.js +1 -1
  16. package/dist/taro.js +1 -1
  17. package/dist/uniapp.js +1 -1
  18. package/dist/wechat.js +1 -1
  19. package/dist/xiaohongshu.js +1 -0
  20. package/package.json +12 -6
  21. package/rollup.config.js +9 -6
  22. package/rollup.plugins.config.js +1 -1
  23. package/src/adapters/gioUniAppAdapter.ts +324 -113
  24. package/src/constants/emitMsg.ts +1 -0
  25. package/src/core/dataStore/eventHooks/appEffects.ts +6 -1
  26. package/src/core/dataStore/eventHooks/index.ts +122 -80
  27. package/src/core/dataStore/eventHooks/minipPage.ts +78 -68
  28. package/src/core/dataStore/eventHooks/pageEffects.ts +9 -2
  29. package/src/core/dataStore/index.ts +1 -1
  30. package/src/core/growingIO.ts +27 -3
  31. package/src/core/uploader.ts +12 -3
  32. package/src/core/userStore.ts +1 -2
  33. package/src/minipInstance/base.ts +62 -23
  34. package/src/minipInstance/framework.ts +3 -1
  35. package/src/minipInstance/my.ts +34 -1
  36. package/src/minipInstance/quickapp.ts +11 -0
  37. package/src/minipInstance/wx.ts +15 -0
  38. package/src/minipInstance/xhs.ts +20 -0
  39. package/src/platformConfig/base.ts +1 -0
  40. package/src/platformConfig/framework.ts +2 -0
  41. package/src/platformConfig/my.ts +1 -0
  42. package/src/platformConfig/xhs.ts +27 -0
  43. package/src/plugins/gioABTest.ts +32 -3
  44. package/src/plugins/gioEventAutoTracking.ts +101 -1
  45. package/src/plugins/gioImpressionTracking.ts +8 -3
  46. package/src/plugins/gioPerformance/exception.ts +152 -0
  47. package/src/plugins/gioPerformance/monitor.ts +284 -0
  48. package/src/plugins/gioPerformance/network.ts +197 -0
  49. package/src/plugins/gioPerformance.ts +131 -0
  50. package/src/types/base.ts +5 -1
  51. package/src/types/eventHooks.ts +5 -4
  52. package/src/types/minipInstance.ts +8 -1
  53. package/src/types/platforms.ts +3 -0
  54. package/src/utils/tools.ts +47 -3
  55. package/src/utils/verifiers.ts +4 -3
  56. package/tsconfig.json +1 -1
  57. package/typings/global.d.ts +8 -0
  58. package/bin/build.sh +0 -38
@@ -13,7 +13,8 @@ import {
13
13
  isString,
14
14
  last,
15
15
  typeOf,
16
- isEmpty
16
+ isEmpty,
17
+ isArray
17
18
  } from '@@/utils/glodash';
18
19
  import EMIT_MSG from '@@/constants/emitMsg';
19
20
  import {
@@ -21,7 +22,8 @@ import {
21
22
  niceTry,
22
23
  getPlainMinip,
23
24
  getPlainPlatform,
24
- getPlainConfig
25
+ getPlainConfig,
26
+ getPlainAppCode
25
27
  } from '@@/utils/tools';
26
28
 
27
29
  // 此基础实现类仅包含所有小程序,快应用所有方法全部单独实现
@@ -139,39 +141,67 @@ class BaseInstance implements MinipInstanceType {
139
141
  if (typeOf(instConfig) === 'string') {
140
142
  instConfig = niceTry(() => JSON.parse(instConfig)) ?? {};
141
143
  }
142
- // 第一优先级在base中的hook setNavigationBarTitle设置的值(在dataStore page实例中实现)
143
- // 第二优先级支持客户自己在页面中设置页面title
144
+ // 第一优先级在base中的hook setNavigationBarTitle设置的值(在dataStore page实例中实现,准确率最高)
145
+ // 第二优先级支持客户自己在页面中设置页面title(保持3.8的向下兼容,不准确但优先级高)
144
146
  const data = page?.data || page.$data || {};
145
147
  title = isString(data?.gioPageTitle) ? data?.gioPageTitle : '';
146
- if (instConfig) {
147
- // 第三优先级app生命周期中拿不到page对象,拿生命周期的参数来匹配
148
+
149
+ let instPage;
150
+ // 第三优先级取页面的配置json的navigationBarTitleText(仅部分支持)
151
+ if (!title) {
152
+ // 存在__[wx]AppCode__时尝试从__[wx]AppCode__中匹配
153
+ niceTry(() => {
154
+ const instAppCode = getPlainAppCode(platform);
155
+ if (instAppCode) {
156
+ instPage = instAppCode[`${page.route}.json`] || {};
157
+ title =
158
+ instPage?.navigationBarTitleText || // wx/qq/jd
159
+ instPage?.mod?.exports?.navigationBarTitleText; // ks
160
+ }
161
+ });
162
+ }
163
+ if (!title && instConfig) {
164
+ // 第四优先级在app生命周期中拿不到page对象,拿生命周期的参数来匹配
148
165
  const { enterParams } = this.growingIO.dataStore.eventHooks.appEffects;
149
166
  if (!page.route && !isEmpty(enterParams)) {
150
167
  page.route = enterParams.path || '';
151
- title = this._getTitleFromTabBar(instConfig, page.route);
168
+ title = page.route
169
+ ? this._getTitleFromTabBar(instConfig, page.route)
170
+ : '';
152
171
  }
153
- // 第四优先级取页面的navigationBarTitleText
154
- niceTry(() => {
155
- if (!title) {
156
- const instPage = instConfig.page || {};
172
+
173
+ // 第五优先级存在pages数组或page对象时尝试从page中匹配(大概率匹配不到,跟框架有关)
174
+ if (!title) {
175
+ if (isArray(instConfig.pages)) {
176
+ instPage = instConfig.pages.find((o) => o.path === page.route) ?? {};
177
+ } else {
178
+ instPage = instConfig.page || {};
179
+ }
180
+ if (instPage) {
157
181
  const pageInfo =
158
- instPage[page.route] || instPage[`${page.route}.html`];
159
- if (pageInfo) {
160
- title = pageInfo?.window?.navigationBarTitleText;
161
- } else if (['wx', 'tt'].includes(platform)) {
162
- title = (instConfig || global || $global)?.global?.window
163
- ?.navigationBarTitleText;
164
- } else {
165
- title = (instConfig || global || $global)?.window
166
- ?.navigationBarTitleText;
167
- }
182
+ instPage[page.route] || instPage[`${page.route}.html`] || instPage;
183
+ title =
184
+ pageInfo?.navigationBarTitleText ||
185
+ pageInfo?.window?.navigationBarTitleText;
168
186
  }
169
- });
170
- // 第五优先级取tabBar配置
187
+ }
188
+
189
+ // 第六优先级取tabBar配置匹配(只有tabbar的4个页面有机会)
171
190
  if (!title) {
172
191
  title = this._getTitleFromTabBar(instConfig, page.route);
173
192
  }
174
193
  }
194
+
195
+ // 第七优先级兜底取全局window的navigationBarTitleText
196
+ if (!title) {
197
+ if (['wx', 'tt'].includes(platform)) {
198
+ title = (instConfig || global || $global)?.global?.window
199
+ ?.navigationBarTitleText;
200
+ } else {
201
+ title = (instConfig || global || $global)?.window
202
+ ?.navigationBarTitleText;
203
+ }
204
+ }
175
205
  return limitString(title);
176
206
  };
177
207
 
@@ -308,6 +338,15 @@ class BaseInstance implements MinipInstanceType {
308
338
  this.minip?.getSetting({ success: resolve, fail: resolve });
309
339
  });
310
340
  };
341
+
342
+ // 监听网络变更
343
+ setNetworkStatusListener = () => {
344
+ this.minip?.onNetworkStatusChange(({ networkType }) => {
345
+ if (networkType) {
346
+ this.network.networkType = networkType;
347
+ }
348
+ });
349
+ };
311
350
  }
312
351
 
313
352
  export default BaseInstance;
@@ -1,5 +1,6 @@
1
1
  import { getPlainPlatform } from '@@/utils/tools';
2
2
 
3
+ import XiaoHongShu from './xhs';
3
4
  import JingDong from './jd';
4
5
  import KuaiShou from './ks';
5
6
  import Alipay from './my';
@@ -16,7 +17,8 @@ const INST = {
16
17
  qq: QQ,
17
18
  tt: Bytedance,
18
19
  ks: KuaiShou,
19
- jd: JingDong
20
+ jd: JingDong,
21
+ xhs: XiaoHongShu
20
22
  };
21
23
 
22
24
  export default INST[plainPlatform];
@@ -1,4 +1,4 @@
1
- import { compareVersion } from '@@/utils/tools';
1
+ import { compareVersion, consoleText } from '@@/utils/tools';
2
2
  import { GrowingIOType } from '@@/types/growingIO';
3
3
  import { isFunction } from '@@/utils/glodash';
4
4
  import BaseImplements from './base';
@@ -93,6 +93,39 @@ class Alipay extends BaseImplements {
93
93
  }
94
94
  return requestTask;
95
95
  };
96
+
97
+ // 执行支付宝特有的promise分享
98
+ handleSharePromise = (originResult, handlePromiseResult) => {
99
+ // 创建监听_result变化的Promise
100
+ const alipayPromise = new Promise((resolve) => {
101
+ // 如果已有_result直接返回
102
+ if (originResult._result) {
103
+ resolve(originResult._result);
104
+ return;
105
+ }
106
+ // 监听_result属性变化
107
+ Object.defineProperty(originResult, '_result', {
108
+ set(value) {
109
+ this.__result = value;
110
+ resolve(value);
111
+ },
112
+ get() {
113
+ return this.__result;
114
+ }
115
+ });
116
+ });
117
+ // 如果三秒内不resolve结果,分享会使用原默认参数
118
+ Promise.race([
119
+ alipayPromise,
120
+ new Promise((resolve) => {
121
+ setTimeout(() => {
122
+ resolve(originResult._result || {});
123
+ }, 3000);
124
+ })
125
+ ])
126
+ .then(handlePromiseResult)
127
+ .catch((error) => consoleText(error, 'error'));
128
+ };
96
129
  }
97
130
 
98
131
  export default Alipay;
@@ -217,6 +217,17 @@ class QuickApp extends BaseImplements {
217
217
  });
218
218
  });
219
219
  };
220
+
221
+ // 监听网络变更
222
+ setNetworkStatusListener = () => {
223
+ network.subscribe({
224
+ callback: (data) => {
225
+ if (data.type) {
226
+ this.network.networkType = data.type;
227
+ }
228
+ }
229
+ });
230
+ };
220
231
  }
221
232
 
222
233
  export default QuickApp;
@@ -1,4 +1,5 @@
1
1
  import { GrowingIOType } from '@@/types/growingIO';
2
+ import { SystemInfo } from '@@/types/minipInstance';
2
3
 
3
4
  import BaseImplements from './base';
4
5
 
@@ -7,6 +8,20 @@ class Weixin extends BaseImplements {
7
8
  super(growingIO);
8
9
  this.hookSetTitle();
9
10
  }
11
+
12
+ // 获取小程序系统信息
13
+ getSystemInfo = (): Promise<SystemInfo> => {
14
+ const self = this;
15
+ return new Promise((resolve) => {
16
+ const systemInfo = {
17
+ ...this.minip?.getDeviceInfo(),
18
+ ...this.minip?.getWindowInfo(),
19
+ ...this.minip?.getAppBaseInfo()
20
+ };
21
+ self.systemInfo = systemInfo;
22
+ resolve(systemInfo);
23
+ });
24
+ };
10
25
  }
11
26
 
12
27
  export default Weixin;
@@ -0,0 +1,20 @@
1
+ import { GrowingIOType } from '@@/types/growingIO';
2
+
3
+ import BaseImplements from './base';
4
+
5
+ class XiaoHongShu extends BaseImplements {
6
+ constructor(public growingIO: GrowingIOType) {
7
+ super(growingIO);
8
+ this.hookSetTitle();
9
+ }
10
+
11
+ // 采集曝光事件
12
+ initImpression = (collectPage: any) => {
13
+ this.growingIO.plugins?.gioImpressionTracking?.main(
14
+ collectPage,
15
+ 'selectAll'
16
+ );
17
+ };
18
+ }
19
+
20
+ export default XiaoHongShu;
@@ -23,6 +23,7 @@ const Config: PlatformConfigType = {
23
23
  'onReachBottom', // 实际sdk不会执行,但需要写在hook里,防止被归为自定义事件
24
24
  'onResize' // 实际sdk不会执行,但需要写在hook里,防止被归为自定义事件
25
25
  ],
26
+ shareEventTypes: ['onShareAppMessage', 'onShareTimeline', 'onAddToFavorites'],
26
27
  actionEventTypes: [
27
28
  'onclick',
28
29
  'tap',
@@ -1,5 +1,6 @@
1
1
  import { niceTry, getPlainPlatform } from '@@/utils/tools';
2
2
 
3
+ import XHSConfig from './xhs';
3
4
  import JDConfig from './jd';
4
5
  import KSConfig from './ks';
5
6
  import MyConfig from './my';
@@ -12,6 +13,7 @@ import WXConfig from './wx';
12
13
  const plainPlatform = getPlainPlatform();
13
14
  const FrameworkConfig = niceTry(() => {
14
15
  const INST = {
16
+ xhs: XHSConfig,
15
17
  jd: JDConfig,
16
18
  ks: KSConfig,
17
19
  my: MyConfig,
@@ -6,6 +6,7 @@ const MyConfig = {
6
6
  name: 'Alipay',
7
7
  platform: 'alip',
8
8
  scnPrefix: 'alip_',
9
+ shareEventTypes: ['onShareAppMessage'],
9
10
  hooks: {
10
11
  ...BaseConfig?.hooks,
11
12
  Behavior: false
@@ -0,0 +1,27 @@
1
+ import BaseConfig from './base';
2
+
3
+ const XHSConfig = {
4
+ ...BaseConfig,
5
+ pageHandlers: [
6
+ ...BaseConfig.pageHandlers,
7
+ 'onShareChat',
8
+ 'onCopyUrl',
9
+ 'onShareAppMessage',
10
+ 'onShareTimeline'
11
+ ],
12
+ shareEventTypes: [...BaseConfig.shareEventTypes, 'onShareChat', 'onCopyUrl'],
13
+ listeners: {
14
+ ...BaseConfig.listeners,
15
+ page: {
16
+ ...BaseConfig.listeners.page,
17
+ shareTime: 'onShareTimeline',
18
+ shareChat: 'onShareChat',
19
+ copyUrl: 'onCopyUrl'
20
+ }
21
+ },
22
+ name: 'XiaoHongShu',
23
+ platform: 'xhsp',
24
+ scnPrefix: 'xhs_'
25
+ };
26
+
27
+ export default XHSConfig;
@@ -33,6 +33,10 @@ class GioABTest {
33
33
  public url: any;
34
34
  // 接口重试计数
35
35
  public retryCount: number;
36
+ // 标记当前是否为新访问设备
37
+ public newDevice: boolean;
38
+ // 各个实例新设备进入时的sessionId;小程序没有刷新页面保持session的问题,所以存在内存里就可以
39
+ public visitSids: any;
36
40
  constructor(public growingIO: GrowingIOType, options: any) {
37
41
  this.pluginVersion = '__PLUGIN_VERSION__';
38
42
  const {
@@ -41,8 +45,9 @@ class GioABTest {
41
45
  requestTimeout
42
46
  } = options ?? {};
43
47
  this.timeoutCheck(requestInterval, requestTimeout);
44
- const { emitter } = this.growingIO;
48
+ const { emitter, userStore } = this.growingIO;
45
49
  this.growingIO.getABTest = this.getABTest;
50
+ this.visitSids = {};
46
51
  emitter.on(EMIT_MSG.OPTION_INITIALIZED, () => {
47
52
  if (!isEmpty(abServerUrl)) {
48
53
  this.abtStorageCheck();
@@ -61,6 +66,21 @@ class GioABTest {
61
66
  );
62
67
  }
63
68
  });
69
+ emitter.on(EMIT_MSG.UID_UPDATE, ({ newUId, oldUId }) => {
70
+ // 没有旧deviceId说明是第一次进入的新设备
71
+ if (!oldUId && newUId) {
72
+ if (isString(abServerUrl)) {
73
+ const trackingId = this.growingIO.trackingId;
74
+ const sId = userStore.getSessionId(trackingId);
75
+ this.visitSids[trackingId] = sId;
76
+ } else if (isObject(abServerUrl)) {
77
+ keys(abServerUrl).forEach((trackingId: string) => {
78
+ const sId = userStore.getSessionId(trackingId);
79
+ this.visitSids[trackingId] = sId;
80
+ });
81
+ }
82
+ }
83
+ });
64
84
  this.retryCount = 0;
65
85
  }
66
86
 
@@ -121,6 +141,14 @@ class GioABTest {
121
141
 
122
142
  // 生成数据接口地址
123
143
  generateUrl = (trackingId: string, abServerUrl: string) => {
144
+ // 如果是延迟初始化的实例,当前又是首次进入设备,要补充把session存起来
145
+ if (this.newDevice && !this.visitSids[trackingId]) {
146
+ // 这里要用userStore中的getSessionId,调用这个方法的时候实例肯定已经初始化了
147
+ // 如果是新初始化可以通过getSessionId准确获取sessionExpires来生成准确的session值;
148
+ // 如果是旧实例则直接用存储中的sessionId
149
+ this.visitSids[trackingId] =
150
+ this.growingIO.userStore.getSessionId(trackingId);
151
+ }
124
152
  if (!startsWith(abServerUrl, 'http')) {
125
153
  this.url[
126
154
  trackingId
@@ -169,7 +197,7 @@ class GioABTest {
169
197
  callback: any
170
198
  ) => {
171
199
  const {
172
- userStore: { getUid },
200
+ userStore: { getUid, getSessionId },
173
201
  dataStore,
174
202
  minipInstance
175
203
  } = this.growingIO;
@@ -182,7 +210,8 @@ class GioABTest {
182
210
  accountId: projectId,
183
211
  datasourceId: dataSourceId,
184
212
  distinctId: getUid(),
185
- layerId
213
+ layerId,
214
+ newDevice: this.visitSids[trackingId] === getSessionId(trackingId)
186
215
  },
187
216
  timeout: this.requestTimeout,
188
217
  success: ({ data }: any) => {
@@ -5,17 +5,21 @@
5
5
  import { ID_REG, SWAN_XID_REG, TARO_XID_REG } from '@@/constants/regex';
6
6
  import { EventTarget } from '@@/types/eventHooks';
7
7
  import { GrowingIOType } from '@@/types/growingIO';
8
- import { consoleText, isTaro3 } from '@@/utils/tools';
8
+ import { consoleText, getExtraData, isTaro3 } from '@@/utils/tools';
9
9
  import EMIT_MSG from '@@/constants/emitMsg';
10
+ import { isEmpty } from '@@/utils/glodash';
10
11
 
11
12
  let ut;
12
13
  class GioEventAutoTracking {
13
14
  public pluginVersion: string;
14
15
  private prevEvent: any;
16
+ public circleServerUrl: string;
17
+ public circleOpen = false;
15
18
  constructor(public growingIO: GrowingIOType) {
16
19
  this.pluginVersion = '__PLUGIN_VERSION__';
17
20
  ut = this.growingIO.utils;
18
21
  this.prevEvent = {};
22
+ this.listenForLunchEvent();
19
23
  }
20
24
 
21
25
  main = (e: EventTarget, eventName: string) => {
@@ -183,6 +187,102 @@ class GioEventAutoTracking {
183
187
  eventInterceptor(event);
184
188
  }
185
189
  };
190
+
191
+ // --------------------- 以下内容是对新版小程序圈选的支持 ---------------------
192
+
193
+ // 监听小程序的onLunch事件
194
+ listenForLunchEvent = () => {
195
+ const { emitter } = this.growingIO;
196
+ emitter.on(EMIT_MSG.MINIP_LIFECYCLE, ({ event, params }) => {
197
+ if (['App onLaunch', 'App onShow'].includes(event)) {
198
+ this.circleInit(params);
199
+ }
200
+ });
201
+ };
202
+
203
+ // 初始化圈选
204
+ circleInit = (params: any) => {
205
+ const { emitter } = this.growingIO;
206
+ const extraData = getExtraData(
207
+ params.referrerInfo?.extraData || params.query || {}
208
+ );
209
+ // 额外参数中存在gdpCircleRoomCollectUrl,则表示是圈选的跳转,进入圈选状态
210
+ if (extraData?.gdpCircleRoomCollectUrl) {
211
+ // 圈选初始化
212
+ if (this.circleServerUrl !== extraData?.gdpCircleRoomCollectUrl) {
213
+ this.circleServerUrl = extraData?.gdpCircleRoomCollectUrl;
214
+ // 提前移除一次事件发送监听,防止重复监听
215
+ emitter.off(EMIT_MSG.ON_SEND_AFTER, this.collectorSendFn);
216
+ // 添加事件发送监听,用于发送圈选事件
217
+ emitter.on(EMIT_MSG.ON_SEND_AFTER, this.collectorSendFn);
218
+ this.showPromptModal('enter');
219
+ }
220
+ this.circleOpen = true;
221
+ }
222
+ };
223
+
224
+ // 数据采集发送监听回调
225
+ collectorSendFn = ({ requestData, trackingId }) => {
226
+ const { uploader } = this.growingIO;
227
+ if (this.circleOpen) {
228
+ // 过滤仅主实例的非CUSTOM事件可以圈选
229
+ const filteredEvents = requestData.filter(
230
+ (e) =>
231
+ e.eventType !== 'CUSTOM' && trackingId === this.growingIO.trackingId
232
+ );
233
+ if (!isEmpty(filteredEvents)) {
234
+ // 同时请求数在3个以下直接发起请求
235
+ if (uploader.requestingNum < uploader.requestLimit) {
236
+ this.circleRequest(filteredEvents);
237
+ } else {
238
+ // 同时有3个请求在发送时,设轮询延时直到请求数在3个以下
239
+ let t = setInterval(() => {
240
+ if (uploader.requestingNum < uploader.requestLimit) {
241
+ this.circleRequest(filteredEvents);
242
+ clearInterval(t);
243
+ t = undefined;
244
+ }
245
+ }, 500);
246
+ }
247
+ }
248
+ }
249
+ };
250
+
251
+ // 圈选结束
252
+ circleClose = () => {
253
+ this.circleOpen = false;
254
+ this.circleServerUrl = '';
255
+ this.growingIO.emitter.off(EMIT_MSG.ON_SEND_AFTER, this.collectorSendFn);
256
+ };
257
+
258
+ // 展示圈选提示
259
+ showPromptModal = (type: 'enter' | 'error', msg?: string) => {
260
+ this.growingIO.minipInstance.minip.showModal({
261
+ title: 'GrowingIO提示',
262
+ content: type === 'error' ? msg : '您已进入圈选模式',
263
+ showCancel: false
264
+ });
265
+ };
266
+
267
+ // 发起圈选请求
268
+ circleRequest = (requestData: any) => {
269
+ const { minipInstance } = this.growingIO;
270
+ minipInstance.request({
271
+ url: this.circleServerUrl,
272
+ header: { 'content-type': 'application/json;charset=UTF-8' },
273
+ method: 'POST',
274
+ data: requestData,
275
+ complete: ({ statusCode, data, errMsg }: any) => {
276
+ if (![200, 204].includes(statusCode) || !data?.success) {
277
+ this.showPromptModal(
278
+ 'error',
279
+ data?.message || data || errMsg || '圈选请求失败,请重试!'
280
+ );
281
+ this.circleClose();
282
+ }
283
+ }
284
+ });
285
+ };
186
286
  }
187
287
 
188
288
  export default { name: 'gioEventAutoTracking', method: GioEventAutoTracking };
@@ -107,6 +107,10 @@ class GioImpressionTracking {
107
107
  return collectTarget.route
108
108
  ? toString(hashCode(collectTarget.route)) // swan page
109
109
  : collectTarget.__nodeId__; // swan component
110
+ case 'xhs':
111
+ return collectTarget.route
112
+ ? collectTarget.pageId // xhs page
113
+ : collectTarget.componentId; // xhs component
110
114
  default:
111
115
  break;
112
116
  }
@@ -117,9 +121,10 @@ class GioImpressionTracking {
117
121
  const { gioPlatform } = this.growingIO;
118
122
  if (
119
123
  (gioPlatform === 'tt' && collectTarget.__nodeId__) ||
120
- (gioPlatform === 'ks' && collectTarget.is)
124
+ (gioPlatform === 'ks' && collectTarget.is) ||
125
+ (gioPlatform === 'xhs' && collectTarget.componentId)
121
126
  ) {
122
- // 字节和快手小程序页面监听时可以拿到自定义组件一次性完成监听,所以组件的节点实例不再处理
127
+ // 字节/快手/小红书小程序页面监听时可以拿到自定义组件一次性完成监听,所以组件的节点实例不再处理
123
128
  return false;
124
129
  }
125
130
  const nodeId = this.getNodeId(collectTarget);
@@ -216,7 +221,7 @@ class GioImpressionTracking {
216
221
  originObserver.disconnect();
217
222
  }
218
223
  // 创建一个新的监听
219
- let observer = ['swan', 'jd'].includes(gioPlatform)
224
+ let observer = ['swan', 'jd', 'xhs'].includes(gioPlatform)
220
225
  ? minipInstance.minip?.createIntersectionObserver(
221
226
  collectTarget,
222
227
  observerOption