gio-miniprogram-sdk 4.2.0 → 4.3.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 (43) hide show
  1. package/.github/workflows/publish.yml +2 -0
  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/qq.js +1 -1
  13. package/dist/quickapp.js +1 -1
  14. package/dist/taobao.js +1 -1
  15. package/dist/taro.js +1 -1
  16. package/dist/uniapp.js +1 -1
  17. package/dist/wechat.js +1 -1
  18. package/package.json +1 -1
  19. package/rollup.config.js +1 -1
  20. package/rollup.plugins.config.js +1 -1
  21. package/src/adapters/gioTaobaoAdapter.ts +5 -3
  22. package/src/adapters/gioTaroAdapter.ts +16 -10
  23. package/src/adapters/gioUniAppAdapter.ts +1 -32
  24. package/src/constants/config.ts +5 -1
  25. package/src/core/dataStore/eventContextBuilder.ts +4 -8
  26. package/src/core/dataStore/eventHooks/appEffects.ts +53 -79
  27. package/src/core/dataStore/eventHooks/index.ts +39 -23
  28. package/src/core/dataStore/eventHooks/minipPage.ts +108 -44
  29. package/src/core/dataStore/eventHooks/pageEffects.ts +31 -40
  30. package/src/core/dataStore/index.ts +90 -61
  31. package/src/core/growingIO.ts +17 -26
  32. package/src/core/userStore.ts +26 -0
  33. package/src/index.ts +12 -12
  34. package/src/minipInstance/base.ts +54 -27
  35. package/src/minipInstance/my.ts +6 -1
  36. package/src/minipInstance/tb.ts +6 -1
  37. package/src/plugins/gioABTest.ts +54 -33
  38. package/src/plugins/gioImpressionTracking.ts +14 -10
  39. package/src/plugins/gioMultipleInstances.ts +2 -0
  40. package/src/types/base.ts +4 -0
  41. package/src/types/eventHooks.ts +12 -9
  42. package/src/types/userStore.ts +2 -0
  43. package/src/utils/tools.ts +22 -3
