@tmsfe/tms-core 0.0.15 → 0.0.19
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/dist/index.js +30 -3
- package/dist/request-f350158c.js +543 -0
- package/dist/request-fea3ef26.js +538 -0
- package/dist/request.js +1 -1
- package/package.json +1 -1
- package/src/index.js +6 -0
- package/src/location/index.ts +44 -0
- package/src/numUtils.js +16 -0
- package/src/objUtils.js +21 -2
- package/src/report.js +2 -2
- package/src/request.js +13 -3
- package/src/stringUtils.js +2 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as Request, g as getLogManager, a as getRealtimeLogManager } from './request-
|
|
1
|
+
import { R as Request, g as getLogManager, a as getRealtimeLogManager } from './request-f350158c.js';
|
|
2
2
|
import { g as getEnvInfo, a as getAuthInfo, s as setAuthInfo, i as isAppPageExist, b as getHomePage, c as setEnvInfo, d as setAppPagePaths } from './env-c7da70e1.js';
|
|
3
3
|
import { s as syncApi, f as formatPlate, a as subStr, h as hidePhoneCenter, i as isValidPhone, b as isValidPlate, c as isValidAuthCode, r as roundStr, d as formatTime, e as formatTimeStr, g as formatTimeWithDetails, j as dateToString, k as ipxInit, l as isIPX, m as getIpxClass, n as getIpxConfig, o as serialize, p as rpxToPx } from './ipxHelper-71ef86c1.js';
|
|
4
4
|
import { m as md5 } from './md5-34a9daf3.js';
|
|
@@ -767,6 +767,7 @@ let cityTheUserAt = '';
|
|
|
767
767
|
// 用户城市变化事件名
|
|
768
768
|
const CityChangeEventName = 'loc_city_changed';
|
|
769
769
|
const LocationType = 'gcj02'; // 获取经纬度时的坐标名称
|
|
770
|
+
let ipLocationPromise = null; // ip定位请求的promise
|
|
770
771
|
/**
|
|
771
772
|
* @class Location
|
|
772
773
|
* @classdesc 基于LocationBase,封装业务侧位置的接口。 将用户经纬度转化为城市等展示信息
|
|
@@ -993,6 +994,32 @@ class Location extends LocationBase$1 {
|
|
|
993
994
|
}
|
|
994
995
|
return request.post('basic/lbs/direction', { from, to, mode });
|
|
995
996
|
}
|
|
997
|
+
/**
|
|
998
|
+
* ip定位
|
|
999
|
+
* 原理:通过调手图接口查询当前IP所在位置,市级的准确率是91%
|
|
1000
|
+
* 注意:由于服务端对该查询服务有次数限制,所以本函数会缓存成功的promise
|
|
1001
|
+
* @param force 是否清除上次的缓存重新请求
|
|
1002
|
+
*/
|
|
1003
|
+
getIpLocation(force = false) {
|
|
1004
|
+
if (ipLocationPromise === null || force) {
|
|
1005
|
+
ipLocationPromise = new Promise((resolve, reject) => {
|
|
1006
|
+
request.post('basic/lbs/decodeip')
|
|
1007
|
+
.then((res) => {
|
|
1008
|
+
if (res.errCode === 0) {
|
|
1009
|
+
resolve(res.resData);
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
reject({ erMsg: res.errMsg });
|
|
1013
|
+
ipLocationPromise = null;
|
|
1014
|
+
})
|
|
1015
|
+
.catch((e) => {
|
|
1016
|
+
reject(e);
|
|
1017
|
+
ipLocationPromise = null;
|
|
1018
|
+
});
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
return ipLocationPromise;
|
|
1022
|
+
}
|
|
996
1023
|
}
|
|
997
1024
|
// 因为在构造函数中会用到wx的api,所以使用到时才实例化
|
|
998
1025
|
let instance;
|
|
@@ -1136,11 +1163,11 @@ const getProvinceInfoByIp = () => {
|
|
|
1136
1163
|
if (!ProvinceInfoCacheByIp) {
|
|
1137
1164
|
ProvinceInfoCacheByIp = new Promise(async resolve => {
|
|
1138
1165
|
try {
|
|
1139
|
-
const loc = await
|
|
1166
|
+
const loc = await getLocInstance().getIpLocation();
|
|
1140
1167
|
const {
|
|
1141
1168
|
city,
|
|
1142
1169
|
province
|
|
1143
|
-
} = loc.
|
|
1170
|
+
} = loc.ad_info;
|
|
1144
1171
|
resolve({
|
|
1145
1172
|
cityName: city,
|
|
1146
1173
|
province
|
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
import { m as md5 } from './md5-34a9daf3.js';
|
|
2
|
+
import { a as getAuthInfo, g as getEnvInfo } from './env-c7da70e1.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 本文件主要负责在小程序中日志打印功能,包含本地日志及实时日志. 主要做了两件事:
|
|
6
|
+
* 1、参数序列化处理;支持传递任意多个参数,并对类型为对象的参数进行字符串序列化处理(避免打印出来是'[Object Object]'的格式);
|
|
7
|
+
* 2、低版本兼容;
|
|
8
|
+
*/
|
|
9
|
+
// 低版本不支持getLogManager或者getRealtimeLogManager时,用ManagerForLowerVersionLib来兼容
|
|
10
|
+
const ManagerForLowerVersionLib = {
|
|
11
|
+
debug: () => {},
|
|
12
|
+
info: () => {},
|
|
13
|
+
log: () => {},
|
|
14
|
+
warn: () => {},
|
|
15
|
+
error: () => {},
|
|
16
|
+
addFilterMsg: () => {},
|
|
17
|
+
setFilterMsg: () => {}
|
|
18
|
+
}; // 小程序基础库2.7.1版本以上支持,所以需要兼容性处理
|
|
19
|
+
|
|
20
|
+
let logInstance = null;
|
|
21
|
+
let rtLogInstance = null;
|
|
22
|
+
|
|
23
|
+
function getLogInstance() {
|
|
24
|
+
if (logInstance === null) {
|
|
25
|
+
logInstance = wx.getLogManager ? wx.getLogManager() : ManagerForLowerVersionLib;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return logInstance;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getRTLogInstance() {
|
|
32
|
+
if (rtLogInstance === null) {
|
|
33
|
+
rtLogInstance = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : ManagerForLowerVersionLib;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return rtLogInstance;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 参数中有对象类型的,将其转换为字符串类型,以便查看
|
|
40
|
+
* @param {Array<Any>} params 需要格式化的数据
|
|
41
|
+
* @returns {Array<String>} 字符串序列化后的数据
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
const format = params => params.map(param => typeof param === 'string' ? param : JSON.stringify(param));
|
|
46
|
+
/**
|
|
47
|
+
* @namespace LOG
|
|
48
|
+
* @description 普通日志管理器,将日志记录在小程序日志文件中,用户上传后,可以在小程序后台-反馈管理中看到
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
const LOG = {
|
|
53
|
+
/**
|
|
54
|
+
* @description 写debug日志
|
|
55
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
56
|
+
* @returns {Void} 无返回值
|
|
57
|
+
*/
|
|
58
|
+
debug(...params) {
|
|
59
|
+
getLogInstance().debug(...format(params));
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @description 写info日志
|
|
64
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
65
|
+
* @returns {Void} 无返回值
|
|
66
|
+
*/
|
|
67
|
+
info(...params) {
|
|
68
|
+
getLogInstance().info(...format(params));
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @description 写log日志
|
|
73
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
74
|
+
* @returns {Void} 无返回值
|
|
75
|
+
*/
|
|
76
|
+
log(...params) {
|
|
77
|
+
getLogInstance().log(...format(params));
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @description 写warn日志
|
|
82
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
83
|
+
* @returns {Void} 无返回值
|
|
84
|
+
*/
|
|
85
|
+
warn(...params) {
|
|
86
|
+
getLogInstance().warn(...format(params));
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @description 写warn日志. LogManager并没有error方法,为了兼容旧代码,所以声明一个error方法
|
|
91
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
92
|
+
* @returns {Void} 无返回值
|
|
93
|
+
*/
|
|
94
|
+
error(...params) {
|
|
95
|
+
LOG.warn(...params);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* @namespace RTLOG
|
|
101
|
+
* @description 实时日志,将日志实时上传至小程序后台-开发-运维中心-实时日志,方便快速排查漏洞,定位问题
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
const RTLOG = {
|
|
105
|
+
/**
|
|
106
|
+
* @description 写info日志
|
|
107
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
108
|
+
* @returns {Void} 无返回值
|
|
109
|
+
*/
|
|
110
|
+
info(...params) {
|
|
111
|
+
getRTLogInstance().info(...format(params));
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @description 写warn日志
|
|
116
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
117
|
+
* @returns {Void} 无返回值
|
|
118
|
+
*/
|
|
119
|
+
warn(...params) {
|
|
120
|
+
getRTLogInstance().warn(...format(params));
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @description 写error日志
|
|
125
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
126
|
+
* @returns {Void} 无返回值
|
|
127
|
+
*/
|
|
128
|
+
error(...params) {
|
|
129
|
+
getRTLogInstance().error(...format(params));
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @description 添加过滤关键字
|
|
134
|
+
* @param {String} msg 关键字
|
|
135
|
+
* @returns {Void} 无返回值
|
|
136
|
+
*/
|
|
137
|
+
addFilterMsg(msg) {
|
|
138
|
+
getRTLogInstance().addFilterMsg(msg);
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @description 设置过滤关键字
|
|
143
|
+
* @param {String} msg 关键字
|
|
144
|
+
* @returns {Void} 无返回值
|
|
145
|
+
*/
|
|
146
|
+
setFilterMsg(msg) {
|
|
147
|
+
getRTLogInstance().setFilterMsg(msg);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* @description 获取日志管理器对象,该对象提供的方法同wx.getLogManager()提供的方法,详见微信文档
|
|
153
|
+
* @returns {Object} [LOG](#namespace-log)
|
|
154
|
+
* @example
|
|
155
|
+
* const logger = getLogManager();
|
|
156
|
+
* logger.log(1, 'str', { a: 1 }, ...);
|
|
157
|
+
* logger.info(1, 'str', { a: 1 }, ...);
|
|
158
|
+
* logger.debug(1, 'str', { a: 1 }, ...);
|
|
159
|
+
* logger.awrn(1, 'str', { a: 1 }, ...);
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
const getLogManager = () => LOG;
|
|
163
|
+
/**
|
|
164
|
+
* @description 获取实时日志管理器对象,该对象提供的方法同wx.getRealtimeLogManager()提供的方法,详见微信文档
|
|
165
|
+
* @returns {Object} [RTLOG](#namespace-rtlog)
|
|
166
|
+
* @example
|
|
167
|
+
* const logger = getRealtimeLogManager();
|
|
168
|
+
* logger.info(1, 'str', { a: 1 }, ...);
|
|
169
|
+
* logger.warn(1, 'str', { a: 1 }, ...);
|
|
170
|
+
* logger.error(1, 'str', { a: 1 }, ...);
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
const getRealtimeLogManager = () => RTLOG;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @copyright 2021-present, Tencent, Inc. All rights reserved.
|
|
178
|
+
* @brief request.js用于发起网络请求.
|
|
179
|
+
* request模块作为基于 tms-core & tms-runtime 的应用的公共请求模块。
|
|
180
|
+
* 目前支持在出行服务小程序或基于出行服务的小程序中调用。在后续tms-runtime支持公众号H5后,
|
|
181
|
+
* 将支持在H5中调用。
|
|
182
|
+
*
|
|
183
|
+
* 考虑到对不同运行环境的支持,强依赖运行环境的依赖,比如 wx.request,应通过注入的形式提供。
|
|
184
|
+
* 框架判断在不同的运行环境,切换调用不同运行环境提供的方法。
|
|
185
|
+
*/
|
|
186
|
+
/**
|
|
187
|
+
* 用于序列化需要签名的参数
|
|
188
|
+
* @private
|
|
189
|
+
* @param {object} param 需要序列化的参数
|
|
190
|
+
* @returns {string} 序列化之后的参数字符串
|
|
191
|
+
*/
|
|
192
|
+
|
|
193
|
+
const seriesParam = param => {
|
|
194
|
+
const keys = Object.keys(param).sort();
|
|
195
|
+
const series = keys.map(key => {
|
|
196
|
+
const val = param[key];
|
|
197
|
+
return `${key}${typeof val === 'object' ? JSON.stringify(val) : val}`;
|
|
198
|
+
});
|
|
199
|
+
return series.join('');
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* 用于对request请求对象做签名
|
|
203
|
+
* @private
|
|
204
|
+
* @param {object} param 需要做签名的参数
|
|
205
|
+
* @returns {object} 签名后的参数对象
|
|
206
|
+
*/
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
const sign = (param = {}) => {
|
|
210
|
+
const token = '';
|
|
211
|
+
const signture = md5(seriesParam(param) + token);
|
|
212
|
+
return { ...param,
|
|
213
|
+
sign: signture
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* 用于对request请求对象添加系统参数
|
|
218
|
+
* @private
|
|
219
|
+
* @param {object} param 接口调用传入的参数
|
|
220
|
+
* @param {Boolean} withAuth 是否需要登录参数
|
|
221
|
+
* @param {object} baseParam request实例定义的基础参数
|
|
222
|
+
* @returns {object} 全部参数对象
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
const composeParam = async (param = {}, withAuth = true, baseParam = {}) => {
|
|
227
|
+
const version = '1.0';
|
|
228
|
+
const {
|
|
229
|
+
appVersion,
|
|
230
|
+
wxAppId,
|
|
231
|
+
client
|
|
232
|
+
} = getEnvInfo();
|
|
233
|
+
const nonce = Math.random().toString(36).substr(2, 10);
|
|
234
|
+
const timestamp = Date.now();
|
|
235
|
+
const random = Math.random().toString().slice(2, 7);
|
|
236
|
+
const sourceId = ['', 'sinan', 'mycar'].indexOf(client) + 7; // 6 未知 7 云函数 8 出行 9 我的车
|
|
237
|
+
|
|
238
|
+
const seqId = `${timestamp}${sourceId}${random}`;
|
|
239
|
+
const paramsWithAuth = await modifyAuthParam(param, withAuth);
|
|
240
|
+
const combinedParam = Object.assign({
|
|
241
|
+
version,
|
|
242
|
+
appVersion,
|
|
243
|
+
nonce,
|
|
244
|
+
timestamp,
|
|
245
|
+
seqId,
|
|
246
|
+
wxAppId
|
|
247
|
+
}, { ...baseParam
|
|
248
|
+
}, { ...paramsWithAuth
|
|
249
|
+
}); // 清理undefined和NaN的参数
|
|
250
|
+
|
|
251
|
+
Object.keys(combinedParam).forEach(key => {
|
|
252
|
+
if (typeof combinedParam[key] === 'number' && isNaN(combinedParam[key])) {
|
|
253
|
+
delete combinedParam[key];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (typeof combinedParam[key] === 'undefined') {
|
|
257
|
+
delete combinedParam[key];
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
return combinedParam;
|
|
261
|
+
};
|
|
262
|
+
/**
|
|
263
|
+
* 用于保证业务参数的登录态参数,
|
|
264
|
+
* 若接口不依赖登录态 如 user/login,则保证参数中不包括userId & token,
|
|
265
|
+
* 若接口依赖登录态,则保证参数中填充userId & token,
|
|
266
|
+
* @private
|
|
267
|
+
* @param {object} param 要校验登录态的业务参数
|
|
268
|
+
* @param {boolean} withAuth 是否要校验登录态
|
|
269
|
+
* @returns {object} 增加登录态后的参数
|
|
270
|
+
*/
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
const modifyAuthParam = async (param, withAuth) => {
|
|
274
|
+
const requestParam = { ...param
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
if (withAuth) {
|
|
278
|
+
const {
|
|
279
|
+
userId,
|
|
280
|
+
token
|
|
281
|
+
} = await getAuthInfo();
|
|
282
|
+
requestParam.userId = userId;
|
|
283
|
+
requestParam.token = token;
|
|
284
|
+
return requestParam;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
delete requestParam.userId;
|
|
288
|
+
delete requestParam.userid;
|
|
289
|
+
delete requestParam.token;
|
|
290
|
+
return requestParam;
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* @public
|
|
294
|
+
* @class Request
|
|
295
|
+
* @classdesc 网络请求类,对签名、鉴权等逻辑进行封装处理,用于向腾讯出行服务平台后台发送网络请求
|
|
296
|
+
*/
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class Request {
|
|
300
|
+
/**
|
|
301
|
+
* 默认的request host域名
|
|
302
|
+
* defaultHost 在tms-runtime初始化时进行设置,为出行服务接入层域名
|
|
303
|
+
* 具体业务模块 new Request() 使用时,不指定自定义 host ,将使用defaultHost
|
|
304
|
+
*/
|
|
305
|
+
static defaultHost = '';
|
|
306
|
+
host = '';
|
|
307
|
+
withAuth = true;
|
|
308
|
+
baseParam = {};
|
|
309
|
+
/**
|
|
310
|
+
* Request 构造函数
|
|
311
|
+
* @param {Object} config 构造参数
|
|
312
|
+
* @param {Object} config.withAuth 是否填充登录态参数
|
|
313
|
+
* @param {Object} config.host 自定义的host域名
|
|
314
|
+
* @param {Object} config.baseParam 默认携带的参数
|
|
315
|
+
*/
|
|
316
|
+
|
|
317
|
+
constructor(config = {
|
|
318
|
+
withAuth: true
|
|
319
|
+
}) {
|
|
320
|
+
if (config.host) {
|
|
321
|
+
this.host = config.host;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (typeof config.withAuth !== 'undefined') {
|
|
325
|
+
this.withAuth = !!config.withAuth;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
this.baseParam = config.baseParam || {};
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* 格式化接口路径
|
|
332
|
+
* @private
|
|
333
|
+
* @param {string} path 需要格式化的接口路径
|
|
334
|
+
* @returns {string} 格式化后的接口路径
|
|
335
|
+
*/
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
makeUrl(path) {
|
|
339
|
+
if (/^http/i.test(path)) return path;
|
|
340
|
+
const host = this.host || Request.defaultHost;
|
|
341
|
+
const validHost = /^http/i.test(host) ? host : `https://${host}`;
|
|
342
|
+
return `${validHost}/${path}`;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* @public
|
|
347
|
+
* @memberof Request
|
|
348
|
+
* @param {String} path 请求接口路径
|
|
349
|
+
* @param {Object} [param] 请求参数
|
|
350
|
+
* @param {Object} [header] 自定义请求头
|
|
351
|
+
* @returns {Promise} 接口响应
|
|
352
|
+
* @example
|
|
353
|
+
* const $ = getApp().tms.createRequest();
|
|
354
|
+
* $.get(apiPath)
|
|
355
|
+
* .then((data) => {
|
|
356
|
+
* // data {Object} 响应数据
|
|
357
|
+
* // {
|
|
358
|
+
* // errCode {Number} 接口响应状态码
|
|
359
|
+
* // errMsg {String} 接口响应状态信息
|
|
360
|
+
* // resData {Object} 接口返回数据
|
|
361
|
+
* // }
|
|
362
|
+
* })
|
|
363
|
+
* .catch((e) => {
|
|
364
|
+
* // e {Object} 错误信息
|
|
365
|
+
* });
|
|
366
|
+
*/
|
|
367
|
+
get(path, param, header) {
|
|
368
|
+
return this.doRequest(path, param, 'GET', header);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* @public
|
|
372
|
+
* @memberof Request
|
|
373
|
+
* @param {String} path 请求接口路径
|
|
374
|
+
* @param {Object} [param] 请求参数
|
|
375
|
+
* @param {Object} [header] 自定义请求头
|
|
376
|
+
* @returns {Promise} 接口响应
|
|
377
|
+
* @example
|
|
378
|
+
* const $ = getApp().tms.createRequest();
|
|
379
|
+
* $.post(apiPath)
|
|
380
|
+
* .then((data) => {
|
|
381
|
+
* // data {Object} 响应数据
|
|
382
|
+
* // {
|
|
383
|
+
* // errCode {Number} 接口响应状态码
|
|
384
|
+
* // errMsg {String} 接口响应状态信息
|
|
385
|
+
* // resData {Object} 接口返回数据
|
|
386
|
+
* // }
|
|
387
|
+
* })
|
|
388
|
+
* .catch((e) => {
|
|
389
|
+
* // e {Object} 错误信息
|
|
390
|
+
* });
|
|
391
|
+
*/
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
post(path, param, header) {
|
|
395
|
+
return this.doRequest(path, param, 'POST', header);
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* 发送get方式的请求,该方法会返回wx.request全量的返回值(含data,header,cookies,statusCode)
|
|
399
|
+
* @memberof Request
|
|
400
|
+
* @param {string} path 请求接口路径
|
|
401
|
+
* @param {object} param 业务参数
|
|
402
|
+
* @param {object} header 自定义请求头
|
|
403
|
+
* @returns {promise} 接口请求promise
|
|
404
|
+
*/
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
execGet(path, param, header) {
|
|
408
|
+
return this.createRequestTask(path, param, 'GET', header);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* 发送post方式的请求,该方法会返回wx.request全量的返回值(含data,header,cookies,statusCode等)
|
|
412
|
+
* @memberof Request
|
|
413
|
+
* @param {string} path 请求接口路径
|
|
414
|
+
* @param {object} param 业务参数
|
|
415
|
+
* @param {object} header 自定义请求头
|
|
416
|
+
* @returns {promise} 接口请求promise
|
|
417
|
+
*/
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
execPost(path, param, header) {
|
|
421
|
+
return this.createRequestTask(path, param, 'POST', header);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* @memberof Request
|
|
425
|
+
* @param {String} path 请求接口路径
|
|
426
|
+
* @param {String} filePath 上传文件的本地路径
|
|
427
|
+
* @param {Object} param 需要携带的其他参数
|
|
428
|
+
* @param {Object} header 自定义的请求头
|
|
429
|
+
* @returns {Object} 接口返回结果
|
|
430
|
+
*/
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
async upload(path, filePath, param, header) {
|
|
434
|
+
const requestParam = await composeParam(param, this.withAuth, this.baseParam);
|
|
435
|
+
const res = await new Promise((resolve, reject) => {
|
|
436
|
+
wx.uploadFile({
|
|
437
|
+
name: 'content',
|
|
438
|
+
url: this.makeUrl(path),
|
|
439
|
+
filePath,
|
|
440
|
+
formData: sign(requestParam),
|
|
441
|
+
header,
|
|
442
|
+
success: resolve,
|
|
443
|
+
fail: reject
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
if (typeof (res === null || res === void 0 ? void 0 : res.data) === 'string') {
|
|
448
|
+
return JSON.parse(res === null || res === void 0 ? void 0 : res.data);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
return res === null || res === void 0 ? void 0 : res.data;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* @memberof Request
|
|
455
|
+
* @param {string} path 请求接口路径
|
|
456
|
+
* @param {string} param 业务参数
|
|
457
|
+
* @param {string} method 请求方法 get/post
|
|
458
|
+
* @param {object} header 自定义的请求头
|
|
459
|
+
* @returns {object} 接口返回结果
|
|
460
|
+
*/
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
async doRequest(path, param = {}, method = 'POST', header = {}) {
|
|
464
|
+
const res = await this.createRequestTask(path, param, method, header);
|
|
465
|
+
|
|
466
|
+
if (typeof (res === null || res === void 0 ? void 0 : res.data) === 'string') {
|
|
467
|
+
return JSON.parse(res === null || res === void 0 ? void 0 : res.data);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
return res === null || res === void 0 ? void 0 : res.data;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* 序列化一个 get 请求地址
|
|
474
|
+
* @memberof Request
|
|
475
|
+
* @param {string} path 请求接口路径
|
|
476
|
+
* @param {object} data 业务参数
|
|
477
|
+
* @returns {Promise} 返回序列化之后的 get 请求地址
|
|
478
|
+
*/
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
async serialize(path, data = {}) {
|
|
482
|
+
let url = this.makeUrl(path);
|
|
483
|
+
const signData = await composeParam(data, this.withAuth, this.baseParam);
|
|
484
|
+
const signture = sign(signData);
|
|
485
|
+
const params = [];
|
|
486
|
+
Object.keys(signture).forEach(key => {
|
|
487
|
+
const val = encodeURIComponent(signture[key]);
|
|
488
|
+
params.push(`${key}=${val}`);
|
|
489
|
+
});
|
|
490
|
+
if (params.length) url += (/\?/.test(url) ? '&' : '?') + params.join('&');
|
|
491
|
+
return Promise.resolve({
|
|
492
|
+
url
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* 创建发送请求任务
|
|
497
|
+
* @memberof Request
|
|
498
|
+
* @param {string} path 请求接口路径
|
|
499
|
+
* @param {string} param 业务参数
|
|
500
|
+
* @param {string} method 请求方法 get/post
|
|
501
|
+
* @param {object} header 自定义的请求头
|
|
502
|
+
* @returns {Promise} 接口返回结果
|
|
503
|
+
*/
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
async createRequestTask(path, param = {}, method = 'POST', header = {}) {
|
|
507
|
+
const requestParam = await composeParam(param, this.withAuth, this.baseParam);
|
|
508
|
+
const data = sign(requestParam);
|
|
509
|
+
const logger = getLogManager();
|
|
510
|
+
const res = await new Promise((resolve, reject) => {
|
|
511
|
+
wx.request({
|
|
512
|
+
url: this.makeUrl(path),
|
|
513
|
+
header,
|
|
514
|
+
method,
|
|
515
|
+
data,
|
|
516
|
+
success: res => {
|
|
517
|
+
resolve(res);
|
|
518
|
+
logger.log({
|
|
519
|
+
path,
|
|
520
|
+
header,
|
|
521
|
+
method,
|
|
522
|
+
param: data,
|
|
523
|
+
res: res === null || res === void 0 ? void 0 : res.data
|
|
524
|
+
});
|
|
525
|
+
},
|
|
526
|
+
fail: err => {
|
|
527
|
+
reject(err);
|
|
528
|
+
logger.log({
|
|
529
|
+
path,
|
|
530
|
+
header,
|
|
531
|
+
method,
|
|
532
|
+
param: data,
|
|
533
|
+
err
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
return res;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
export { Request as R, getRealtimeLogManager as a, getLogManager as g };
|
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
import { m as md5 } from './md5-34a9daf3.js';
|
|
2
|
+
import { a as getAuthInfo, g as getEnvInfo } from './env-c7da70e1.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 本文件主要负责在小程序中日志打印功能,包含本地日志及实时日志. 主要做了两件事:
|
|
6
|
+
* 1、参数序列化处理;支持传递任意多个参数,并对类型为对象的参数进行字符串序列化处理(避免打印出来是'[Object Object]'的格式);
|
|
7
|
+
* 2、低版本兼容;
|
|
8
|
+
*/
|
|
9
|
+
// 低版本不支持getLogManager或者getRealtimeLogManager时,用ManagerForLowerVersionLib来兼容
|
|
10
|
+
const ManagerForLowerVersionLib = {
|
|
11
|
+
debug: () => {},
|
|
12
|
+
info: () => {},
|
|
13
|
+
log: () => {},
|
|
14
|
+
warn: () => {},
|
|
15
|
+
error: () => {},
|
|
16
|
+
addFilterMsg: () => {},
|
|
17
|
+
setFilterMsg: () => {}
|
|
18
|
+
}; // 小程序基础库2.7.1版本以上支持,所以需要兼容性处理
|
|
19
|
+
|
|
20
|
+
let logInstance = null;
|
|
21
|
+
let rtLogInstance = null;
|
|
22
|
+
|
|
23
|
+
function getLogInstance() {
|
|
24
|
+
if (logInstance === null) {
|
|
25
|
+
logInstance = wx.getLogManager ? wx.getLogManager() : ManagerForLowerVersionLib;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return logInstance;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getRTLogInstance() {
|
|
32
|
+
if (rtLogInstance === null) {
|
|
33
|
+
rtLogInstance = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : ManagerForLowerVersionLib;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return rtLogInstance;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 参数中有对象类型的,将其转换为字符串类型,以便查看
|
|
40
|
+
* @param {Array<Any>} params 需要格式化的数据
|
|
41
|
+
* @returns {Array<String>} 字符串序列化后的数据
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
const format = params => params.map(param => typeof param === 'string' ? param : JSON.stringify(param));
|
|
46
|
+
/**
|
|
47
|
+
* @namespace LOG
|
|
48
|
+
* @description 普通日志管理器,将日志记录在小程序日志文件中,用户上传后,可以在小程序后台-反馈管理中看到
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
const LOG = {
|
|
53
|
+
/**
|
|
54
|
+
* @description 写debug日志
|
|
55
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
56
|
+
* @returns {Void} 无返回值
|
|
57
|
+
*/
|
|
58
|
+
debug(...params) {
|
|
59
|
+
getLogInstance().debug(...format(params));
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @description 写info日志
|
|
64
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
65
|
+
* @returns {Void} 无返回值
|
|
66
|
+
*/
|
|
67
|
+
info(...params) {
|
|
68
|
+
getLogInstance().info(...format(params));
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @description 写log日志
|
|
73
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
74
|
+
* @returns {Void} 无返回值
|
|
75
|
+
*/
|
|
76
|
+
log(...params) {
|
|
77
|
+
getLogInstance().log(...format(params));
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @description 写warn日志
|
|
82
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
83
|
+
* @returns {Void} 无返回值
|
|
84
|
+
*/
|
|
85
|
+
warn(...params) {
|
|
86
|
+
getLogInstance().warn(...format(params));
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @description 写warn日志. LogManager并没有error方法,为了兼容旧代码,所以声明一个error方法
|
|
91
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
92
|
+
* @returns {Void} 无返回值
|
|
93
|
+
*/
|
|
94
|
+
error(...params) {
|
|
95
|
+
LOG.warn(...params);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* @namespace RTLOG
|
|
101
|
+
* @description 实时日志,将日志实时上传至小程序后台-开发-运维中心-实时日志,方便快速排查漏洞,定位问题
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
const RTLOG = {
|
|
105
|
+
/**
|
|
106
|
+
* @description 写info日志
|
|
107
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
108
|
+
* @returns {Void} 无返回值
|
|
109
|
+
*/
|
|
110
|
+
info(...params) {
|
|
111
|
+
getRTLogInstance().info(...format(params));
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @description 写warn日志
|
|
116
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
117
|
+
* @returns {Void} 无返回值
|
|
118
|
+
*/
|
|
119
|
+
warn(...params) {
|
|
120
|
+
getRTLogInstance().warn(...format(params));
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @description 写error日志
|
|
125
|
+
* @param {...Any} params 需要打印的数据,支持任意多个
|
|
126
|
+
* @returns {Void} 无返回值
|
|
127
|
+
*/
|
|
128
|
+
error(...params) {
|
|
129
|
+
getRTLogInstance().error(...format(params));
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @description 添加过滤关键字
|
|
134
|
+
* @param {String} msg 关键字
|
|
135
|
+
* @returns {Void} 无返回值
|
|
136
|
+
*/
|
|
137
|
+
addFilterMsg(msg) {
|
|
138
|
+
getRTLogInstance().addFilterMsg(msg);
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @description 设置过滤关键字
|
|
143
|
+
* @param {String} msg 关键字
|
|
144
|
+
* @returns {Void} 无返回值
|
|
145
|
+
*/
|
|
146
|
+
setFilterMsg(msg) {
|
|
147
|
+
getRTLogInstance().setFilterMsg(msg);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* @description 获取日志管理器对象,该对象提供的方法同wx.getLogManager()提供的方法,详见微信文档
|
|
153
|
+
* @returns {Object} [LOG](#namespace-log)
|
|
154
|
+
* @example
|
|
155
|
+
* const logger = getLogManager();
|
|
156
|
+
* logger.log(1, 'str', { a: 1 }, ...);
|
|
157
|
+
* logger.info(1, 'str', { a: 1 }, ...);
|
|
158
|
+
* logger.debug(1, 'str', { a: 1 }, ...);
|
|
159
|
+
* logger.awrn(1, 'str', { a: 1 }, ...);
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
const getLogManager = () => LOG;
|
|
163
|
+
/**
|
|
164
|
+
* @description 获取实时日志管理器对象,该对象提供的方法同wx.getRealtimeLogManager()提供的方法,详见微信文档
|
|
165
|
+
* @returns {Object} [RTLOG](#namespace-rtlog)
|
|
166
|
+
* @example
|
|
167
|
+
* const logger = getRealtimeLogManager();
|
|
168
|
+
* logger.info(1, 'str', { a: 1 }, ...);
|
|
169
|
+
* logger.warn(1, 'str', { a: 1 }, ...);
|
|
170
|
+
* logger.error(1, 'str', { a: 1 }, ...);
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
const getRealtimeLogManager = () => RTLOG;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @copyright 2021-present, Tencent, Inc. All rights reserved.
|
|
178
|
+
* @brief request.js用于发起网络请求.
|
|
179
|
+
* request模块作为基于 tms-core & tms-runtime 的应用的公共请求模块。
|
|
180
|
+
* 目前支持在出行服务小程序或基于出行服务的小程序中调用。在后续tms-runtime支持公众号H5后,
|
|
181
|
+
* 将支持在H5中调用。
|
|
182
|
+
*
|
|
183
|
+
* 考虑到对不同运行环境的支持,强依赖运行环境的依赖,比如 wx.request,应通过注入的形式提供。
|
|
184
|
+
* 框架判断在不同的运行环境,切换调用不同运行环境提供的方法。
|
|
185
|
+
*/
|
|
186
|
+
/**
|
|
187
|
+
* 用于序列化需要签名的参数
|
|
188
|
+
* @private
|
|
189
|
+
* @param {object} param 需要序列化的参数
|
|
190
|
+
* @returns {string} 序列化之后的参数字符串
|
|
191
|
+
*/
|
|
192
|
+
|
|
193
|
+
const seriesParam = param => {
|
|
194
|
+
const keys = Object.keys(param).filter(key => typeof param[key] !== 'undefined').sort();
|
|
195
|
+
const series = keys.map(key => {
|
|
196
|
+
const val = param[key];
|
|
197
|
+
|
|
198
|
+
if (typeof val === 'number' && isNaN(val)) {
|
|
199
|
+
return `${key}null`;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return `${key}${typeof val === 'object' ? JSON.stringify(val) : val}`;
|
|
203
|
+
});
|
|
204
|
+
return series.join('');
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* 用于对request请求对象做签名
|
|
208
|
+
* @private
|
|
209
|
+
* @param {object} param 需要做签名的参数
|
|
210
|
+
* @returns {object} 签名后的参数对象
|
|
211
|
+
*/
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
const sign = (param = {}) => {
|
|
215
|
+
const token = '';
|
|
216
|
+
const signture = md5(seriesParam(param) + token);
|
|
217
|
+
return { ...param,
|
|
218
|
+
sign: signture
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
/**
|
|
222
|
+
* 用于对request请求对象添加系统参数
|
|
223
|
+
* @private
|
|
224
|
+
* @param {object} param 接口调用传入的参数
|
|
225
|
+
* @param {Boolean} withAuth 是否需要登录参数
|
|
226
|
+
* @param {object} baseParam request实例定义的基础参数
|
|
227
|
+
* @returns {object} 全部参数对象
|
|
228
|
+
*/
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
const composeParam = async (param = {}, withAuth = true, baseParam = {}) => {
|
|
232
|
+
const version = '1.0';
|
|
233
|
+
const {
|
|
234
|
+
appVersion,
|
|
235
|
+
wxAppId,
|
|
236
|
+
client
|
|
237
|
+
} = getEnvInfo();
|
|
238
|
+
const nonce = Math.random().toString(36).substr(2, 10);
|
|
239
|
+
const timestamp = Date.now();
|
|
240
|
+
const random = Math.random().toString().slice(2, 7);
|
|
241
|
+
const sourceId = ['', 'sinan', 'mycar'].indexOf(client) + 7; // 6 未知 7 云函数 8 出行 9 我的车
|
|
242
|
+
|
|
243
|
+
const seqId = `${timestamp}${sourceId}${random}`;
|
|
244
|
+
const paramsWithAuth = await modifyAuthParam(param, withAuth);
|
|
245
|
+
const combinedParam = Object.assign({
|
|
246
|
+
version,
|
|
247
|
+
appVersion,
|
|
248
|
+
nonce,
|
|
249
|
+
timestamp,
|
|
250
|
+
seqId,
|
|
251
|
+
wxAppId
|
|
252
|
+
}, { ...baseParam
|
|
253
|
+
}, { ...paramsWithAuth
|
|
254
|
+
});
|
|
255
|
+
return combinedParam;
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* 用于保证业务参数的登录态参数,
|
|
259
|
+
* 若接口不依赖登录态 如 user/login,则保证参数中不包括userId & token,
|
|
260
|
+
* 若接口依赖登录态,则保证参数中填充userId & token,
|
|
261
|
+
* @private
|
|
262
|
+
* @param {object} param 要校验登录态的业务参数
|
|
263
|
+
* @param {boolean} withAuth 是否要校验登录态
|
|
264
|
+
* @returns {object} 增加登录态后的参数
|
|
265
|
+
*/
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
const modifyAuthParam = async (param, withAuth) => {
|
|
269
|
+
const requestParam = { ...param
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
if (withAuth) {
|
|
273
|
+
const {
|
|
274
|
+
userId,
|
|
275
|
+
token
|
|
276
|
+
} = await getAuthInfo();
|
|
277
|
+
requestParam.userId = userId;
|
|
278
|
+
requestParam.token = token;
|
|
279
|
+
return requestParam;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
delete requestParam.userId;
|
|
283
|
+
delete requestParam.userid;
|
|
284
|
+
delete requestParam.token;
|
|
285
|
+
return requestParam;
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* @public
|
|
289
|
+
* @class Request
|
|
290
|
+
* @classdesc 网络请求类,对签名、鉴权等逻辑进行封装处理,用于向腾讯出行服务平台后台发送网络请求
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class Request {
|
|
295
|
+
/**
|
|
296
|
+
* 默认的request host域名
|
|
297
|
+
* defaultHost 在tms-runtime初始化时进行设置,为出行服务接入层域名
|
|
298
|
+
* 具体业务模块 new Request() 使用时,不指定自定义 host ,将使用defaultHost
|
|
299
|
+
*/
|
|
300
|
+
static defaultHost = '';
|
|
301
|
+
host = '';
|
|
302
|
+
withAuth = true;
|
|
303
|
+
baseParam = {};
|
|
304
|
+
/**
|
|
305
|
+
* Request 构造函数
|
|
306
|
+
* @param {Object} config 构造参数
|
|
307
|
+
* @param {Object} config.withAuth 是否填充登录态参数
|
|
308
|
+
* @param {Object} config.host 自定义的host域名
|
|
309
|
+
* @param {Object} config.baseParam 默认携带的参数
|
|
310
|
+
*/
|
|
311
|
+
|
|
312
|
+
constructor(config = {
|
|
313
|
+
withAuth: true
|
|
314
|
+
}) {
|
|
315
|
+
if (config.host) {
|
|
316
|
+
this.host = config.host;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (typeof config.withAuth !== 'undefined') {
|
|
320
|
+
this.withAuth = !!config.withAuth;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
this.baseParam = config.baseParam || {};
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* 格式化接口路径
|
|
327
|
+
* @private
|
|
328
|
+
* @param {string} path 需要格式化的接口路径
|
|
329
|
+
* @returns {string} 格式化后的接口路径
|
|
330
|
+
*/
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
makeUrl(path) {
|
|
334
|
+
if (/^http/i.test(path)) return path;
|
|
335
|
+
const host = this.host || Request.defaultHost;
|
|
336
|
+
const validHost = /^http/i.test(host) ? host : `https://${host}`;
|
|
337
|
+
return `${validHost}/${path}`;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* @public
|
|
342
|
+
* @memberof Request
|
|
343
|
+
* @param {String} path 请求接口路径
|
|
344
|
+
* @param {Object} [param] 请求参数
|
|
345
|
+
* @param {Object} [header] 自定义请求头
|
|
346
|
+
* @returns {Promise} 接口响应
|
|
347
|
+
* @example
|
|
348
|
+
* const $ = getApp().tms.createRequest();
|
|
349
|
+
* $.get(apiPath)
|
|
350
|
+
* .then((data) => {
|
|
351
|
+
* // data {Object} 响应数据
|
|
352
|
+
* // {
|
|
353
|
+
* // errCode {Number} 接口响应状态码
|
|
354
|
+
* // errMsg {String} 接口响应状态信息
|
|
355
|
+
* // resData {Object} 接口返回数据
|
|
356
|
+
* // }
|
|
357
|
+
* })
|
|
358
|
+
* .catch((e) => {
|
|
359
|
+
* // e {Object} 错误信息
|
|
360
|
+
* });
|
|
361
|
+
*/
|
|
362
|
+
get(path, param, header) {
|
|
363
|
+
return this.doRequest(path, param, 'GET', header);
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* @public
|
|
367
|
+
* @memberof Request
|
|
368
|
+
* @param {String} path 请求接口路径
|
|
369
|
+
* @param {Object} [param] 请求参数
|
|
370
|
+
* @param {Object} [header] 自定义请求头
|
|
371
|
+
* @returns {Promise} 接口响应
|
|
372
|
+
* @example
|
|
373
|
+
* const $ = getApp().tms.createRequest();
|
|
374
|
+
* $.post(apiPath)
|
|
375
|
+
* .then((data) => {
|
|
376
|
+
* // data {Object} 响应数据
|
|
377
|
+
* // {
|
|
378
|
+
* // errCode {Number} 接口响应状态码
|
|
379
|
+
* // errMsg {String} 接口响应状态信息
|
|
380
|
+
* // resData {Object} 接口返回数据
|
|
381
|
+
* // }
|
|
382
|
+
* })
|
|
383
|
+
* .catch((e) => {
|
|
384
|
+
* // e {Object} 错误信息
|
|
385
|
+
* });
|
|
386
|
+
*/
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
post(path, param, header) {
|
|
390
|
+
return this.doRequest(path, param, 'POST', header);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* 发送get方式的请求,该方法会返回wx.request全量的返回值(含data,header,cookies,statusCode)
|
|
394
|
+
* @memberof Request
|
|
395
|
+
* @param {string} path 请求接口路径
|
|
396
|
+
* @param {object} param 业务参数
|
|
397
|
+
* @param {object} header 自定义请求头
|
|
398
|
+
* @returns {promise} 接口请求promise
|
|
399
|
+
*/
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
execGet(path, param, header) {
|
|
403
|
+
return this.createRequestTask(path, param, 'GET', header);
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* 发送post方式的请求,该方法会返回wx.request全量的返回值(含data,header,cookies,statusCode等)
|
|
407
|
+
* @memberof Request
|
|
408
|
+
* @param {string} path 请求接口路径
|
|
409
|
+
* @param {object} param 业务参数
|
|
410
|
+
* @param {object} header 自定义请求头
|
|
411
|
+
* @returns {promise} 接口请求promise
|
|
412
|
+
*/
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
execPost(path, param, header) {
|
|
416
|
+
return this.createRequestTask(path, param, 'POST', header);
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* @memberof Request
|
|
420
|
+
* @param {String} path 请求接口路径
|
|
421
|
+
* @param {String} filePath 上传文件的本地路径
|
|
422
|
+
* @param {Object} param 需要携带的其他参数
|
|
423
|
+
* @param {Object} header 自定义的请求头
|
|
424
|
+
* @returns {Object} 接口返回结果
|
|
425
|
+
*/
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
async upload(path, filePath, param, header) {
|
|
429
|
+
const requestParam = await composeParam(param, this.withAuth, this.baseParam);
|
|
430
|
+
const res = await new Promise((resolve, reject) => {
|
|
431
|
+
wx.uploadFile({
|
|
432
|
+
name: 'content',
|
|
433
|
+
url: this.makeUrl(path),
|
|
434
|
+
filePath,
|
|
435
|
+
formData: sign(requestParam),
|
|
436
|
+
header,
|
|
437
|
+
success: resolve,
|
|
438
|
+
fail: reject
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
if (typeof (res === null || res === void 0 ? void 0 : res.data) === 'string') {
|
|
443
|
+
return JSON.parse(res === null || res === void 0 ? void 0 : res.data);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return res === null || res === void 0 ? void 0 : res.data;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* @memberof Request
|
|
450
|
+
* @param {string} path 请求接口路径
|
|
451
|
+
* @param {string} param 业务参数
|
|
452
|
+
* @param {string} method 请求方法 get/post
|
|
453
|
+
* @param {object} header 自定义的请求头
|
|
454
|
+
* @returns {object} 接口返回结果
|
|
455
|
+
*/
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
async doRequest(path, param = {}, method = 'POST', header = {}) {
|
|
459
|
+
const res = await this.createRequestTask(path, param, method, header);
|
|
460
|
+
|
|
461
|
+
if (typeof (res === null || res === void 0 ? void 0 : res.data) === 'string') {
|
|
462
|
+
return JSON.parse(res === null || res === void 0 ? void 0 : res.data);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return res === null || res === void 0 ? void 0 : res.data;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* 序列化一个 get 请求地址
|
|
469
|
+
* @memberof Request
|
|
470
|
+
* @param {string} path 请求接口路径
|
|
471
|
+
* @param {object} data 业务参数
|
|
472
|
+
* @returns {Promise} 返回序列化之后的 get 请求地址
|
|
473
|
+
*/
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
async serialize(path, data = {}) {
|
|
477
|
+
let url = this.makeUrl(path);
|
|
478
|
+
const signData = await composeParam(data, this.withAuth, this.baseParam);
|
|
479
|
+
const signture = sign(signData);
|
|
480
|
+
const params = [];
|
|
481
|
+
Object.keys(signture).forEach(key => {
|
|
482
|
+
const val = encodeURIComponent(signture[key]);
|
|
483
|
+
params.push(`${key}=${val}`);
|
|
484
|
+
});
|
|
485
|
+
if (params.length) url += (/\?/.test(url) ? '&' : '?') + params.join('&');
|
|
486
|
+
return Promise.resolve({
|
|
487
|
+
url
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* 创建发送请求任务
|
|
492
|
+
* @memberof Request
|
|
493
|
+
* @param {string} path 请求接口路径
|
|
494
|
+
* @param {string} param 业务参数
|
|
495
|
+
* @param {string} method 请求方法 get/post
|
|
496
|
+
* @param {object} header 自定义的请求头
|
|
497
|
+
* @returns {Promise} 接口返回结果
|
|
498
|
+
*/
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
async createRequestTask(path, param = {}, method = 'POST', header = {}) {
|
|
502
|
+
const requestParam = await composeParam(param, this.withAuth, this.baseParam);
|
|
503
|
+
const data = sign(requestParam);
|
|
504
|
+
const logger = getLogManager();
|
|
505
|
+
const res = await new Promise((resolve, reject) => {
|
|
506
|
+
wx.request({
|
|
507
|
+
url: this.makeUrl(path),
|
|
508
|
+
header,
|
|
509
|
+
method,
|
|
510
|
+
data,
|
|
511
|
+
success: res => {
|
|
512
|
+
resolve(res);
|
|
513
|
+
logger.log({
|
|
514
|
+
path,
|
|
515
|
+
header,
|
|
516
|
+
method,
|
|
517
|
+
param: data,
|
|
518
|
+
res: res === null || res === void 0 ? void 0 : res.data
|
|
519
|
+
});
|
|
520
|
+
},
|
|
521
|
+
fail: err => {
|
|
522
|
+
reject(err);
|
|
523
|
+
logger.log({
|
|
524
|
+
path,
|
|
525
|
+
header,
|
|
526
|
+
method,
|
|
527
|
+
param: data,
|
|
528
|
+
err
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
return res;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
export { Request as R, getRealtimeLogManager as a, getLogManager as g };
|
package/dist/request.js
CHANGED
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -20,6 +20,9 @@ import {
|
|
|
20
20
|
isValidAuthCode,
|
|
21
21
|
roundStr,
|
|
22
22
|
} from './stringUtils';
|
|
23
|
+
import {
|
|
24
|
+
round,
|
|
25
|
+
} from './numUtils';
|
|
23
26
|
import {
|
|
24
27
|
formatTime,
|
|
25
28
|
formatTimeStr,
|
|
@@ -152,6 +155,9 @@ const api = {
|
|
|
152
155
|
isValidAuthCode,
|
|
153
156
|
roundStr,
|
|
154
157
|
|
|
158
|
+
/* 数字方法 */
|
|
159
|
+
round,
|
|
160
|
+
|
|
155
161
|
/* 时间方法 */
|
|
156
162
|
formatTime,
|
|
157
163
|
formatTimeStr,
|
package/src/location/index.ts
CHANGED
|
@@ -16,6 +16,22 @@ interface UserLocationType {
|
|
|
16
16
|
[key: string]: Promise<PostionType | void>
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
interface IpLocationType {
|
|
20
|
+
ip: string,
|
|
21
|
+
ad_info: {
|
|
22
|
+
adcode: number,
|
|
23
|
+
city: string,
|
|
24
|
+
cityCode: string,
|
|
25
|
+
district: string,
|
|
26
|
+
nation: string,
|
|
27
|
+
province: string,
|
|
28
|
+
},
|
|
29
|
+
location: {
|
|
30
|
+
lat: number,
|
|
31
|
+
lng: number,
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
|
|
19
35
|
const request = new Request();
|
|
20
36
|
const event = new EventDispatcher();
|
|
21
37
|
|
|
@@ -27,6 +43,7 @@ let cityTheUserAt = '';
|
|
|
27
43
|
// 用户城市变化事件名
|
|
28
44
|
const CityChangeEventName = 'loc_city_changed';
|
|
29
45
|
const LocationType = 'gcj02'; // 获取经纬度时的坐标名称
|
|
46
|
+
let ipLocationPromise: null | Promise<IpLocationType> = null; // ip定位请求的promise
|
|
30
47
|
|
|
31
48
|
/**
|
|
32
49
|
* @class Location
|
|
@@ -272,6 +289,33 @@ class Location extends LocationBase {
|
|
|
272
289
|
}
|
|
273
290
|
return request.post('basic/lbs/direction', { from, to, mode });
|
|
274
291
|
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* ip定位
|
|
295
|
+
* 原理:通过调手图接口查询当前IP所在位置,市级的准确率是91%
|
|
296
|
+
* 注意:由于服务端对该查询服务有次数限制,所以本函数会缓存成功的promise
|
|
297
|
+
* @param force 是否清除上次的缓存重新请求
|
|
298
|
+
*/
|
|
299
|
+
getIpLocation(force = false): Promise<IpLocationType> {
|
|
300
|
+
if (ipLocationPromise === null || force) {
|
|
301
|
+
ipLocationPromise = new Promise((resolve, reject) => {
|
|
302
|
+
request.post('basic/lbs/decodeip')
|
|
303
|
+
.then((res) => {
|
|
304
|
+
if (res.errCode === 0) {
|
|
305
|
+
resolve(res.resData as IpLocationType);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
reject({ erMsg: res.errMsg });
|
|
309
|
+
ipLocationPromise = null;
|
|
310
|
+
})
|
|
311
|
+
.catch((e) => {
|
|
312
|
+
reject(e);
|
|
313
|
+
ipLocationPromise = null;
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
return ipLocationPromise;
|
|
318
|
+
}
|
|
275
319
|
}
|
|
276
320
|
|
|
277
321
|
// 因为在构造函数中会用到wx的api,所以使用到时才实例化
|
package/src/numUtils.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { roundStr } from './stringUtils';
|
|
2
|
+
/**
|
|
3
|
+
* 四舍五入(支持保留n位小数,n>=0)
|
|
4
|
+
* @param {any} x 原数字
|
|
5
|
+
* 如果n不是合法数字或者无法转换为合法数字,round结果返回NaN
|
|
6
|
+
* @param {any} n 保留几位小数,默认0
|
|
7
|
+
* 如果n不是合法数字或者无法转换为合法数字,round结果返回NaN
|
|
8
|
+
* 如果n小于0,round结果返回NaN
|
|
9
|
+
* 如果n的值包含小数部分,round处理时只关注n的整数部分值
|
|
10
|
+
* @return {number} 返回一个保留n位小数的数字,异常情况下可能是NaN
|
|
11
|
+
*/
|
|
12
|
+
const round = (x, n = 0) => parseFloat(roundStr(x, n, false));
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
round,
|
|
16
|
+
};
|
package/src/objUtils.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @param {Object} queryObj 需要进行序列化的对象
|
|
10
10
|
* @returns {String} 拼接后的字符串
|
|
11
11
|
*/
|
|
12
|
-
const serialize = (queryObj = {}) => {
|
|
12
|
+
export const serialize = (queryObj = {}) => {
|
|
13
13
|
if (!queryObj) {
|
|
14
14
|
return '';
|
|
15
15
|
}
|
|
@@ -23,4 +23,23 @@ const serialize = (queryObj = {}) => {
|
|
|
23
23
|
return queryArray.join('&');
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
export
|
|
26
|
+
export class JsonParseError extends Error {
|
|
27
|
+
constructor(text, data) {
|
|
28
|
+
super(text);
|
|
29
|
+
this.data = data;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 安全的JSON.parse
|
|
35
|
+
*/
|
|
36
|
+
export function safeJsonParse(data, throwErrIfParseFail = false) {
|
|
37
|
+
try {
|
|
38
|
+
return JSON.parse(data);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
if (throwErrIfParseFail) {
|
|
41
|
+
throw new JsonParseError('JSON.parse error', data);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return data;
|
|
45
|
+
}
|
package/src/report.js
CHANGED
|
@@ -106,8 +106,8 @@ const getProvinceInfoByIp = () => {
|
|
|
106
106
|
if (!ProvinceInfoCacheByIp) {
|
|
107
107
|
ProvinceInfoCacheByIp = new Promise(async (resolve) => {
|
|
108
108
|
try {
|
|
109
|
-
const loc = await
|
|
110
|
-
const { city, province } = loc.
|
|
109
|
+
const loc = await getLocInstance().getIpLocation();
|
|
110
|
+
const { city, province } = loc.ad_info;
|
|
111
111
|
resolve({ cityName: city, province });
|
|
112
112
|
} catch (_) {
|
|
113
113
|
resolve({ cityName: '', province: '' });
|
package/src/request.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import md5 from './md5';
|
|
12
12
|
import { getLogManager } from './log';
|
|
13
13
|
import { getEnvInfo, getAuthInfo } from './env';
|
|
14
|
+
import { safeJsonParse } from './objUtils';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* 用于序列化需要签名的参数
|
|
@@ -20,7 +21,6 @@ import { getEnvInfo, getAuthInfo } from './env';
|
|
|
20
21
|
*/
|
|
21
22
|
const seriesParam = (param) => {
|
|
22
23
|
const keys = Object.keys(param)
|
|
23
|
-
.filter(key => typeof param[key] !== 'undefined')
|
|
24
24
|
.sort();
|
|
25
25
|
const series = keys.map((key) => {
|
|
26
26
|
const val = param[key];
|
|
@@ -73,6 +73,16 @@ const composeParam = async (param = {}, withAuth = true, baseParam = {}) => {
|
|
|
73
73
|
{ ...baseParam },
|
|
74
74
|
{ ...paramsWithAuth },
|
|
75
75
|
);
|
|
76
|
+
// 清理undefined和NaN的参数
|
|
77
|
+
Object.keys(combinedParam)
|
|
78
|
+
.forEach((key) => {
|
|
79
|
+
if (typeof combinedParam[key] === 'number' && isNaN(combinedParam[key])) {
|
|
80
|
+
delete combinedParam[key];
|
|
81
|
+
}
|
|
82
|
+
if (typeof combinedParam[key] === 'undefined') {
|
|
83
|
+
delete combinedParam[key];
|
|
84
|
+
}
|
|
85
|
+
});
|
|
76
86
|
return combinedParam;
|
|
77
87
|
};
|
|
78
88
|
|
|
@@ -245,7 +255,7 @@ export default class Request {
|
|
|
245
255
|
});
|
|
246
256
|
|
|
247
257
|
if (typeof res?.data === 'string') {
|
|
248
|
-
return
|
|
258
|
+
return safeJsonParse(res?.data);
|
|
249
259
|
}
|
|
250
260
|
return res?.data;
|
|
251
261
|
}
|
|
@@ -262,7 +272,7 @@ export default class Request {
|
|
|
262
272
|
const res = await this.createRequestTask(path, param, method, header);
|
|
263
273
|
|
|
264
274
|
if (typeof res?.data === 'string') {
|
|
265
|
-
return
|
|
275
|
+
return safeJsonParse(res?.data);
|
|
266
276
|
}
|
|
267
277
|
|
|
268
278
|
return res?.data;
|
package/src/stringUtils.js
CHANGED
|
@@ -113,8 +113,8 @@ const isValidPlate = (plate) => {
|
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
115
|
* 四舍五入,并返回格式化的字符串
|
|
116
|
-
* 支持保留n位小数,n>=0,如
|
|
117
|
-
* 支持格式化字符串时取出末尾的0,如
|
|
116
|
+
* 支持保留n位小数,n>=0,如 roundStr(1.325, 2)=1.33
|
|
117
|
+
* 支持格式化字符串时取出末尾的0,如roundStr(1.109, 2, true)=1.1
|
|
118
118
|
* @param {any} x 原数字
|
|
119
119
|
* 如果n不是合法数字或者无法转换为合法数字,roundStr结果返回''
|
|
120
120
|
* @param {any} n 保留几位小数,默认0
|