gio-miniprogram-sdk 4.0.0

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 (103) hide show
  1. package/.babelrc +4 -0
  2. package/.eslintignore +11 -0
  3. package/.eslintrc.js +120 -0
  4. package/.github/workflows/greetings.yml +13 -0
  5. package/.github/workflows/publish.yml +43 -0
  6. package/.prettierignore +19 -0
  7. package/.prettierrc.js +9 -0
  8. package/LICENSE +674 -0
  9. package/README.md +103 -0
  10. package/babel.config.js +6 -0
  11. package/bin/build/all.sh +38 -0
  12. package/bin/build/full.sh +32 -0
  13. package/bin/build/jd.sh +14 -0
  14. package/bin/build/ks.sh +14 -0
  15. package/bin/build/my.sh +14 -0
  16. package/bin/build/plugins.sh +5 -0
  17. package/bin/build/qq.sh +14 -0
  18. package/bin/build/quickapp.sh +14 -0
  19. package/bin/build/swan.sh +14 -0
  20. package/bin/build/taro.sh +18 -0
  21. package/bin/build/tb.sh +18 -0
  22. package/bin/build/tt.sh +14 -0
  23. package/bin/build/uniapp.sh +18 -0
  24. package/bin/build/wx.sh +14 -0
  25. package/dist/alipay.js +1 -0
  26. package/dist/baidu.js +1 -0
  27. package/dist/bytedance.js +1 -0
  28. package/dist/jingdong.js +1 -0
  29. package/dist/kuaishou.js +1 -0
  30. package/dist/plugins/gioABTest.js +1 -0
  31. package/dist/plugins/gioCompress.js +1 -0
  32. package/dist/plugins/gioEventAutoTracking.js +1 -0
  33. package/dist/plugins/gioImpressionTracking.js +1 -0
  34. package/dist/qq.js +1 -0
  35. package/dist/quickapp.js +1 -0
  36. package/dist/taobao.js +1 -0
  37. package/dist/taro.js +1 -0
  38. package/dist/uniapp.js +1 -0
  39. package/dist/wechat.js +1 -0
  40. package/package.json +144 -0
  41. package/rollup.config.js +92 -0
  42. package/rollup.plugins.config.js +76 -0
  43. package/src/constants/config.ts +136 -0
  44. package/src/constants/regex.ts +4 -0
  45. package/src/core/dataStore/eventContextBuilder.ts +70 -0
  46. package/src/core/dataStore/eventHooks/appEffects.ts +220 -0
  47. package/src/core/dataStore/eventHooks/index.ts +403 -0
  48. package/src/core/dataStore/eventHooks/minipPage.ts +132 -0
  49. package/src/core/dataStore/eventHooks/pageEffects.ts +168 -0
  50. package/src/core/dataStore/index.ts +543 -0
  51. package/src/core/growingIO.ts +433 -0
  52. package/src/core/plugins.ts +152 -0
  53. package/src/core/uploader.ts +219 -0
  54. package/src/core/userStore.ts +203 -0
  55. package/src/index.ts +68 -0
  56. package/src/minipInstance/base.ts +287 -0
  57. package/src/minipInstance/framework.ts +22 -0
  58. package/src/minipInstance/jd.ts +11 -0
  59. package/src/minipInstance/ks.ts +12 -0
  60. package/src/minipInstance/my.ts +53 -0
  61. package/src/minipInstance/qq.ts +12 -0
  62. package/src/minipInstance/quickapp.ts +230 -0
  63. package/src/minipInstance/swan.ts +20 -0
  64. package/src/minipInstance/tb.ts +53 -0
  65. package/src/minipInstance/tt.ts +12 -0
  66. package/src/minipInstance/wx.ts +12 -0
  67. package/src/platformConfig/base.ts +86 -0
  68. package/src/platformConfig/framework.ts +29 -0
  69. package/src/platformConfig/jd.ts +11 -0
  70. package/src/platformConfig/ks.ts +11 -0
  71. package/src/platformConfig/my.ts +15 -0
  72. package/src/platformConfig/qq.ts +13 -0
  73. package/src/platformConfig/quickapp.ts +48 -0
  74. package/src/platformConfig/swan.ts +11 -0
  75. package/src/platformConfig/tb.ts +29 -0
  76. package/src/platformConfig/tt.ts +11 -0
  77. package/src/platformConfig/wx.ts +20 -0
  78. package/src/pluginsOut/README.md +50 -0
  79. package/src/pluginsOut/frameworks/gioTaobaoAdapter.ts +195 -0
  80. package/src/pluginsOut/frameworks/gioTaroAdapter.ts +358 -0
  81. package/src/pluginsOut/frameworks/gioUniAppAdapter.ts +220 -0
  82. package/src/pluginsOut/ordinary/gioABTest.ts +254 -0
  83. package/src/pluginsOut/ordinary/gioCompress.ts +251 -0
  84. package/src/pluginsOut/ordinary/gioCustomTracking.ts +71 -0
  85. package/src/pluginsOut/ordinary/gioEventAutoTracking.ts +164 -0
  86. package/src/pluginsOut/ordinary/gioImpressionTracking.ts +298 -0
  87. package/src/types/base.ts +150 -0
  88. package/src/types/dataStore.ts +43 -0
  89. package/src/types/eventHooks.ts +141 -0
  90. package/src/types/gioCustomTracking.ts +9 -0
  91. package/src/types/gioEventTracking.ts +10 -0
  92. package/src/types/gioPerformance.ts +8 -0
  93. package/src/types/growingIO.ts +102 -0
  94. package/src/types/minipInstance.ts +126 -0
  95. package/src/types/platforms.ts +65 -0
  96. package/src/types/plugins.ts +24 -0
  97. package/src/types/uploader.ts +26 -0
  98. package/src/types/userStore.ts +22 -0
  99. package/src/utils/glodash.ts +423 -0
  100. package/src/utils/tools.ts +384 -0
  101. package/src/utils/verifiers.ts +76 -0
  102. package/tsconfig.json +32 -0
  103. package/typings/global.d.ts +92 -0
