gio-miniprogram-sdk 4.3.2 → 4.4.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.
- package/.github/workflows/publish.yml +3 -3
- package/dist/alipay.js +1 -1
- package/dist/baidu.js +1 -1
- package/dist/bytedance.js +1 -1
- package/dist/jingdong.js +1 -1
- package/dist/kuaishou.js +1 -1
- package/dist/plugins/gioABTest.js +1 -1
- package/dist/plugins/gioCompress.js +1 -1
- package/dist/plugins/gioEventAutoTracking.js +1 -1
- package/dist/plugins/gioImpressionTracking.js +1 -1
- package/dist/plugins/gioMultipleInstances.js +1 -1
- package/dist/plugins/gioPerformance.js +1 -0
- package/dist/qq.js +1 -1
- package/dist/quickapp.js +1 -1
- package/dist/taobao.js +1 -1
- package/dist/taro.js +1 -1
- package/dist/uniapp.js +1 -1
- package/dist/wechat.js +1 -1
- package/dist/xiaohongshu.js +1 -0
- package/package.json +12 -6
- package/rollup.config.js +9 -6
- package/rollup.plugins.config.js +1 -1
- package/src/constants/emitMsg.ts +1 -0
- package/src/core/dataStore/eventHooks/appEffects.ts +3 -0
- package/src/core/dataStore/eventHooks/index.ts +4 -2
- package/src/core/dataStore/eventHooks/pageEffects.ts +1 -0
- package/src/core/growingIO.ts +27 -3
- package/src/core/uploader.ts +12 -3
- package/src/core/userStore.ts +1 -2
- package/src/minipInstance/base.ts +62 -23
- package/src/minipInstance/framework.ts +3 -1
- package/src/minipInstance/quickapp.ts +11 -0
- package/src/minipInstance/wx.ts +15 -0
- package/src/minipInstance/xhs.ts +20 -0
- package/src/platformConfig/base.ts +1 -0
- package/src/platformConfig/xhs.ts +20 -0
- package/src/plugins/gioABTest.ts +32 -3
- package/src/plugins/gioEventAutoTracking.ts +99 -1
- package/src/plugins/gioImpressionTracking.ts +3 -1
- package/src/plugins/gioPerformance/exception.ts +152 -0
- package/src/plugins/gioPerformance/monitor.ts +284 -0
- package/src/plugins/gioPerformance/network.ts +197 -0
- package/src/plugins/gioPerformance.ts +131 -0
- package/src/types/base.ts +5 -1
- package/src/types/minipInstance.ts +3 -1
- package/src/types/platforms.ts +3 -0
- package/src/utils/tools.ts +46 -3
- package/src/utils/verifiers.ts +4 -3
- package/tsconfig.json +1 -1
- package/typings/global.d.ts +8 -0
- package/bin/build.sh +0 -38
package/rollup.config.js
CHANGED
|
@@ -19,7 +19,8 @@ const platform = processENV[0];
|
|
|
19
19
|
// 框架平台
|
|
20
20
|
const frameName = processENV[1];
|
|
21
21
|
// 插件实例的入口名
|
|
22
|
-
const pluginInstanceName =
|
|
22
|
+
const pluginInstanceName =
|
|
23
|
+
frameName || platform === 'tb' ? frameName || platform : 'base';
|
|
23
24
|
// 小程序平台文件名枚举
|
|
24
25
|
const PLATFORMS = {
|
|
25
26
|
wx: 'wechat',
|
|
@@ -30,20 +31,22 @@ const PLATFORMS = {
|
|
|
30
31
|
ks: 'kuaishou',
|
|
31
32
|
tb: 'taobao',
|
|
32
33
|
jd: 'jingdong',
|
|
33
|
-
quickapp: 'quickapp'
|
|
34
|
+
quickapp: 'quickapp',
|
|
35
|
+
xhs: 'xiaohongshu'
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
// 控制台打印当前打包的环境和小程序平台
|
|
37
39
|
console.log(
|
|
38
|
-
`Packaging ${
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
`Packaging ${
|
|
41
|
+
PLATFORMS[platform]
|
|
42
|
+
? 'platform:' + PLATFORMS[platform]
|
|
43
|
+
: 'framework:' + frameName
|
|
41
44
|
}`
|
|
42
45
|
);
|
|
43
46
|
|
|
44
47
|
const fileName = () => {
|
|
45
48
|
let n = 'dist/';
|
|
46
|
-
n +=
|
|
49
|
+
n += PLATFORMS[platform] ? PLATFORMS[platform] : frameName;
|
|
47
50
|
n += '.js';
|
|
48
51
|
return n;
|
|
49
52
|
};
|
package/rollup.plugins.config.js
CHANGED
|
@@ -16,7 +16,7 @@ const processENV = process.argv[process.argv.length - 1]
|
|
|
16
16
|
.split('-')
|
|
17
17
|
.filter((o) => o);
|
|
18
18
|
// 获取是否打包全量插件
|
|
19
|
-
const folder = processENV[0]
|
|
19
|
+
const folder = processENV[0] ? processENV[0] : 'plugins';
|
|
20
20
|
|
|
21
21
|
// 获取外置插件的目录
|
|
22
22
|
const plugInFolder = fs
|
package/src/constants/emitMsg.ts
CHANGED
|
@@ -9,6 +9,7 @@ export default {
|
|
|
9
9
|
ON_SDK_INITIALIZE_BEFORE: 'ON_SDK_INITIALIZE_BEFORE', // SDK开始初始化之前
|
|
10
10
|
ON_SEND_AFTER: 'ON_SEND_AFTER', // 插件生命周期:发送事件后
|
|
11
11
|
ON_SEND_BEFORE: 'ON_SEND_BEFORE', // 插件生命周期:发送事件前
|
|
12
|
+
ON_SEND_ERROR: 'ON_SEND_ERROR', // 插件生命周期:发送事件错误
|
|
12
13
|
OPTION_CHANGE: 'OPTION_CHANGE', // 设置变更事件
|
|
13
14
|
OPTION_INITIALIZED: 'OPTION_INITIALIZED', // 配置项初始化完成
|
|
14
15
|
SCENE_UPDATE: 'SCENE_UPDATE', // scene变更事件
|
|
@@ -17,6 +17,7 @@ class AppEffects {
|
|
|
17
17
|
platformConfig,
|
|
18
18
|
uploader,
|
|
19
19
|
dataStore,
|
|
20
|
+
minipInstance,
|
|
20
21
|
dataStore: {
|
|
21
22
|
trackersExecute,
|
|
22
23
|
shareOut,
|
|
@@ -81,6 +82,8 @@ class AppEffects {
|
|
|
81
82
|
userStore.setSessionId(trackingId);
|
|
82
83
|
});
|
|
83
84
|
}
|
|
85
|
+
// 添加网络状态变更监听
|
|
86
|
+
minipInstance.setNetworkStatusListener();
|
|
84
87
|
break;
|
|
85
88
|
}
|
|
86
89
|
case appListeners.appClose: {
|
|
@@ -17,6 +17,7 @@ class EventHooks implements EventHooksType {
|
|
|
17
17
|
public defPageCbs: any;
|
|
18
18
|
public appHandlers: string[];
|
|
19
19
|
public pageHandlers: string[];
|
|
20
|
+
public shareEventTypes: string[];
|
|
20
21
|
public actionEventTypes: string[];
|
|
21
22
|
public originalApp: (any: any) => any;
|
|
22
23
|
public originalPage: (any: any) => any;
|
|
@@ -33,6 +34,7 @@ class EventHooks implements EventHooksType {
|
|
|
33
34
|
this.defPageCbs = {};
|
|
34
35
|
this.appHandlers = config.appHandlers;
|
|
35
36
|
this.pageHandlers = config.pageHandlers;
|
|
37
|
+
this.shareEventTypes = config.shareEventTypes;
|
|
36
38
|
this.actionEventTypes = config.actionEventTypes;
|
|
37
39
|
this.appEffects = new AppEffects(this.growingIO);
|
|
38
40
|
this.pageEffects = new PageEffects(this.growingIO);
|
|
@@ -115,7 +117,7 @@ class EventHooks implements EventHooksType {
|
|
|
115
117
|
let result;
|
|
116
118
|
try {
|
|
117
119
|
// 分享处理
|
|
118
|
-
if (eventName
|
|
120
|
+
if (self.shareEventTypes.includes(eventName)) {
|
|
119
121
|
// 先执行分享的生命周期拿到分享数据
|
|
120
122
|
// 与基础库保持一致,没有返回值时默认使用{}
|
|
121
123
|
result = method.apply(this, args) ?? {};
|
|
@@ -160,7 +162,7 @@ class EventHooks implements EventHooksType {
|
|
|
160
162
|
consoleText(error, 'error');
|
|
161
163
|
}
|
|
162
164
|
// 执行分享之外的生命周期函数
|
|
163
|
-
if (eventName
|
|
165
|
+
if (!self.shareEventTypes.includes(eventName)) {
|
|
164
166
|
result = method.apply(this, args);
|
|
165
167
|
}
|
|
166
168
|
self.growingIO.emitter.emit(EMIT_MSG.MINIP_LIFECYCLE, {
|
package/src/core/growingIO.ts
CHANGED
|
@@ -18,7 +18,8 @@ import {
|
|
|
18
18
|
getPlainPlatform,
|
|
19
19
|
guid,
|
|
20
20
|
limitObject,
|
|
21
|
-
niceCallback
|
|
21
|
+
niceCallback,
|
|
22
|
+
qsParse
|
|
22
23
|
} from '@@/utils/tools';
|
|
23
24
|
import { ALLOW_SET_OPTIONS, DEFAULT_SETTINGS } from '@@/constants/config';
|
|
24
25
|
import { DataStoreType, OriginOptions } from '@@/types/dataStore';
|
|
@@ -65,6 +66,7 @@ class GrowingIO implements GrowingIOType {
|
|
|
65
66
|
// 当前主SDK的trackingId,用于区分事件归属。
|
|
66
67
|
public trackingId: string;
|
|
67
68
|
public subInstance: any;
|
|
69
|
+
private _identified: boolean;
|
|
68
70
|
constructor() {
|
|
69
71
|
this.utils = { ...glodash, ...tools, qs };
|
|
70
72
|
this.emitter = mitt();
|
|
@@ -288,6 +290,8 @@ class GrowingIO implements GrowingIOType {
|
|
|
288
290
|
this.userStore.setUid(asId);
|
|
289
291
|
// 修改forceLogin配置项
|
|
290
292
|
this.dataStore.setOption(this.trackingId, 'forceLogin', false);
|
|
293
|
+
// 标记当前已被identify过
|
|
294
|
+
this._identified = true;
|
|
291
295
|
// 为已积压的请求使用assignmentId全部赋值deviceId
|
|
292
296
|
this.dataStore.trackersExecute((tid: string) => {
|
|
293
297
|
const hq = this.uploader.getHoardingQueue(tid);
|
|
@@ -295,6 +299,8 @@ class GrowingIO implements GrowingIOType {
|
|
|
295
299
|
// 发送积压队列中的请求
|
|
296
300
|
this.uploader.initiateRequest(tid, true);
|
|
297
301
|
});
|
|
302
|
+
} else if (this._identified) {
|
|
303
|
+
callError('identify', !1, '请勿重复调用');
|
|
298
304
|
} else {
|
|
299
305
|
callError('identify', !1, 'forceLogin未开启');
|
|
300
306
|
}
|
|
@@ -338,9 +344,14 @@ class GrowingIO implements GrowingIOType {
|
|
|
338
344
|
userId = toString(userId).slice(0, 1000);
|
|
339
345
|
userKey = toString(userKey).slice(0, 1000);
|
|
340
346
|
this.userStore.setUserId(trackingId, userId);
|
|
347
|
+
const processedUserKey =
|
|
348
|
+
!isNil(userKey) && toString(userKey).length > 0
|
|
349
|
+
? toString(userKey).slice(0, 1000)
|
|
350
|
+
: '';
|
|
351
|
+
this.userStore.setUserKey(trackingId, processedUserKey);
|
|
341
352
|
const { idMapping } = this.dataStore.getTrackerVds(trackingId);
|
|
342
|
-
if (idMapping) {
|
|
343
|
-
|
|
353
|
+
if (!idMapping && processedUserKey) {
|
|
354
|
+
consoleText('您设置了 userKey ,请初始化开启 idMapping!', 'warn');
|
|
344
355
|
}
|
|
345
356
|
// 切换userId时重置session
|
|
346
357
|
if (prevId && prevId !== userId) {
|
|
@@ -606,6 +617,19 @@ class GrowingIO implements GrowingIOType {
|
|
|
606
617
|
}
|
|
607
618
|
});
|
|
608
619
|
}
|
|
620
|
+
// 只有主实例有可能会带圈选的字段
|
|
621
|
+
if (trackingId === this.trackingId) {
|
|
622
|
+
// 小程序处于圈选状态时,把圈选上报地址带给web
|
|
623
|
+
const { circleServerUrl, circleOpen } =
|
|
624
|
+
this.plugins?.gioEventAutoTracking ?? {};
|
|
625
|
+
if (circleServerUrl && circleOpen) {
|
|
626
|
+
// infos.giocircleserverurl = encodeURIComponent(circleServerUrl);
|
|
627
|
+
const circleParam: any = qsParse(circleServerUrl.split('?')[1]);
|
|
628
|
+
if (circleParam.roomId) {
|
|
629
|
+
infos.giocircleroomid = circleParam.roomId;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
609
633
|
return qs.stringify(infos);
|
|
610
634
|
};
|
|
611
635
|
}
|
package/src/core/uploader.ts
CHANGED
|
@@ -33,10 +33,10 @@ class Uploader implements UploaderType {
|
|
|
33
33
|
this.retryLimit = 2;
|
|
34
34
|
this.retryIds = {};
|
|
35
35
|
this.requestingNum = 0;
|
|
36
|
-
|
|
37
|
-
emitter.on(
|
|
36
|
+
this.growingIO.emitter.on(
|
|
38
37
|
EMIT_MSG.ON_SEND_BEFORE,
|
|
39
38
|
({ eventsQueue, requestData, trackingId }) => {
|
|
39
|
+
const { vdsConfig, plugins } = this.growingIO;
|
|
40
40
|
// 核心逻辑中只发送主实例的事件
|
|
41
41
|
if (trackingId === this.growingIO.trackingId) {
|
|
42
42
|
if (vdsConfig?.tbConfig?.cloudAppId) {
|
|
@@ -223,11 +223,20 @@ class Uploader implements UploaderType {
|
|
|
223
223
|
this.requestFailFn(o);
|
|
224
224
|
});
|
|
225
225
|
consoleText(`请求失败!${JSON.stringify(result)}`, 'error');
|
|
226
|
+
emitter.emit(EMIT_MSG.ON_SEND_ERROR, {
|
|
227
|
+
eventsQueue,
|
|
228
|
+
requestData,
|
|
229
|
+
trackingId
|
|
230
|
+
});
|
|
226
231
|
}
|
|
227
232
|
},
|
|
228
233
|
complete: (args: any) => {
|
|
229
234
|
this.requestingNum -= 1;
|
|
230
|
-
emitter.emit(EMIT_MSG.ON_SEND_AFTER, {
|
|
235
|
+
emitter.emit(EMIT_MSG.ON_SEND_AFTER, {
|
|
236
|
+
result: args,
|
|
237
|
+
requestData,
|
|
238
|
+
trackingId
|
|
239
|
+
});
|
|
231
240
|
this.initiateRequest(trackingId);
|
|
232
241
|
}
|
|
233
242
|
});
|
package/src/core/userStore.ts
CHANGED
|
@@ -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
|
-
|
|
147
|
-
|
|
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 =
|
|
168
|
+
title = page.route
|
|
169
|
+
? this._getTitleFromTabBar(instConfig, page.route)
|
|
170
|
+
: '';
|
|
152
171
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
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];
|
|
@@ -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;
|
package/src/minipInstance/wx.ts
CHANGED
|
@@ -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;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import BaseConfig from './base';
|
|
2
|
+
|
|
3
|
+
const XHSConfig = {
|
|
4
|
+
...BaseConfig,
|
|
5
|
+
pageHandlers: [...BaseConfig.pageHandlers, 'onShareChat', 'onCopyUrl'],
|
|
6
|
+
shareEventTypes: ['onShareAppMessage', 'onShareChat'],
|
|
7
|
+
listeners: {
|
|
8
|
+
...BaseConfig.listeners,
|
|
9
|
+
page: {
|
|
10
|
+
...BaseConfig.listeners.page,
|
|
11
|
+
shareChat: 'onShareChat',
|
|
12
|
+
copyUrl: 'onCopyUrl'
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
name: 'XiaoHongShu',
|
|
16
|
+
platform: 'xhsp',
|
|
17
|
+
scnPrefix: 'xhs_'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default XHSConfig;
|
package/src/plugins/gioABTest.ts
CHANGED
|
@@ -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,100 @@ 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(params.referrerInfo?.extraData);
|
|
207
|
+
// 额外参数中存在gdpCircleRoomCollectUrl,则表示是圈选的跳转,进入圈选状态
|
|
208
|
+
if (extraData?.gdpCircleRoomCollectUrl) {
|
|
209
|
+
// 圈选初始化
|
|
210
|
+
if (this.circleServerUrl !== extraData?.gdpCircleRoomCollectUrl) {
|
|
211
|
+
this.circleServerUrl = extraData?.gdpCircleRoomCollectUrl;
|
|
212
|
+
// 提前移除一次事件发送监听,防止重复监听
|
|
213
|
+
emitter.off(EMIT_MSG.ON_SEND_AFTER, this.collectorSendFn);
|
|
214
|
+
// 添加事件发送监听,用于发送圈选事件
|
|
215
|
+
emitter.on(EMIT_MSG.ON_SEND_AFTER, this.collectorSendFn);
|
|
216
|
+
this.showPromptModal('enter');
|
|
217
|
+
}
|
|
218
|
+
this.circleOpen = true;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// 数据采集发送监听回调
|
|
223
|
+
collectorSendFn = ({ requestData, trackingId }) => {
|
|
224
|
+
const { uploader } = this.growingIO;
|
|
225
|
+
if (this.circleOpen) {
|
|
226
|
+
// 过滤仅主实例的非CUSTOM事件可以圈选
|
|
227
|
+
const filteredEvents = requestData.filter(
|
|
228
|
+
(e) =>
|
|
229
|
+
e.eventType !== 'CUSTOM' && trackingId === this.growingIO.trackingId
|
|
230
|
+
);
|
|
231
|
+
if (!isEmpty(filteredEvents)) {
|
|
232
|
+
// 同时请求数在3个以下直接发起请求
|
|
233
|
+
if (uploader.requestingNum < uploader.requestLimit) {
|
|
234
|
+
this.circleRequest(filteredEvents);
|
|
235
|
+
} else {
|
|
236
|
+
// 同时有3个请求在发送时,设轮询延时直到请求数在3个以下
|
|
237
|
+
let t = setInterval(() => {
|
|
238
|
+
if (uploader.requestingNum < uploader.requestLimit) {
|
|
239
|
+
this.circleRequest(filteredEvents);
|
|
240
|
+
clearInterval(t);
|
|
241
|
+
t = undefined;
|
|
242
|
+
}
|
|
243
|
+
}, 500);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// 圈选结束
|
|
250
|
+
circleClose = () => {
|
|
251
|
+
this.circleOpen = false;
|
|
252
|
+
this.circleServerUrl = '';
|
|
253
|
+
this.growingIO.emitter.off(EMIT_MSG.ON_SEND_AFTER, this.collectorSendFn);
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// 展示圈选提示
|
|
257
|
+
showPromptModal = (type: 'enter' | 'error', msg?: string) => {
|
|
258
|
+
this.growingIO.minipInstance.minip.showModal({
|
|
259
|
+
title: 'GrowingIO提示',
|
|
260
|
+
content: type === 'error' ? msg : '您已进入圈选模式',
|
|
261
|
+
showCancel: false
|
|
262
|
+
});
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// 发起圈选请求
|
|
266
|
+
circleRequest = (requestData: any) => {
|
|
267
|
+
const { minipInstance } = this.growingIO;
|
|
268
|
+
minipInstance.request({
|
|
269
|
+
url: this.circleServerUrl,
|
|
270
|
+
header: { 'content-type': 'application/json;charset=UTF-8' },
|
|
271
|
+
method: 'POST',
|
|
272
|
+
data: requestData,
|
|
273
|
+
complete: ({ statusCode, data, errMsg }: any) => {
|
|
274
|
+
if (![200, 204].includes(statusCode) || !data?.success) {
|
|
275
|
+
this.showPromptModal(
|
|
276
|
+
'error',
|
|
277
|
+
data?.message || data || errMsg || '圈选请求失败,请重试!'
|
|
278
|
+
);
|
|
279
|
+
this.circleClose();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
};
|
|
186
284
|
}
|
|
187
285
|
|
|
188
286
|
export default { name: 'gioEventAutoTracking', method: GioEventAutoTracking };
|