@tmsfe/tms-core 0.0.26 → 0.0.30

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.26",
3
+ "version": "0.0.30",
4
4
  "description": "tms运行时框架",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,199 @@
1
+ /**
2
+ * 调用云函数上报埋点
3
+ */
4
+
5
+ import syncApi from './syncfnmanager';
6
+
7
+ type DataType = string | null;
8
+
9
+ interface IInitOptions {
10
+ client: string, // sinan、mycar等
11
+ appVersion: string,
12
+ cloudEnvId: string,
13
+ }
14
+
15
+ interface IPage {
16
+ route: string,
17
+ options: object,
18
+ }
19
+
20
+ const openidIndex = 7; // openId的下标,由云函数填充
21
+
22
+ let initOptions: IInitOptions;
23
+
24
+ function init(options: IInitOptions): void {
25
+ if (!initOptions) {
26
+ initOptions = options;
27
+ wx.cloud.init({ env: options.cloudEnvId });
28
+ }
29
+ }
30
+
31
+ function getSystemInfoString(): string {
32
+ const system = syncApi.getSystemInfoSync();
33
+ // @ts-ignore
34
+ // eslint-disable-next-line
35
+ const { model = '', version: wxVersion = '', platform = '', SDKVersion = '', host = '' } = system;
36
+ const info = { model, wxVersion, platform, SDKVersion, host };
37
+ return encodeURIComponent(JSON.stringify(info));
38
+ }
39
+
40
+ function convert2String(value: any): string {
41
+ const type = typeof value;
42
+ if (type === 'string') {
43
+ return value;
44
+ }
45
+ if (type === 'object') {
46
+ return JSON.stringify(value);
47
+ }
48
+ return String(value);
49
+ }
50
+
51
+ function getSeqInfo(): { timestamp: number, seqId: string } {
52
+ const timestamp = Date.now();
53
+ const random = Math.random().toString();
54
+ const randomStr = random.slice(2, 7);
55
+ const sourceId = 7; // 6 未知 7 云函数 8 出行 9 我的车
56
+ const seqId = `${timestamp}${sourceId}${randomStr}`;
57
+ return { timestamp, seqId };
58
+ }
59
+
60
+ function getPageInfo(): IPage | null {
61
+ const pages = getCurrentPages();
62
+ // 首页未渲染
63
+ if (pages.length === 0) {
64
+ const launch = syncApi.getLaunchOptionsSync();
65
+ return { route: launch.path, options: launch.query };
66
+ }
67
+ const page = pages.pop();
68
+ // 插件页
69
+ if (!page) {
70
+ return null;
71
+ }
72
+ return page;
73
+ }
74
+
75
+ /**
76
+ * 获取埋点的基础字段
77
+ * @param page
78
+ * @param seqId 请求ID
79
+ */
80
+ function getBaseData(page: IPage, seqId: string): { arr: DataType[], nextIndex: number } {
81
+ const pageQuery = encodeURIComponent(JSON.stringify(page.options));
82
+ const pageUrl = page.route;
83
+ const { appVersion, client } = initOptions;
84
+ const system = getSystemInfoString();
85
+ // @ts-ignore
86
+ const { scene = -1 } = syncApi.getLaunchOptionsSync();
87
+
88
+ const arr = new Array(41);
89
+ // 0: log_time
90
+ // 1: access_time,用户点击时间,服务端统一处理
91
+ // 2: user_ip,前端无需赋值
92
+ // 3: qimei,灯塔中的用户ID
93
+ // 4: imei,Android手机的imei IOS系统中的idfv 车联网中的wecarid
94
+ // 5: user_id,用户ID
95
+ // 6: qq_no,登录QQ的openid,
96
+ // 7: wechat_id,登录微信的openid,由云函数填充
97
+ // 8: phone_no,手机号
98
+ // 9: platform,客户端请求来源,小程序是2
99
+ arr[9] = '2';
100
+ // 10: app_version,客户端|小程序版本号
101
+ arr[10] = appVersion;
102
+ // 11: channel,外部推广渠道或车辆所属渠道
103
+ // 12: net_type,wifi、3G、4G等
104
+ // 13: product_id,手图APP、车联网等
105
+ // 14: busi_type,1: 定位、2: 检索、3: 导航、4: 车主服务、5: 小程序
106
+ arr[14] = '5';
107
+ // 15: request_id,请求ID
108
+ arr[15] = seqId;
109
+ // 16: session_id,标识用户一次访问过程的ID
110
+ // 17: f17 - province,省份
111
+ // 18: f18 - city,城市
112
+ // 19: f19 - 系统信息
113
+ arr[19] = system;
114
+ // 20: f20 - sinan、mycar等
115
+ arr[20] = client;
116
+ // 21: f21 - 小程序场景值
117
+ arr[21] = scene.toString();
118
+ // 22: f22 - 标记是云函数上报
119
+ arr[22] = 'cloud';
120
+ // 23: f23 - 当前页面的url
121
+ arr[23] = pageUrl;
122
+ // 24: f24 - 当前页面的query
123
+ arr[24] = pageQuery;
124
+ // 25 ~ 30: 预留字典给后续扩展使用
125
+ // 31 ~ 40: 提供给开发自定义
126
+ return { arr, nextIndex: 31 };
127
+ }
128
+
129
+ function formatData(page: IPage, seqId: string, data: any[]): DataType[] {
130
+ const { arr, nextIndex } = getBaseData(page, seqId);
131
+ let index = nextIndex;
132
+ for (const item of data) {
133
+ if (index >= arr.length) {
134
+ console.error(data);
135
+ throw new Error('埋点参数个数超出上限');
136
+ }
137
+ arr[index] = convert2String(item);
138
+ index += 1;
139
+ }
140
+ return arr;
141
+ }
142
+
143
+ function report(...data: any[]): void {
144
+ console.log('云埋点', data);
145
+ const page = getPageInfo();
146
+ if (page === null) {
147
+ console.log('插件页不上报埋点');
148
+ return;
149
+ }
150
+ // @ts-ignore
151
+ const { scene = -1 } = syncApi.getLaunchOptionsSync();
152
+ // 小程序爬虫产生的日志
153
+ if (scene === 1129 || scene === 1030) {
154
+ console.warn('小程序爬虫,不上报');
155
+ } else {
156
+ const { timestamp, seqId } = getSeqInfo();
157
+ const arr = formatData(page, seqId, data);
158
+ doCallCloudFunc(arr, timestamp, seqId, openidIndex);
159
+ }
160
+ }
161
+
162
+ function doCallCloudFunc(arr: DataType[], timestamp: number, seqId: string, openidIndex: number): void {
163
+ const { cloudEnvId, appVersion } = initOptions;
164
+ const onFail = (err: any) => {
165
+ console.error('云埋点失败:', arr, err);
166
+ };
167
+ wx.cloud.callFunction({
168
+ name: 'report',
169
+ data: {
170
+ openidIndex,
171
+ params: { seqId, timestamp, appVersion, batch: [arr] },
172
+ },
173
+ config: { env: cloudEnvId },
174
+ success: (res: any) => {
175
+ const body = JSON.parse(res.result.body);
176
+ if (body.errCode !== 0) {
177
+ onFail(res);
178
+ }
179
+ },
180
+ fail: onFail,
181
+ });
182
+ }
183
+
184
+ /**
185
+ * 调用云函数将已经组装完整的埋点数据arr发出去
186
+ * @param arr
187
+ */
188
+ function callCloudFunc(arr: string[]): void {
189
+ const { timestamp, seqId } = getSeqInfo();
190
+ doCallCloudFunc(arr, timestamp, seqId, openidIndex);
191
+ }
192
+
193
+ export default {
194
+ init,
195
+ report,
196
+ callCloudFunc,
197
+ convert2String,
198
+ getSystemInfoString,
199
+ };
package/src/fastreport.js CHANGED
@@ -3,28 +3,14 @@
3
3
  * @author Fenggang.Sun <fenggangsun@tencent.com>