@@ -6,10 +6,8 @@ import EMIT_MSG from '@@/constants/emitMsg';
6
6
  class PageEffects {
7
7
  public buildTabClickEvent: (tabItem: any) => void;
8
8
  private prevEvent: any;
9
- private argQuery: any;
10
9
  constructor(public growingIO: GrowingIOType) {
11
10
  this.prevEvent = {};
12
- this.argQuery = {};
13
11
  }
14
12
 
15
13
  main = (page: any, event: PageHookLifeCircle, args: any) => {
@@ -22,15 +20,15 @@ class PageEffects {
22
20
  platformConfig,
23
21
  dataStore: {
24
22
  getTrackerVds,
23
+ getOriginalSource,
24
+ setOriginalSource,
25
25
  trackersExecute,
26
- shareOut,
27
26
  eventHooks,
28
27
  toggleShareOut,
29
28
  buildAppMessageEvent,
30
29
  buildTimelineEvent,
31
30
  buildAddFavorites
32
- },
33
- inPlugin
31
+ }
34
32
  }: GrowingIOType = this.growingIO;
35
33
  const { currentPage } = eventHooks;
36
34
  if (
@@ -68,43 +66,34 @@ class PageEffects {
68
66
  currentPage.currentLifecycle = event;
69
67
  switch (event) {
70
68
  case pageListeners.pageLoad: {
71
- this.argQuery[path] =
69
+ // 获取一次页面参数存起来,防止类似支付宝小程序只能通过生命周期获取页面参数或页面堆栈拿不到页面参数,做兜底
70
+ currentPage.queryOption[path] =
72
71
  get(page, 'options') ||
73
72
  get(page, '__displayReporter.query') ||
74
73
  get(page, '$page.query') ||
75
74
  get(page, '$wx.__displayReporter.query') ||
75
+ get(page, '$taroParams') ||
76
76
  args[0] ||
77
77
  {};
78
- unset(this.argQuery[path], '$taroTimestamp');
79
- currentPage.parsePage(page, this.argQuery[path]);
78
+ unset(currentPage.queryOption[path], '$taroTimestamp');
80
79
  break;
81
80
  }
82
81
  case pageListeners.pageShow: {
83
- if (inPlugin) {
84
- currentPage.parsePage(page, this.argQuery[path]);
85
- if (!currentPage.path) {
86
- // 插件中没有页面时直接将插件appId作为页面信息
87
- currentPage.path = `/插件${vdsConfig.appId}}`;
88
- currentPage.title = `/插件${vdsConfig.appId}}`;
82
+ trackersExecute((trackingId: string) => {
83
+ // 检查originalSource内容是否已经被消费,如果没有被消费是同一个页面,说明visit还没被发出去,要更新title
84
+ const originalSource = getOriginalSource(trackingId);
85
+ if (!isEmpty(originalSource) && originalSource.path === path) {
86
+ setOriginalSource(trackingId, {
87
+ ...originalSource,
88
+ title: currentPage.getPageTitle()
89
+ });
89
90
  }
90
- trackersExecute((trackingId: string) => {
91
- const { trackPage } = getTrackerVds(trackingId);
92
- if (trackPage) {
93
- this.buildPageEvent(trackingId);
94
- }
95
- });
96
- } else if (!shareOut || !eventHooks.currentPage.time) {
97
- // 不是因为分享切出再返回的onshow(视为第一次进入改页面)和切出去以后因为超时或者进入的场景值不一致时(会在appshow清掉页面时间),发page
98
- currentPage.parsePage(page, this.argQuery[path]);
99
- // 超时进入页面时前后path一致parsePage方法不会重置页面时间,可能会没有值,所以要补充重设一次
100
- eventHooks.currentPage.time = Date.now();
101
- trackersExecute((trackingId: string) => {
102
- const { trackPage } = getTrackerVds(trackingId);
103
- if (trackPage) {
104
- this.buildPageEvent(trackingId);
105
- }
106
- });
107
- }
91
+ // 发page事件
92
+ const { trackPage } = getTrackerVds(trackingId);
93
+ if (trackPage) {
94
+ this.buildPageEvent(trackingId);
95
+ }
96
+ });
108
97
  // 分享标记置为false
109
98
  toggleShareOut(false);
110
99
  break;
@@ -156,6 +145,14 @@ class PageEffects {
156
145
  default:
157
146
  break;
158
147
  }
148
+ currentPage.lastLifecycle = currentPage.currentLifecycle;
149
+ currentPage.currentLifecycle = `${event}End`;
150
+ if (['onHideEnd', 'onUnloadEnd'].includes(currentPage.currentLifecycle)) {
151
+ currentPage.lifeBeforeShow = true;
152
+ }
153
+ if (currentPage.currentLifecycle === 'onShowEnd') {
154
+ currentPage.lifeBeforeShow = false;
155
+ }
159
156
  };
160
157
 
161
158
  // 构建页面访问事件
@@ -165,18 +162,12 @@ class PageEffects {
165
162
  eventContextBuilder,
166
163
  eventInterceptor,
167
164
  eventHooks: { currentPage }
168
- },
169
- minipInstance
165
+ }
170
166
  } = this.growingIO;
171
167
  const event = {
172
168
  eventType: 'PAGE',
173
169
  referralPage: currentPage.getReferralPage(trackingId),
174
- ...eventContextBuilder(trackingId),
175
- // page事件要单独设一个title以覆盖eventContextBuilder中的lastPage的title错误值
176
- title:
177
- currentPage?.title ||
178
- minipInstance.getPageTitle(minipInstance.getCurrentPage()),
179
- timestamp: currentPage.time
170
+ ...eventContextBuilder(trackingId)
180
171
  };
181
172
  // 合并页面属性
182
173
  event.attributes = currentPage.eventSetPageProps(trackingId, event);
@@ -13,7 +13,6 @@ import {
13
13
  isBoolean,
14
14
  isEmpty,
15
15
  isFunction,
16
- isNil,
17
16
  isString,
18
17
  keys,
19
18
  typeOf,
@@ -94,7 +93,7 @@ class DataStore implements DataStoreType {
94
93
  EMIT_MSG.ON_COMMIT_REQUEST,
95
94
  ({ eventData: event, trackingId }) => {
96
95
  if (event.eventType === 'VISIT') {
97
- this.lastVisitEvent = event;
96
+ this.lastVisitEvent[trackingId] = event;
98
97
  }
99
98
  if (event.eventType === 'PAGE') {
100
99
  this.lastPageEvent[trackingId] = event;
@@ -135,6 +134,33 @@ class DataStore implements DataStoreType {
135
134
  });
136
135
  }
137
136
  });
137
+ // session更新要补发当前页面的visit和page
138
+ this.growingIO.emitter.on(
139
+ EMIT_MSG.SESSIONID_UPDATE,
140
+ ({ oldSessionId, trackingId }) => {
141
+ if (oldSessionId) {
142
+ // 补发visit
143
+ const { getPagePath, getPageQuery: getPageQuery } =
144
+ this.eventHooks.currentPage;
145
+ const path = getPagePath();
146
+ const query = getPageQuery();
147
+ if (!path) {
148
+ // 个别(说的就是你:淘宝)小程序场景值不一样后台拉起时可能args中会没有path和query,直接取上一个最后发送的page中的值
149
+ const lastPage = this.lastPageEvent[trackingId];
150
+ this.sendVisit(trackingId, {
151
+ path: lastPage.path,
152
+ query: lastPage.query
153
+ });
154
+ } else {
155
+ this.sendVisit(trackingId, { path, query });
156
+ }
157
+ // 页面显示以后触发切session要补发page,离开页面到页面加载显示完成前的切session不补发,由onshow生命周期触发
158
+ if (!this.eventHooks.currentPage.lifeBeforeShow) {
159
+ this.sendPage(trackingId);
160
+ }
161
+ }
162
+ }
163
+ );
138
164
  }
139
165
 
140
166
  // 获取存储key
@@ -219,26 +245,25 @@ class DataStore implements DataStoreType {
219
245
  };
220
246
 
221
247
  // 保存初始来源信息
222
- setOriginalSource = (trackingId: string, { path, query }) => {
248
+ setOriginalSource = (trackingId: string, origins: any) => {
223
249
  const { minipInstance } = this.growingIO;
224
- if (isNil(this.getOriginalSource(trackingId))) {
225
- const originalSource = { path, query, title: '' };
226
- minipInstance.setStorageSync(
227
- this.getStorageKey(trackingId, 'originalSource'),
228
- JSON.stringify(originalSource)
229
- );
230
- }
250
+ minipInstance.setStorageSync(
251
+ this.getStorageKey(trackingId, 'originalSource'),
252
+ JSON.stringify(origins)
253
+ );
231
254
  };
232
255
 
233
256
  // 获取初始来源信息
234
257
  getOriginalSource = (trackingId: string) => {
235
258
  const { minipInstance } = this.growingIO;
236
- return niceTry(() =>
237
- JSON.parse(
238
- minipInstance.getStorageSync(
239
- this.getStorageKey(trackingId, 'originalSource')
259
+ return (
260
+ niceTry(() =>
261
+ JSON.parse(
262
+ minipInstance.getStorageSync(
263
+ this.getStorageKey(trackingId, 'originalSource')
264
+ )
240
265
  )
241
- )
266
+ ) ?? {}
242
267
  );
243
268
  };
244
269
 
@@ -263,12 +288,14 @@ class DataStore implements DataStoreType {
263
288
  const { platformConfig, inPlugin, minipInstance, plugins } = this.growingIO;
264
289
  const { uniVue, taro } = vdsConfig;
265
290
  // 如果是使用全量版本时,当前小程序不是框架的,要允许原生的hook
266
- if (!(uniVue || taro)) {
291
+ if (!(uniVue || taro || minipInstance.platform === 'quickapp')) {
267
292
  platformConfig.canHook = true;
268
293
  }
269
294
  // 初始化核心钩子(重写全局)
270
295
  if (!inPlugin || ['tbp', 'jdp'].includes(minipInstance.platform)) {
271
296
  this.eventHooks.initEventHooks();
297
+ } else {
298
+ this.eventHooks.initOriginalValue();
272
299
  }
273
300
  /** 第三方框架重写 */
274
301
  // uniapp
@@ -338,6 +365,22 @@ class DataStore implements DataStoreType {
338
365
  configs.requestTimeout = 5000;
339
366
  }
340
367
 
368
+ // 曝光比例不在合法范围内改回默认值
369
+ if (configs.impressionScale < 0 || configs.impressionScale > 1) {
370
+ configs.impressionScale = 0;
371
+ }
372
+
373
+ // keepAlive有效时长不在合法范围内改回默认值
374
+ if (configs.keepAlive < 0 || configs.keepAlive > 60 * 24) {
375
+ configs.keepAlive = 5;
376
+ }
377
+
378
+ // session有效时长不在合法范围内改回默认值
379
+ if (configs.sessionExpires < 1 || configs.sessionExpires > 60 * 24) {
380
+ // -1为默认不超时切session
381
+ configs.sessionExpires = -1;
382
+ }
383
+
341
384
  return {
342
385
  ...configs,
343
386
  projectId,
@@ -356,28 +399,17 @@ class DataStore implements DataStoreType {
356
399
  // 全局配置修改
357
400
  setOption = (trackingId: string, k: string, v: any) => {
358
401
  const { userStore, emitter } = this.growingIO;
359
- const trakerVds = this.getTrackerVds(trackingId);
402
+ const trackerVds = this.getTrackerVds(trackingId);
360
403
  // 检查 k
361
404
  const validKey = isString(k) && this.ALLOW_SETTING_KEYS.includes(k);
362
405
  const validValue = validKey && typeof v === DEFAULT_SETTINGS[k]?.type;
363
406
  if (validKey && validValue) {
364
- const prevConfig = { ...trakerVds };
365
- this.updateVdsConfig(trackingId, { ...trakerVds, [k]: v });
407
+ const prevConfig = { ...trackerVds };
408
+ this.updateVdsConfig(trackingId, { ...trackerVds, [k]: v });
366
409
  // 从关闭到打开dataCollect时补发visit和page
367
410
  if (k === 'dataCollect' && prevConfig.dataCollect !== v && v) {
411
+ // 更新session
368
412
  userStore.setSessionId(trackingId);
369
- const { path, query, settedTitle } = this.eventHooks.currentPage;
370
- // 重新获取页面title,防止切换配置前修改了title没取到
371
- this.eventHooks.currentPage.title =
372
- settedTitle[path] ||
373
- this.growingIO.minipInstance.getPageTitle(
374
- this.growingIO.minipInstance.getCurrentPage()
375
- );
376
- // visit取当前页面值
377
- this.sendVisit(trackingId, { path, query });
378
- // 要重设一次页面时间,防止比visit早
379
- this.eventHooks.currentPage.time = Date.now();
380
- this.sendPage(trackingId, { path, query });
381
413
  }
382
414
  // 配置项有变更要全局广播
383
415
  emitter.emit(EMIT_MSG.OPTION_CHANGE, { optionName: k, optionValue: v });
@@ -390,15 +422,15 @@ class DataStore implements DataStoreType {
390
422
 
391
423
  // 获取全局配置
392
424
  getOption = (trackingId: string, k?: string) => {
393
- const trakerVds = this.getTrackerVds(trackingId);
425
+ const trackerVds = this.getTrackerVds(trackingId);
394
426
  if (k && has(this.growingIO.vdsConfig, k)) {
395
- if (has(trakerVds, k)) {
396
- return trakerVds[k];
427
+ if (has(trackerVds, k)) {
428
+ return trackerVds[k];
397
429
  } else {
398
430
  return this.growingIO.vdsConfig[k];
399
431
  }
400
432
  } else if (isEmpty(k)) {
401
- return trakerVds;
433
+ return trackerVds;
402
434
  } else {
403
435
  callError(`getOption > ${k}`);
404
436
  return undefined;
@@ -431,10 +463,7 @@ class DataStore implements DataStoreType {
431
463
 
432
464
  // 手动调用visit事件的方法
433
465
  sendVisit = (trackingId: string, props?: any) => {
434
- (this.eventHooks.appEffects as any).buildVisitEvent(
435
- trackingId,
436
- props ?? this.lastVisitEvent
437
- );
466
+ (this.eventHooks.appEffects as any).buildVisitEvent(trackingId, props);
438
467
  };
439
468
 
440
469
  // 手动调用page事件的方法
@@ -482,6 +511,26 @@ class DataStore implements DataStoreType {
482
511
  }
483
512
  };
484
513
 
514
+ // 事件重组
515
+ eventRefactor = (e: any) => {
516
+ // 有的事件的path和query不能再用页面的值,所以直接使用事件中已有的值
517
+ const ne = {
518
+ ...e,
519
+ ...this.eventContextBuilder(e.trackingId, {
520
+ path: e.path,
521
+ query: e.query,
522
+ // page事件需要使用事件中原有的时间戳,其他事件也要用原来的时间戳保证事件的准确性
523
+ timestamp: e.timestamp
524
+ })
525
+ };
526
+ // 防止事件原有的属性被通用属性直接覆盖
527
+ ne.attributes = {
528
+ ...(ne.attributes ?? {}),
529
+ ...(e.attributes ?? {})
530
+ };
531
+ return ne;
532
+ };
533
+
485
534
  // 事件拦截器(有的通用维度字段需要异步获取,为了防止事件在通用维度还没返回之前就发出去)一般只有最开始的个别事件会被拦住
486
535
  eventInterceptor = (event: any) => {
487
536
  const { systemInfo, network } = this.growingIO.minipInstance;
@@ -491,17 +540,7 @@ class DataStore implements DataStoreType {
491
540
  } else if (!isEmpty(this.interceptEvents)) {
492
541
  // 有通用维度字段了,且有被拦截的事件,放一起重新添加通用维度字段再提交转换
493
542
  [...this.interceptEvents, event].forEach((e: any) => {
494
- // 有的事件的path和query不能再用页面的值,所以直接使用事件中已有的值
495
- const ne = {
496
- ...e,
497
- ...this.eventContextBuilder(event.trackingId, {
498
- path: e.path,
499
- query: e.query,
500
- // page事件需要使用事件中原有的时间戳,其他事件也要用原来的时间戳保证事件的准确性
501
- timestamp: e.timestamp
502
- })
503
- };
504
- this.eventConverter(ne);
543
+ this.eventConverter(this.eventRefactor(e));
505
544
  });
506
545
  this.interceptEvents = [];
507
546
  } else {
@@ -517,17 +556,7 @@ class DataStore implements DataStoreType {
517
556
  } = this.growingIO;
518
557
  if (systemInfo && network && !isEmpty(this.interceptEvents)) {
519
558
  [...this.interceptEvents].forEach((e: any) => {
520
- // 有的事件的path和query不能再用页面的值,所以直接使用事件中已有的值
521
- const ne = {
522
- ...e,
523
- ...this.eventContextBuilder(e.trackingId, {
524
- path: e.path,
525
- query: e.query,
526
- // page事件需要使用事件中原有的时间戳,其他事件也要用原来的时间戳保证事件的准确性
527
- timestamp: e.timestamp
528
- })
529
- };
530
- this.eventConverter(ne);
559
+ this.eventConverter(this.eventRefactor(e));
531
560
  });
532
561
  this.interceptEvents = [];
533
562
  }
@@ -163,8 +163,8 @@ class GrowingIO implements GrowingIOType {
163
163
  // 需要校验实例的方法执行
164
164
  handlerDistribute = (trackingId: string, handler: string, args: any) => {
165
165
  const { initializedTrackingIds, getTrackerVds } = this.dataStore;
166
- const trakerVds = getTrackerVds(trackingId);
167
- if (trakerVds && initializedTrackingIds.includes(trackingId)) {
166
+ const trackerVds = getTrackerVds(trackingId);
167
+ if (trackerVds && initializedTrackingIds.includes(trackingId)) {
168
168
  return this[handler](trackingId, ...args);
169
169
  } else {
170
170
  consoleText(`不存在实例:${trackingId},请检查!`, 'warn');
@@ -208,22 +208,21 @@ class GrowingIO implements GrowingIOType {
208
208
  setPageAttributes = (trackingId: string, properties: any) => {
209
209
  if (isObject(properties) && !isEmpty(properties)) {
210
210
  const { currentPage } = this.dataStore.eventHooks;
211
+ const path = currentPage.getPagePath();
211
212
  if (isEmpty(currentPage.pageProps[trackingId])) {
212
213
  currentPage.pageProps[trackingId] = {};
213
214
  }
214
- if (isEmpty(currentPage.pageProps[trackingId][currentPage.path])) {
215
- currentPage.pageProps[trackingId][currentPage.path] = {};
215
+ if (isEmpty(currentPage.pageProps[trackingId][path])) {
216
+ currentPage.pageProps[trackingId][path] = {};
216
217
  }
217
218
  // 结果合并,动态属性不作处理
218
219
  if (!isEmpty(properties)) {
219
220
  forEach(properties, (v, k) => {
220
221
  if (
221
- !isFunction(
222
- currentPage.pageProps[trackingId][currentPage.path][k]
223
- ) ||
222
+ !isFunction(currentPage.pageProps[trackingId][path][k]) ||
224
223
  isFunction(v)
225
224
  ) {
226
- currentPage.pageProps[trackingId][currentPage.path][k] = v;
225
+ currentPage.pageProps[trackingId][path][k] = v;
227
226
  }
228
227
  });
229
228
  }
@@ -244,15 +243,13 @@ class GrowingIO implements GrowingIOType {
244
243
  !isEmpty(this.dataStore.eventHooks.currentPage.pageProps[trackingId])
245
244
  ) {
246
245
  const { currentPage } = this.dataStore.eventHooks;
246
+ const path = currentPage.getPagePath();
247
247
  if (isArray(properties) && !isEmpty(properties)) {
248
248
  properties.forEach((propName: string) => {
249
- unset(
250
- currentPage.pageProps[trackingId][currentPage.path],
251
- propName
252
- );
249
+ unset(currentPage.pageProps[trackingId][path], propName);
253
250
  });
254
251
  } else {
255
- currentPage.pageProps[trackingId][currentPage.path] = {};
252
+ currentPage.pageProps[trackingId][path] = {};
256
253
  }
257
254
  }
258
255
  } catch (error) {
@@ -319,9 +316,9 @@ class GrowingIO implements GrowingIOType {
319
316
  // 该方法很可能被放在在app的onShow中的wx.login异步回调中,
320
317
  // 此时页面的path和query可能还没取到,就拿visit事件的path和query补上
321
318
  if (!event.path) {
322
- event.path = lastVisitEvent.path;
323
- event.query = lastVisitEvent.query;
324
- event.title = lastVisitEvent.title;
319
+ event.path = lastVisitEvent[trackingId]?.path;
320
+ event.query = lastVisitEvent[trackingId]?.query;
321
+ event.title = lastVisitEvent[trackingId]?.title;
325
322
  }
326
323
  eventInterceptor(event);
327
324
  } else {
@@ -345,17 +342,9 @@ class GrowingIO implements GrowingIOType {
345
342
  if (idMapping) {
346
343
  this.userStore.setUserKey(trackingId, isNil(userKey) ? '' : userKey);
347
344
  }
348
- // 切换userId时重置session并补发visit
345
+ // 切换userId时重置session
349
346
  if (prevId && prevId !== userId) {
350
347
  this.userStore.setSessionId(trackingId);
351
- const { path, query, settedTitle } =
352
- this.dataStore.eventHooks.currentPage;
353
- // 重新获取页面title,防止切换配置前修改了title没取到
354
- this.dataStore.eventHooks.currentPage.title =
355
- settedTitle[path] ||
356
- this.minipInstance.getPageTitle(this.minipInstance.getCurrentPage());
357
- // visit取当前页面值
358
- this.dataStore.sendVisit(trackingId, { path, query });
359
348
  }
360
349
  } else {
361
350
  callError('setUserId');
@@ -611,7 +600,9 @@ class GrowingIO implements GrowingIOType {
611
600
  if (!isEmpty(extraParams)) {
612
601
  extraParams.forEach((o) => {
613
602
  if (!ignoreFields.includes(o)) {
614
- infos[`gio${o}`] = this.dataStore.lastVisitEvent[o];
603
+ infos[`gio${o}`] = (this.dataStore.lastVisitEvent[trackingId] ?? {})[
604
+ o
605
+ ];
615
606
  }
616
607
  });
617
608
  }
@@ -26,12 +26,15 @@ class UserStore implements UserStoreType {
26
26
  public _userKey: StringObject;
27
27
  // 最后一次登录用户id(持久性存储)
28
28
  public _gioId: StringObject;
29
+ // 设置了session有效期以后判断用的session失效时间
30
+ public _sessionExpires: number;
29
31
  constructor(public growingIO: GrowingIOType) {
30
32
  this._uid = undefined;
31
33
  this._sessionId = {};
32
34
  this._userId = {};
33
35
  this._userKey = {};
34
36
  this._gioId = {};
37
+ this._sessionExpires = -1;
35
38
  }
36
39
 
37
40
  // 获取sessionId存储key
@@ -69,9 +72,26 @@ class UserStore implements UserStoreType {
69
72
 
70
73
  // 获取sessionId
71
74
  getSessionId = (trackingId: string) => {
75
+ // 设置了session时长,就需要检查session是否过期
76
+ const {
77
+ vdsConfig: { sessionExpires },
78
+ dataStore: { trackersExecute }
79
+ } = this.growingIO;
80
+ // 不存在sessionId(即新进)要设一个新的sessionId
72
81
  if (!this._sessionId[trackingId]) {
73
82
  this.setSessionId(trackingId);
74
83
  }
84
+ // 设置了session时长且过期
85
+ if (sessionExpires > -1) {
86
+ // 只要有一个session超时,所有实例都要重设sessionId
87
+ if (Date.now() > this._sessionExpires) {
88
+ trackersExecute((id: string) => {
89
+ this.setSessionId(id);
90
+ });
91
+ }
92
+ // 每次获取session后要更新过期时间
93
+ this._sessionExpires = Date.now() + 1000 * 60 * sessionExpires;
94
+ }
75
95
  return this._sessionId[trackingId];
76
96
  };
77
97
 
@@ -83,9 +103,15 @@ class UserStore implements UserStoreType {
83
103
  }
84
104
  // 小程序中sessionId只需要在内存中存储就可以,不需要持久化存储
85
105
  this._sessionId[trackingId] = id;
106
+ // 设置了session时长,就需要更新过期时间
107
+ const { sessionExpires } = this.growingIO.vdsConfig;
108
+ if (sessionExpires > -1) {
109
+ this._sessionExpires = Date.now() + 1000 * 60 * sessionExpires;
110
+ }
86
111
  // 广播通知登录sessionId变更
87
112
  if (prevId !== id) {
88
113
  this.growingIO.emitter.emit(EMIT_MSG.SESSIONID_UPDATE, {
114
+ trackingId,
89
115
  newSessionId: id,
90
116
  oldSessionId: prevId
91
117
  });
package/src/index.ts CHANGED
@@ -62,16 +62,16 @@ const gdp = function () {
62
62
  getGlobal().gdp = gdp;
63
63
  getGlobal().gioSDKVersion = gioInstance.sdkVersion;
64
64
 
65
- export const GioApp = niceTry(
66
- () => gioInstance.dataStore.eventHooks.growingApp ?? App
67
- );
68
- export const GioPage = niceTry(
69
- () => gioInstance.dataStore.eventHooks.growingPage ?? Page
70
- );
71
- export const GioComponent = niceTry(
72
- () => gioInstance.dataStore.eventHooks.growingComponent ?? Component
73
- );
74
- export const GioBehavior = niceTry(
75
- () => gioInstance.dataStore.eventHooks.growingBehavior ?? Behavior
76
- );
65
+ const {
66
+ growingApp,
67
+ growingPage,
68
+ growingComponent,
69
+ growingBehavior,
70
+ initOriginalValue
71
+ } = gioInstance.dataStore.eventHooks;
72
+ initOriginalValue();
73
+ export const GioApp = niceTry(() => growingApp ?? App);
74
+ export const GioPage = niceTry(() => growingPage ?? Page);
75
+ export const GioComponent = niceTry(() => growingComponent ?? Component);
76
+ export const GioBehavior = niceTry(() => growingBehavior ?? Behavior);
77
77
  export default gdp;
@@ -7,7 +7,14 @@ import {
7
7
  SystemInfo
8
8
  } from '@@/types/minipInstance';
9
9
  import { PLATFORMS } from '@@/types/platforms';
10
- import { isFunction, isObject, isString, last } from '@@/utils/glodash';
10
+ import {
11
+ isFunction,
12
+ isObject,
13
+ isString,
14
+ last,
15
+ typeOf,
16
+ isEmpty
17
+ } from '@@/utils/glodash';
11
18
  import EMIT_MSG from '@@/constants/emitMsg';
12
19
  import {
13
20
  limitString,
@@ -57,7 +64,7 @@ class BaseInstance implements MinipInstanceType {
57
64
  // 这个currentPath一般认为是在onLoad中获取的当前小程序页面的path,此时SDK还没有parse,保存的还是上一个页面的信息
58
65
  const currentPath = self.getCurrentPath();
59
66
  const { title } = arguments[0] || {};
60
- self.growingIO.dataStore.eventHooks.currentPage.settedTitle[
67
+ self.growingIO.dataStore.eventHooks.currentPage.configuredTitle[
61
68
  currentPath
62
69
  ] = title;
63
70
  }
@@ -126,38 +133,58 @@ class BaseInstance implements MinipInstanceType {
126
133
 
127
134
  // 获取页面标题
128
135
  getPageTitle = (page) => {
136
+ const platform = getPlainPlatform();
129
137
  let title = '';
130
- const instConfig = getPlainConfig(getPlainPlatform());
131
- try {
132
- // 第一优先级在base中的hook setNavigationBarTitle设置的值
133
- // 第二优先级支持客户自己在页面中设置页面title
134
- const data = page?.data || page.$data || {};
135
- title = isString(data?.gioPageTitle) ? data?.gioPageTitle : '';
136
- // 第三优先级取页面的navigationBarTitleText
137
- if (title.length === 0) {
138
- const pageInfo =
139
- instConfig.page[page.route] || instConfig.page[`${page.route}.html`];
140
- if (pageInfo) {
141
- title = pageInfo.window.navigationBarTitleText;
142
- } else {
143
- title = instConfig.global.window.navigationBarTitleText;
144
- }
138
+ let instConfig = getPlainConfig(platform);
139
+ if (typeOf(instConfig) === 'string') {
140
+ instConfig = niceTry(() => JSON.parse(instConfig)) ?? {};
141
+ }
142
+ // 第一优先级在base中的hook setNavigationBarTitle设置的值(在dataStore page实例中实现)
143
+ // 第二优先级支持客户自己在页面中设置页面title
144
+ const data = page?.data || page.$data || {};
145
+ title = isString(data?.gioPageTitle) ? data?.gioPageTitle : '';
146
+ if (instConfig) {
147
+ // 第三优先级app生命周期中拿不到page对象,拿生命周期的参数来匹配
148
+ const { enterParams } = this.growingIO.dataStore.eventHooks.appEffects;
149
+ if (!page.route && !isEmpty(enterParams)) {
150
+ page.route = enterParams.path || '';
151
+ title = this._getTitleFromTabBar(instConfig, page.route);
145
152
  }
146
- // 第四优先级取tabBar配置
147
- if (title.length === 0) {
148
- const tabPage = instConfig?.tabBar?.list?.find((p) => {
149
- return (
150
- p.pagePath === page.route || p.pagePath === `${page.route}.html`
151
- );
152
- });
153
- title = tabPage?.text || '';
153
+ // 第四优先级取页面的navigationBarTitleText
154
+ niceTry(() => {
155
+ if (!title) {
156
+ const instPage = instConfig.page || {};
157
+ 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
+ }
168
+ }
169
+ });
170
+ // 第五优先级取tabBar配置
171
+ if (!title) {
172
+ title = this._getTitleFromTabBar(instConfig, page.route);
154
173
  }
155
- } catch (e) {
156
- return '';
157
174
  }
158
175
  return limitString(title);
159
176
  };
160
177
 
178
+ private _getTitleFromTabBar = (
179
+ instConfig: any,
180
+ pageRoute: string
181
+ ): string => {
182
+ const tabPage = instConfig?.tabBar?.list?.find((p) => {
183
+ return p.pagePath === pageRoute || p.pagePath === `${pageRoute}.html`;
184
+ });
185
+ return tabPage?.text || '';
186
+ };
187
+
161
188
  /**
162
189
  * 存储相关
163
190
  */