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,92 @@
1
+ // @ts-nocheck
2
+ import { babel } from '@rollup/plugin-babel';
3
+ import { version } from './package.json';
4
+ import alias from '@rollup/plugin-alias';
5
+ import commonjs from '@rollup/plugin-commonjs';
6
+ import filesize from 'rollup-plugin-filesize';
7
+ import path from 'path';
8
+ import replace from '@rollup/plugin-replace';
9
+ import resolve from '@rollup/plugin-node-resolve';
10
+ import terser from '@rollup/plugin-terser';
11
+ import typescript from '@rollup/plugin-typescript';
12
+
13
+ const processENV = process.argv[process.argv.length - 1]
14
+ .split('-')
15
+ .filter((o) => o);
16
+
17
+ const platform = processENV[0];
18
+ const frameName = processENV[1];
19
+ const PLATFORMS = {
20
+ wx: 'wechat',
21
+ my: 'alipay',
22
+ swan: 'baidu',
23
+ tt: 'bytedance',
24
+ qq: 'qq',
25
+ ks: 'kuaishou',
26
+ tb: 'taobao',
27
+ jd: 'jingdong',
28
+ quickapp: 'quickapp'
29
+ };
30
+
31
+ // 控制台打印当前打包的环境和小程序平台
32
+ console.log(
33
+ `Packaging ${
34
+ PLATFORMS[platform]
35
+ ? 'platform:' + PLATFORMS[platform]
36
+ : 'framework:' + frameName
37
+ }`
38
+ );
39
+
40
+ const fileName = () => {
41
+ let n = 'dist/';
42
+ n += PLATFORMS[platform] ?? frameName;
43
+ n += '.js';
44
+ return n;
45
+ };
46
+
47
+ const config = {
48
+ input: 'src/index.ts',
49
+ output: {
50
+ file: fileName(),
51
+ format: 'es'
52
+ },
53
+ plugins: [
54
+ replace({
55
+ __SDK_VERSION__: version,
56
+ __GIO_PLATFORM__: PLATFORMS[platform] ? platform : 'framework',
57
+ __GIO_FRAMEWORK__: PLATFORMS[platform] ? 'native' : frameName,
58
+ __GIO_PLATFORM_CONFIG__: `@@/platformConfig/${platform}.ts`,
59
+ __GIO_PLATFORM_INSTANCE__: `@@/minipInstance/${platform}.ts`
60
+ }),
61
+ alias({
62
+ entries: {
63
+ '@@': path.resolve(__dirname, 'src')
64
+ }
65
+ }),
66
+ resolve(),
67
+ commonjs({ extensions: ['.js', '.ts'] }),
68
+ typescript(),
69
+ babel({
70
+ babelHelpers: 'bundled',
71
+ exclude: 'node_modules/**',
72
+ extensions: ['.ts', '.js', '.json']
73
+ }),
74
+ terser({
75
+ ecma: 'es6',
76
+ format: { comments: false },
77
+ compress: {
78
+ passes: 2,
79
+ unsafe: true,
80
+ unsafe_comps: true,
81
+ unsafe_proto: true,
82
+ unsafe_undefined: true
83
+ }
84
+ }),
85
+ filesize({
86
+ showMinifiedSize: false,
87
+ showGzippedSize: false
88
+ })
89
+ ]
90
+ };
91
+
92
+ export default config;
@@ -0,0 +1,76 @@
1
+ // @ts-nocheck
2
+ import { babel } from '@rollup/plugin-babel';
3
+ import alias from '@rollup/plugin-alias';
4
+ import commonjs from '@rollup/plugin-commonjs';
5
+ import filesize from 'rollup-plugin-filesize';
6
+ import path from 'path';
7
+ import resolve from '@rollup/plugin-node-resolve';
8
+ import terser from '@rollup/plugin-terser';
9
+ import typescript from '@rollup/plugin-typescript';
10
+
11
+ const fs = require('fs');
12
+
13
+ const processENV = process.argv[process.argv.length - 1]
14
+ .split('-')
15
+ .filter((o) => o);
16
+ // 获取是否打包全量插件
17
+ const folder = processENV[0] ?? 'all';
18
+
19
+ const expls = [];
20
+ const plgs = fs.readdirSync(`./src/pluginsOut/${folder}`);
21
+ plgs.forEach((plg) => {
22
+ if (plg && plg.endsWith('.ts') && plg !== 'gioCustomTracking.ts') {
23
+ const outName = plg.split('.')[0];
24
+ expls.push({
25
+ input: `${folder}/${plg}`,
26
+ output: `${folder === 'ordinary' ? 'plugins/' : folder + '/'
27
+ }${outName}.js`,
28
+ name: `${outName}.js`
29
+ });
30
+ }
31
+ });
32
+
33
+ const configs = [];
34
+ const configGenerat = ({ input, output, name }) => ({
35
+ input: `src/pluginsOut/${input}`,
36
+ output: {
37
+ file: `dist/${output}`,
38
+ format: 'es',
39
+ name
40
+ },
41
+ plugins: [
42
+ alias({
43
+ entries: {
44
+ '@@': path.resolve(__dirname, 'src')
45
+ }
46
+ }),
47
+ resolve(),
48
+ commonjs({ extensions: ['.js', '.ts'] }),
49
+ typescript({ target: 'ES5' }),
50
+ babel({
51
+ babelHelpers: 'bundled',
52
+ exclude: 'node_modules/**',
53
+ extensions: ['.ts']
54
+ }),
55
+ terser({
56
+ ecma: 'es5',
57
+ format: { comments: false },
58
+ compress: {
59
+ passes: 2,
60
+ unsafe: true,
61
+ unsafe_comps: true,
62
+ unsafe_proto: true,
63
+ unsafe_undefined: true
64
+ }
65
+ }),
66
+ filesize({
67
+ showMinifiedSize: false,
68
+ showGzippedSize: false
69
+ })
70
+ ]
71
+ });
72
+ expls.forEach((o) => {
73
+ if (o) configs.push(configGenerat(o));
74
+ });
75
+
76
+ export default configs;
@@ -0,0 +1,136 @@
1
+ // SDK系统的默认配置项
2
+ export const DEFAULT_SETTINGS = {
3
+ // 是否开启无埋点
4
+ autotrack: { type: 'boolean', default: true },
5
+ // 是否开启加密压缩
6
+ compress: { type: 'boolean', default: true },
7
+ // 是否开启数据采集
8
+ dataCollect: { type: 'boolean', default: true },
9
+ // 是否开启调试模式
10
+ debug: { type: 'boolean', default: false },
11
+ // 是否开启
12
+ idMapping: { type: 'boolean', default: false },
13
+ enableIdMapping: { type: 'boolean', default: false },
14
+ // 与内嵌页打通时额外的信息参数
15
+ extraParams: { type: 'array', default: [] },
16
+ // 是否开启分享跟踪
17
+ followShare: { type: 'boolean', default: true },
18
+ // 是否开启强制登录
19
+ forceLogin: { type: 'boolean', default: false },
20
+ // 或略上报字段
21
+ ignoreFields: { type: 'array', default: [] },
22
+ // 是否开启强制插件模式
23
+ pluginMode: { type: 'boolean', default: false },
24
+ // 是否使用原始来源信息作为访问事件的参数上报
25
+ originalSource: { type: 'boolean', default: true },
26
+ // session保活时长(5分钟)
27
+ keepAlive: { type: 'number', default: 300000 },
28
+ // 性能采集配置
29
+ performance: { type: 'object', default: { monitor: true, exception: true } },
30
+ // 数据上报域名
31
+ serverUrl: { type: 'string', default: 'https://napi.growingio.com' },
32
+ // 是否标记为分包
33
+ subpackage: { type: 'boolean', default: false },
34
+ // taro框架实例
35
+ taro: { type: ['object', 'module'], default: false },
36
+ // taro框架vue实例
37
+ taroVue: { type: ['object', 'function'], default: false },
38
+ // 淘宝小程序/小部件配置
39
+ tbConfig: {
40
+ type: 'object',
41
+ default: {
42
+ cloud: undefined,
43
+ cloudFuncSend: false,
44
+ cloudFuncName: 'httpTunnel',
45
+ cloudFuncHandler: 'main',
46
+ cloudAppId: undefined,
47
+ path: undefined
48
+ }
49
+ },
50
+ // uniapp vue实例
51
+ uniVue: { type: ['object', 'function'], default: false },
52
+ // 上报间隔(1秒)
53
+ uploadInterval: { type: 'number', default: 1000 },
54
+ // 小程序应用版本
55
+ version: { type: 'string', default: '1.0.0' }
56
+ };
57
+
58
+ // 通过gdp(xxxx)允许调用的通用方法
59
+ export const HANDLERS = [
60
+ 'clearGeneralProps', // 移除埋点通用属性
61
+ 'clearTrackTimer', // 清除所有事件计时器
62
+ 'clearUserId', // 清除登录用户ID
63
+ 'getDeviceId', // 获取设备ID(匿名用户ID)
64
+ 'getGioInfo', // 内嵌页打通信息
65
+ 'getOption', // 获取当前配置项状态
66
+ 'identify', // 强制登录
67
+ 'init', // 初始化SDK
68
+ 'registerPlugins', // 手动注册插件
69
+ 'removeTimer', // 移除事件计时器
70
+ 'setGeneralProps', // 设置埋点通用属性
71
+ 'setLocation', // 手动设置位置信息(2022/4/29新增api,原getLocation废弃)
72
+ 'setOption', // 动态修改配置项
73
+ 'setPageAttributes', // 设置页面属性
74
+ 'setUserAttributes', // 设置用户属性
75
+ 'setUserId', // 设置登录用户ID
76
+ 'track', // 埋点
77
+ 'trackTimerEnd', // 停止事件计时器并上报事件
78
+ 'trackTimerPause', // 暂停事件计时器
79
+ 'trackTimerResume', // 恢复事件计时器
80
+ 'trackTimerStart', // 初始化事件计时器
81
+ 'updateImpression', // 手动更新曝光监听
82
+ 'getABTest' // 获取ABTest数据
83
+ ];
84
+
85
+ // 允许通过setOption修改的配置项
86
+ export const ALLOWED_MODIFY_OPTIONS = {
87
+ autotrack: '无埋点',
88
+ dataCollect: '数据采集',
89
+ debug: '调试模式',
90
+ serverUrl: '数据上报服务地址'
91
+ };
92
+
93
+ // 已废弃方法
94
+ export const DEPRECATED_HANDLERS = [
95
+ 'enableDebug', // 4.0废弃
96
+ 'setAutotrack', // 4.0废弃
97
+ 'setDataCollect', // 4.0废弃
98
+ 'setTrackerHost', // 4.0废弃
99
+ 'setTrackerScheme', // 4.0废弃
100
+ 'setConfig', // 3.8重构时废弃,原因:太多的客户以为是修改配置的接口导致用错
101
+ 'collectImp', // 3.8重构时废弃,原因:重构时在页面onShow/onReady是自动注册
102
+ 'setPlatformProfile', // 3.8重构时废弃,原因:使用setUserAttributes代替
103
+ 'getLocation' // 2022/4/29废弃,原因:https://developers.weixin.qq.com/community/develop/doc/000e8ccb5ac498318cbd26c495bc01 ;https://developers.weixin.qq.com/miniprogram/dev/api/location/wx.getLocation.html
104
+ ];
105
+
106
+ // 允许忽略的上报字段
107
+ export const IGNORE_PARAMS = [
108
+ 'deviceBrand',
109
+ 'deviceModel',
110
+ 'deviceType',
111
+ 'networkState',
112
+ 'screenHeight',
113
+ 'screenWidth',
114
+ 'operatingSystem'
115
+ ];
116
+
117
+ // 额外打通的字段
118
+ export const EXTRA_INFO_PARAMS: string[] = [
119
+ ...IGNORE_PARAMS,
120
+ 'appChannel',
121
+ 'language',
122
+ 'platformVersion'
123
+ ];
124
+
125
+ // 小程序平台
126
+ export const PLATFORMTYPES = [
127
+ 'wx',
128
+ 'my',
129
+ 'swan',
130
+ 'qq',
131
+ 'tt',
132
+ 'ks',
133
+ 'jd',
134
+ 'xhs',
135
+ 'quickapp'
136
+ ];
@@ -0,0 +1,4 @@
1
+ export const IPReg =
2
+ /^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}/i;
3
+ export const URLReg =
4
+ /^(https?:\/\/)|(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i;
@@ -0,0 +1,70 @@
1
+ import { GrowingIOType } from '@@/types/growingIO';
2
+ import { getOS, getScreenHeight, getScreenWidth } from '@@/utils/tools';
3
+ import { isEmpty, unset } from '@@/utils/glodash';
4
+
5
+ class EventContextBuilder {
6
+ constructor(public growingIO: GrowingIOType) {}
7
+
8
+ // 通用字段组装
9
+ main = (params?: any) => {
10
+ const {
11
+ sdkVersion,
12
+ vdsConfig,
13
+ platformConfig,
14
+ minipInstance,
15
+ userStore,
16
+ dataStore: { scene, eventHooks, locationData, lastVisitEvent }
17
+ } = this.growingIO;
18
+ const { systemInfo = {}, network = {} } = minipInstance;
19
+ const { brand, model, platform, language, version } = systemInfo;
20
+ // 事件主要内容组装
21
+ const context: any = {
22
+ appChannel: `scn:${scene || 'NA'}`,
23
+ appVersion: vdsConfig.version,
24
+ dataSourceId: vdsConfig.dataSourceId,
25
+ deviceBrand: brand,
26
+ deviceId: userStore.uid,
27
+ deviceModel: model,
28
+ deviceType: getOS(platform, platformConfig.name),
29
+ domain: vdsConfig.appId,
30
+ language: language,
31
+ latitude: locationData?.latitude,
32
+ longitude: locationData?.longitude,
33
+ networkState: network?.networkType || network?.type || network?.subtype,
34
+ operatingSystem: getOS(platform, platformConfig.name),
35
+ path: eventHooks.currentPage?.path
36
+ ? eventHooks.currentPage?.path
37
+ : lastVisitEvent.path, // 如果页面中的path取不到,说明页面没初始化,还在app的生命周期中(appOnLoad/appOnShow),需要拿visit的path补上
38
+ platform: platformConfig.platform,
39
+ platformVersion: platformConfig.name + (version ? ` ${version}` : ''),
40
+ query: eventHooks.currentPage?.path
41
+ ? eventHooks.currentPage?.query
42
+ : lastVisitEvent.query, // 如果页面中的path取不到,说明页面没初始化,还在app的生命周期中(appOnLoad/appOnShow),需要拿visit的query补上
43
+ screenHeight: getScreenHeight(systemInfo),
44
+ screenWidth: getScreenWidth(systemInfo),
45
+ sdkVersion,
46
+ sessionId: userStore.sessionId,
47
+ title:
48
+ eventHooks.currentPage?.title ||
49
+ minipInstance.getPageTitle(minipInstance.getCurrentPage()),
50
+ timestamp: Date.now(),
51
+ timezoneOffset: new Date().getTimezoneOffset(),
52
+ userId: userStore.userId
53
+ };
54
+ if (vdsConfig.idMapping) {
55
+ context.userKey = userStore.userKey;
56
+ }
57
+ if (!isEmpty(vdsConfig.ignoreFields)) {
58
+ vdsConfig.ignoreFields.forEach((o) => {
59
+ unset(context, o);
60
+ });
61
+ }
62
+ // 此时可能存在数据为空的字段,在数据组装完成后由转换方法移除空值字段
63
+ if (!isEmpty(params)) {
64
+ return { ...context, ...params };
65
+ }
66
+ return context;
67
+ };
68
+ }
69
+
70
+ export default EventContextBuilder;
@@ -0,0 +1,220 @@
1
+ import { AppHookLifeCircle } from '@@/types/eventHooks';
2
+ import { GrowingIOType } from '@@/types/growingIO';
3
+ import {
4
+ isEmpty,
5
+ isObject,
6
+ typeOf,
7
+ keys,
8
+ forEach,
9
+ has,
10
+ isNil
11
+ } from '@@/utils/glodash';
12
+ import { qsStringify } from '@@/utils/tools';
13
+
14
+ class AppEffects {
15
+ constructor(public growingIO: GrowingIOType) {}
16
+
17
+ main = (event: AppHookLifeCircle, args: any) => {
18
+ const eventTime = Date.now();
19
+ const {
20
+ emitter,
21
+ userStore,
22
+ vdsConfig,
23
+ platformConfig,
24
+ uploader,
25
+ dataStore,
26
+ dataStore: {
27
+ shareOut,
28
+ keepAlive,
29
+ lastCloseTime,
30
+ eventHooks,
31
+ saveStorageInfo
32
+ }
33
+ }: GrowingIOType = this.growingIO;
34
+ emitter.emit('minipLifecycle', {
35
+ event: `App ${event}`,
36
+ timestamp: eventTime,
37
+ params: args[0] ?? {}
38
+ });
39
+ if (vdsConfig.debug) {
40
+ console.log('App:', event, eventTime);
41
+ }
42
+ const appListeners = platformConfig.listeners.app;
43
+ // 向插件广播事件
44
+ emitter.emit('onComposeBefore', {
45
+ event: `App ${event}`,
46
+ params: args[0] ?? {}
47
+ });
48
+ switch (event) {
49
+ // 快应用是执行onCreate
50
+ case appListeners.appCreate:
51
+ // 各小程序执行onShow
52
+ case appListeners.appShow: {
53
+ // 获取进入小程序的path、query和scene
54
+ const { path, query } = this.enterParamsParse(args[0]);
55
+ if (!shareOut && vdsConfig.originalSource) {
56
+ // 保存初始来源信息
57
+ dataStore.setOriginalSource({ path, query });
58
+ }
59
+ // 以下条件均会被认为是一次新的访问
60
+ // 没有关闭时间说明是新访问
61
+ if (!lastCloseTime) {
62
+ // 保存进入小程序的参数
63
+ this.growingIO.dataStore.lastVisitEvent = { path, query };
64
+ this.buildVisitEvent({ path, query });
65
+ } else if (
66
+ // 两次打开间隔时间超过keepAlive设定(默认5分钟)
67
+ Date.now() - lastCloseTime > keepAlive ||
68
+ // 两次打开时的场景值不一样(即从不同的来源进入小程序)
69
+ (dataStore.lastScene && dataStore.scene !== dataStore.lastScene)
70
+ ) {
71
+ // 重置sessionId
72
+ userStore.sessionId = '';
73
+ // 需要按自然逻辑发visit时,清掉pagetime,防止取值错误(会在page中重新生成)
74
+ eventHooks.currentPage.time = undefined;
75
+ this.buildVisitEvent({ path, query });
76
+ }
77
+ break;
78
+ }
79
+ case appListeners.appClose: {
80
+ // 同步信息
81
+ dataStore.lastScene = dataStore.scene;
82
+ dataStore.lastCloseTime = Date.now();
83
+ saveStorageInfo();
84
+ userStore.saveUserInfo();
85
+ this.buildCloseEvent();
86
+ // forceLogin不生效时强制把请求队列中的事件全部发送
87
+ if (!vdsConfig.forceLogin) {
88
+ uploader.initiateRequest(true);
89
+ }
90
+ break;
91
+ }
92
+ default:
93
+ break;
94
+ }
95
+ };
96
+
97
+ // 进入小程序时的相关数据处理
98
+ enterParamsParse = (args: any) => {
99
+ const { gioPlatform, minipInstance, dataStore } = this.growingIO;
100
+ let vPath = ''; // 进入小程序时的path
101
+ let vQuery = ''; // 进入小程序时的参数(启动参数)
102
+ const assignment = (p: string, q = {}) => {
103
+ vPath = p;
104
+ vQuery = keys(q)
105
+ .map((k) => `${k}=${q[k]}`)
106
+ .join('&');
107
+ };
108
+ // 支持getEnterOptionsSync
109
+ if (
110
+ gioPlatform !== 'quickapp' &&
111
+ minipInstance.minip.canIUse('getEnterOptionsSync')
112
+ ) {
113
+ const { path, query, scene, referrerInfo } =
114
+ minipInstance.minip.getEnterOptionsSync() || {};
115
+ const originQuery = args.query || query;
116
+ assignment(args.path || path, originQuery);
117
+ dataStore.scene = args.scene || scene;
118
+ // extraData字段计入query
119
+ if (!isEmpty(referrerInfo) && isObject(referrerInfo?.extraData)) {
120
+ let extraQuery = [];
121
+ forEach(referrerInfo.extraData, (v, k) => {
122
+ if (
123
+ // 与原始query中的key冲突时,以原始query为准
124
+ !has(originQuery, k) &&
125
+ // 只处理字符串、数字和布尔类型的值
126
+ ['string', 'number', 'boolean'].includes(typeOf(v))
127
+ ) {
128
+ extraQuery.push(`${k}=${v}`);
129
+ }
130
+ });
131
+ const extraQueryString = extraQuery.join('&');
132
+ vQuery =
133
+ vQuery && extraQueryString
134
+ ? `${vQuery}&${extraQueryString}`
135
+ : vQuery || extraQueryString;
136
+ }
137
+ } else {
138
+ // 不支持的按老逻辑兜底
139
+ const { path, query } = args;
140
+ assignment(path, query);
141
+ this.parseScene(args);
142
+ }
143
+ return { path: vPath, query: vQuery };
144
+ };
145
+
146
+ // 获取来源场景值
147
+ /**
148
+ * wx:https://developers.weixin.qq.com/miniprogram/dev/reference/scene-list.html
149
+ * alipay:https://opendocs.alipay.com/mini/framework/scene
150
+ * swan:https://smartprogram.baidu.com/docs/data/host_scene/
151
+ * tt:https://microapp.bytedance.com/docs/zh-CN/mini-app/develop/framework/scene-value/
152
+ * qq:https://q.qq.com/wiki/develop/game/frame/scene/
153
+ * quickapp:https://doc.quickapp.cn/features/system/app.html?h=%E6%9D%A5%E6%BA%90
154
+ */
155
+
156
+ parseScene = (args) => {
157
+ const { minipInstance, gioPlatform, dataStore } = this.growingIO;
158
+ let newScene;
159
+ // 快应用处理逻辑
160
+ if (gioPlatform === 'quickapp') {
161
+ const { extra, type } = minipInstance.getAppSource();
162
+ newScene = extra?.scene || type;
163
+ } else if (!isEmpty(args)) {
164
+ if (args?.query?.wxShoppingListScene) {
165
+ newScene = args.query.wxShoppingListScene;
166
+ } else if (args?.scene) {
167
+ newScene = args.scene;
168
+ } else {
169
+ dataStore.scene = 'NA';
170
+ }
171
+ }
172
+ dataStore.scene = newScene;
173
+ };
174
+
175
+ // 构建访问事件
176
+ buildVisitEvent = (props: any) => {
177
+ const { dataStore, vdsConfig, minipInstance } = this.growingIO;
178
+ const {
179
+ originalSourceName,
180
+ getOriginalSource,
181
+ eventContextBuilder,
182
+ eventInterceptor
183
+ } = dataStore;
184
+ const originalSource = getOriginalSource();
185
+ // 生命周期中调用构建使用参数赋值,补发场景调用构建使用上一次的值
186
+ const query = props?.query || '';
187
+ let event = {
188
+ eventType: 'VISIT',
189
+ ...eventContextBuilder({
190
+ // params.path是生命周期值或者是已有的值
191
+ path: props?.path || '',
192
+ // params.query是对象说明是生命周期调用,否则是补发调用
193
+ query: typeOf(query) === 'string' ? query : qsStringify(query)
194
+ })
195
+ };
196
+ // 配置使用初始来源时,visit使用初始来源数据
197
+ if (vdsConfig.originalSource && !isNil(originalSource)) {
198
+ event = { ...event, ...originalSource };
199
+ // 采集开关开启状态下的第一个visit消费过初始来源信息后删除
200
+ if (vdsConfig.dataCollect) {
201
+ minipInstance.removeStorageSync(originalSourceName);
202
+ }
203
+ }
204
+ eventInterceptor(event);
205
+ };
206
+
207
+ // 构建关闭事件
208
+ buildCloseEvent = () => {
209
+ const {
210
+ dataStore: { eventContextBuilder, eventInterceptor }
211
+ } = this.growingIO;
212
+ const event = {
213
+ eventType: 'APP_CLOSED',
214
+ ...eventContextBuilder()
215
+ };
216
+ eventInterceptor(event);
217
+ };
218
+ }
219
+
220
+ export default AppEffects;