4
4
  * @file 快速上报数据,不处理过多逻辑,保证快速上报
5
5
  */
6
- import Request from './request';
7
- import { getEnvInfo } from './env';
8
- import Sync from './syncfnmanager';
9
-
10
- let simulatedUserIdCache; // 模拟用户id在内存里的缓存
11
-
12
- const getSystemInfo = () => {
13
- const system = Sync.getSystemInfoSync();
14
- const { model = '', version: wxVersion = '', platform = '', SDKVersion = '', host = '' } = system;
15
-
16
- return { model, wxVersion, platform, SDKVersion, host };
17
- };
6
+ import { getEnvInfo, getAuthInfo } from './env';
7
+ import CloudReport from './cloudReport';
18
8
 
19
9
  const handleParamOfDifferentType = (param) => {
20
10
  const data = new Array(41);
21
11
  Object.keys(param).forEach((key) => {
22
- const valType = typeof param[key];
23
- if (valType === 'string') data[key] = param[key];
24
- else if (valType === 'object') data[key] = JSON.stringify(param[key]);
25
- else data[key] = String(param[key]);
12
+ data[key] = CloudReport.convert2String(param[key]);
26
13
  });
27
-
28
14
  return data;
29
15
  };
30
16
 
@@ -39,52 +25,27 @@ export default class FastReport {
39
25
  * @memberof FastReport
40
26
  * @description 快速上报
41
27
  * @param {Object} param 埋点数据
42
- * @param {Boolean} simulatedUserId 是否上报模拟用户Id
43
- * @param {Number} simulatedUserIdIndex 上报模拟用户ID时放在哪个字段
44
- * @param {Boolean} reportShowScene 是否上报小程序onShow场景值
45
- * @param {Boolean} appVer 是否上报小程序版本
46
- * @returns {Promsie} 返回上报结果
47
28
  */
48
- static report(param = {}, simulatedUserId = true, simulatedUserIdIndex = 40, reportShowScene = true, appVer = true) {
49
- if (!param[27]) return Promise.reject('invalid report param');
29
+ static report(param = {}) {
30
+ if (!param[27]) {
31
+ return Promise.reject('invalid report param');
32
+ }
50
33
  const env = getEnvInfo();
51
34
  const data = handleParamOfDifferentType(param);
52
35
  data[9] = '2';
53
- data[33] = encodeURIComponent(JSON.stringify(getSystemInfo()));
54
- if (appVer) {
55
- data[10] = defAssign(data[10], env.appVersion);
56
- }
36
+ data[10] = defAssign(data[10], env.appVersion);
57
37
  data[26] = defAssign(data[26], data[27]?.[0]);
58
38
  data[28] = env.client;
59
- if (reportShowScene && !data[29]) {
39
+ if (!data[29]) {
60
40
  const appShowScene = wx.getStorageSync('appShowScene');
61
- if (appShowScene) data[29] = String(appShowScene);
41
+ if (appShowScene) {
42
+ data[29] = String(appShowScene);
43
+ }
62
44
  }
63
- if (simulatedUserId && !data[simulatedUserIdIndex]) {
64
- data[simulatedUserIdIndex] = FastReport.getSimulatedUserId();
65
- }
66
-
67
- return new Request().post('basic/event/upload', { batch: [data] })
68
- .catch(() => null);
69
- }
70
-
71
- /**
72
- * @memberof FastReport
73
- * @description 获取模拟的用户身份标识
74
- * @returns {String} 用户的临时标识
75
- */
76
- static getSimulatedUserId() {
77
- // 优先使用内存级缓存
78
- if (simulatedUserIdCache) return simulatedUserIdCache;
79
- const key = 'SimulatedUserKey';
80
- // 读取本地缓存记录的值
81
- simulatedUserIdCache = wx.getStorageSync(key);
82
- if (simulatedUserIdCache) return simulatedUserIdCache;
83
- // 生成新的值
84
- const nonce = Math.random().toString(36)
85
- .substr(2, 10);
86
- simulatedUserIdCache = `${Date.now()}_${nonce}`;
87
- wx.setStorage({ key, data: simulatedUserIdCache });
88
- return simulatedUserIdCache;
45
+ data[33] = CloudReport.getSystemInfoString();
46
+ getAuthInfo().then((user) => {
47
+ data[5] = user.uid;
48
+ CloudReport.callCloudFunc(data);
49
+ });
89
50
  }
90
51
  };
@@ -7,6 +7,7 @@
7
7
 
8
8
  import syncApi from './syncfnmanager';
9
9
  import md5 from './md5';
10
+ import CloudReport from './cloudReport';
10
11
  import { rpxToPx } from './rpx';
11
12
  import { serialize } from './objUtils';
12
13
  import * as stringUtils from './stringUtils';
@@ -39,6 +40,7 @@ function invoke(obj, funcName, args) {
39
40
  function initProxy(appObj, options) {
40
41
  app = appObj;
41
42
  initOptions = options;
43
+ CloudReport.init(options);
42
44
  }
43
45
 
44
46
  function awaitTMS() {
@@ -201,10 +203,18 @@ function getHomePage() {
201
203
  return initOptions.homePage;
202
204
  }
203
205
 
206
+ function getCloudReport() {
207
+ if (tms) {
208
+ return tms.getCloudReport();
209
+ }
210
+ return CloudReport;
211
+ }
212
+
204
213
  const api = {
205
214
  isProxy: true, // 方便定位问题时判断是否proxy
206
215
  initProxy,
207
216
  md5,
217
+ getCloudReport,
208
218
  getCarManager,
209
219
  getLocationManager,
210
220
  rpxToPx,
package/src/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import Request from './request';
2
2
  import FastReport from './fastreport';
3
+ import CloudReport from './cloudReport';
3
4
  import { getConfig } from './config';
4
5
  import syncApi from './syncfnmanager';
5
6
  import nav from './navigator';
@@ -11,7 +12,6 @@ import { cache as report, startListenApp } from './report';
11
12
  import EventDispatcher from './eventDispatcher';
12
13
  import { serialize } from './objUtils';
13
14
  import { rpxToPx } from './rpx';
14
- import { distanceBetweenPoints } from './distanceBetweenPoints';
15
15
  import {
16
16
  formatPlate,
17
17
  subStr,
@@ -74,6 +74,11 @@ const getReporter = () => ({ report });
74
74
  */
75
75
  const getFastReporter = () => FastReport;
76
76
 
77
+ /**
78
+ * @description 云函数埋点上报
79
+ */
80
+ const getCloudReport = () => CloudReport;
81
+
77
82
  /**
78
83
  * @description 自定义事件机制
79
84
  * @returns {Object} [EventDispatcher实例](#class-eventdispatcher)
@@ -100,14 +105,16 @@ const getLocationBaseClass = () => LocationBase;
100
105
  const init = (options = {}) => {
101
106
  startListenApp();
102
107
  const { appVersion, wxAppId, client, defaultHost, cloudEnvId, appEnv, appPagePaths, homePage } = options;
103
- setEnvInfo({
108
+ const envInfo = {
104
109
  wxAppId,
105
110
  appVersion,
106
111
  appEnv,
107
112
  client,
108
113
  cloudEnvId,
109
- });
114
+ };
115
+ setEnvInfo(envInfo);
110
116
  setAppPagePaths(appPagePaths, homePage);
117
+ CloudReport.init(envInfo);
111
118
  Request.defaultHost = defaultHost;
112
119
  // 初始化云环境
113
120
  wx.cloud.init({ env: cloudEnvId });
@@ -133,6 +140,7 @@ const api = {
133
140
  getRealtimeLogManager,
134
141
  md5,
135
142
  getReporter,
143
+ getCloudReport,
136
144
  getFastReporter,
137
145
  getLocationManager,
138
146
  getLocationBaseClass,
@@ -181,7 +189,6 @@ const api = {
181
189
 
182
190
  /** rpx转px */
183
191
  rpxToPx,
184
- distanceBetweenPoints,
185
192
 
186
193
  storage,
187
194
 
@@ -1,73 +0,0 @@
1
-
2
- // 墨卡托坐标转经纬度
3
- function mercator2LonLat(p) {
4
- const r = p.y / 111319.49077777778;
5
- const n = Math.atan(Math.exp(0.017453292519943295 * r)) / 0.008726646259971648 - 90;
6
- return {
7
- x: p.x / 111319.49077777778,
8
- y: n,
9
- };
10
- }
11
-
12
-
13
- // 角度转弧度
14
- function angle2Rad(t) {
15
- return (t * Math.PI) / 180;
16
- }
17
-
18
-
19
- function client2ServerX(t) {
20
- return t - 20037508;
21
- }
22
-
23
- function client2ServerY(t) {
24
- return t - 30240971;
25
- }
26
-
27
- function longitude2ClientX(t) {
28
- return Number(111319.49077777778 * Number(t) + 20037508).toFixed(0);
29
- }
30
-
31
- function latitude2ClientY(t) {
32
- const n = Math.log(Math.tan(0.008726646259971648 * (90 + Number(t)))) / 0.017453292519943295;
33
- return Number(111319.49077777778 * n + 30240971).toFixed(0);
34
- }
35
-
36
- function geoPointToServerPoint(t) {
37
- let n = {};
38
- if (t) {
39
- n = {
40
- x: client2ServerX(longitude2ClientX(t.longitude)),
41
- y: client2ServerY(latitude2ClientY(t.latitude)),
42
- };
43
- }
44
- return n;
45
- }
46
-
47
-
48
- /**
49
- * 两个经纬度间地理距离(单位:米)
50
- * @param {*} start {longitude, latitude}
51
- * @param {*} end {longitude, latitude}
52
- * @returns
53
- */
54
- function distanceBetweenPoints(start, end) {
55
- let s = geoPointToServerPoint(start);
56
- let t = geoPointToServerPoint(end);
57
- s = mercator2LonLat(s); // eslint-disable-line
58
- t = mercator2LonLat(t); // eslint-disable-line
59
- const deltaY = angle2Rad(s.y) - angle2Rad(t.y);
60
- const deltaX = angle2Rad(s.x) - angle2Rad(t.x);
61
- let res = 2
62
- * Math.asin(Math.sqrt(Math.pow(Math.sin(deltaY / 2), 2) // eslint-disable-line
63
- + Math.cos(angle2Rad(s.y))
64
- * Math.cos(angle2Rad(t.y))
65
- * Math.pow(Math.sin(deltaX / 2), 2))); // eslint-disable-line
66
- res *= 6378137;
67
- res = Math.floor(res * 10000 + 0.5) / 10000;
68
- return res;
69
- }
70
-
71
- export {
72
- distanceBetweenPoints,
73
- };