@tmsfe/tms-core 0.0.20 → 0.0.24

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 DELETED
@@ -1,1763 +0,0 @@
1
- import { R as Request, g as getLogManager, a as getRealtimeLogManager } from './request-f8a4745b.js';
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
- import { s as syncApi, r as roundStr, f as formatPlate, a as subStr, h as hidePhoneCenter, i as isValidPhone, b as isValidPlate, c as isValidAuthCode, 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 rpxToPx } from './ipxHelper-c5ab3693.js';
4
- import { m as md5, s as serialize } from './objUtils-154b94db.js';
5
- import { callCloudFunc } from './cloudService.js';
6
-
7
- /**
8
- * @copyright 2020-present, Tencent, Inc. All rights reserved.
9
- * @author Fenggang.Sun <fenggangsun@tencent.com>
10
- * @file 快速上报数据,不处理过多逻辑,保证快速上报
11
- */
12
- let simulatedUserIdCache; // 模拟用户id在内存里的缓存
13
-
14
- const getSystemInfo$1 = () => {
15
- const system = syncApi.getSystemInfoSync();
16
- const {
17
- model = '',
18
- version: wxVersion = '',
19
- platform = '',
20
- SDKVersion = '',
21
- host = ''
22
- } = system;
23
- return {
24
- model,
25
- wxVersion,
26
- platform,
27
- SDKVersion,
28
- host
29
- };
30
- };
31
-
32
- const handleParamOfDifferentType = param => {
33
- const data = new Array(41);
34
- Object.keys(param).forEach(key => {
35
- const valType = typeof param[key];
36
- if (valType === 'string') data[key] = param[key];else if (valType === 'object') data[key] = JSON.stringify(param[key]);else data[key] = String(param[key]);
37
- });
38
- return data;
39
- };
40
-
41
- const defAssign = (value, defaultValue) => value || defaultValue;
42
- /**
43
- * @class FastReport
44
- * @classdesc 快速上报模块,不依赖用户标识和位置
45
- */
46
-
47
-
48
- class FastReport {
49
- /**
50
- * @memberof FastReport
51
- * @description 快速上报
52
- * @param {Object} param 埋点数据
53
- * @param {Boolean} simulatedUserId 是否上报模拟用户Id
54
- * @param {Number} simulatedUserIdIndex 上报模拟用户ID时放在哪个字段
55
- * @param {Boolean} reportShowScene 是否上报小程序onShow场景值
56
- * @param {Boolean} appVer 是否上报小程序版本
57
- * @returns {Promsie} 返回上报结果
58
- */
59
- static report(param = {}, simulatedUserId = true, simulatedUserIdIndex = 40, reportShowScene = true, appVer = true) {
60
- var _data$;
61
-
62
- if (!param[27]) return Promise.reject('invalid report param');
63
- const env = getEnvInfo();
64
- const data = handleParamOfDifferentType(param);
65
- data[9] = '2';
66
- data[33] = encodeURIComponent(JSON.stringify(getSystemInfo$1()));
67
-
68
- if (appVer) {
69
- data[10] = defAssign(data[10], env.appVersion);
70
- }
71
-
72
- data[26] = defAssign(data[26], (_data$ = data[27]) === null || _data$ === void 0 ? void 0 : _data$[0]);
73
- data[28] = env.client;
74
-
75
- if (reportShowScene && !data[29]) {
76
- const appShowScene = wx.getStorageSync('appShowScene');
77
- if (appShowScene) data[29] = String(appShowScene);
78
- }
79
-
80
- if (simulatedUserId && !data[simulatedUserIdIndex]) {
81
- data[simulatedUserIdIndex] = FastReport.getSimulatedUserId();
82
- }
83
-
84
- return new Request().post('basic/event/upload', {
85
- batch: [data]
86
- }).catch(() => null);
87
- }
88
- /**
89
- * @memberof FastReport
90
- * @description 获取模拟的用户身份标识
91
- * @returns {String} 用户的临时标识
92
- */
93
-
94
-
95
- static getSimulatedUserId() {
96
- // 优先使用内存级缓存
97
- if (simulatedUserIdCache) return simulatedUserIdCache;
98
- const key = 'SimulatedUserKey'; // 读取本地缓存记录的值
99
-
100
- simulatedUserIdCache = wx.getStorageSync(key);
101
- if (simulatedUserIdCache) return simulatedUserIdCache; // 生成新的值
102
-
103
- const nonce = Math.random().toString(36).substr(2, 10);
104
- simulatedUserIdCache = `${Date.now()}_${nonce}`;
105
- wx.setStorage({
106
- key,
107
- data: simulatedUserIdCache
108
- });
109
- return simulatedUserIdCache;
110
- }
111
-
112
- }
113
-
114
- /**
115
- * 小程序云控配置实现
116
- */
117
-
118
- const parseAllCfgs = (configPaths, resData, defaultCfgs) => configPaths.map((path, index) => {
119
- const found = resData.find(cfg => cfg.configPath === path);
120
-
121
- if (found) {
122
- return JSON.parse(found.configValue);
123
- }
124
-
125
- if (defaultCfgs && defaultCfgs[index]) {
126
- return defaultCfgs[index];
127
- }
128
-
129
- return {}; // 没找到配置,返回一个空对象
130
- });
131
-
132
- const formatConfigPaths = configPath => {
133
- const configPaths = Array.isArray(configPath) ? configPath : [configPath];
134
- const {
135
- client
136
- } = getEnvInfo();
137
- configPaths.forEach((path, index) => {
138
- configPaths[index] = path.replace(/\$\{client\}/, client);
139
- });
140
- return configPaths;
141
- };
142
- /**
143
- * getConfig 批量拉取配置
144
- * @description 拉取运营平台上的配置内容。关于运营平台的具体用法,参见{@link https://iwiki.woa.com/pages/viewpage.action?pageId=527948584}
145
- * @category 配置相关
146
- * @example <caption>拉取单个配置</caption>
147
- * const cfg = await app.tms.getConfig('/${client}/violation/subscribe', {}, { title: '当前城市不支持订阅'})
148
- * console.log(cfg); // 成功则返回服务端存储的配置,失败返回默认值
149
- * @example <caption>批量拉取配置</caption>
150
- const cfgs = await app.tms.getConfig([
151
- '/${client}/home/service',
152
- '/${client}/home/navbar',
153
- ], {}, [
154
- [
155
- { caption: '违章代缴', icon: 'violation.png' }
156
- ],
157
- { title: '晚上好,欢迎~' }
158
- ]);
159
- console.log(cfgs); // 成功则返回服务端存储的配置,失败返回默认值
160
- * @param {String|Array} configPath 配置路径,单个路径或配置路径数组,支持替换${client}为当前小程序。例如在出行小程序,${client}会变替换为sinan
161
- * @param {Object} extendAttr 扩展属性,传给配置服务用于检索哪个版本的配置适用于当前用户。
162
- * @param {Object} [defaultCfg] 默认配置,请求失败返回默认值。
163
- * @returns {Promise<Object|Array<Object>>}
164
- * 有默认值时,请求失败返回默认值。无默认值时,请求失败返回Promise.reject
165
- */
166
-
167
-
168
- function getConfig(configPath, extendAttr = {}, defaultCfg) {
169
- if (Array.isArray(configPath)) {
170
- // 复数形式
171
- if (defaultCfg) {
172
- // 有默认值
173
- if (!Array.isArray(defaultCfg) || configPath.length !== defaultCfg.length) {
174
- throw new Error('配置路径和默认值的数组长度不一致');
175
- }
176
- }
177
- }
178
-
179
- const configPaths = formatConfigPaths(configPath);
180
- const defaultCfgs = defaultCfg && (Array.isArray(defaultCfg) ? defaultCfg : [defaultCfg]) || null;
181
- const extendAttrs = typeof extendAttr === 'string' ? extendAttr : JSON.stringify(extendAttr);
182
- const api = new Request();
183
- return api.post('marketing/config', {
184
- extendAttrs,
185
- configPaths
186
- }).then((res = {}) => {
187
- const {
188
- errCode,
189
- resData
190
- } = res || {};
191
-
192
- if (resData && resData.length > 0) {
193
- const parsed = parseAllCfgs(configPaths, resData, defaultCfgs);
194
-
195
- if (Array.isArray(configPath)) {
196
- return parsed;
197
- }
198
-
199
- return parsed[0];
200
- }
201
-
202
- if (defaultCfgs) {
203
- return Array.isArray(configPath) ? defaultCfgs : defaultCfgs[0];
204
- }
205
-
206
- return Promise.reject({
207
- errCode,
208
- resData,
209
- msg: `获取${configPaths.join(',')}配置失败,接口调用出错`
210
- });
211
- }).catch(e => {
212
- if (defaultCfgs) {
213
- return Promise.resolve(Array.isArray(configPath) ? defaultCfgs : defaultCfgs[0]);
214
- }
215
-
216
- return Promise.reject({
217
- err: e,
218
- msg: `获取${configPaths.join(',')}配置失败,接口调用出错`
219
- });
220
- });
221
- }
222
-
223
- /**
224
- * @copyright 2021-present, Tencent, Inc. All rights reserved.
225
- * @author Davislu <davislu@tencent.com>
226
- * @brief navigator provides some function to navigate pages in miniprogram.
227
- *
228
- */
229
-
230
- /**
231
- * DEFN 空方法
232
- * @private
233
- * @returns {undefined} 无返回值
234
- */
235
- const DEFN = () => {};
236
- /**
237
- * navigateToWebview 方法 跳转到小程序的 web-view 容器打开 H5
238
- * @param {object} setting 配置信息
239
- * @param {string} setting.url 需要跳转的 H5 连接
240
- * @param {function} setting.complete 跳转成功后的回调函数
241
- * @param {function} setting.message 用于获取 H5 中的 postMessage 的数据
242
- * @param {object} setting.share 页面分享信息
243
- * @param {string} setting.share.title 页面分享标题
244
- * @param {string} setting.share.image 页面分享图片
245
- * @param {string} setting.share.disable 是否禁用页面分享
246
- * @param {object} setting.navbar 页面导航栏设置
247
- * @param {string} setting.navbar.frontColor 导航栏字体颜色
248
- * @param {string} setting.navbar.backgroundColor 导航栏背景颜色
249
- * @returns {undefined} 无返回值
250
- */
251
-
252
-
253
- const navigateToWebview = ({
254
- url: webUrl,
255
- complete = DEFN,
256
- message = DEFN,
257
- share = {},
258
- navbar = {}
259
- }) => {
260
- const page = '/modules/x/webcontainer/webcontainer';
261
- let query = `url=${encodeURIComponent(webUrl)}`;
262
-
263
- if (share.disable) {
264
- query += '&disableShare=true';
265
- } else if (share.title) {
266
- const image = share.image ? `&image=${encodeURIComponent(share.image)}` : '';
267
- query += `&title=${encodeURIComponent(share.title)}${image}`;
268
- }
269
-
270
- if (navbar.frontColor) query += `&navbarFront=${navbar.frontColor}`;
271
- if (navbar.backgroundColor) query += `&navbarBg=${navbar.backgroundColor}`;
272
- const url = `${page}${/\?/.test(page) ? '&' : '?'}${query}`;
273
- const navSetting = {
274
- url,
275
- complete
276
- };
277
- navSetting.events = {
278
- onMessage: message
279
- };
280
- wx.navigateTo(navSetting);
281
- };
282
-
283
- const obj = {
284
- navigateToWebview
285
- };
286
- var nav = obj;
287
-
288
- /* eslint-disable require-jsdoc */
289
-
290
- /**
291
- * Copyright 2017-present, Tencent, Inc.
292
- * All rights reserved.
293
- *
294
- * @desc: 自定义事件机制
295
- * @author: kexinwu@tencent.com
296
- *
297
- */
298
-
299
- /**
300
- * EventDispatcher 类 事件监听器
301
- * @class EventDispatcher
302
- * @classdesc 用于统一维护小程序的事件
303
- */
304
- class EventDispatcher {
305
- constructor() {
306
- this.handlers = [];
307
- }
308
- /**
309
- * @memberof EventDispatcher
310
- * @param {String} type 事件名
311
- * @param {Function} handler 事件处理函数
312
- * @returns {Function} handler 事件处理函数
313
- */
314
-
315
-
316
- bind(type, handler) {
317
- if (typeof this.handlers[type] === 'undefined') {
318
- this.handlers[type] = [];
319
- }
320
-
321
- this.handlers[type].push(handler);
322
- }
323
- /**
324
- * @memberof EventDispatcher
325
- * @param {String} type 事件名
326
- * @param {Function} handler 事件处理函数
327
- * @returns {Function} handler 事件处理函数
328
- */
329
-
330
-
331
- bindOnce(type, handler) {
332
- if (typeof this.handlers[type] === 'undefined') {
333
- this.handlers[type] = [];
334
- }
335
-
336
- const isBinded = this.handlers[type].length === 0;
337
-
338
- if (isBinded) {
339
- this.handlers[type].push(handler);
340
- }
341
- }
342
- /**
343
- * @memberof EventDispatcher
344
- * @param {String} type 事件名
345
- * @returns {Void} 无返回值
346
- */
347
-
348
-
349
- remove(type) {
350
- this.handlers[type] = [];
351
- }
352
- /**
353
- * @memberof EventDispatcher
354
- * @param {String} type 事件名
355
- * @param {Function} handler 事件处理函数
356
- * @returns {Void} 无返回值
357
- */
358
-
359
-
360
- unbind(type, handler) {
361
- if (this.handlers[type] instanceof Array) {
362
- const handlers = this.handlers[type];
363
- let i = 0;
364
- const l = handlers.length;
365
-
366
- for (; i < l; i += 1) {
367
- if (handlers[i] === handler) {
368
- break;
369
- }
370
- }
371
-
372
- handlers.splice(i, 1);
373
- }
374
- }
375
- /**
376
- * @memberof EventDispatcher
377
- * @param {Object} evt 事件描述
378
- * @param {String} evt.type 事件类型
379
- * @returns {Function} handler 事件处理函数
380
- */
381
-
382
-
383
- dispatch(evt) {
384
- if (this.handlers[evt.type] instanceof Array) {
385
- const handlers = this.handlers[evt.type];
386
- handlers.forEach(handler => handler(evt));
387
- }
388
- }
389
-
390
- }
391
-
392
- const event$2 = new EventDispatcher();
393
- // 获取位置状态 -- true: 成功 false: 失败
394
- let getLocationStatus = true; // eslint-disable-line
395
- const LocationScopeKey = 'scope.userLocation';
396
- // 获取授权设置promise
397
- let getSettingPromise;
398
- const EventName$1 = 'loc_status_changed';
399
- /**
400
- * @param {string} scopeKey 授权项
401
- * @returns {promise} 授权页操作状态
402
- */
403
- function openSetting(scopeKey = LocationScopeKey) {
404
- return new Promise((resolve, reject) => {
405
- // 打开设置页
406
- wx.openSetting({
407
- success: (res) => {
408
- // 从authSetting中获取用户的授权结果
409
- const { authSetting } = res;
410
- const authResult = authSetting[scopeKey];
411
- // 已经打开授权
412
- if (authResult) {
413
- resolve(res);
414
- return;
415
- }
416
- // 未打开授权
417
- reject(res);
418
- },
419
- fail: reject,
420
- });
421
- });
422
- }
423
- /**
424
- * @description 更新获取位置状态
425
- * @param {Boolean} status 成功true或失败false
426
- * @returns {Promise<void>} 用户是否授权
427
- */
428
- async function updateLocStatus(status) {
429
- if (status && !getLocationStatus) {
430
- let isAuthed = false;
431
- try {
432
- isAuthed = await getSetting();
433
- getLocationStatus = true;
434
- }
435
- catch (e) {
436
- if (isAuthed !== false) {
437
- event$2.dispatch({ type: EventName$1 });
438
- }
439
- const timer = setTimeout(() => {
440
- updateLocStatus(status);
441
- clearTimeout(timer);
442
- }, 200);
443
- }
444
- }
445
- else {
446
- getLocationStatus = status;
447
- }
448
- }
449
- /**
450
- * 获取用户授权信息
451
- * @param { string } scopeKey 是否授权过位置信息
452
- * @returns { Promise } 用户授权对象
453
- */
454
- function getSetting(scopeKey = LocationScopeKey) {
455
- if (getSettingPromise) { // eslint-disable-line
456
- return getSettingPromise;
457
- }
458
- getSettingPromise = new Promise((resolve, reject) => {
459
- wx.getSetting({
460
- success: ({ authSetting = {} }) => {
461
- resolve(authSetting[scopeKey]);
462
- getSettingPromise = null;
463
- },
464
- fail: (err) => {
465
- getSettingPromise = null;
466
- const { errMsg = '' } = err || {};
467
- // wx.getSetting接口没有响应时errMsg
468
- const reason = 'getSetting:fail data no response';
469
- // 部分机型上,wx.getSetting接口没有响应,此时,当做位置开关是打开的来处理
470
- if (errMsg.indexOf(reason) > -1) {
471
- resolve(true);
472
- return;
473
- }
474
- reject(err);
475
- },
476
- });
477
- });
478
- return getSettingPromise;
479
- }
480
- /**
481
- * getTextByReason 获取提示语文案
482
- * @param {*} locationEnabled 是否开启位置授权
483
- * @param {*} isSysAndWechatAllowedGetLoc 是否开启微信位置授权
484
- * @returns {object} 提示语文案
485
- */
486
- function getTextByReason(locationEnabled, isSysAndWechatAllowedGetLoc) {
487
- const authLevelName = locationEnabled ? '微信' : '系统';
488
- const confirmText = isSysAndWechatAllowedGetLoc ? '去开启' : '好的';
489
- return { authLevelName, confirmText };
490
- }
491
- /**
492
- * @function
493
- * @description 获取设备系统信息
494
- * @returns {Object} 设备系统信息
495
- */
496
- function getSystemInfo() {
497
- try {
498
- const sys = wx.getSystemInfoSync();
499
- // 方便开发时调试
500
- if (sys.platform === 'devtools') {
501
- sys.locationEnabled = true;
502
- sys.locationAuthorized = true;
503
- }
504
- return sys;
505
- }
506
- catch (err) { }
507
- }
508
- /**
509
- * @function
510
- * @description 格式化城市编码
511
- * @param {String} cityCode 城市编码,以国家编码开始
512
- * @param {String} nationCode 国家编码
513
- * @returns {String} 去掉国家编码后的城市编码
514
- */
515
- function formatCityCode(cityCode, nationCode) {
516
- let code = cityCode;
517
- if (cityCode.startsWith(nationCode)) {
518
- code = cityCode.substr(nationCode.length);
519
- }
520
- return code;
521
- }
522
- /**
523
- * 格式化poi数据
524
- * @param {Object} geo 逆地址解析接口返回的数据
525
- * @returns {object} 格式化后的poi结果
526
- */
527
- function formatPoi(geo) {
528
- const { pois = [], address_reference: addressRefer } = geo;
529
- if (pois.length) {
530
- return pois[0];
531
- }
532
- if (addressRefer?.landmark_l2) {
533
- return addressRefer.landmark_l2;
534
- }
535
- return {};
536
- }
537
-
538
- const event$1 = new EventDispatcher();
539
- let getLocPromise = null;
540
- // 用户位置信息缓存
541
- let userLocationCache$1;
542
- // 默认获取经纬度坐标的名称
543
- const defaultLocationType = 'gcj02';
544
- // 派发事件的名称
545
- const EventName = 'loc_status_changed';
546
- /**
547
- * @private 将wx.getLocation获取位置方法用promise封装
548
- * @param { string } type 获取位置类型
549
- * @returns { Promise<any> } 用户位置信息
550
- */
551
- function getWxLocation(type = defaultLocationType) {
552
- return new Promise((resolve, reject) => {
553
- wx.getLocation({
554
- type,
555
- success: (res) => {
556
- resolve(res);
557
- },
558
- fail: reject,
559
- });
560
- });
561
- }
562
- // 是否开启监听位置变更
563
- let isListenerLocation = false;
564
- /**
565
- * @class Location
566
- * @classdesc 基于微信api,封装location相关的接口。 包括监听位置变化, 获取用户位置信息
567
- * 获取位置授权等等。业务无关
568
- */
569
- class LocationBase {
570
- /**
571
- * @private 开启监听位置变更,要在授权之后才能开启
572
- */
573
- listenerLocation() {
574
- if (!isListenerLocation) {
575
- isListenerLocation = true;
576
- wx.onLocationChange(this.subscribeLocationChnage);
577
- wx.startLocationUpdate({});
578
- }
579
- }
580
- /**
581
- * 获取用户当前位置(经纬度)
582
- * @memberof Location
583
- * @param {boolean} showModalWhenCloseAuth 获取位置时,如果用户关闭了位置授权,是否弹窗提示用户打开授权
584
- * @param {string} type 坐标类型
585
- * @param {string} content 弹窗内容
586
- * @param {boolean} showCancel 是否显示取消按钮
587
- * @returns {Promise<LOC|ERR>} 返回对象
588
- * @returns {Promise<LOC|ERR>} 返回对象
589
- */
590
- getLocation(showModalWhenCloseAuth, type, content = '', showCancel = true) {
591
- // 如果缓存中没有, 并且getLocPromise有值, 说明正在请求中。 返回请求的promise
592
- if (!userLocationCache$1 && getLocPromise) { // eslint-disable-line
593
- return getLocPromise;
594
- }
595
- // 如果缓存中没有, 并且getLocPromise没有值,新建一个请求
596
- if (!userLocationCache$1 && !getLocPromise) { // eslint-disable-line
597
- getLocPromise = this.getWxLocationPromise(showModalWhenCloseAuth, type, content, showCancel);
598
- return getLocPromise;
599
- }
600
- // 缓存中有数据, 证明用户已经获取过, 那么直接返回缓存中的位置
601
- return Promise.resolve(userLocationCache$1);
602
- }
603
- /**
604
- * @description 获取位置(经纬度)底层封装
605
- * @memberof Location
606
- * @param {boolean} showModalWhenCloseAuth 获取位置时,如果用户关闭了位置授权,是否弹窗提示用户打开授权
607
- * @param {string} type 坐标类型
608
- * @param {string} content 弹窗内容
609
- * @param {boolean} showCancel 是否显示取消按钮
610
- * @returns {Promise<LOC|ERR>} 返回对象
611
- * @example
612
- * <caption>LOC类型示例</caption>
613
- * {
614
- * cityName: '北京市',
615
- * cityCode: '100100',
616
- * latitude: 325.255333,
617
- * longitude: 116.2545454,
618
- * adCode: 1212144,
619
- * poi: {
620
- * id: '1114545554511',
621
- * title: '腾讯北京总部大厦',
622
- * address : '北京市海淀区东北旺西路',
623
- * }
624
- */
625
- getWxLocationPromise(showModalWhenCloseAuth, type, content = '', showCancel = true) {
626
- return new Promise((resolve, reject) => {
627
- getWxLocation(type).then((res) => {
628
- this.listenerLocation();
629
- userLocationCache$1 = res;
630
- // 更新用户状态 -- todo
631
- updateLocStatus(true);
632
- resolve(res);
633
- })
634
- .catch((err) => {
635
- getLocPromise = null;
636
- updateLocStatus(false);
637
- this.openLocationAuth(showModalWhenCloseAuth, type, content, showCancel, err).then((res) => {
638
- resolve(res);
639
- }, (err) => {
640
- reject(err);
641
- });
642
- });
643
- });
644
- }
645
- /**
646
- * 如果没有权限,自动开启授权弹窗
647
- * @memberof Location
648
- * @param {boolean} showModalWhenCloseAuth 获取位置时,如果用户关闭了位置授权,是否弹窗提示用户打开授权
649
- * @param {string} type 坐标类型
650
- * @param {string} content 弹窗内容
651
- * @param {boolean} showCancel 是否显示取消按钮
652
- * @param {object} err 错误信息
653
- * @returns {Promise} 返回对象
654
- */
655
- openLocationAuth(showModalWhenCloseAuth, type, content, showCancel, err) {
656
- return new Promise((resolve, reject) => {
657
- const { locationEnabled, locationAuthorized } = getSystemInfo();
658
- // 系统位置定位开关打开 && 允许微信使用位置定位能力开关打开
659
- if (locationEnabled && locationAuthorized) {
660
- if (err.errMsg.search(/auth [deny|denied]|authorize/) < 0) {
661
- reject();
662
- return;
663
- }
664
- }
665
- if (!showModalWhenCloseAuth) {
666
- const rejectData = { ...err, unAuthed: true };
667
- reject(rejectData);
668
- return;
669
- }
670
- // 控制地理位置开关的名称(系统控制的开关,还是微信层面的开关)
671
- const isSysAndWechatAllowedGetLoc = (locationEnabled && locationAuthorized);
672
- const { authLevelName, confirmText } = getTextByReason(locationEnabled, isSysAndWechatAllowedGetLoc);
673
- wx.showModal({
674
- confirmText,
675
- title: `未开启${authLevelName}位置信息权限`,
676
- content: content || `开启${authLevelName}位置信息权限\n体验更顺畅的出行服务`,
677
- showCancel: (showCancel && isSysAndWechatAllowedGetLoc),
678
- confirmColor: '#4875fd',
679
- success: (res) => {
680
- // 用户拒绝去授权
681
- if (!res.confirm || !locationEnabled || !locationAuthorized) {
682
- const rejectData = { ...err, unAuthed: true };
683
- return reject(rejectData);
684
- }
685
- // 用户同意去打开授权(只是打开小程序设置页,用户不一定打开了位置授权,所以需要重新进行获取位置)
686
- openSetting()
687
- .then(() => {
688
- resolve(this.getLocation(showModalWhenCloseAuth, type, content, showCancel));
689
- })
690
- .catch((err) => {
691
- const rejectData = { ...err, unAuthed: true };
692
- reject(rejectData);
693
- });
694
- },
695
- });
696
- });
697
- }
698
- /**
699
- * 订阅用户位置信息变化
700
- * @param { object } res 用户位置信息对象
701
- * @returns { undefined } no retrurn
702
- */
703
- subscribeLocationChnage(res) {
704
- userLocationCache$1 = res;
705
- }
706
- /**
707
- * @description
708
- * 以静默方式获取用户位置(经纬度),说明如下:<br>
709
- * 1、从未授权情况下 | 用户删除小程序之后调用该方法不会弹微信自带的授权弹窗;<br>
710
- * 2、拒绝授权后,调用该方法不会弹窗提示用户去授权(wx.showModal);<br>
711
- * @memberof Location
712
- * @param {String} type 非必填。坐标类型,默认'gcj02'
713
- * @returns {Promise<LOC|ERR>} 返回位置信息
714
- * @example
715
- * <caption>LOC类型示例</caption>
716
- * {
717
- * latitude: 33.253321,
718
- * longitude: 115.2444,
719
- * }
720
- * @example
721
- * <caption>ERR类型示例</caption>
722
- * {
723
- * err,
724
- * unAuthed: true,
725
- * locationScopeStatus: false
726
- * }
727
- */
728
- async getLocationSilent(type) {
729
- let err = null;
730
- let locationScopeStatus;
731
- try {
732
- locationScopeStatus = await getSetting();
733
- // 用户已授权. locationScopeStatus = true
734
- if (locationScopeStatus) {
735
- return this.getLocation(false, type);
736
- }
737
- }
738
- catch (ex) {
739
- err = ex;
740
- }
741
- updateLocStatus(false);
742
- // 用户关闭了授权. locationScopeStatus = false
743
- // 用户未授权过(删除小程序之后再次打开小程序). locationScopeStatus = undefined
744
- return Promise.reject({ err, unAuthed: true, locationScopeStatus });
745
- }
746
- /**
747
- * @memberof Location
748
- * @description 监听获取位置状态变化(目前只有失败->成功时会触发事件)
749
- * @param {Function} cb 监听事件回调函数
750
- * @returns {void}
751
- */
752
- onLocStatusChange(cb) {
753
- if (cb && typeof cb === 'function') {
754
- event$1.bind(EventName, cb);
755
- }
756
- }
757
- }
758
- var LocationBase$1 = LocationBase;
759
-
760
- const request = new Request();
761
- const event = new EventDispatcher();
762
- const userLocationCache = {}; // 获取位置缓存
763
- // 用户手动选择的位置信息(切换城市后的位置信息)
764
- let userLocation;
765
- // 用户所在的城市
766
- let cityTheUserAt = '';
767
- // 用户城市变化事件名
768
- const CityChangeEventName = 'loc_city_changed';
769
- const LocationType = 'gcj02'; // 获取经纬度时的坐标名称
770
- let ipLocationPromise = null; // ip定位请求的promise
771
- /**
772
- * @class Location
773
- * @classdesc 基于LocationBase,封装业务侧位置的接口。 将用户经纬度转化为城市等展示信息
774
- */
775
- class Location extends LocationBase$1 {
776
- // 默认位置信息
777
- locForNoAuth = {
778
- province: '广东省',
779
- cityCode: '440300',
780
- cityName: '深圳市',
781
- latitude: 22.54286,
782
- longitude: 114.05956,
783
- };
784
- /**
785
- * 构造函数
786
- */
787
- constructor() {
788
- super();
789
- }
790
- /**
791
- * 获取解析后的用户位置, 比如城市信息
792
- * @param { number } lat 用户纬度信息
793
- * @param { number } lng 用户经度信息
794
- * @param { number } getPoi 位置
795
- * @returns { Promise<PostionType | void> } 获取位置信息的promise
796
- */
797
- getPoiInfo(lat, lng, getPoi) {
798
- // 优先查询缓存中是否有位置信息,如果有直接返回
799
- const cacheName = `${lat}-${lng}-${getPoi}`;
800
- // @ts-ignore
801
- if (userLocationCache[cacheName]) { // eslint-disable-line
802
- return userLocationCache[cacheName];
803
- }
804
- userLocationCache[cacheName] = request.post('basic/lbs/decode', { lat, lng, getPoi }).then((res) => {
805
- const { errCode, resData = {} } = res;
806
- if (errCode === 0) {
807
- const { result = {} } = resData;
808
- const { ad_info: adInfo = {} } = result;
809
- const loc = {
810
- province: adInfo.province,
811
- cityName: adInfo.city,
812
- adCode: adInfo.adcode,
813
- cityCode: formatCityCode(adInfo.city_code, adInfo.nation_code),
814
- latitude: lat,
815
- longitude: lng,
816
- };
817
- if (getPoi === 0) {
818
- return loc;
819
- }
820
- loc.adCode = adInfo.adcode;
821
- loc.poi = formatPoi(result);
822
- return loc;
823
- }
824
- return Promise.reject(res);
825
- })
826
- .catch(err => Promise.reject(err));
827
- return userLocationCache[cacheName];
828
- }
829
- /**
830
- * @function
831
- * @memberof Location
832
- * @description 获取位置、城市信息
833
- * @param {Boolean} showModalWhenCloseAuth 获取位置时,如果用户关闭了位置授权,是否弹窗提示用户打开授权
834
- * @param {String} type 坐标类型
835
- * @param {String} content 弹窗内容
836
- * @param {Number} getPoi 是否获取详细poi信息, 0 - 不获取(不返回poi字段), 1 - 获取(返回poi字段)
837
- * @returns {Promise<POI|ERR>} 返回对象
838
- * @example
839
- * <caption>POI类型示例</caption>
840
- * {
841
- * cityName: '北京市',
842
- * cityCode: '100100',
843
- * province: '北京市',
844
- * latitude: 325.255333,
845
- * longitude: 116.2545454,
846
- * adCode: 1212144,
847
- * poi: {
848
- * id: '1114545554511',
849
- * title: '腾讯北京总部大厦',
850
- * address : '北京市海淀区东北旺西路',
851
- * }
852
- * }
853
- * @example
854
- * <caption>ERR类型示例</caption>
855
- * {
856
- * err,
857
- * unAuthed: true,
858
- * locationScopeStatus: false
859
- * }
860
- */
861
- getLocationDetail(showModalWhenCloseAuth = false, type = LocationType, content = '', getPoi = 0) {
862
- return this.getLocation(showModalWhenCloseAuth, type, content)
863
- .then((res) => this.getPoiInfo(res.latitude, res.longitude, getPoi))
864
- .catch(err => Promise.reject(err));
865
- }
866
- /**
867
- * @description 以静默方式获取用户详细位置(经纬度,poi信息, 省市信息),说明如下:<br>
868
- * 1、从未授权情况下 | 用户删除小程序之后调用该方法不会弹微信自带的授权弹窗;<br>
869
- * 2、拒绝授权后,调用该方法不会弹窗提示用户去授权(wx.showModal);<br>
870
- * @memberof Location
871
- * @param {Number} getPoi 是否获取详细poi信息, 0 - 不获取(不返回poi字段), 1 - 获取(返回poi字段)
872
- * @param {String} type 非必填。坐标类型,默认'gcj02'
873
- * @returns {Promise<LOC|ERR>} 返回对象
874
- * @example
875
- * <caption>LOC类型示例</caption>
876
- * {
877
- * cityName: '北京市',
878
- * cityCode: '100100',
879
- * latitude: 325.255333,
880
- * longitude: 116.2545454,
881
- * adCode: 1212144,
882
- * poi: {
883
- * id: '1114545554511',
884
- * title: '腾讯北京总部大厦',
885
- * address : '北京市海淀区东北旺西路',
886
- * }
887
- * }
888
- * @example
889
- * <caption>ERR类型示例</caption>
890
- * {
891
- * err,
892
- * unAuthed: true,
893
- * locationScopeStatus: false
894
- * }
895
- */
896
- getLocationDetailSilent(getPoi = 0, type = 'gcj02') {
897
- return this.getLocationSilent(type)
898
- .then((res) => this.getPoiInfo(res.latitude, res.longitude, getPoi))
899
- .catch(err => Promise.reject(err));
900
- }
901
- /**
902
- * @description 获取用户手动选择的位置信息
903
- * @memberof Location
904
- * @returns {Null|LOC} 返回用户位置信息
905
- * @example
906
- * <caption>LOC类型示例</caption>
907
- * {
908
- * province: '北京市',
909
- * cityName: '北京市',
910
- * cityCode: '100100',
911
- * latitude: 325.255333,
912
- * longitude: 116.2545454,
913
- * adCode: 1212144,
914
- * }
915
- */
916
- getUserLocation() {
917
- return userLocation;
918
- }
919
- /**
920
- * @description 设置用户位置(小程序生命周期内有效)
921
- * @memberof Location
922
- * @param {Object} loc 用户手动选择的位置
923
- * @params {String} loc.province 省份
924
- * @params {String} loc.cityName 城市
925
- * @params {String} loc.cityCode citycode
926
- * @params {Number} loc.latitude 纬度
927
- * @params {Number} loc.longitude 经度
928
- * @params {Number} loc.adCode adCode
929
- * @returns {Void} 无返回值
930
- * @example
931
- * <caption>loc类型示例</caption>
932
- * {
933
- * province: '北京市',
934
- * cityName: '北京市',
935
- * cityCode: '100100',
936
- * latitude: 325.255333,
937
- * longitude: 116.2545454,
938
- * adCode: 1212144,
939
- * }
940
- */
941
- setUserLocation(loc) {
942
- if (!loc || typeof loc !== 'object') {
943
- return;
944
- }
945
- // 如果城市发生变化,派发事件
946
- const { cityName: curCityName } = loc;
947
- if (curCityName && (cityTheUserAt !== curCityName)) {
948
- cityTheUserAt = curCityName;
949
- userLocation = loc;
950
- event.dispatch({ type: CityChangeEventName });
951
- }
952
- }
953
- /**
954
- * @description 获取用户选择的城市位置信息 或者 用户真实的位置信息(这个方法说明有问题)
955
- * @memberof Location
956
- * @param {Boolean} showModalWhenCloseAuth 没有授权时是否展示授权弹窗
957
- * @returns {Promise} 用户位置信息
958
- */
959
- async getMergedLocation(showModalWhenCloseAuth = true) {
960
- const userLocatioin = this.getUserLocation();
961
- // 优先用户选择的城市
962
- if (userLocatioin) {
963
- return userLocatioin;
964
- }
965
- return await this.getLocationDetail(showModalWhenCloseAuth, LocationType);
966
- }
967
- /**
968
- * @memberof Location
969
- * @description 监听用户城市变化(如: 北京市->深圳市)
970
- * @param {Function} cb 监听事件回调函数
971
- * @returns {void}
972
- */
973
- onCityChange(cb) {
974
- if (cb && typeof cb === 'function') {
975
- event.bind(CityChangeEventName, cb);
976
- }
977
- }
978
- /**
979
- * @memberof Location
980
- * @description 获取路线规划
981
- * @param {String} to 目的地坐标,格式:lat,lng
982
- * @param {String} depart 出发地坐标,格式:lat,lng
983
- * @param {String} mode 出行方式, driving 驾车[默认]
984
- * @returns {Object} result.routes 返回数据 [{}, ...]
985
- */
986
- async getRoute(to, depart, mode = 'driving') {
987
- let from = depart;
988
- const coorReg = new RegExp(/(\d+\.\d{6,}),(\d+\.\d{6,})/);
989
- if (!coorReg.test(to))
990
- throw Error('目的地参数格式错误');
991
- if (!coorReg.test(from)) { // 出发地缺省使用当前位置
992
- const { latitude, longitude } = await this.getMergedLocation();
993
- from = `${latitude},${longitude}`;
994
- }
995
- return request.post('basic/lbs/direction', { from, to, mode });
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
- }
1023
- }
1024
- // 因为在构造函数中会用到wx的api,所以使用到时才实例化
1025
- let instance;
1026
- function getLocInstance() {
1027
- if (!instance) {
1028
- instance = new Location();
1029
- }
1030
- return instance;
1031
- }
1032
-
1033
- const R = new Request();
1034
- const ReportInterval = 3000; // 轮训上报间隔
1035
-
1036
- const ReportDataQueue = []; // 上报数据队列
1037
-
1038
- let ReportTaskId = -1; // 轮训上报id
1039
-
1040
- let appShowOptions = null; // 设置小程序onShow参数
1041
-
1042
- function getAppShowOptions() {
1043
- if (appShowOptions === null) {
1044
- try {
1045
- appShowOptions = wx.getLaunchOptionsSync();
1046
- } catch (_) {
1047
- appShowOptions = {};
1048
- }
1049
- }
1050
-
1051
- return appShowOptions;
1052
- }
1053
-
1054
- function getTMS() {
1055
- return getApp({
1056
- allowDefault: true
1057
- }).tms;
1058
- } // 缓存系统信息,避免每次都重新获取系统信息
1059
-
1060
-
1061
- let systemPromise = null;
1062
- /**
1063
- * 获取系统信息
1064
- * @private
1065
- * @returns {object} 系统信息
1066
- */
1067
-
1068
- const getSystemPromise = () => {
1069
- if (systemPromise === null) {
1070
- systemPromise = new Promise(resolve => {
1071
- wx.getSystemInfo({
1072
- success: systemInfo => {
1073
- const {
1074
- model,
1075
- version: wxVersion,
1076
- platform,
1077
- SDKVersion,
1078
- host
1079
- } = systemInfo;
1080
- resolve({
1081
- model,
1082
- wxVersion,
1083
- platform,
1084
- SDKVersion,
1085
- host
1086
- });
1087
- },
1088
- fail: () => {
1089
- resolve({});
1090
- }
1091
- });
1092
- });
1093
- }
1094
-
1095
- return systemPromise;
1096
- };
1097
-
1098
- let networkPromise = null;
1099
- /**
1100
- * 获取网络信息
1101
- * @private
1102
- * @returns {string} 网络信息
1103
- */
1104
-
1105
- const getNetworkType = () => {
1106
- if (networkPromise === null) {
1107
- networkPromise = new Promise(resolve => {
1108
- wx.getNetworkType({
1109
- success: netInfo => {
1110
- resolve(netInfo.networkType);
1111
- },
1112
- fail: () => {
1113
- resolve('unknown');
1114
- }
1115
- });
1116
- });
1117
- }
1118
-
1119
- return networkPromise;
1120
- };
1121
-
1122
- let ProvinceInfoCache = null;
1123
- /**
1124
- * 获取省市信息
1125
- * @private
1126
- */
1127
-
1128
- const getProvinceInfo = () => {
1129
- if (!ProvinceInfoCache) {
1130
- ProvinceInfoCache = new Promise(async resolve => {
1131
- try {
1132
- const loc = await getLocInstance().getLocationDetailSilent();
1133
- resolve({
1134
- cityName: loc.cityName,
1135
- province: loc.province
1136
- });
1137
- } catch (_) {
1138
- // 获取位置失败时,尝试获取本地存储的位置信息
1139
- const loc = getLocInstance().getUserLocation();
1140
-
1141
- if (loc !== null && loc !== void 0 && loc.cityName) {
1142
- resolve(loc);
1143
- } else {
1144
- resolve({
1145
- cityName: '',
1146
- province: ''
1147
- });
1148
- }
1149
- }
1150
- });
1151
- }
1152
-
1153
- return ProvinceInfoCache;
1154
- };
1155
-
1156
- let ProvinceInfoCacheByIp = null;
1157
- /**
1158
- * 调接口获取省市信息
1159
- * @private
1160
- */
1161
-
1162
- const getProvinceInfoByIp = () => {
1163
- if (!ProvinceInfoCacheByIp) {
1164
- ProvinceInfoCacheByIp = new Promise(async resolve => {
1165
- try {
1166
- const loc = await getLocInstance().getIpLocation();
1167
- const {
1168
- city,
1169
- province
1170
- } = loc.ad_info;
1171
- resolve({
1172
- cityName: city,
1173
- province
1174
- });
1175
- } catch (_) {
1176
- resolve({
1177
- cityName: '',
1178
- province: ''
1179
- });
1180
- }
1181
- });
1182
- }
1183
-
1184
- return ProvinceInfoCacheByIp;
1185
- }; // 用于缓存用户唯一标识userId
1186
-
1187
-
1188
- let userId = '';
1189
- /**
1190
- * 获取用户唯一标识userId
1191
- * @private
1192
- * @returns {string} userId
1193
- */
1194
-
1195
- const getUserId = async () => {
1196
- if (userId) {
1197
- return userId;
1198
- }
1199
-
1200
- ({
1201
- userId
1202
- } = await getAuthInfo());
1203
- return userId;
1204
- };
1205
-
1206
- let launchFrom = '';
1207
- /**
1208
- * 获取用户启动小程序时的渠道来源值
1209
- * @private
1210
- * @returns {string} 用户启动小程序时的渠道来源值
1211
- */
1212
-
1213
- const getLaunchFrom = () => {
1214
- if (launchFrom) {
1215
- return launchFrom;
1216
- }
1217
-
1218
- try {
1219
- const LaunchOptions = wx.getLaunchOptionsSync() || {};
1220
- const {
1221
- query = {}
1222
- } = LaunchOptions;
1223
- launchFrom = query.from || '';
1224
- return launchFrom;
1225
- } catch (_) {
1226
- return '';
1227
- }
1228
- };
1229
- /**
1230
- * 将上报的对象类型的数据转换成数组类型
1231
- * @private
1232
- * @param {object} reportData 需要上报的数据
1233
- * @returns {array} 数组格式的上报数据
1234
- */
1235
-
1236
-
1237
- const getReportDataList = (reportData = {}) => {
1238
- const reportList = [];
1239
- reportList.length = 40;
1240
- Object.keys(reportData).forEach(key => {
1241
- const reportIndex = Number(key);
1242
- reportList[reportIndex] = reportData[key];
1243
- });
1244
- return reportList;
1245
- }; // 小程序版本号
1246
-
1247
-
1248
- let verNum = null;
1249
-
1250
- function getMiniProgramVersion() {
1251
- if (verNum === null) {
1252
- const {
1253
- miniProgram: {
1254
- version
1255
- } = {}
1256
- } = wx.getAccountInfoSync() || {};
1257
- verNum = version;
1258
- }
1259
-
1260
- return verNum;
1261
- }
1262
- /**
1263
- * 格式化上报数据
1264
- * @private
1265
- * @param {object} reportData 需要上报的数据
1266
- * @param {object} deviceData 设备数据(系统信息,网络状况,位置信息)
1267
- * @returns {array} 格式化后的上报数据
1268
- */
1269
-
1270
-
1271
- const formatReportData = async (reportData, deviceData) => {
1272
- const [system, netType, provinceInfo] = deviceData;
1273
- const param = Array.isArray(reportData.param) ? reportData.param : getReportDataList(reportData);
1274
- const {
1275
- client
1276
- } = await getTMS().getEnvInfo();
1277
- param[5] = await getUserId();
1278
- param[10] = getMiniProgramVersion(); // 上报小程序版本号
1279
-
1280
- param[16] = getLaunchFrom(); // 渠道公共参数
1281
-
1282
- param[17] = param[17] || (provinceInfo === null || provinceInfo === void 0 ? void 0 : provinceInfo.province);
1283
- param[18] = param[18] || (provinceInfo === null || provinceInfo === void 0 ? void 0 : provinceInfo.cityName);
1284
- param[19] = system === null || system === void 0 ? void 0 : system.host; // 上报宿主app信息 { appId, env, version }
1285
-
1286
- param[28] = client; // 默认上报数据
1287
-
1288
- const defaultReportData = {
1289
- 9: '2',
1290
- 12: netType,
1291
- 13: '2',
1292
- 29: getAppShowOptions().scene,
1293
- // 打开小程序的场景值
1294
- 33: JSON.stringify(system),
1295
- // 数据字符串化
1296
- 36: getAppShowOptions() // 打开小程序的场景值及参数
1297
-
1298
- }; // 对部分空数据使用默认数据填充
1299
-
1300
- const handleDefaultData = (paramItem, defaultData) => {
1301
- const arr = [paramItem, paramItem === 0, paramItem === false];
1302
- return arr.some(item => !!item) ? paramItem : defaultData || '';
1303
- };
1304
-
1305
- Object.keys(defaultReportData).forEach(index => {
1306
- const paramItem = param[index];
1307
- param[index] = handleDefaultData(paramItem, defaultReportData[index]);
1308
- }); // 所有上报数据都转换为字符串
1309
-
1310
- param.forEach((reportItem, index) => {
1311
- if (reportItem && typeof reportItem !== 'string') {
1312
- param[index] = `${JSON.stringify(reportItem)}`;
1313
- } else {
1314
- param[index] = handleDefaultData(reportItem, '');
1315
- }
1316
- });
1317
- return param.map(item => item !== null ? encodeURIComponent(item) : item);
1318
- };
1319
- /**
1320
- * 格式化上报到小程序后台的数据(自定义分析使用)
1321
- * @private
1322
- * @param {array} data 埋点数据
1323
- * @returns {object} 格式化的数据
1324
- */
1325
-
1326
-
1327
- const formatAnalyticsData = async data => {
1328
- const analyticsData = {};
1329
- const {
1330
- 10: version,
1331
- 29: scene
1332
- } = data;
1333
- analyticsData[10] = version; // 小程序版本号
1334
-
1335
- analyticsData[29] = scene; // 小程序场景值
1336
-
1337
- analyticsData[17] = decodeURIComponent(data[17]); // 用户所在省份
1338
-
1339
- analyticsData[18] = decodeURIComponent(data[18]); // 用户所在城市
1340
- // 将30-40位埋点字段补充到上报数据中
1341
-
1342
- for (let i = 30; i < 41; i += 1) {
1343
- analyticsData[i] = decodeURIComponent(data[i] || ''); // 如果第33列是设备信息,则忽略
1344
-
1345
- if (data[33] && data[33].indexOf('model') > -1) {
1346
- analyticsData[33] = '';
1347
- }
1348
- }
1349
-
1350
- const {
1351
- client
1352
- } = await getTMS().getEnvInfo();
1353
- return {
1354
- analyticsData,
1355
- eventName: `${client}_${data[27]}`
1356
- };
1357
- };
1358
- /**
1359
- * 上报数据到小程序后台
1360
- * @private
1361
- * @param {array} list 需要上报的数据列表
1362
- * @returns {void}
1363
- */
1364
-
1365
-
1366
- const reportAnalytics = (list = []) => {
1367
- try {
1368
- list.forEach(item => {
1369
- const {
1370
- eventName,
1371
- analyticsData
1372
- } = formatAnalyticsData(item);
1373
- wx.reportAnalytics(eventName, analyticsData);
1374
- });
1375
- } catch (_) {}
1376
- };
1377
- /**
1378
- * @description report 方法 将上报数据缓存到内存中
1379
- * @name report
1380
- * @param {object} reportData 需要上报的数据
1381
- * @param {boolean} reportNow 是否立即上报
1382
- * @param {boolean} locPoi 是否通过微信接口获取poi
1383
- * @returns {Void} 无返回值
1384
- */
1385
-
1386
-
1387
- const cache = (reportData, reportNow, locPoi = true) => {
1388
- // 如果是微信爬虫 | 自动化测试场景,则不进行数据上报
1389
- const DO_NOT_NEED_REPORT_SCENES = [1030, 1129];
1390
-
1391
- if (DO_NOT_NEED_REPORT_SCENES.includes(getAppShowOptions().scene)) {
1392
- return Promise.resolve();
1393
- }
1394
-
1395
- const task = [getSystemPromise(), getNetworkType()];
1396
-
1397
- if (locPoi) {
1398
- task.push(getProvinceInfo());
1399
- } else {
1400
- task.push(getProvinceInfoByIp());
1401
- }
1402
-
1403
- return Promise.all(task).then(async deviceData => {
1404
- // 先对上报数据进行预处理
1405
- const result = await formatReportData(reportData, deviceData); // 将需要上报的数据缓存在队列中
1406
-
1407
- ReportDataQueue.push(result);
1408
- }).then(() => {
1409
- if (reportNow) {
1410
- return sendData();
1411
- }
1412
-
1413
- return {
1414
- cache: true
1415
- };
1416
- });
1417
- };
1418
- /**
1419
- * 发送数据到服务端
1420
- * @private
1421
- * @returns {promise} 发送请求
1422
- */
1423
-
1424
-
1425
- const sendData = async () => {
1426
- // 没有数据时,不发送上报请求
1427
- if (ReportDataQueue.length === 0) {
1428
- return Promise.resolve();
1429
- }
1430
-
1431
- const cacheReportData = [...ReportDataQueue];
1432
- return R.post('basic/event/upload', {
1433
- userId: await getUserId(),
1434
- batch: cacheReportData
1435
- }).then((res = {}) => {
1436
- const {
1437
- errCode
1438
- } = res || {}; // 已经发送成功,则将本次发送的数据从数据队列中删除
1439
-
1440
- if (errCode === 0) {
1441
- ReportDataQueue.splice(0, cacheReportData.length);
1442
- reportAnalytics(cacheReportData); // 将数据上报至小程序后台
1443
- }
1444
- });
1445
- };
1446
- /**
1447
- * 开启轮询上报定时器
1448
- * @private
1449
- * @param {boolean} clearTimerAfterSend 是发送完数据后否清除定时器标识
1450
- * @returns {void}
1451
- */
1452
-
1453
-
1454
- const startSendTimer = clearTimerAfterSend => {
1455
- ReportTaskId = setInterval(async () => {
1456
- sendData();
1457
-
1458
- if (clearTimerAfterSend) {
1459
- clearInterval(ReportTaskId);
1460
- }
1461
- }, ReportInterval);
1462
- };
1463
- /**
1464
- * 停止定时器
1465
- * @private
1466
- * @returns {void}
1467
- */
1468
-
1469
-
1470
- const stopSendTimer = () => {
1471
- clearInterval(ReportTaskId);
1472
- };
1473
- /**
1474
- * 发送上报数据到服务端
1475
- * @private
1476
- * @param {boolean} reportNow 是否立即上报
1477
- * @param {boolean} clearTimerAfterSend 是否发送之后清除定时器
1478
- * @returns {void}
1479
- */
1480
-
1481
-
1482
- const report = (reportNow = false, clearTimerAfterSend = false) => {
1483
- if (reportNow) {
1484
- if (ReportDataQueue.length > 0) {
1485
- sendData();
1486
- }
1487
-
1488
- if (!clearTimerAfterSend) {
1489
- startSendTimer(clearTimerAfterSend);
1490
- } else {
1491
- stopSendTimer();
1492
- }
1493
- } else {
1494
- startSendTimer(clearTimerAfterSend);
1495
- }
1496
- };
1497
- /**
1498
- * 更新小程序onShow参数
1499
- * @private
1500
- * @param {object} options 小程序onShow参数
1501
- * @returns {void}
1502
- */
1503
-
1504
-
1505
- const setAppShowOptions = options => {
1506
- appShowOptions = options;
1507
- };
1508
- /**
1509
- * init之后再监听
1510
- */
1511
-
1512
-
1513
- const startListenApp = () => {
1514
- /**
1515
- * 监听小程序onShow事件
1516
- * @private
1517
- */
1518
- wx.onAppShow(options => {
1519
- // 更新onShow参数
1520
- setAppShowOptions(options); // 上报数据
1521
-
1522
- report(true);
1523
- });
1524
- /**
1525
- * 监听小程序onHide事件
1526
- * @private
1527
- */
1528
-
1529
- wx.onAppHide(() => {
1530
- // onHide时立即上报,并清除定时器
1531
- report(true, true);
1532
- });
1533
- };
1534
-
1535
- /**
1536
- * 四舍五入(支持保留n位小数,n>=0)
1537
- * @param {any} x 原数字
1538
- * 如果n不是合法数字或者无法转换为合法数字,round结果返回NaN
1539
- * @param {any} n 保留几位小数,默认0
1540
- * 如果n不是合法数字或者无法转换为合法数字,round结果返回NaN
1541
- * 如果n小于0,round结果返回NaN
1542
- * 如果n的值包含小数部分,round处理时只关注n的整数部分值
1543
- * @return {number} 返回一个保留n位小数的数字,异常情况下可能是NaN
1544
- */
1545
-
1546
- const round = (x, n = 0) => parseFloat(roundStr(x, n, false));
1547
-
1548
- /**
1549
- * 支持服务接入相关接口
1550
- */
1551
- /**
1552
- * getMpOpenId 获取接入方用户唯一标识 [变更为 getOuterOpenId]
1553
- * @private
1554
- * @description 唯一标识 openId 用于与服务商建立账号关联关系
1555
- * @category 服务接入
1556
- * @param {String} mpId 接入服务商渠道标识
1557
- * @param {String} userId 出行用户标识
1558
- * @returns {Promise<String>} 返回 openId,失败时返回空
1559
- */
1560
-
1561
- async function getMpOpenId(mpId, userId) {
1562
- const {
1563
- resData
1564
- } = await new Request().post('user/mpinfo', {
1565
- userId,
1566
- mpId
1567
- });
1568
- const {
1569
- openId = ''
1570
- } = resData || {};
1571
- return openId;
1572
- }
1573
- /**
1574
- * getOuterOpenId 获取接入方用户唯一标识
1575
- * @public
1576
- * @description 唯一标识 openId 用于服务接入方作为唯一标识、向腾讯出行服务同步订单等
1577
- * @category 服务接入
1578
- * @param {String} apiKey 服务接入方渠道标识
1579
- * @returns {Promise<String>} 返回 openId,失败时返回空
1580
- */
1581
-
1582
-
1583
- async function getOuterOpenId(apiKey) {
1584
- const {
1585
- resData
1586
- } = await new Request().post('user/mpinfo', {
1587
- mpId: apiKey
1588
- });
1589
- const {
1590
- openId = ''
1591
- } = resData || {};
1592
- return openId;
1593
- }
1594
-
1595
- /**
1596
- * @public
1597
- * @description 创建网络请求对象,用于向腾讯出行服务平台后台发送网络请求
1598
- * @param {Object} [config] 参数配置
1599
- * @param {Boolean} [config.withAuth=true] 是否填充登录态参数
1600
- * @param {String} [config.host] 自定义的host域名
1601
- * @param {Object} [config.baseParam] 默认携带的参数
1602
- * @returns {Object} [Request实例](#class-request)
1603
- * @example
1604
- * const $ = getApp().tms.createRequest();
1605
- * $.get(apiPath)
1606
- * .then((resp) => {
1607
- * // ...
1608
- * })
1609
- * .catch((err) => {
1610
- * // ...
1611
- * });
1612
- */
1613
-
1614
- const createRequest = (config = {}) => new Request(config);
1615
- /**
1616
- * @description 埋点上报
1617
- * @returns {Object} 包含[report方法](#report)的对象
1618
- * @example
1619
- * getReporter().report(reportData, reportNow);
1620
- */
1621
-
1622
-
1623
- const getReporter = () => ({
1624
- report: cache
1625
- });
1626
- /**
1627
- * @description 埋点上报(快速上报,不依赖用户userId标识)
1628
- * @returns {Class} [FastReporter类](#class-fastreport)
1629
- */
1630
-
1631
-
1632
- const getFastReporter = () => FastReport;
1633
- /**
1634
- * @description 自定义事件机制
1635
- * @returns {Object} [EventDispatcher实例](#class-eventdispatcher)
1636
- */
1637
-
1638
-
1639
- const getEventDispatcher = () => new EventDispatcher();
1640
- /**
1641
- * @description 获取地理位置方法的集合
1642
- * @returns {Class} [Location类](#class-location)
1643
- */
1644
-
1645
-
1646
- const getLocationManager = () => getLocInstance();
1647
- /**
1648
- * @description 获取位置信息base类(业务无关)
1649
- * @returns {Class} [Location类](#class-location)
1650
- */
1651
-
1652
-
1653
- const getLocationBaseClass = () => LocationBase$1;
1654
- /**
1655
- * @description init core包初始化, 小程序已在app.js中对齐初始化
1656
- * @param {Object} options 初始化
1657
- * @returns {undefined} 无返回值.
1658
- */
1659
-
1660
-
1661
- const init = (options = {}) => {
1662
- startListenApp();
1663
- const {
1664
- appVersion,
1665
- wxAppId,
1666
- client,
1667
- defaultHost,
1668
- cloudEnvId,
1669
- appEnv,
1670
- appPagePaths,
1671
- homePage
1672
- } = options;
1673
- setEnvInfo({
1674
- wxAppId,
1675
- appVersion,
1676
- appEnv,
1677
- client,
1678
- cloudEnvId
1679
- });
1680
- setAppPagePaths(appPagePaths, homePage);
1681
- Request.defaultHost = defaultHost; // 初始化云环境
1682
-
1683
- wx.cloud.init({
1684
- env: cloudEnvId
1685
- });
1686
- };
1687
- /**
1688
- * @description 获取用户位置信息 -- 兼容版 现有业务中有的使用promise, 有的没有, 做一下兼容
1689
- * @returns { Promise } 位置信息
1690
- */
1691
-
1692
-
1693
- const getUserLocation = () => {
1694
- const userLocation = getLocInstance().getUserLocation();
1695
-
1696
- if (userLocation) {
1697
- return Promise.resolve(userLocation);
1698
- }
1699
-
1700
- return getLocInstance().getLocationDetail(false);
1701
- };
1702
-
1703
- const api = {
1704
- init,
1705
- createRequest,
1706
- setAuthInfo,
1707
- getLogManager,
1708
- getRealtimeLogManager,
1709
- md5,
1710
- getReporter,
1711
- getFastReporter,
1712
- getLocationManager,
1713
- getLocationBaseClass,
1714
- getEventDispatcher,
1715
- getEnvInfo,
1716
- getConfig,
1717
- navigateToWebview: nav.navigateToWebview,
1718
- isAppPageExist,
1719
- getHomePage,
1720
- callCloudFunc,
1721
- setUserLocation: loc => {
1722
- getLocInstance().setUserLocation(loc);
1723
- },
1724
- getUserLocation,
1725
-
1726
- /* 字符串方法 */
1727
- formatPlate,
1728
- subStr,
1729
- hidePhoneCenter,
1730
- isValidPhone,
1731
- isValidPlate,
1732
- isValidAuthCode,
1733
- roundStr,
1734
-
1735
- /* 数字方法 */
1736
- round,
1737
-
1738
- /* 时间方法 */
1739
- formatTime,
1740
- formatTimeStr,
1741
- formatTimeWithDetails,
1742
- dateToString,
1743
-
1744
- /* IPX方法 */
1745
- ipxInit,
1746
- isIPX,
1747
- getIpxClass,
1748
- getIpxConfig,
1749
-
1750
- /* 处理对象方法 */
1751
- serialize,
1752
-
1753
- /* 获取外部合作商openid */
1754
- getMpOpenId,
1755
- // 变更为 getOuterOpenId
1756
- getOuterOpenId,
1757
-
1758
- /** rpx转px */
1759
- rpxToPx,
1760
- ...syncApi
1761
- };
1762
-
1763
- export { api as default };