@@ -0,0 +1,403 @@
1
+ import { EventHooksType, MinipPageType } from '@@/types/eventHooks';
2
+ import { GrowingIOType } from '@@/types/growingIO';
3
+ import { has, isArray, isFunction, typeOf, unset } from '@@/utils/glodash';
4
+ import { consoleText, getGlobal, niceTry } from '@@/utils/tools';
5
+
6
+ import AppEffects from './appEffects';
7
+ import MinipPage from './minipPage';
8
+ import PageEffects from './pageEffects';
9
+
10
+ class EventHooks implements EventHooksType {
11
+ private appHooked: boolean;
12
+ private pageHooked: boolean;
13
+ private componentHooked: boolean;
14
+ private behaviorHooked: boolean;
15
+ public defAppCbs: any;
16
+ public defPageCbs: any;
17
+ public appHandlers: string[];
18
+ public pageHandlers: string[];
19
+ public actionEventTypes: string[];
20
+ public originalApp: (any: any) => any;
21
+ public originalPage: (any: any) => any;
22
+ public originalComponent: (any: any) => any;
23
+ public originalBehavior: (any: any) => any;
24
+ public appEffects: any;
25
+ public pageEffects: any;
26
+ public actionEffects: any;
27
+ public currentPage: MinipPageType;
28
+
29
+ constructor(public growingIO: GrowingIOType) {
30
+ const config = this.growingIO?.platformConfig;
31
+ this.defAppCbs = {};
32
+ this.defPageCbs = {};
33
+ this.appHandlers = config.appHandlers;
34
+ this.pageHandlers = config.pageHandlers;
35
+ this.actionEventTypes = config.actionEventTypes;
36
+ this.originalApp = config.originalApp;
37
+ this.originalPage = config.originalPage;
38
+ this.originalComponent = config.originalComponent;
39
+ this.originalBehavior = config.originalBehavior ?? function () {}; // eslint-disable-line
40
+ this.appEffects = new AppEffects(this.growingIO);
41
+ this.pageEffects = new PageEffects(this.growingIO);
42
+ this.currentPage = new MinipPage(this.growingIO);
43
+ }
44
+
45
+ // 判断是否为非构造函数的一个函数
46
+ isNormalFc = (key: string, method: any) => {
47
+ return isFunction(method) && key !== 'constructor';
48
+ };
49
+
50
+ // 对象的遍历
51
+ objectTraverse = (target: any, fn: any) => {
52
+ Object.getOwnPropertyNames(target).forEach((k: string) => fn(k, target));
53
+ if (has(target, 'methods')) {
54
+ Object.getOwnPropertyNames(target.methods).forEach((k: string) => {
55
+ if (!target[k]) {
56
+ fn(k, target.methods);
57
+ }
58
+ });
59
+ }
60
+ if (has(target, 'lifetimes')) {
61
+ Object.getOwnPropertyNames(target.lifetimes).forEach((k: string) => {
62
+ if (!target[k]) {
63
+ fn(k, target.lifetimes);
64
+ }
65
+ });
66
+ }
67
+ if (has(target, 'pageLifetimes')) {
68
+ Object.getOwnPropertyNames(target.pageLifetimes).forEach((k: string) => {
69
+ if (!target[k]) {
70
+ fn(k, target.pageLifetimes);
71
+ }
72
+ });
73
+ }
74
+ };
75
+
76
+ // 补充生命周期函数
77
+ supLifeFcs = (target: any, type: 'app' | 'page') => {
78
+ if (isArray(this[`${type}Handlers`])) {
79
+ this[`${type}Handlers`].forEach((k: string) => {
80
+ // 除分享以外
81
+ if (
82
+ !isFunction(target[k]) &&
83
+ !['onShareAppMessage', 'onShareTimeline'].includes(k)
84
+ ) {
85
+ target[k] = () => {}; // eslint-disable-line
86
+ }
87
+ });
88
+ }
89
+ };
90
+
91
+ // 生命周期方法effects
92
+ lifeFcEffects = (eventName: string, method: any, cType: 'App' | 'Page') => {
93
+ const self = this;
94
+ if (['onShareTimeline', 'onAddToFavorites'].includes(eventName)) {
95
+ // onShareTimeline和onAddToFavorites不能异步执行,单独处理
96
+ return function (...args) {
97
+ let result = method.apply(this, args);
98
+ if (
99
+ eventName === 'onShareTimeline' &&
100
+ self.growingIO.vdsConfig.followShare
101
+ ) {
102
+ result = self.currentPage.updateTimelineResult(result ?? {});
103
+ }
104
+ if (eventName === 'onAddToFavorites') {
105
+ result = self.currentPage.updateAddFavoritesResult(result ?? {});
106
+ }
107
+ const argsArray = Array.prototype.slice.call(args);
108
+ if (result) {
109
+ argsArray.push(result);
110
+ }
111
+ // 执行effects
112
+ self[`def${cType}Cbs`][eventName].apply(this, argsArray);
113
+ return result;
114
+ };
115
+ } else {
116
+ // 其他生命周期可以异步执行
117
+ return async function (...args) {
118
+ let result;
119
+ try {
120
+ // 分享处理
121
+ if (eventName === 'onShareAppMessage') {
122
+ // 先执行分享的生命周期拿到分享数据
123
+ // 与基础库保持一致,没有返回值时默认使用{}
124
+ result = (await method.apply(this, args)) ?? {};
125
+ if (typeOf(result.promise) === 'promise') {
126
+ const f = async function () {
127
+ let sRes = result;
128
+ return new Promise((resolve) => {
129
+ // 如果3秒后result.promise没有返回结果,则返回的是默认的result值
130
+ // https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html#onShareAppMessage-Object-object
131
+ let t = setTimeout(() => {
132
+ resolve({ ...sRes });
133
+ clearTimeout(t);
134
+ t = undefined;
135
+ }, 3000);
136
+ result.promise.then((res) => {
137
+ sRes = res;
138
+ resolve({ ...sRes });
139
+ clearTimeout(t);
140
+ t = undefined;
141
+ });
142
+ });
143
+ };
144
+ result = { ...result, ...((await f()) as any) };
145
+ unset(result, 'promise');
146
+ }
147
+ if (self.growingIO.vdsConfig.followShare) {
148
+ result = self.currentPage.updateAppMessageResult(result ?? {});
149
+ }
150
+ }
151
+ const argsArray = Array.prototype.slice.call(args);
152
+ if (result) {
153
+ argsArray.push(result);
154
+ }
155
+ // 执行effects
156
+ self[`def${cType}Cbs`][eventName].apply(this, argsArray);
157
+ } catch (error) {
158
+ consoleText(error, 'error');
159
+ }
160
+ // 执行分享之外的生命周期函数
161
+ if (eventName !== 'onShareAppMessage') {
162
+ result = method.apply(this, args);
163
+ }
164
+ self.growingIO.emitter.emit('minipLifecycle', {
165
+ event: `${cType} ${eventName}End`,
166
+ timestamp: Date.now(),
167
+ params: { instance: this, arguments: Array.from(args) }
168
+ });
169
+ return result;
170
+ };
171
+ }
172
+ };
173
+
174
+ // 自定义方法effects
175
+ customFcEffects = (eventName: string, method: any) => {
176
+ const self = this;
177
+ return function (...args) {
178
+ let result;
179
+ if (
180
+ self.growingIO.vdsConfig.autotrack &&
181
+ self.growingIO.plugins.gioEventAutoTracking
182
+ ) {
183
+ try {
184
+ let event: any = args[0] || {};
185
+ // 有的框架的点击事件传参时需要在最后一个参数加上原生event才能触发SDK的事件
186
+ if (
187
+ !(has(event, 'type') && (event?.currentTarget || event?.target))
188
+ ) {
189
+ event = args[args.length - 1];
190
+ }
191
+ if (
192
+ (event?.currentTarget || event?.target) &&
193
+ self.actionEventTypes.includes(event.type)
194
+ ) {
195
+ // 无埋点事件插件未挂载时进行挂载
196
+ if (!isFunction(self.actionEffects)) {
197
+ self.actionEffects =
198
+ self.growingIO.plugins?.gioEventAutoTracking?.main ||
199
+ function () {}; //eslint-disable-line
200
+ }
201
+ self?.actionEffects(event, eventName);
202
+ }
203
+ } catch (error) {
204
+ consoleText(error, 'error');
205
+ }
206
+ }
207
+ // 执行原逻辑
208
+ result = method.apply(this, args);
209
+ return result;
210
+ };
211
+ };
212
+
213
+ // App中方法代理
214
+ appApplyProxy = (eventName: string, method: any) => {
215
+ if (this.appHandlers.includes(eventName)) {
216
+ return this.lifeFcEffects(eventName, method, 'App');
217
+ } else {
218
+ return this.customFcEffects(eventName, method);
219
+ }
220
+ };
221
+
222
+ // Page中方法代理
223
+ pageApplyProxy = (eventName: string, method: any) => {
224
+ if (this.pageHandlers.includes(eventName)) {
225
+ return this.lifeFcEffects(eventName, method, 'Page');
226
+ } else {
227
+ return this.customFcEffects(eventName, method);
228
+ }
229
+ };
230
+
231
+ // App重写遍历
232
+ appOverriding = (options: any) => {
233
+ this.setAppEffectCbs();
234
+ const fn = (k: string, target: any) => {
235
+ if (this.isNormalFc(k, target[k])) {
236
+ target[k] = this.appApplyProxy(k, target[k]);
237
+ }
238
+ };
239
+ // 补充未定义的生命周期,防止不触发vst和cls事件(vst依赖onShow、cls依赖onHide)
240
+ this.supLifeFcs(options, 'app');
241
+ // 遍历方法,进行重写
242
+ this.objectTraverse(options, fn);
243
+ return options;
244
+ };
245
+
246
+ // Page重写遍历
247
+ pageOverriding = (options: any) => {
248
+ this.setPageEffectCbs();
249
+ const fn = (k: string, target: any) => {
250
+ if (this.isNormalFc(k, target[k])) {
251
+ target[k] = this.pageApplyProxy(k, target[k]);
252
+ }
253
+ };
254
+ // 补充未定义的生命周期,防止不触发page事件(page依赖onShow)
255
+ this.supLifeFcs(options, 'page');
256
+ // 遍历方法,进行重写
257
+ this.objectTraverse(options, fn);
258
+ return options;
259
+ };
260
+
261
+ // Component/Behavior重写(重写除构造函数之外的所有方法)
262
+ componentOverriding = (options: any) => {
263
+ this.setPageEffectCbs();
264
+ const fn = (k: string, target: any) => {
265
+ if (this.isNormalFc(k, target[k])) {
266
+ target[k] = this.pageApplyProxy(k, target[k]);
267
+ }
268
+ };
269
+ if (!options.methods) {
270
+ options.methods = {};
271
+ }
272
+ // 补充生命周期方法
273
+ this.supLifeFcs(
274
+ this.growingIO.inPlugin ? options : options.methods,
275
+ 'page'
276
+ );
277
+ // 遍历重写方法
278
+ this.objectTraverse(
279
+ this.growingIO.inPlugin ? options : options.methods,
280
+ fn
281
+ );
282
+ return options;
283
+ };
284
+
285
+ // 挂载App生命周期的effect方法
286
+ setAppEffectCbs = () => {
287
+ const self = this;
288
+ this.appHandlers.forEach((handlerName: string) => {
289
+ this.defAppCbs[handlerName] = function (...args) {
290
+ self.appEffects.main(handlerName, args);
291
+ };
292
+ });
293
+ };
294
+
295
+ // 挂载Page/Component生命周期的effect方法
296
+ setPageEffectCbs = () => {
297
+ const self = this;
298
+ this.pageHandlers.forEach((handlerName: string) => {
299
+ this.defPageCbs[handlerName] = function (...args) {
300
+ self.pageEffects.main(this, handlerName, args);
301
+ };
302
+ });
303
+ };
304
+
305
+ growingApp = (app: any) => this.originalApp(this.appOverriding(app));
306
+
307
+ growingPage = (page: any) => this.originalPage(this.pageOverriding(page));
308
+
309
+ growingComponent = (component: any) =>
310
+ this.originalComponent(this.componentOverriding(component));
311
+
312
+ growingBehavior = (behavior: any) =>
313
+ this.originalBehavior(this.componentOverriding(behavior));
314
+
315
+ nativeGrowing = (
316
+ designated: string[] = ['App', 'Page', 'Component', 'Behavior']
317
+ ) => {
318
+ const self = this;
319
+ const { platformConfig } = this.growingIO;
320
+ const platformHooks = platformConfig.hooks;
321
+ this.setAppEffectCbs();
322
+ this.setPageEffectCbs();
323
+ if (designated.includes('App')) {
324
+ try {
325
+ // 重写App
326
+ if (platformHooks.App && !this.appHooked) {
327
+ App = function (...args) {
328
+ return self.growingApp(args[0]);
329
+ };
330
+ this.appHooked = true;
331
+ }
332
+ } catch (error) {
333
+ // 在插件中可能会不存在App
334
+ }
335
+ }
336
+ if (designated.includes('Page')) {
337
+ try {
338
+ // 重写Page
339
+ if (platformHooks.Page && !this.pageHooked) {
340
+ Page = function (...args) {
341
+ return self.growingPage(args[0]);
342
+ };
343
+ this.pageHooked = true;
344
+ }
345
+ } catch (error) {
346
+ // 在插件中可能会不存在Page
347
+ }
348
+ }
349
+ if (designated.includes('Component')) {
350
+ try {
351
+ // 重写Component
352
+ if (platformHooks.Component && !this.componentHooked) {
353
+ Component = function (...args) {
354
+ return self.growingComponent(args[0]);
355
+ };
356
+ this.componentHooked = true;
357
+ }
358
+ } catch (error) {
359
+ //
360
+ }
361
+ }
362
+ if (designated.includes('Behavior')) {
363
+ try {
364
+ // 重写Behavior
365
+ if (platformHooks.Behavior && !this.behaviorHooked) {
366
+ Behavior = function (...args) {
367
+ return self.growingBehavior(args[0]);
368
+ };
369
+ this.behaviorHooked = true;
370
+ }
371
+ } catch (error) {
372
+ // 部分小程序不存在Behavior
373
+ }
374
+ }
375
+ };
376
+
377
+ // 初始化无埋点
378
+ initEventHooks = () => {
379
+ const self = this;
380
+ const { platformConfig, gioPlatform } = this.growingIO;
381
+ if (platformConfig.canHook) {
382
+ this.nativeGrowing();
383
+ getGlobal().GioApp = niceTry(() => App ?? window.GioApp);
384
+ getGlobal().GioPage = niceTry(() => Page ?? window.GioPage);
385
+ getGlobal().GioComponent = niceTry(
386
+ () => Component ?? window.GioComponent
387
+ );
388
+ getGlobal().GioBehavior = niceTry(() => Behavior);
389
+ } else if (gioPlatform === 'quickapp') {
390
+ window.GioApp = function (...args) {
391
+ return self.appOverriding(args[0]);
392
+ };
393
+ window.GioPage = function (...args) {
394
+ return self.pageOverriding(args[0]);
395
+ };
396
+ window.GioComponent = function (...args) {
397
+ return self.pageOverriding(args[0]);
398
+ };
399
+ }
400
+ };
401
+ }
402
+
403
+ export default EventHooks;
@@ -0,0 +1,132 @@
1
+ import { has, head, isEmpty, last, unset } from '@@/utils/glodash';
2
+ import { GrowingIOType } from '@@/types/growingIO';
3
+ import { MinipPageType, PageShareResult } from '@@/types/eventHooks';
4
+ import { qsStringify, normalPath, splitPath, qsParse } from '@@/utils/tools';
5
+
6
+ class MinipPage implements MinipPageType {
7
+ public path: string;
8
+ public time: number;
9
+ public query: any;
10
+ // 页面title (优先级:setNavigationBarTitle > data.gioPageTitle[不保证能取到] > config.js中设置的值 > tabBar配置)
11
+ public title: string;
12
+ // 通过调用wx.setNavigationBarTitle设置的title
13
+ public settedTitle: any;
14
+ // 当前页面参数中的分享id
15
+ public queryShareId: string;
16
+ // 页面级属性
17
+ public pageProps: any;
18
+ // 上一个执行的小程序生命周期
19
+ public lastLifecycle: string;
20
+ // 当前执行的小程序生命周期
21
+ public currentLifecycle: string;
22
+
23
+ constructor(public growingIO: GrowingIOType) {
24
+ this.query = undefined;
25
+ this.settedTitle = {};
26
+ this.pageProps = {};
27
+ }
28
+
29
+ // 存储页面参数
30
+ parsePage = (page: any, query: any) => {
31
+ // wx/my取route; swan取uri; tt取__route__; qq无值
32
+ const path =
33
+ page.route || page.uri || page.__route__ || page?.$page?.fullPath || '';
34
+ if (!isEmpty(query)) {
35
+ this.query = this.getQuery(query);
36
+ } else {
37
+ this.query = undefined;
38
+ }
39
+ if (this.path !== path) {
40
+ this.time = Date.now();
41
+ }
42
+ this.path = path;
43
+ this.title =
44
+ // 如果在parse前(onLoad)动态设置了title,则优先获取动态设置的值
45
+ this.settedTitle[this.path] ||
46
+ this.growingIO.minipInstance.getPageTitle(
47
+ page || this.growingIO.minipInstance.getCurrentPage()
48
+ );
49
+ };
50
+
51
+ // 获取页面参数
52
+ getQuery = (query: any) => {
53
+ const filtQeury = { ...query };
54
+ unset(filtQeury, 'wxShoppingListScene');
55
+ return qsStringify(filtQeury);
56
+ };
57
+
58
+ // 获取上一个页面路径
59
+ getReferralPage = () => {
60
+ const {
61
+ minipInstance,
62
+ dataStore: { lastPageEvent, scene }
63
+ } = this.growingIO;
64
+ return (
65
+ lastPageEvent?.path ||
66
+ (scene ? `scn:${minipInstance.scnPrefix}${scene}` : null)
67
+ );
68
+ };
69
+
70
+ // 保存分享id(记录是从哪个用户id的分享来的)
71
+ saveShareId = (query: any) => {
72
+ if (query?.gioShareId) {
73
+ this.queryShareId = query.gioShareId;
74
+ }
75
+ };
76
+
77
+ // 处理分享参数
78
+ buildShareQuery(
79
+ result: PageShareResult // 客户自定义的参数
80
+ ): [string, string] {
81
+ // 自定义path的地址参数截取(onShareAppMessage中的页面参数是拼在地址中的)
82
+ const customSplit = splitPath(result.path ?? '');
83
+
84
+ let path = this.path;
85
+ let parsedQeury: any = {};
86
+ let resultHasPath = has(result, 'path');
87
+ // 优先使用自定义的地址
88
+ if (resultHasPath) {
89
+ path = head(customSplit);
90
+ parsedQeury = qsParse(last(customSplit)) || {};
91
+ }
92
+
93
+ // 自定义path中没有截取到query说明是在onShareAppMessage中没有参数,或是在onShareTimeline中需要取自定义query
94
+ if (isEmpty(parsedQeury)) {
95
+ parsedQeury = qsParse(result.query ?? '') || {};
96
+ }
97
+
98
+ // 以上两种都是自定义的地址和参数,不做处理直接用,防止出现encode/decode的问题。
99
+
100
+ // 自定义query没有值则使用当前页面默认参数
101
+ // 如果path存在,但是不携带参数,此时不使用当前页面的默认参数
102
+ if (!resultHasPath && isEmpty(parsedQeury)) {
103
+ parsedQeury = qsParse(this.query ?? '') || {};
104
+ }
105
+
106
+ return [path, qsStringify(parsedQeury)];
107
+ }
108
+
109
+ // 更新分享结果
110
+ updateShareResult = (result: PageShareResult) => {
111
+ const [path, queryString] = this.buildShareQuery(result);
112
+ result.path = normalPath(path + (queryString ? `?${queryString}` : ''));
113
+ result.query = queryString;
114
+ return result;
115
+ };
116
+
117
+ // 更新分享转发事件的结果
118
+ updateAppMessageResult = this.updateShareResult;
119
+
120
+ // 更新分享朋友圈结果
121
+ updateTimelineResult = this.updateShareResult;
122
+
123
+ // 更新收藏结果
124
+ updateAddFavoritesResult = (result: PageShareResult) => {
125
+ const [path, queryString] = this.buildShareQuery(result);
126
+ result.path = normalPath(path + (queryString ? `?${queryString}` : ''));
127
+ result.query = queryString;
128
+ return result;
129
+ };
130
+ }
131
+
132
+ export default MinipPage;
@@ -0,0 +1,168 @@
1
+ import { get, isEmpty, isFunction, unset } from '@@/utils/glodash';
2
+ import { GrowingIOType } from '@@/types/growingIO';
3
+ import { PageHookLifeCircle } from '@@/types/eventHooks';
4
+
5
+ class PageEffects {
6
+ public buildTabClickEvent: (tabItem: any) => void;
7
+ private prevEvent: any;
8
+ private argQuery: any;
9
+ constructor(public growingIO: GrowingIOType) {
10
+ this.prevEvent = {};
11
+ this.argQuery = {};
12
+ }
13
+
14
+ main = (page: any, event: PageHookLifeCircle, args: any) => {
15
+ const eventTime = Date.now();
16
+ const {
17
+ emitter,
18
+ minipInstance,
19
+ plugins,
20
+ vdsConfig,
21
+ platformConfig,
22
+ dataStore: {
23
+ shareOut,
24
+ eventHooks,
25
+ toggleShareOut,
26
+ buildAppMessageEvent,
27
+ buildTimelineEvent,
28
+ buildAddFavorites
29
+ },
30
+ inPlugin
31
+ }: GrowingIOType = this.growingIO;
32
+ const { currentPage } = eventHooks;
33
+ if (
34
+ // 防止重写页面后可能出现重复的事件
35
+ this.prevEvent[event] &&
36
+ Date.now() - Number(this.prevEvent[event]) < 50
37
+ ) {
38
+ return;
39
+ }
40
+ if (!page) {
41
+ page = minipInstance.getCurrentPage();
42
+ }
43
+ if (!page.route) {
44
+ page.route = minipInstance.getCurrentPath(page);
45
+ }
46
+ const path =
47
+ page.route || page.uri || page.__route__ || page?.$page?.fullPath || '';
48
+ emitter.emit('minipLifecycle', {
49
+ event: `Page ${event}`,
50
+ timestamp: eventTime,
51
+ params: { page, args: args[0] }
52
+ });
53
+ if (vdsConfig.debug) {
54
+ console.log('Page:', path, '#', event, eventTime);
55
+ }
56
+ this.prevEvent[event] = Date.now();
57
+ const pageListeners = platformConfig.listeners.page;
58
+ // 向插件广播事件
59
+ emitter.emit('onComposeBefore', {
60
+ page,
61
+ event: `Page ${event}`,
62
+ params: { page, args: args[0] }
63
+ });
64
+ currentPage.lastLifecycle = currentPage.currentLifecycle;
65
+ currentPage.currentLifecycle = event;
66
+ switch (event) {
67
+ case pageListeners.pageLoad: {
68
+ this.argQuery[path] =
69
+ get(page, 'options') ||
70
+ get(page, '__displayReporter.query') ||
71
+ get(page, '$page.query') ||
72
+ get(page, '$wx.__displayReporter.query') ||
73
+ args[0] ||
74
+ {};
75
+ unset(this.argQuery[path], '$taroTimestamp');
76
+ currentPage.parsePage(page, this.argQuery[path]);
77
+ break;
78
+ }
79
+ case pageListeners.pageShow: {
80
+ if (inPlugin) {
81
+ currentPage.parsePage(page, this.argQuery[path]);
82
+ if (!currentPage.path) {
83
+ // 插件中没有页面时直接将插件appId作为页面信息
84
+ currentPage.path = `/插件${vdsConfig.appId}}`;
85
+ currentPage.title = `/插件${vdsConfig.appId}}`;
86
+ }
87
+ this.buildPageEvent();
88
+ } else if (!shareOut || !eventHooks.currentPage.time) {
89
+ // 不是因为分享切出再返回的onshow(视为第一次进入改页面)和切出去以后因为超时或者进入的场景值不一致时(会在appshow清掉页面时间),发page
90
+ currentPage.parsePage(page, this.argQuery[path]);
91
+ // 超时进入页面时前后path一致parsePage方法不会重置页面时间,可能会没有值,所以要补充重设一次
92
+ eventHooks.currentPage.time = Date.now();
93
+ this.buildPageEvent();
94
+ }
95
+ // 分享标记置为false
96
+ toggleShareOut(false);
97
+ // 保存分享id(记录是从哪个用户id的分享来的)
98
+ currentPage.saveShareId(this.argQuery[path]);
99
+ break;
100
+ }
101
+ case pageListeners.pageHide:
102
+ case pageListeners.pageUnload: {
103
+ break;
104
+ }
105
+ case pageListeners.shareApp: {
106
+ toggleShareOut(true);
107
+ if (vdsConfig.followShare) {
108
+ buildAppMessageEvent(args);
109
+ }
110
+ break;
111
+ }
112
+ case pageListeners.shareTime: {
113
+ if (vdsConfig.followShare) {
114
+ buildTimelineEvent(args);
115
+ }
116
+ break;
117
+ }
118
+ case pageListeners.addFavorites: {
119
+ buildAddFavorites(args);
120
+ break;
121
+ }
122
+ case pageListeners.tabTap: {
123
+ const buildTabClickEvent =
124
+ plugins?.gioEventAutoTracking?.buildTabClickEvent;
125
+ if (
126
+ vdsConfig.autotrack &&
127
+ buildTabClickEvent &&
128
+ isFunction(buildTabClickEvent)
129
+ ) {
130
+ buildTabClickEvent(args[0]);
131
+ }
132
+ break;
133
+ }
134
+ default:
135
+ break;
136
+ }
137
+ // 页面销毁移除当前页面的属性
138
+ if (event === pageListeners.pageUnload) {
139
+ currentPage.pageProps[path] = undefined;
140
+ }
141
+ };
142
+
143
+ // 构建页面访问事件
144
+ buildPageEvent = (props?: any) => {
145
+ const {
146
+ dataStore: { eventContextBuilder, eventInterceptor, eventHooks }
147
+ } = this.growingIO;
148
+ const { currentPage } = eventHooks;
149
+ const event = {
150
+ eventType: 'PAGE',
151
+ referralPage: currentPage.getReferralPage(),
152
+ ...eventContextBuilder(),
153
+ timestamp: currentPage.time
154
+ };
155
+ // 添加页面属性
156
+ if (!isEmpty(currentPage.pageProps[event.path])) {
157
+ event.attributes = currentPage.pageProps[event.path];
158
+ }
159
+ if (!isEmpty(props) && props.path) {
160
+ event.path = props.path;
161
+ event.query = props.query;
162
+ event.title = props.title ?? event.title;
163
+ }
164
+ eventInterceptor(event);
165
+ };
166
+ }
167
+
168
+ export default PageEffects;