@tmsfe/tms-core 0.0.123 → 0.0.125

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmsfe/tms-core",
3
- "version": "0.0.123",
3
+ "version": "0.0.125",
4
4
  "description": "tms运行时框架",
5
5
  "repository": {
6
6
  "type": "git",
@@ -45,7 +45,18 @@ function invoke(obj, funcName, args) {
45
45
  function initProxy(appObj, options) {
46
46
  app = appObj;
47
47
  initOptions = options;
48
- AutoReport.init();
48
+ // 如果是在app.js的onLaunch中调用,则没有getApp().tms为空
49
+ const getTms = () => getApp()?.tms || wx.tms;
50
+ AutoReport.init({
51
+ report: (...data) => {
52
+ const tms = getTms();
53
+ tms.getReporter().report2(...data);
54
+ },
55
+ fastReport: (...data) => {
56
+ const tms = getTms();
57
+ tms.getReporter().fastReport2(...data);
58
+ },
59
+ });
49
60
  }
50
61
 
51
62
  function awaitTMS() {
package/src/index.js CHANGED
@@ -120,8 +120,28 @@ const init = (options = {}) => {
120
120
  };
121
121
  setEnvInfo(envInfo);
122
122
  setAppPagePaths(appPagePaths, homePage);
123
- Reporter.init(envInfo);
124
- AutoReport.init();
123
+
124
+ Reporter.init({
125
+ client,
126
+ appVersion,
127
+ logger: wx.getLogManager({}),
128
+ post: (api, params) => createRequest().post(api, params),
129
+ getLocation: async () => {
130
+ try {
131
+ const res = await getLocationManager().getIpLocation();
132
+ const ad = res.ad_info;
133
+ return { province: ad.province, cityName: ad.city };
134
+ } catch {
135
+ return null;
136
+ }
137
+ },
138
+ });
139
+
140
+ AutoReport.init({
141
+ report: Reporter.report2,
142
+ fastReport: Reporter.fastReport2,
143
+ });
144
+
125
145
  Request.defaultHost = defaultHost;
126
146
  Request.defaultSecretKey = secretKey;
127
147
  // 初始化云环境
@@ -41,6 +41,9 @@ function getWxLocation(type: string = defaultLocationType): Promise<WxPostionTyp
41
41
  success: (res: WxPostionType) => {
42
42
  logger.log(`wx.getLocation('${type}') 成功:\n`, JSON.stringify(res, null, ' '));
43
43
  resolve(res);
44
+ const reporter = getApp().tms.getReporter();
45
+ // 首次打开小程序时用户定位信息|用户定位|来源
46
+ reporter.report2('wxLocationInitInfo', res, 'tms-core');
44
47
  },
45
48
  fail: (err) => {
46
49
  logger.warn(`wx.getLocation('${type}') 失败:\n`, JSON.stringify(err, null, ' '));
@@ -3,15 +3,20 @@
3
3
  * @private: true
4
4
  */
5
5
 
6
- // / <reference path='./types.ts'/>
7
6
  import helper from './helper';
7
+ import {
8
+ DataItem,
9
+ IOldParams,
10
+ IDeviceData,
11
+ } from './types';
8
12
 
9
13
  /**
10
14
  * 获取埋点的基础字段
11
15
  */
12
16
  function getBaseData(deviceData: IDeviceData): DataItem[] {
13
17
  const { networkType, location } = deviceData;
14
- const { appVersion, client } = helper.getInitOptions();
18
+ const client = helper.getClientName();
19
+ const appVersion = helper.getAppVersion();
15
20
  const { host } = helper.getSystemInfo();
16
21
  const arr = new Array<DataItem>(helper.dataArrLen);
17
22
  // todo: 如何区分新旧埋点?新:f20不为空,旧:f20为空
@@ -3,15 +3,20 @@
3
3
  * @private: true
4
4
  */
5
5
 
6
- // / <reference path='./types.ts'/>
7
6
  import helper from './helper';
7
+ import {
8
+ IPage,
9
+ DataItem,
10
+ IDeviceData,
11
+ } from './types';
8
12
 
9
13
  /**
10
14
  * 获取埋点的基础字段
11
15
  */
12
16
  function getBaseData(page: IPage, deviceData: IDeviceData): { arr: DataItem[], nextIndex: number } {
13
17
  const { networkType, location } = deviceData;
14
- const { appVersion, client } = helper.getInitOptions();
18
+ const client = helper.getClientName();
19
+ const appVersion = helper.getAppVersion();
15
20
  const arr = new Array<DataItem>(helper.dataArrLen);
16
21
  // todo: 如何区分新旧埋点?新:f20不为空,旧:f20为空
17
22
  // ++++++++++++++++++++++++++字段列表++++++++++++++++++++++++++
@@ -73,7 +78,7 @@ function jointData(page: IPage, data: any[], deviceData: IDeviceData): DataItem[
73
78
  let index = nextIndex;
74
79
  for (const item of data) {
75
80
  if (index >= arr.length) {
76
- console.error('埋点参数个数超出上限而被截断', data);
81
+ console.warn('埋点参数个数超出上限而被截断', data);
77
82
  break;
78
83
  }
79
84
  arr[index] = item;
@@ -3,14 +3,14 @@
3
3
  * @private: true
4
4
  */
5
5
 
6
- // / <reference path='./types.ts'/>
7
- import syncApi from '../syncfnmanager';
8
6
  import clone from './clone';
9
-
10
- function getTms(): any {
11
- // 如果是在app.js的onLaunch中调用,则没有getApp().tms为空
12
- return getApp()?.tms || (wx as any).tms;
13
- }
7
+ import {
8
+ IPage,
9
+ DataItem,
10
+ IDeviceData,
11
+ ISystemInfo,
12
+ IInitOptions,
13
+ } from './types';
14
14
 
15
15
  let initOptions: IInitOptions;
16
16
 
@@ -18,43 +18,31 @@ let initOptions: IInitOptions;
18
18
  * 初始化
19
19
  */
20
20
  function init(options: IInitOptions): void {
21
- if (initOptions) {
22
- return;
23
- }
24
-
25
21
  initOptions = options;
22
+ }
26
23
 
27
- // 从上次缓存中读取,方便首次Report可以先带上
28
- const loc = wx.getStorageSync('home.location_city') || wx.getStorageSync('home.city');
29
- deviceData = {
30
- networkType: '',
31
- location: {
32
- province: loc?.province as string,
33
- cityName: loc?.cityName as string,
34
- },
35
- };
36
-
37
- wx.onAppShow((options) => {
38
- // 克隆函数内会限制对象字段
39
- launchOptions = clone.deepClone(options);
40
- });
24
+ /**
25
+ * 获取小程序名
26
+ */
27
+ function getClientName(): string {
28
+ return initOptions.client;
41
29
  }
42
30
 
43
31
  /**
44
- * 获取初始化时的参数
32
+ * 获取小程序版本号
45
33
  */
46
- function getInitOptions(): IInitOptions {
47
- return initOptions;
34
+ function getAppVersion(): string {
35
+ return initOptions.appVersion;
48
36
  }
49
37
 
50
- let systemInfo: ISystemInfo | null = null;
38
+ let systemInfo: ISystemInfo;
51
39
 
52
40
  /**
53
41
  * 获取系统信息
54
42
  */
55
43
  function getSystemInfo(): ISystemInfo {
56
- if (systemInfo === null) {
57
- const system = syncApi.getSystemInfoSync() as any;
44
+ if (!systemInfo) {
45
+ const system = wx.getSystemInfoSync() as any;
58
46
  // eslint-disable-next-line
59
47
  const { model = '', version: wxVersion = '', platform = '', SDKVersion = '', host } = system;
60
48
  systemInfo = { model, wxVersion, platform, SDKVersion, host };
@@ -159,14 +147,14 @@ function getPageInfo(): IPage {
159
147
  return { route, options, depth };
160
148
  }
161
149
 
162
- let launchOptions: any = null;
150
+ let launchOptions: any;
163
151
 
164
152
  /**
165
153
  * 获取小程序启动参数
166
154
  */
167
155
  function getLaunchOptions(): any {
168
- if (launchOptions === null) {
169
- launchOptions = syncApi.getLaunchOptionsSync();
156
+ if (!launchOptions) {
157
+ launchOptions = wx.getLaunchOptionsSync();
170
158
  // 克隆函数内会限制对象字段
171
159
  launchOptions = clone.deepClone(launchOptions);
172
160
  }
@@ -210,9 +198,15 @@ function canReport(): boolean {
210
198
  const dataArrLen = 41;
211
199
 
212
200
  // 缓存设备等信息,方便FastReport使用
213
- let deviceData: IDeviceData;
201
+ const deviceData: IDeviceData = {
202
+ networkType: '',
203
+ location: {
204
+ province: '',
205
+ cityName: '',
206
+ },
207
+ };
214
208
 
215
- let devicePromise: Promise<IDeviceData> | null = null;
209
+ let devicePromise: Promise<IDeviceData> = null;
216
210
 
217
211
  /**
218
212
  * 获取设备信息(网络状况,位置信息)
@@ -231,16 +225,12 @@ function getDeviceData(): Promise<IDeviceData> {
231
225
  });
232
226
 
233
227
  const locPromise = new Promise<void>((resolve) => {
234
- // 首次如果有缓存则先用缓存,请求后再更新给下次用
235
- if (deviceData.location.province) {
236
- resolve();
237
- }
238
- const LOC = getTms().getLocationManager();
239
- LOC.getIpLocation()
240
- .then((res: any) => {
241
- const ad = res.ad_info;
242
- deviceData.location.province = ad.province;
243
- deviceData.location.cityName = ad.city;
228
+ initOptions.getLocation()
229
+ .then((loc) => {
230
+ if (loc) {
231
+ deviceData.location.province = loc.province;
232
+ deviceData.location.cityName = loc.cityName;
233
+ }
244
234
  resolve();
245
235
  })
246
236
  .catch(() => resolve());
@@ -271,10 +261,18 @@ function setSystemField(fieldName: string, value: number | string): void {
271
261
  systemInfo[fieldName] = value;
272
262
  }
273
263
 
264
+ /**
265
+ * 请求接口
266
+ */
267
+ function post(api: string, params: any): Promise<{ errCode: number, errMsg: string }> {
268
+ return initOptions.post(api, params);
269
+ }
270
+
274
271
  export default {
275
272
  init,
276
- getTms,
277
- getInitOptions,
273
+ post,
274
+ getClientName,
275
+ getAppVersion,
278
276
  getSystemInfo,
279
277
  convert2StringArray,
280
278
  getNowString,
@@ -3,21 +3,26 @@
3
3
  * @module: report
4
4
  */
5
5
 
6
- // / <reference path='./types.ts'/>
7
6
  import helper from './helper';
8
7
  import sender from './sender';
9
8
  import formatV1 from './formatV1';
10
9
  import formatV2 from './formatV2';
10
+ import { ILogger, IOldParams, IInitOptions } from './types';
11
11
 
12
- const logger = wx.getLogManager({});
13
- logger.log('report模块代码被装载');
12
+ let logger: ILogger;
13
+
14
+ let isInit = false;
14
15
 
15
16
  /**
16
17
  * 初始化
17
18
  * @private
18
19
  */
19
20
  function init(options: IInitOptions): void {
20
- helper.init(options);
21
+ if (!isInit) {
22
+ isInit = true;
23
+ logger = options.logger;
24
+ helper.init(options);
25
+ }
21
26
  }
22
27
 
23
28
  /**
@@ -60,7 +65,7 @@ function fastReport(data: IOldParams = {}): void {
60
65
  */
61
66
  function report2(...data: any[]): void {
62
67
  if (helper.canReport()) {
63
- logger.log('新埋点:', data);
68
+ logger.log('新埋点:', data[0]); // 日志太长了,只输出事件名就好了
64
69
  formatV2.formatData(data).then(arr => sender.queue(arr));
65
70
  }
66
71
  }
@@ -3,8 +3,6 @@
3
3
  * @private: true
4
4
  */
5
5
 
6
- // / <reference path='./types.ts'/>
7
-
8
6
  import helper from './helper';
9
7
 
10
8
  // 劫持导航api
@@ -3,8 +3,6 @@
3
3
  * @private: true
4
4
  */
5
5
 
6
- // / <reference path='./types.ts'/>
7
-
8
6
  import helper from './helper';
9
7
 
10
8
  // 劫持Component的生命周期
@@ -3,39 +3,39 @@
3
3
  * @private: true
4
4
  */
5
5
 
6
- // / <reference path='./types.ts'/>
7
-
8
6
  import clone from '../clone';
7
+ import { IInitOptions, IBindEvent } from './types';
8
+
9
+ let initOptions: IInitOptions;
9
10
 
10
- function getReporter(): any {
11
- // 如果是在app.js的onLaunch中调用,则没有getApp().tms为空
12
- const tms = getApp()?.tms || (wx as any).tms;
13
- return tms.getReporter();
11
+ /**
12
+ * 初始化
13
+ */
14
+ function init(options: IInitOptions): void {
15
+ initOptions = options;
14
16
  }
15
17
 
16
18
  /**
17
19
  * 聚合上报埋点
18
20
  */
19
21
  function reportData(...args: any[]): any {
20
- console.log('自动埋点:', ...args);
21
- getReporter().report2(...args);
22
+ initOptions.report(...args);
22
23
  }
23
24
 
24
25
  /**
25
26
  * 立即上报埋点
26
27
  */
27
28
  function fastReportData(...args: any[]): any {
28
- console.log('快速自动埋点:', ...args);
29
- getReporter().fastReport2(...args);
29
+ initOptions.fastReport(...args);
30
30
  }
31
31
 
32
- let systemInfo: any = null;
32
+ let systemInfo: WechatMiniprogram.SystemInfo;
33
33
 
34
34
  /**
35
35
  * 获取wx.getSystemInfoSync()
36
36
  */
37
37
  function getSystemInfo(): any {
38
- if (systemInfo === null) {
38
+ if (!systemInfo) {
39
39
  systemInfo = wx.getSystemInfoSync();
40
40
  }
41
41
  return systemInfo;
@@ -141,6 +141,7 @@ function getEventExtra(event: any): any {
141
141
  }
142
142
 
143
143
  export default {
144
+ init,
144
145
  emptyFunc,
145
146
  cloneData,
146
147
  reportData,
@@ -3,16 +3,21 @@
3
3
  * @private: true
4
4
  */
5
5
 
6
+ import helper from './helper';
6
7
  import proxyApp from './app';
7
8
  import proxyPage from './page';
8
9
  import proxyComponent from './component';
10
+ import { IInitOptions } from './types';
9
11
 
10
- proxyApp.init();
11
- proxyPage.init();
12
- proxyComponent.init();
13
-
14
- // 目前没有需要控制初始化时机的场景
15
- function init(): void {
12
+ function init(options: IInitOptions): void {
13
+ // 与独立分包共用过全埋点代理,避免重复劫持
14
+ if (!wx.isTmsReportInit) {
15
+ wx.isTmsReportInit = true;
16
+ helper.init(options);
17
+ proxyApp.init();
18
+ proxyPage.init();
19
+ proxyComponent.init();
20
+ }
16
21
  }
17
22
 
18
23
  export default {
@@ -3,9 +3,8 @@
3
3
  * @private: true
4
4
  */
5
5
 
6
- // / <reference path='./types.ts'/>
7
-
8
6
  import helper from './helper';
7
+ import { IPageTouchExtra, IPageLifeExtra } from './types';
9
8
 
10
9
  // 工具为页面根节点插入的触摸事件
11
10
  const pageTouchEvent = 'onReportPageTouch';
@@ -1,10 +1,18 @@
1
- /* eslint-disable */
1
+ /**
2
+ * 初始化参数对象
3
+ */
4
+ export interface IInitOptions {
5
+ // 发送埋点
6
+ report: (...data: any[]) => void,
7
+ // 立即发送埋点
8
+ fastReport: (...data: any[]) => void,
9
+ }
2
10
 
3
11
  /**
4
12
  * 绑定的触发事件埋点
5
13
  * @private: true
6
14
  */
7
- interface IBindEvent {
15
+ export interface IBindEvent {
8
16
  /**
9
17
  * 触发事件的页面url
10
18
  */
@@ -30,7 +38,7 @@ interface IBindEvent {
30
38
  /**
31
39
  * 页面生命周期函数的埋点附加数据
32
40
  */
33
- interface IPageLifeExtra {
41
+ export interface IPageLifeExtra {
34
42
  /**
35
43
  * 页面生命周期内第几次曝光
36
44
  */
@@ -49,7 +57,7 @@ interface IPageLifeExtra {
49
57
  touchCount: number,
50
58
  }
51
59
 
52
- interface IPageTouchExtra {
60
+ export interface IPageTouchExtra {
53
61
  /**
54
62
  * 页面生命周期内第几次曝光
55
63
  */
@@ -3,8 +3,8 @@
3
3
  * @private: true
4
4
  */
5
5
 
6
- // / <reference path='./types.ts'/>
7
6
  import helper from './helper';
7
+ import { DataItem } from './types';
8
8
 
9
9
  // 缓存队列
10
10
  const cacheArr = new Array<string[]>();
@@ -47,8 +47,7 @@ function batchSendData(): void {
47
47
  }
48
48
 
49
49
  const batch = cacheArr.splice(0, max);
50
- const request = helper.getTms().createRequest();
51
- request.post('basic/event/upload', { batch })
50
+ helper.post('basic/event/upload', { batch })
52
51
  .then((res: any) => {
53
52
  if (res.errCode === 0) {
54
53
  startTimer();
@@ -58,7 +57,7 @@ function batchSendData(): void {
58
57
  }
59
58
  })
60
59
  .catch((e: any) => {
61
- console.error(e);
60
+ console.error('发送埋点失败', e);
62
61
  requestFail(batch);
63
62
  });
64
63
  }
@@ -1,19 +1,33 @@
1
- /* eslint-disable */
2
-
3
- type DataItem = any;
1
+ export type DataItem = any;
4
2
 
5
3
  /**
6
4
  * 初始化参数对象
7
5
  */
8
- interface IInitOptions {
9
- client: string, // sinan、mycar等
6
+ export interface IInitOptions {
7
+ // 小程序项目名,如:sinan、mycar等
8
+ client: string,
9
+ // 小程序版本号
10
10
  appVersion: string,
11
+ // 获取定位信息
12
+ getLocation: () => Promise<{ province: string, cityName: string } | null>,
13
+ // 允许自定义日志输出
14
+ logger: ILogger,
15
+ // post方法,用于发送埋点
16
+ post: (api: string, params: any) => Promise<{ errCode: number, errMsg: string }>,
17
+ }
18
+
19
+ export interface ILogger {
20
+ log: (...args: any[]) => void,
21
+ info: (...args: any[]) => void,
22
+ debug: (...args: any[]) => void,
23
+ warn: (...args: any[]) => void,
24
+ // wx.getLogManager跟wx.getRealtimeLogManager是没有error的
11
25
  }
12
26
 
13
27
  /**
14
28
  * 页面对象
15
29
  */
16
- interface IPage {
30
+ export interface IPage {
17
31
  route: string,
18
32
  options: object,
19
33
  depth: number,
@@ -22,11 +36,11 @@ interface IPage {
22
36
  /**
23
37
  * 旧的埋点参数类型
24
38
  */
25
- interface IOldParams {
39
+ export interface IOldParams {
26
40
  [key: number]: any,
27
41
  }
28
42
 
29
- interface ISystemInfo {
43
+ export interface ISystemInfo {
30
44
  model: string,
31
45
  wxVersion: string,
32
46
  platform: string,
@@ -35,12 +49,12 @@ interface ISystemInfo {
35
49
  host: object,
36
50
  }
37
51
 
38
- interface ILocation {
52
+ export interface ILocation {
39
53
  province: string,
40
54
  cityName: string,
41
55
  }
42
56
 
43
- interface IDeviceData {
57
+ export interface IDeviceData {
44
58
  networkType: string,
45
59
  location: ILocation,
46
60
  }
package/src/request.js CHANGED
@@ -357,7 +357,7 @@ export default class Request {
357
357
  obj.err = result;
358
358
  }
359
359
 
360
- const str = JSON.stringify(obj, null, ' ').replace(/\\"/ig, '\'');
360
+ const str = JSON.stringify(obj, null, 2).replace(/\\"/ig, '\'');
361
361
  if (isSuccess) {
362
362
  logger.log(`接口请求成功:\n${str}`);
363
363
  } else {
@@ -34,34 +34,31 @@ const getCode = () => new Promise((resolve, reject) => {
34
34
  wx.login({ success: ({ code }) => resolve(code), fail: reject });
35
35
  });
36
36
 
37
- let loginProcessing = false; // 是否有进行中的登录流程
38
37
  /**
39
38
  * login 方法 获取用户信息
40
39
  * @private
41
40
  * @return {object} userInfo
42
41
  */
43
42
  const loginFn = async () => {
44
- if (loginProcessing) return;
45
- loginProcessing = true;
46
-
47
- let userInfo = {};
48
- try {
49
- let userData = await login();
50
-
51
- if (userData.errCode === 10 || !userData.resData.userInfo || !userData.resData.userInfo.uid) {
52
- userData = await login();
53
- }
54
-
55
- if (userData.errCode === 0) {
56
- wx.setStorageSync('userInfo', userData.resData.userInfo);
57
- userInfo = userData.resData.userInfo;
58
- }
59
-
60
- loginProcessing = false;
61
- } catch (e) {
62
- loginProcessing = false;
43
+ // 与独立分包共用登录,避免登录互斥
44
+ if (!wx.tmsLoginPromise) {
45
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
46
+ wx.tmsLoginPromise = new Promise(async (resolve) => {
47
+ let userInfo = {} as any;
48
+ try {
49
+ let userData = await login();
50
+ if (userData.errCode === 10 || !userData.resData.userInfo || !userData.resData.userInfo.uid) {
51
+ userData = await login();
52
+ }
53
+ if (userData.errCode === 0) {
54
+ userInfo = userData.resData.userInfo;
55
+ }
56
+ } catch (e) {}
57
+ resolve(userInfo);
58
+ });
63
59
  }
64
- return userInfo;
60
+
61
+ return wx.tmsLoginPromise;
65
62
  };
66
63
 
67
64
  /**