gis-common 4.2.1 → 4.2.2
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/constant/GraphicConstant.d.ts +6 -0
- package/dist/core/AudioPlayer.d.ts +16 -0
- package/dist/core/Cookie.d.ts +5 -0
- package/dist/core/MqttClient.d.ts +3 -3
- package/dist/core/Storage.d.ts +28 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/gis-common.es.js +1912 -1076
- package/dist/gis-common.umd.js +1 -1
- package/dist/utils/AjaxUtil.d.ts +7 -7
- package/dist/utils/ArrayUtil.d.ts +2 -2
- package/dist/utils/CommUtil.d.ts +22 -0
- package/dist/utils/MathUtil.d.ts +6 -29
- package/dist/utils/OptimizeUtil.d.ts +7 -0
- package/dist/utils/StringUtil.d.ts +0 -8
- package/dist/utils/index.d.ts +0 -2
- package/package.json +2 -1
- package/dist/utils/Cookie.d.ts +0 -6
- package/dist/utils/StoreUtil.d.ts +0 -10
package/dist/gis-common.es.js
CHANGED
|
@@ -1,16 +1,123 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { connect
|
|
5
|
-
var
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import { connect } from "mqtt-browser";
|
|
5
|
+
var EventType = /* @__PURE__ */ ((EventType2) => {
|
|
6
|
+
EventType2["MAP_RENDER"] = "mapRender";
|
|
7
|
+
EventType2["MAP_READY"] = "mapReady";
|
|
8
|
+
EventType2["MOUSE_CLICK"] = "click";
|
|
9
|
+
EventType2["MOUSE_DOUBLE_CLICK"] = "dblclick";
|
|
10
|
+
EventType2["MOUSE_MOVE"] = "mousemove";
|
|
11
|
+
EventType2["MOUSE_IN"] = "mousein";
|
|
12
|
+
EventType2["MOUSE_OUT"] = "mouseout";
|
|
13
|
+
EventType2["MOUSE_RIGHT_CLICK"] = "mouseRightClick";
|
|
14
|
+
EventType2["KEY_DOWN"] = "keyDown";
|
|
15
|
+
EventType2["KEY_UP"] = "keyUp";
|
|
16
|
+
EventType2["DRAW_ACTIVE"] = "drawActive";
|
|
17
|
+
EventType2["DRAW_MOVE"] = "drawMove";
|
|
18
|
+
EventType2["DRAW_COMPLETE"] = "drawComplete";
|
|
19
|
+
EventType2["MQTT_CONNECT"] = "mqttConnect";
|
|
20
|
+
EventType2["MQTT_ERROR"] = "mqttError";
|
|
21
|
+
EventType2["MQTT_MESSAGE"] = "mqttMessage";
|
|
22
|
+
EventType2["MQTT_CLOSE"] = "mqttClose";
|
|
23
|
+
EventType2["WEB_SOCKET_CONNECT"] = "webSocketConnect";
|
|
24
|
+
EventType2["WEB_SOCKET_ERROR"] = "webSocketError";
|
|
25
|
+
EventType2["WEB_SOCKET_MESSAGE"] = "webSocketMessage";
|
|
26
|
+
EventType2["WEB_SOCKET_CLOSE"] = "webSocketClose";
|
|
27
|
+
return EventType2;
|
|
28
|
+
})(EventType || {});
|
|
29
|
+
var ErrorType = /* @__PURE__ */ ((ErrorType2) => {
|
|
30
|
+
ErrorType2["LOGIN_EXPIRED"] = "登录信息过期,请重新登录";
|
|
31
|
+
ErrorType2["CROSS_ERROR"] = "跨域访问";
|
|
32
|
+
ErrorType2["UNEXIST_RESOURCE"] = "资源不存在";
|
|
33
|
+
ErrorType2["TIMEOUT"] = "请求超时";
|
|
34
|
+
ErrorType2["INTERNAL_ERROR"] = "内部错误";
|
|
35
|
+
ErrorType2["NETWORK_ERROR"] = "请求失败,请检查网络是否已连接";
|
|
36
|
+
ErrorType2["PROCESS_FAIL"] = "处理失败";
|
|
37
|
+
ErrorType2["AUTH_VERIFY_ERROR"] = "权限验证失败";
|
|
38
|
+
ErrorType2["NO_DATA_FOUND"] = "未找到数据";
|
|
39
|
+
ErrorType2["DUPLICATE_INSTANCE"] = "实例为单例模式,不允许重复构建";
|
|
40
|
+
ErrorType2["COORDINATE_ERROR"] = "坐标验证失败";
|
|
41
|
+
ErrorType2["JSON_PARSE_ERROR"] = "JSON解析失败,格式有误";
|
|
42
|
+
ErrorType2["JSON_VALUE_ERROR"] = "JSON无此键";
|
|
43
|
+
ErrorType2["PARAMETER_ERROR"] = "验证数据类型失败";
|
|
44
|
+
ErrorType2["PARAMETER_ERROR_ARRAY"] = "格式类型验证失败:必须是数组";
|
|
45
|
+
ErrorType2["PARAMETER_ERROR_STRING"] = "格式类型验证失败:必须是字符";
|
|
46
|
+
ErrorType2["PARAMETER_ERROR_FUNCTION"] = "格式类型验证失败:必须是函数";
|
|
47
|
+
ErrorType2["PARAMETER_ERROR_OBJECT"] = "格式类型验证失败:必须是对象";
|
|
48
|
+
ErrorType2["PARAMETER_ERROR_LACK"] = "参数缺失";
|
|
49
|
+
ErrorType2["STRING_CHECK_LOSS"] = "字符缺少关键字";
|
|
50
|
+
return ErrorType2;
|
|
51
|
+
})(ErrorType || {});
|
|
52
|
+
var LayerType = /* @__PURE__ */ ((LayerType2) => {
|
|
53
|
+
LayerType2["SUPER_MAP_IMAGES"] = "SuperMapImages";
|
|
54
|
+
LayerType2["SUPER_MAP_DATA"] = "SuperMapData";
|
|
55
|
+
LayerType2["ARC_GIS_MAP_IMAGES"] = "ArcGisMapImages";
|
|
56
|
+
LayerType2["ARC_GIS_MAP_DATA"] = "ArcGisMapData";
|
|
57
|
+
LayerType2["OSGB_LAYER"] = "OSGBLayer";
|
|
58
|
+
LayerType2["S3M_GROUP"] = "S3MGroup";
|
|
59
|
+
LayerType2["TERRAIN_LAYER"] = "TerrainFileLayer";
|
|
60
|
+
return LayerType2;
|
|
61
|
+
})(LayerType || {});
|
|
62
|
+
var GraphicType = /* @__PURE__ */ ((GraphicType2) => {
|
|
63
|
+
GraphicType2["POINT"] = "point";
|
|
64
|
+
GraphicType2["POLYLINE"] = "polyline";
|
|
65
|
+
GraphicType2["POLYGON"] = "polygon";
|
|
66
|
+
GraphicType2["BILLBOARD"] = "billboard";
|
|
67
|
+
GraphicType2["CYLINDER"] = "cylinder";
|
|
68
|
+
GraphicType2["ELLIPSOID"] = "ellipsoid";
|
|
69
|
+
GraphicType2["LABEL"] = "label";
|
|
70
|
+
GraphicType2["MODEL"] = "model";
|
|
71
|
+
GraphicType2["WALL"] = "wall";
|
|
72
|
+
return GraphicType2;
|
|
73
|
+
})(GraphicType || {});
|
|
74
|
+
var LineSymbol = /* @__PURE__ */ ((LineSymbol2) => {
|
|
75
|
+
LineSymbol2["DASH"] = "10,5";
|
|
76
|
+
LineSymbol2["DOT"] = "3";
|
|
77
|
+
LineSymbol2["DASHDOT"] = "10,3,3,3";
|
|
78
|
+
LineSymbol2["DASHDOTDOT"] = "10,3,3,3,3,3";
|
|
79
|
+
return LineSymbol2;
|
|
80
|
+
})(LineSymbol || {});
|
|
81
|
+
var MeasureMode = /* @__PURE__ */ ((MeasureMode2) => {
|
|
82
|
+
MeasureMode2["DISTANCE"] = "distance";
|
|
83
|
+
MeasureMode2["AREA"] = "area";
|
|
84
|
+
MeasureMode2["HEIGHT"] = "height";
|
|
85
|
+
return MeasureMode2;
|
|
86
|
+
})(MeasureMode || {});
|
|
87
|
+
var ObjectState = /* @__PURE__ */ ((ObjectState2) => {
|
|
88
|
+
ObjectState2["ADD"] = "add";
|
|
89
|
+
ObjectState2["REMOVE"] = "remove";
|
|
90
|
+
ObjectState2["INIT"] = "init";
|
|
91
|
+
return ObjectState2;
|
|
92
|
+
})(ObjectState || {});
|
|
93
|
+
class AudioPlayer {
|
|
94
|
+
constructor(url) {
|
|
8
95
|
/**
|
|
9
96
|
* Creates an instance of AudioPlayer.
|
|
10
97
|
* @param {*} url
|
|
11
98
|
*/
|
|
12
|
-
|
|
13
|
-
this.audio = new Audio()
|
|
99
|
+
__publicField(this, "audio");
|
|
100
|
+
this.audio = new Audio();
|
|
101
|
+
this.audio.src = url;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 朗读文本
|
|
105
|
+
*
|
|
106
|
+
* @param message 要朗读的文本内容
|
|
107
|
+
* @param options 朗读选项,可选参数包括:
|
|
108
|
+
* - lang: 使用的语言,默认为中文
|
|
109
|
+
* - volume: 声音音量,默认为1
|
|
110
|
+
* - rate: 语速,默认为1
|
|
111
|
+
* - pitch: 音高,默认为1
|
|
112
|
+
*/
|
|
113
|
+
static speak(message, options = {}) {
|
|
114
|
+
const msg = new SpeechSynthesisUtterance();
|
|
115
|
+
msg.text = message;
|
|
116
|
+
msg.lang = options.lang || "zh-CN";
|
|
117
|
+
msg.volume = options.volume || 1;
|
|
118
|
+
msg.rate = options.rate || 1;
|
|
119
|
+
msg.pitch = options.pitch || 1;
|
|
120
|
+
window.speechSynthesis.speak(msg);
|
|
14
121
|
}
|
|
15
122
|
play() {
|
|
16
123
|
!this.muted && this.audio.play();
|
|
@@ -24,18 +131,44 @@ class H {
|
|
|
24
131
|
/**
|
|
25
132
|
* @description 设置静音状态,如果静音,autoplay属性将失效
|
|
26
133
|
*/
|
|
27
|
-
set muted(
|
|
28
|
-
this.audio.muted =
|
|
134
|
+
set muted(val) {
|
|
135
|
+
this.audio.muted = val;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
class Cookie {
|
|
139
|
+
static set(name, value, days = 30) {
|
|
140
|
+
if (typeof name !== "string" || typeof value !== "string" || typeof days !== "number") {
|
|
141
|
+
throw new Error("Invalid arguments");
|
|
142
|
+
}
|
|
143
|
+
const exp = /* @__PURE__ */ new Date();
|
|
144
|
+
exp.setTime(exp.getTime() + days * 24 * 60 * 60 * 1e3);
|
|
145
|
+
document.cookie = `${name}=${encodeURIComponent(value)};expires=${exp.toUTCString()}`;
|
|
146
|
+
}
|
|
147
|
+
static remove(name) {
|
|
148
|
+
var exp = /* @__PURE__ */ new Date();
|
|
149
|
+
exp.setTime(exp.getTime() - 1);
|
|
150
|
+
var cval = this.get(name);
|
|
151
|
+
if (cval != null) {
|
|
152
|
+
document.cookie = name + "=" + cval + ";expires=" + exp.toUTCString();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
static get(name) {
|
|
156
|
+
var arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
|
|
157
|
+
if (arr != null) {
|
|
158
|
+
return arr[2];
|
|
159
|
+
} else {
|
|
160
|
+
return "";
|
|
161
|
+
}
|
|
29
162
|
}
|
|
30
163
|
}
|
|
31
|
-
const
|
|
164
|
+
const MathUtils = {
|
|
32
165
|
DEG2RAD: Math.PI / 180,
|
|
33
166
|
RAD2DEG: 180 / Math.PI,
|
|
34
|
-
randInt(
|
|
35
|
-
return
|
|
167
|
+
randInt(low, high) {
|
|
168
|
+
return low + Math.floor(Math.random() * (high - low + 1));
|
|
36
169
|
},
|
|
37
|
-
randFloat(
|
|
38
|
-
return
|
|
170
|
+
randFloat(low, high) {
|
|
171
|
+
return low + Math.random() * (high - low);
|
|
39
172
|
},
|
|
40
173
|
/**
|
|
41
174
|
* 角度转弧度
|
|
@@ -43,17 +176,8 @@ const R = {
|
|
|
43
176
|
* @param {*} degrees
|
|
44
177
|
* @returns {*}
|
|
45
178
|
*/
|
|
46
|
-
|
|
47
|
-
return
|
|
48
|
-
},
|
|
49
|
-
/**
|
|
50
|
-
* 角度转弧度
|
|
51
|
-
*
|
|
52
|
-
* @param {*} degrees
|
|
53
|
-
* @returns {*}
|
|
54
|
-
*/
|
|
55
|
-
toRadians(t) {
|
|
56
|
-
return t * this.DEG2RAD;
|
|
179
|
+
deg2Rad(degrees) {
|
|
180
|
+
return degrees * this.DEG2RAD;
|
|
57
181
|
},
|
|
58
182
|
/**
|
|
59
183
|
* 弧度转角度
|
|
@@ -61,57 +185,43 @@ const R = {
|
|
|
61
185
|
* @param {*} radians
|
|
62
186
|
* @returns {*}
|
|
63
187
|
*/
|
|
64
|
-
|
|
65
|
-
return
|
|
188
|
+
rad2Deg(radians) {
|
|
189
|
+
return radians * this.RAD2DEG;
|
|
66
190
|
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
*
|
|
70
|
-
* @param {*} radians
|
|
71
|
-
* @returns {*}
|
|
72
|
-
*/
|
|
73
|
-
toDegrees(t) {
|
|
74
|
-
return t * this.RAD2DEG;
|
|
75
|
-
},
|
|
76
|
-
formatFloat(t, e = 2) {
|
|
77
|
-
return Math.round(t * Math.pow(10, e)) / Math.pow(10, e);
|
|
191
|
+
round(value, n = 2) {
|
|
192
|
+
return Math.round(value * Math.pow(10, n)) / Math.pow(10, n);
|
|
78
193
|
},
|
|
79
194
|
/**
|
|
80
|
-
*
|
|
195
|
+
* 将数值限制在指定范围内
|
|
81
196
|
*
|
|
82
|
-
* @param val
|
|
197
|
+
* @param val 需要限制的数值
|
|
83
198
|
* @param min 最小值
|
|
84
199
|
* @param max 最大值
|
|
85
200
|
* @returns 返回限制后的数值
|
|
86
201
|
*/
|
|
87
|
-
|
|
88
|
-
return Math.min(Math.max(
|
|
89
|
-
},
|
|
90
|
-
/**
|
|
91
|
-
* 根据给定值返回指定的最小值和最大值之间的最大值
|
|
92
|
-
*
|
|
93
|
-
* @param val 给定的数值
|
|
94
|
-
* @param min 最小值
|
|
95
|
-
* @param max 最大值
|
|
96
|
-
* @returns 返回限制后的数值
|
|
97
|
-
*/
|
|
98
|
-
maxMin(t, e, n) {
|
|
99
|
-
return Math.max(Math.min(t, n), e);
|
|
202
|
+
clamp(val, min, max) {
|
|
203
|
+
return Math.min(Math.max(val, min), max);
|
|
100
204
|
}
|
|
101
205
|
};
|
|
102
|
-
class
|
|
103
|
-
constructor(
|
|
104
|
-
|
|
105
|
-
if (typeof
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
206
|
+
class CanvasDrawer {
|
|
207
|
+
constructor(el) {
|
|
208
|
+
__publicField(this, "context", null);
|
|
209
|
+
if (typeof el === "string") {
|
|
210
|
+
el = document.querySelector("#" + el);
|
|
211
|
+
if (!el) {
|
|
212
|
+
throw new Error("Element not found");
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (el instanceof HTMLElement) {
|
|
216
|
+
const canvas = el;
|
|
217
|
+
if (canvas.getContext) {
|
|
218
|
+
this.context = canvas.getContext("2d");
|
|
219
|
+
} else {
|
|
112
220
|
throw new Error("getContext is not available on this element");
|
|
113
|
-
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
114
223
|
throw new Error("Element is not an HTMLElement");
|
|
224
|
+
}
|
|
115
225
|
}
|
|
116
226
|
/**
|
|
117
227
|
* 绘制线条
|
|
@@ -121,12 +231,18 @@ class j {
|
|
|
121
231
|
* @param options 绘制选项,包括线条宽度和颜色
|
|
122
232
|
* @throws 当画布上下文不存在时抛出错误
|
|
123
233
|
*/
|
|
124
|
-
drawLine({ x:
|
|
125
|
-
if (!this.context)
|
|
234
|
+
drawLine({ x: startX, y: startY }, { x: endX, y: endY }, options = {}) {
|
|
235
|
+
if (!this.context) {
|
|
126
236
|
throw new Error("Canvas context is null or undefined");
|
|
237
|
+
}
|
|
127
238
|
this.context.beginPath();
|
|
128
|
-
const
|
|
129
|
-
|
|
239
|
+
const width = options.width || 1;
|
|
240
|
+
const color = options.color || "#000";
|
|
241
|
+
this.context.lineWidth = width;
|
|
242
|
+
this.context.strokeStyle = color;
|
|
243
|
+
this.context.moveTo(startX, startY);
|
|
244
|
+
this.context.lineTo(endX, endY);
|
|
245
|
+
this.context.stroke();
|
|
130
246
|
}
|
|
131
247
|
/**
|
|
132
248
|
* 绘制圆弧
|
|
@@ -141,67 +257,107 @@ class j {
|
|
|
141
257
|
* @param bgColor 背景颜色
|
|
142
258
|
* @throws 当Canvas context为null或undefined时抛出错误
|
|
143
259
|
*/
|
|
144
|
-
drawArc({ x
|
|
145
|
-
if (!this.context)
|
|
260
|
+
drawArc({ x, y }, radius, startAngle, endAngle, anticlockwise, isFill, bgColor) {
|
|
261
|
+
if (!this.context) {
|
|
146
262
|
throw new Error("Canvas context is null or undefined");
|
|
147
|
-
|
|
263
|
+
}
|
|
264
|
+
if (isFill) {
|
|
265
|
+
this.context.fillStyle = bgColor;
|
|
266
|
+
this.context.beginPath();
|
|
267
|
+
this.context.arc(x, y, radius, MathUtils.deg2Rad(startAngle), MathUtils.deg2Rad(endAngle), anticlockwise);
|
|
268
|
+
this.context.fill();
|
|
269
|
+
} else {
|
|
270
|
+
this.context.strokeStyle = bgColor;
|
|
271
|
+
this.context.beginPath();
|
|
272
|
+
this.context.arc(x, y, radius, MathUtils.deg2Rad(startAngle), MathUtils.deg2Rad(endAngle), anticlockwise);
|
|
273
|
+
this.context.stroke();
|
|
274
|
+
}
|
|
148
275
|
}
|
|
149
|
-
static createCanvas(
|
|
150
|
-
let
|
|
151
|
-
if (typeof document
|
|
152
|
-
|
|
276
|
+
static createCanvas(width = 1, height = 1) {
|
|
277
|
+
let canvas;
|
|
278
|
+
if (typeof document !== "undefined") {
|
|
279
|
+
canvas = document.createElement("canvas");
|
|
280
|
+
if (width) {
|
|
281
|
+
canvas.width = width;
|
|
282
|
+
}
|
|
283
|
+
if (height) {
|
|
284
|
+
canvas.height = height;
|
|
285
|
+
}
|
|
286
|
+
return canvas;
|
|
287
|
+
}
|
|
153
288
|
}
|
|
154
289
|
}
|
|
155
|
-
class
|
|
290
|
+
class EventDispatcher {
|
|
156
291
|
constructor() {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
292
|
+
__publicField(this, "_listeners");
|
|
293
|
+
__publicField(this, "_mutex", {});
|
|
294
|
+
__publicField(this, "_context");
|
|
160
295
|
}
|
|
161
|
-
addEventListener(
|
|
162
|
-
this._listeners === void 0
|
|
163
|
-
|
|
164
|
-
|
|
296
|
+
addEventListener(type, listener, context, mutexStatus) {
|
|
297
|
+
if (this._listeners === void 0) this._listeners = {};
|
|
298
|
+
this._context = context;
|
|
299
|
+
const mutex = this._mutex;
|
|
300
|
+
const listeners = this._listeners;
|
|
301
|
+
if (listeners[type] === void 0) {
|
|
302
|
+
listeners[type] = [];
|
|
303
|
+
}
|
|
304
|
+
if (listeners[type].indexOf(listener) === -1) {
|
|
305
|
+
if (mutexStatus) {
|
|
306
|
+
mutex[type] = listener;
|
|
307
|
+
}
|
|
308
|
+
listeners[type].push(listener);
|
|
309
|
+
}
|
|
310
|
+
return this;
|
|
165
311
|
}
|
|
166
|
-
hasEventListener(
|
|
167
|
-
if (this._listeners === null || this._listeners === void 0) return
|
|
168
|
-
const
|
|
169
|
-
return
|
|
312
|
+
hasEventListener(type, listener) {
|
|
313
|
+
if (this._listeners === null || this._listeners === void 0) return false;
|
|
314
|
+
const listeners = this._listeners;
|
|
315
|
+
return listeners[type] !== void 0 && listeners[type].indexOf(listener) !== -1;
|
|
170
316
|
}
|
|
171
|
-
removeEventListener(
|
|
317
|
+
removeEventListener(type, listener) {
|
|
172
318
|
if (this._listeners === void 0) return;
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
319
|
+
const listeners = this._listeners;
|
|
320
|
+
const listenerArray = listeners[type];
|
|
321
|
+
if (this._mutex[type] === listener) {
|
|
322
|
+
this._mutex[type] = null;
|
|
323
|
+
}
|
|
324
|
+
if (listenerArray !== void 0) {
|
|
325
|
+
const index = listenerArray.map((d) => d.toString()).indexOf(listener.toString());
|
|
326
|
+
if (index !== -1) {
|
|
327
|
+
listenerArray.splice(index, 1);
|
|
328
|
+
}
|
|
177
329
|
}
|
|
178
330
|
}
|
|
179
|
-
dispatchEvent(
|
|
331
|
+
dispatchEvent(event) {
|
|
180
332
|
if (this._listeners === void 0) return;
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
333
|
+
const listeners = this._listeners;
|
|
334
|
+
const listenerArray = listeners[event.type];
|
|
335
|
+
if (listenerArray !== void 0) {
|
|
336
|
+
event.target = this;
|
|
337
|
+
const array = listenerArray.slice(0);
|
|
338
|
+
if (this._mutex[event.type] !== void 0) {
|
|
339
|
+
const find = array.find((item) => item === this._mutex[event.type]);
|
|
340
|
+
if (find) {
|
|
341
|
+
find.call(this._context || this, event);
|
|
189
342
|
return;
|
|
190
343
|
}
|
|
191
344
|
}
|
|
192
|
-
for (let
|
|
193
|
-
const
|
|
194
|
-
typeof
|
|
345
|
+
for (let i = 0, l = array.length; i < l; i++) {
|
|
346
|
+
const item = array[i];
|
|
347
|
+
if (typeof item === "function") {
|
|
348
|
+
item.call(this._context || this, event);
|
|
349
|
+
}
|
|
195
350
|
}
|
|
196
351
|
}
|
|
197
352
|
}
|
|
198
353
|
removeAllListener() {
|
|
199
354
|
this._mutex = {};
|
|
200
|
-
for (const
|
|
201
|
-
this._listeners[
|
|
355
|
+
for (const key in this._listeners) {
|
|
356
|
+
this._listeners[key] = [];
|
|
357
|
+
}
|
|
202
358
|
}
|
|
203
359
|
}
|
|
204
|
-
class
|
|
360
|
+
class HashMap extends Map {
|
|
205
361
|
isEmpty() {
|
|
206
362
|
return this.size === 0;
|
|
207
363
|
}
|
|
@@ -217,90 +373,143 @@ class C extends Map {
|
|
|
217
373
|
fromEntries() {
|
|
218
374
|
}
|
|
219
375
|
}
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
Array.isArray(
|
|
224
|
-
|
|
376
|
+
HashMap.prototype.fromEntries = function(array = []) {
|
|
377
|
+
const hashMap = new HashMap();
|
|
378
|
+
array.forEach((element) => {
|
|
379
|
+
if (Array.isArray(element) && element.length === 2) {
|
|
380
|
+
hashMap.set(element[0], element[1]);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
return hashMap;
|
|
225
384
|
};
|
|
226
|
-
class
|
|
227
|
-
constructor(
|
|
385
|
+
class WebSocketClient extends EventDispatcher {
|
|
386
|
+
constructor(url = "ws://127.0.0.1:10088") {
|
|
228
387
|
super();
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
this.maxCheckTimes = 10
|
|
388
|
+
__publicField(this, "maxCheckTimes", 10);
|
|
389
|
+
__publicField(this, "url");
|
|
390
|
+
__publicField(this, "checkTimes", 0);
|
|
391
|
+
__publicField(this, "connectStatus", false);
|
|
392
|
+
__publicField(this, "client", null);
|
|
393
|
+
this.maxCheckTimes = 10;
|
|
394
|
+
this.url = url;
|
|
395
|
+
this.checkTimes = 0;
|
|
396
|
+
this.connect();
|
|
397
|
+
this.connCheckStatus(this.maxCheckTimes);
|
|
235
398
|
}
|
|
236
399
|
connect() {
|
|
237
|
-
|
|
400
|
+
this.disconnect();
|
|
401
|
+
if (this.url) {
|
|
238
402
|
try {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
403
|
+
console.info("创建ws连接>>>" + this.url);
|
|
404
|
+
this.client = new WebSocket(this.url);
|
|
405
|
+
if (this.client) {
|
|
406
|
+
const self = this;
|
|
407
|
+
this.client.onopen = function(message) {
|
|
408
|
+
self.dispatchEvent({
|
|
409
|
+
type: EventType.WEB_SOCKET_CONNECT,
|
|
410
|
+
message
|
|
245
411
|
});
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
412
|
+
};
|
|
413
|
+
this.client.onmessage = function(message) {
|
|
414
|
+
self.connectStatus = true;
|
|
415
|
+
self.dispatchEvent({
|
|
416
|
+
type: EventType.WEB_SOCKET_MESSAGE,
|
|
417
|
+
message
|
|
250
418
|
});
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
419
|
+
};
|
|
420
|
+
this.client.onclose = function(message) {
|
|
421
|
+
self.dispatchEvent({
|
|
422
|
+
type: EventType.WEB_SOCKET_CLOSE,
|
|
423
|
+
message
|
|
255
424
|
});
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
425
|
+
};
|
|
426
|
+
if (this.checkTimes === this.maxCheckTimes) {
|
|
427
|
+
this.client.onerror = function(message) {
|
|
428
|
+
self.dispatchEvent({
|
|
429
|
+
type: EventType.WEB_SOCKET_ERROR,
|
|
430
|
+
message
|
|
431
|
+
});
|
|
432
|
+
};
|
|
433
|
+
}
|
|
262
434
|
}
|
|
263
|
-
} catch (
|
|
264
|
-
console.error("创建ws连接失败" + this.url + ":" +
|
|
435
|
+
} catch (ex) {
|
|
436
|
+
console.error("创建ws连接失败" + this.url + ":" + ex);
|
|
265
437
|
}
|
|
438
|
+
}
|
|
266
439
|
}
|
|
267
440
|
disconnect() {
|
|
268
|
-
if (this.client)
|
|
441
|
+
if (this.client) {
|
|
269
442
|
try {
|
|
270
|
-
console.log("ws断开连接" + this.url)
|
|
271
|
-
|
|
443
|
+
console.log("ws断开连接" + this.url);
|
|
444
|
+
this.client.close();
|
|
445
|
+
this.client = null;
|
|
446
|
+
} catch (ex) {
|
|
272
447
|
this.client = null;
|
|
273
448
|
}
|
|
449
|
+
}
|
|
274
450
|
}
|
|
275
|
-
connCheckStatus(
|
|
276
|
-
this.checkTimes >
|
|
277
|
-
|
|
451
|
+
connCheckStatus(times) {
|
|
452
|
+
if (this.checkTimes > times) return;
|
|
453
|
+
setTimeout(() => {
|
|
454
|
+
this.checkTimes++;
|
|
455
|
+
if (this.client && this.client.readyState !== 0 && this.client.readyState !== 1) {
|
|
456
|
+
this.connect();
|
|
457
|
+
}
|
|
458
|
+
this.connCheckStatus(times);
|
|
278
459
|
}, 2e3);
|
|
279
460
|
}
|
|
280
|
-
send(
|
|
281
|
-
|
|
461
|
+
send(message) {
|
|
462
|
+
if (this.client && this.client.readyState === 1) {
|
|
463
|
+
this.client.send(message);
|
|
464
|
+
return true;
|
|
465
|
+
}
|
|
466
|
+
console.error(this.url + "消息发送失败:" + message);
|
|
467
|
+
return false;
|
|
282
468
|
}
|
|
283
469
|
heartbeat() {
|
|
284
470
|
setTimeout(() => {
|
|
285
|
-
this.client && this.client.readyState === 1
|
|
471
|
+
if (this.client && this.client.readyState === 1) {
|
|
472
|
+
this.send("HeartBeat");
|
|
473
|
+
}
|
|
474
|
+
console.log("HeartBeat," + this.url);
|
|
475
|
+
setTimeout(this.heartbeat, 3e4);
|
|
286
476
|
}, 1e3);
|
|
287
477
|
}
|
|
288
478
|
}
|
|
289
|
-
const
|
|
479
|
+
const CommUtils = {
|
|
290
480
|
/**
|
|
291
481
|
* 获取数据类型
|
|
292
482
|
*
|
|
293
483
|
* @param data 待判断的数据
|
|
294
484
|
* @returns 返回数据类型字符串
|
|
295
485
|
*/
|
|
296
|
-
getDataType(
|
|
297
|
-
return Object.prototype.toString.call(
|
|
486
|
+
getDataType(data) {
|
|
487
|
+
return Object.prototype.toString.call(data).slice(8, -1);
|
|
298
488
|
},
|
|
299
|
-
asArray(
|
|
300
|
-
return this.isEmpty(
|
|
489
|
+
asArray(obj) {
|
|
490
|
+
return this.isEmpty(obj) ? [] : Array.isArray(obj) ? obj : [obj];
|
|
301
491
|
},
|
|
302
|
-
asNumber(
|
|
303
|
-
return Number.isNaN(Number(
|
|
492
|
+
asNumber(a) {
|
|
493
|
+
return Number.isNaN(Number(a)) ? 0 : Number(a);
|
|
494
|
+
},
|
|
495
|
+
/**
|
|
496
|
+
* 将值转换为字符串
|
|
497
|
+
*
|
|
498
|
+
* @param value 要转换的值
|
|
499
|
+
* @returns 转换后的字符串,如果值为空,则返回空字符串
|
|
500
|
+
*/
|
|
501
|
+
asString(value) {
|
|
502
|
+
if (this.isEmpty(value)) {
|
|
503
|
+
return "";
|
|
504
|
+
} else {
|
|
505
|
+
switch (this.getDataType(value)) {
|
|
506
|
+
case "Object":
|
|
507
|
+
case "Array":
|
|
508
|
+
return JSON.stringify(value);
|
|
509
|
+
default:
|
|
510
|
+
return value;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
304
513
|
},
|
|
305
514
|
/**
|
|
306
515
|
* 判断传入的值是否为空
|
|
@@ -308,24 +517,26 @@ const M = {
|
|
|
308
517
|
* @param value 待判断的值
|
|
309
518
|
* @returns 返回布尔值,表示是否为空
|
|
310
519
|
*/
|
|
311
|
-
isEmpty(
|
|
312
|
-
if (
|
|
313
|
-
return
|
|
314
|
-
|
|
520
|
+
isEmpty(value) {
|
|
521
|
+
if (value == null) {
|
|
522
|
+
return true;
|
|
523
|
+
}
|
|
524
|
+
const type = this.getDataType(value);
|
|
525
|
+
switch (type) {
|
|
315
526
|
case "String":
|
|
316
|
-
return
|
|
527
|
+
return value.trim() === "";
|
|
317
528
|
case "Array":
|
|
318
|
-
return !
|
|
529
|
+
return !value.length;
|
|
319
530
|
case "Object":
|
|
320
|
-
return !Object.keys(
|
|
531
|
+
return !Object.keys(value).length;
|
|
321
532
|
case "Boolean":
|
|
322
|
-
return !
|
|
533
|
+
return !value;
|
|
323
534
|
default:
|
|
324
|
-
return
|
|
535
|
+
return false;
|
|
325
536
|
}
|
|
326
537
|
},
|
|
327
|
-
isNotEmpty(
|
|
328
|
-
return !this.isEmpty(
|
|
538
|
+
isNotEmpty(val) {
|
|
539
|
+
return !this.isEmpty(val);
|
|
329
540
|
},
|
|
330
541
|
/**
|
|
331
542
|
* 将JSON对象转换为FormData对象
|
|
@@ -333,11 +544,12 @@ const M = {
|
|
|
333
544
|
* @param json 待转换的JSON对象,其属性值为字符串或Blob类型
|
|
334
545
|
* @returns 转换后的FormData对象
|
|
335
546
|
*/
|
|
336
|
-
json2form(
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
})
|
|
547
|
+
json2form(json) {
|
|
548
|
+
const formData = new FormData();
|
|
549
|
+
Object.keys(json).forEach((key) => {
|
|
550
|
+
formData.append(key, json[key] instanceof Object ? JSON.stringify(json[key]) : json[key]);
|
|
551
|
+
});
|
|
552
|
+
return formData;
|
|
341
553
|
},
|
|
342
554
|
/**
|
|
343
555
|
* 生成GUID
|
|
@@ -345,10 +557,10 @@ const M = {
|
|
|
345
557
|
* @returns 返回一个由8个16进制数组成的GUID字符串
|
|
346
558
|
*/
|
|
347
559
|
guid() {
|
|
348
|
-
const
|
|
560
|
+
const S4 = function() {
|
|
349
561
|
return ((1 + Math.random()) * 65536 | 0).toString(16).substring(1);
|
|
350
562
|
};
|
|
351
|
-
return
|
|
563
|
+
return S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4();
|
|
352
564
|
},
|
|
353
565
|
/**
|
|
354
566
|
* 将参数进行解码并返回解码后的字符串
|
|
@@ -356,18 +568,23 @@ const M = {
|
|
|
356
568
|
* @param args 参数
|
|
357
569
|
* @returns 解码后的字符串
|
|
358
570
|
*/
|
|
359
|
-
decodeDict(...
|
|
360
|
-
let
|
|
361
|
-
if (
|
|
362
|
-
const
|
|
363
|
-
for (let
|
|
364
|
-
const
|
|
365
|
-
|
|
571
|
+
decodeDict(...args) {
|
|
572
|
+
let res = "";
|
|
573
|
+
if (args.length > 1) {
|
|
574
|
+
const items = args.slice(1, args.length % 2 === 0 ? args.length - 1 : args.length);
|
|
575
|
+
for (let i = 0; i < items.length; i = i + 2) {
|
|
576
|
+
const item = items[i];
|
|
577
|
+
if (args[0] === item) {
|
|
578
|
+
res = items[i + 1];
|
|
579
|
+
}
|
|
366
580
|
}
|
|
367
|
-
!
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
581
|
+
if (!res && args.length % 2 === 0) {
|
|
582
|
+
res = args[args.length - 1];
|
|
583
|
+
}
|
|
584
|
+
} else {
|
|
585
|
+
res = args[0];
|
|
586
|
+
}
|
|
587
|
+
return res;
|
|
371
588
|
},
|
|
372
589
|
/**
|
|
373
590
|
* 将一个或多个对象的所有可枚举属性复制到目标对象。
|
|
@@ -376,14 +593,15 @@ const M = {
|
|
|
376
593
|
* @param args 一个或多个源对象,用于提供要复制的属性。
|
|
377
594
|
* @returns 返回目标对象,包含所有复制的属性。
|
|
378
595
|
*/
|
|
379
|
-
extend(
|
|
380
|
-
let
|
|
381
|
-
for (
|
|
382
|
-
|
|
383
|
-
for (
|
|
384
|
-
|
|
596
|
+
extend(dest, ...args) {
|
|
597
|
+
let i, j, len, src;
|
|
598
|
+
for (j = 0, len = args.length; j < len; j++) {
|
|
599
|
+
src = args[j];
|
|
600
|
+
for (i in src) {
|
|
601
|
+
dest[i] = src[i];
|
|
602
|
+
}
|
|
385
603
|
}
|
|
386
|
-
return
|
|
604
|
+
return dest;
|
|
387
605
|
},
|
|
388
606
|
/**
|
|
389
607
|
* 将扁平化数组转换为树形结构数组
|
|
@@ -394,34 +612,55 @@ const M = {
|
|
|
394
612
|
* @param childrenPropertyName 树形结构中标识子节点的字段名,默认为'children'
|
|
395
613
|
* @returns 转换后的树形结构数组
|
|
396
614
|
*/
|
|
397
|
-
convertToTree2(
|
|
398
|
-
const
|
|
399
|
-
function
|
|
400
|
-
const
|
|
401
|
-
|
|
615
|
+
convertToTree2(data, idPropertyName = "id", parentIdPropertyName = "parentId", childrenPropertyName = "children") {
|
|
616
|
+
const result = [];
|
|
617
|
+
function buildChildren(item) {
|
|
618
|
+
const children = data.filter((item2) => item2[parentIdPropertyName] === item[idPropertyName]).map((child) => {
|
|
619
|
+
if (!result.some((r) => r[idPropertyName] === child[idPropertyName])) {
|
|
620
|
+
buildChildren(child);
|
|
621
|
+
}
|
|
622
|
+
return child;
|
|
623
|
+
});
|
|
624
|
+
if (children.length > 0) {
|
|
625
|
+
item[childrenPropertyName] = children;
|
|
626
|
+
}
|
|
402
627
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
628
|
+
data.forEach((item) => {
|
|
629
|
+
if (!data.some((other) => other[parentIdPropertyName] === item[idPropertyName])) {
|
|
630
|
+
buildChildren(item);
|
|
631
|
+
result.push(item);
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
return result;
|
|
406
635
|
},
|
|
407
636
|
/**
|
|
408
637
|
* 异步加载script
|
|
409
638
|
*
|
|
410
639
|
* @param {*} url
|
|
411
640
|
*/
|
|
412
|
-
asyncLoadScript(
|
|
413
|
-
return new Promise((
|
|
641
|
+
asyncLoadScript(url) {
|
|
642
|
+
return new Promise((resolve, reject) => {
|
|
414
643
|
try {
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
644
|
+
const oscript = document.createElement("script");
|
|
645
|
+
oscript.type = "text/javascript";
|
|
646
|
+
oscript.src = url;
|
|
647
|
+
if ("readyState" in oscript) {
|
|
648
|
+
oscript.onreadystatechange = function() {
|
|
649
|
+
if (oscript.readyState === "complete" || oscript.readyState === "loaded") {
|
|
650
|
+
resolve(oscript);
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
} else {
|
|
654
|
+
oscript.onload = function() {
|
|
655
|
+
resolve(oscript);
|
|
656
|
+
};
|
|
657
|
+
oscript.onerror = function() {
|
|
658
|
+
reject(new Error("Script failed to load for URL: " + url));
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
document.body.appendChild(oscript);
|
|
662
|
+
} catch (error) {
|
|
663
|
+
reject(error);
|
|
425
664
|
}
|
|
426
665
|
});
|
|
427
666
|
},
|
|
@@ -431,12 +670,16 @@ const M = {
|
|
|
431
670
|
* @param urls 样式文件URL数组
|
|
432
671
|
* @returns 无返回值
|
|
433
672
|
*/
|
|
434
|
-
loadStyle(
|
|
435
|
-
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
673
|
+
loadStyle(urls) {
|
|
674
|
+
urls.forEach((url) => {
|
|
675
|
+
const css = document.createElement("link");
|
|
676
|
+
css.href = url;
|
|
677
|
+
css.rel = "stylesheet";
|
|
678
|
+
css.type = "text/css";
|
|
679
|
+
css.onerror = function() {
|
|
680
|
+
console.error(`Style loading failed for URL: ${url}`);
|
|
681
|
+
};
|
|
682
|
+
document.head.appendChild(css);
|
|
440
683
|
});
|
|
441
684
|
},
|
|
442
685
|
/**
|
|
@@ -447,13 +690,17 @@ const M = {
|
|
|
447
690
|
* @returns 替换后的字符串
|
|
448
691
|
* @throws 当对象中没有找到与占位符对应的值时,抛出错误
|
|
449
692
|
*/
|
|
450
|
-
template(
|
|
451
|
-
const
|
|
452
|
-
return
|
|
453
|
-
const
|
|
454
|
-
if (
|
|
455
|
-
throw new Error(`${
|
|
456
|
-
|
|
693
|
+
template(str, data) {
|
|
694
|
+
const templateRe = /\{ *([\w_-]+) *\}/g;
|
|
695
|
+
return str.replace(templateRe, (match, key) => {
|
|
696
|
+
const value = data[key];
|
|
697
|
+
if (value === void 0) {
|
|
698
|
+
throw new Error(`${ErrorType.JSON_VALUE_ERROR}: ${match}`);
|
|
699
|
+
} else if (typeof value === "function") {
|
|
700
|
+
return value(data);
|
|
701
|
+
} else {
|
|
702
|
+
return value;
|
|
703
|
+
}
|
|
457
704
|
});
|
|
458
705
|
},
|
|
459
706
|
/**
|
|
@@ -462,18 +709,32 @@ const M = {
|
|
|
462
709
|
* @param data 待处理的对象
|
|
463
710
|
* @returns 返回处理后的对象
|
|
464
711
|
*/
|
|
465
|
-
deleteEmptyProperty(
|
|
712
|
+
deleteEmptyProperty(data) {
|
|
466
713
|
return Object.fromEntries(
|
|
467
|
-
Object.keys(
|
|
714
|
+
Object.keys(data).filter((d) => !this.isEmpty(data[d])).map((i) => [i, data[i]])
|
|
468
715
|
);
|
|
469
716
|
},
|
|
470
|
-
deepAssign(
|
|
471
|
-
(typeof
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
717
|
+
deepAssign(target, ...sources) {
|
|
718
|
+
if (typeof target !== "object" || target === null) {
|
|
719
|
+
target = {};
|
|
720
|
+
}
|
|
721
|
+
for (const source of sources) {
|
|
722
|
+
if (typeof source === "object" && source !== null) {
|
|
723
|
+
for (const key in source) {
|
|
724
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
725
|
+
if (typeof source[key] === "object" && source[key] !== null) {
|
|
726
|
+
if (!target[key]) {
|
|
727
|
+
target[key] = Array.isArray(source[key]) ? [] : {};
|
|
728
|
+
}
|
|
729
|
+
this.deepAssign(target[key], source[key]);
|
|
730
|
+
} else {
|
|
731
|
+
target[key] = source[key];
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return target;
|
|
477
738
|
},
|
|
478
739
|
/**
|
|
479
740
|
* 复制文本到剪贴板
|
|
@@ -481,96 +742,141 @@ const M = {
|
|
|
481
742
|
* @param text 要复制的文本
|
|
482
743
|
* @returns 返回一个Promise,表示复制操作的结果
|
|
483
744
|
*/
|
|
484
|
-
handleCopyValue(
|
|
485
|
-
if (navigator.clipboard && window.isSecureContext)
|
|
486
|
-
return navigator.clipboard.writeText(
|
|
487
|
-
{
|
|
488
|
-
const
|
|
489
|
-
|
|
745
|
+
handleCopyValue(text) {
|
|
746
|
+
if (navigator.clipboard && window.isSecureContext) {
|
|
747
|
+
return navigator.clipboard.writeText(text);
|
|
748
|
+
} else {
|
|
749
|
+
const textArea = document.createElement("textarea");
|
|
750
|
+
textArea.style.position = "fixed";
|
|
751
|
+
textArea.style.top = textArea.style.left = "-100vh";
|
|
752
|
+
textArea.style.opacity = "0";
|
|
753
|
+
textArea.value = text;
|
|
754
|
+
document.body.appendChild(textArea);
|
|
755
|
+
textArea.focus();
|
|
756
|
+
textArea.select();
|
|
757
|
+
return new Promise((resolve, reject) => {
|
|
490
758
|
try {
|
|
491
|
-
document.execCommand("copy")
|
|
492
|
-
|
|
493
|
-
|
|
759
|
+
document.execCommand("copy");
|
|
760
|
+
resolve();
|
|
761
|
+
} catch (error) {
|
|
762
|
+
reject(new Error("copy failed"));
|
|
494
763
|
} finally {
|
|
495
|
-
|
|
764
|
+
textArea.remove();
|
|
496
765
|
}
|
|
497
766
|
});
|
|
498
767
|
}
|
|
499
768
|
},
|
|
500
|
-
isArray(
|
|
501
|
-
return Array.isArray(
|
|
769
|
+
isArray(a) {
|
|
770
|
+
return Array.isArray(a);
|
|
771
|
+
},
|
|
772
|
+
isObject(a) {
|
|
773
|
+
return Object.prototype.toString.call(a).indexOf("Object") > -1;
|
|
502
774
|
},
|
|
503
|
-
|
|
504
|
-
return
|
|
775
|
+
isNil(a) {
|
|
776
|
+
return a === void 0 || a === "undefined" || a === null || a === "null";
|
|
505
777
|
},
|
|
506
|
-
|
|
507
|
-
return
|
|
778
|
+
isNumber(a) {
|
|
779
|
+
return typeof a === "number" && !isNaN(a) || typeof a === "string" && Number.isFinite(+a);
|
|
780
|
+
},
|
|
781
|
+
isFunction(obj) {
|
|
782
|
+
if (this.isNil(obj)) {
|
|
783
|
+
return false;
|
|
784
|
+
}
|
|
785
|
+
return typeof obj === "function" || obj.constructor !== null && obj.constructor === Function;
|
|
508
786
|
},
|
|
509
|
-
|
|
510
|
-
|
|
787
|
+
/**
|
|
788
|
+
* 判断传入参数是否为DOM元素
|
|
789
|
+
*
|
|
790
|
+
* @param a 待判断的参数
|
|
791
|
+
* @returns 返回布尔值,表示是否为DOM元素
|
|
792
|
+
*/
|
|
793
|
+
isElement(a) {
|
|
794
|
+
return typeof a === "object" && a.nodeType === 1;
|
|
511
795
|
},
|
|
512
|
-
|
|
513
|
-
|
|
796
|
+
/**
|
|
797
|
+
* 检查版本
|
|
798
|
+
*
|
|
799
|
+
* @param currentV 当前版本号
|
|
800
|
+
* @param targetV 要求版本号
|
|
801
|
+
* @returns 返回布尔值,表示当前版本是否需要升级到目标版本
|
|
802
|
+
*/
|
|
803
|
+
checheVersion(currentV, targetV) {
|
|
804
|
+
var numC = currentV.replace(/[^0-9]/gi, "");
|
|
805
|
+
var numT = targetV.replace(/[^0-9]/gi, "");
|
|
806
|
+
return numC < numT;
|
|
514
807
|
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
|
|
808
|
+
};
|
|
809
|
+
const ObjectUtil = {
|
|
810
|
+
deepClone(a) {
|
|
811
|
+
return structuredClone(a);
|
|
518
812
|
},
|
|
519
|
-
isEqual(
|
|
520
|
-
return JSON.stringify(
|
|
813
|
+
isEqual(a, b) {
|
|
814
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
521
815
|
},
|
|
522
|
-
parse(
|
|
523
|
-
|
|
816
|
+
parse(str) {
|
|
817
|
+
if (!str || !(typeof str === "string")) {
|
|
818
|
+
return str;
|
|
819
|
+
}
|
|
820
|
+
return JSON.parse(str);
|
|
524
821
|
}
|
|
525
822
|
};
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
823
|
+
const myArray = Object.create(Array);
|
|
824
|
+
myArray.groupBy = function(f) {
|
|
825
|
+
var groups = {};
|
|
826
|
+
this.forEach(function(o) {
|
|
827
|
+
var group = JSON.stringify(f(o));
|
|
828
|
+
groups[group] = groups[group] || [];
|
|
829
|
+
groups[group].push(o);
|
|
830
|
+
});
|
|
831
|
+
return Object.keys(groups).map((group) => groups[group]);
|
|
532
832
|
};
|
|
533
|
-
|
|
534
|
-
const
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
833
|
+
myArray.distinct = function(f = (d) => d) {
|
|
834
|
+
const arr = [];
|
|
835
|
+
const obj = {};
|
|
836
|
+
this.forEach((item) => {
|
|
837
|
+
const val = f(item);
|
|
838
|
+
const key = String(val);
|
|
839
|
+
if (!obj[key]) {
|
|
840
|
+
obj[key] = true;
|
|
841
|
+
arr.push(item);
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
return arr;
|
|
539
845
|
};
|
|
540
|
-
|
|
846
|
+
myArray.prototype.max = function() {
|
|
541
847
|
return Math.max.apply({}, this);
|
|
542
848
|
};
|
|
543
|
-
|
|
849
|
+
myArray.prototype.min = function() {
|
|
544
850
|
return Math.min.apply({}, this);
|
|
545
851
|
};
|
|
546
|
-
|
|
547
|
-
return this.length > 0 ? this.reduce((
|
|
852
|
+
myArray.sum = function() {
|
|
853
|
+
return this.length > 0 ? this.reduce((prev = 0, curr = 0) => prev + curr) : 0;
|
|
548
854
|
};
|
|
549
|
-
|
|
855
|
+
myArray.avg = function() {
|
|
550
856
|
return this.length ? this.sum() / this.length : 0;
|
|
551
857
|
};
|
|
552
|
-
|
|
553
|
-
return this.sort((
|
|
554
|
-
};
|
|
555
|
-
Array.prototype.asc = function(t = (e) => e) {
|
|
556
|
-
return this.sort((e, n) => t(e) - t(n));
|
|
858
|
+
myArray.desc = function(f = (d) => d) {
|
|
859
|
+
return this.sort((n1, n2) => f(n2) - f(n1));
|
|
557
860
|
};
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
return e > -1 && this.splice(e, 1), this;
|
|
861
|
+
myArray.asc = function(f = (d) => d) {
|
|
862
|
+
return this.sort((n1, n2) => f(n1) - f(n2));
|
|
561
863
|
};
|
|
562
|
-
|
|
563
|
-
|
|
864
|
+
myArray.remove = function(obj) {
|
|
865
|
+
const i = this.indexOf(obj);
|
|
866
|
+
if (i > -1) {
|
|
867
|
+
this.splice(i, 1);
|
|
868
|
+
}
|
|
869
|
+
return this;
|
|
564
870
|
};
|
|
565
|
-
const
|
|
871
|
+
const ArrayUtil = {
|
|
566
872
|
/**
|
|
567
873
|
* 创建指定长度的数组,并返回其索引数组
|
|
568
874
|
*
|
|
569
875
|
* @param length 数组长度
|
|
570
876
|
* @returns 索引数组
|
|
571
877
|
*/
|
|
572
|
-
create(
|
|
573
|
-
return [...new Array(
|
|
878
|
+
create(length) {
|
|
879
|
+
return [...new Array(length).keys()];
|
|
574
880
|
},
|
|
575
881
|
/**
|
|
576
882
|
* 合并多个数组,并去重
|
|
@@ -578,11 +884,14 @@ const S = {
|
|
|
578
884
|
* @param args 需要合并的数组
|
|
579
885
|
* @returns 合并后的去重数组
|
|
580
886
|
*/
|
|
581
|
-
union(...
|
|
582
|
-
let
|
|
583
|
-
|
|
584
|
-
Array.isArray(
|
|
585
|
-
|
|
887
|
+
union(...args) {
|
|
888
|
+
let res = [];
|
|
889
|
+
args.forEach((arg) => {
|
|
890
|
+
if (Array.isArray(arg)) {
|
|
891
|
+
res = res.concat(arg.filter((v) => !res.includes(v)));
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
return res;
|
|
586
895
|
},
|
|
587
896
|
/**
|
|
588
897
|
* 求多个数组的交集
|
|
@@ -590,11 +899,14 @@ const S = {
|
|
|
590
899
|
* @param args 多个需要求交集的数组
|
|
591
900
|
* @returns 返回多个数组的交集数组
|
|
592
901
|
*/
|
|
593
|
-
intersection(...
|
|
594
|
-
let
|
|
595
|
-
|
|
596
|
-
Array.isArray(
|
|
597
|
-
|
|
902
|
+
intersection(...args) {
|
|
903
|
+
let res = args[0] || [];
|
|
904
|
+
args.forEach((arg) => {
|
|
905
|
+
if (Array.isArray(arg)) {
|
|
906
|
+
res = res.filter((v) => arg.includes(v));
|
|
907
|
+
}
|
|
908
|
+
});
|
|
909
|
+
return res;
|
|
598
910
|
},
|
|
599
911
|
/**
|
|
600
912
|
* 将多个数组拼接为一个数组,并去除其中的空值。
|
|
@@ -602,8 +914,8 @@ const S = {
|
|
|
602
914
|
* @param args 需要拼接的数组列表。
|
|
603
915
|
* @returns 拼接并去空后的数组。
|
|
604
916
|
*/
|
|
605
|
-
unionAll(...
|
|
606
|
-
return [...
|
|
917
|
+
unionAll(...args) {
|
|
918
|
+
return [...args].flat().filter((d) => !!d);
|
|
607
919
|
},
|
|
608
920
|
/**
|
|
609
921
|
* 求差集
|
|
@@ -611,106 +923,256 @@ const S = {
|
|
|
611
923
|
* @param args 任意个集合
|
|
612
924
|
* @returns 返回差集结果
|
|
613
925
|
*/
|
|
614
|
-
difference(...
|
|
615
|
-
|
|
926
|
+
difference(...args) {
|
|
927
|
+
if (args.length === 0) return [];
|
|
928
|
+
return this.union(...args).filter((d) => !this.intersection(...args).includes(d));
|
|
616
929
|
}
|
|
617
|
-
}
|
|
618
|
-
|
|
930
|
+
};
|
|
931
|
+
const _MqttClient = class _MqttClient extends EventDispatcher {
|
|
932
|
+
constructor(url = `ws://${window.document.domain}:20007/mqtt`, config = {}) {
|
|
619
933
|
super();
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
this
|
|
934
|
+
__publicField(this, "state");
|
|
935
|
+
__publicField(this, "url");
|
|
936
|
+
__publicField(this, "context");
|
|
937
|
+
__publicField(this, "options");
|
|
938
|
+
__publicField(this, "client");
|
|
939
|
+
__publicField(this, "topics");
|
|
940
|
+
this.context = CommUtils.extend(_MqttClient.defaultContext, config);
|
|
941
|
+
this.options = {
|
|
626
942
|
connectTimeout: this.context.MQTT_TIMEOUTM,
|
|
627
|
-
clientId:
|
|
943
|
+
clientId: CommUtils.guid(),
|
|
628
944
|
username: this.context.MQTT_USERNAME,
|
|
629
945
|
password: this.context.MQTT_PASSWORD,
|
|
630
|
-
clean:
|
|
631
|
-
}
|
|
946
|
+
clean: true
|
|
947
|
+
};
|
|
948
|
+
this.url = url;
|
|
949
|
+
this.client = connect(this.url, this.options);
|
|
950
|
+
this._onConnect();
|
|
951
|
+
this._onMessage();
|
|
952
|
+
this.state = 0;
|
|
953
|
+
this.topics = [];
|
|
632
954
|
}
|
|
633
955
|
_onConnect() {
|
|
634
956
|
this.client.on("connect", () => {
|
|
635
|
-
this.state = 1
|
|
636
|
-
|
|
637
|
-
|
|
957
|
+
this.state = 1;
|
|
958
|
+
console.log("链接mqtt成功==>" + this.url);
|
|
959
|
+
this.dispatchEvent({ type: EventType.MQTT_CONNECT, message: this });
|
|
960
|
+
});
|
|
961
|
+
this.client.on("error", (err) => {
|
|
962
|
+
console.log("链接mqtt报错", err);
|
|
963
|
+
this.state = -1;
|
|
964
|
+
this.dispatchEvent({ type: EventType.MQTT_ERROR, message: this });
|
|
965
|
+
this.client.end();
|
|
966
|
+
this.client.reconnect();
|
|
638
967
|
});
|
|
639
968
|
}
|
|
640
969
|
_onMessage() {
|
|
641
|
-
this.client.on("message", (
|
|
642
|
-
let
|
|
643
|
-
|
|
970
|
+
this.client.on("message", (topic, message) => {
|
|
971
|
+
let dataString = message;
|
|
972
|
+
let data = "";
|
|
973
|
+
if (message instanceof Uint8Array) {
|
|
974
|
+
dataString = message.toString();
|
|
975
|
+
}
|
|
644
976
|
try {
|
|
645
|
-
|
|
646
|
-
} catch {
|
|
647
|
-
throw new Error(
|
|
977
|
+
data = ObjectUtil.parse(dataString);
|
|
978
|
+
} catch (error) {
|
|
979
|
+
throw new Error(ErrorType.JSON_PARSE_ERROR);
|
|
648
980
|
}
|
|
649
981
|
this.dispatchEvent({
|
|
650
|
-
type:
|
|
651
|
-
message: { topic
|
|
982
|
+
type: EventType.MQTT_MESSAGE,
|
|
983
|
+
message: { topic, data }
|
|
652
984
|
});
|
|
653
985
|
});
|
|
654
986
|
}
|
|
655
|
-
sendMsg(
|
|
987
|
+
sendMsg(topic, msg) {
|
|
656
988
|
if (!this.client.connected) {
|
|
657
989
|
console.error("客户端未连接");
|
|
658
990
|
return;
|
|
659
991
|
}
|
|
660
|
-
this.client.publish(
|
|
992
|
+
this.client.publish(topic, msg, { qos: 1, retain: true });
|
|
661
993
|
}
|
|
662
|
-
subscribe(
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
}) : this.addEventListener(
|
|
666
|
-
this.client.subscribe(
|
|
667
|
-
|
|
994
|
+
subscribe(topic) {
|
|
995
|
+
this.state === 1 ? this.client.subscribe(topic, { qos: 1 }, (error, e) => {
|
|
996
|
+
error instanceof Error ? console.error("订阅失败==>" + topic, error) : (this.topics = ArrayUtil.union(this.topics, topic), console.log("订阅成功==>" + topic));
|
|
997
|
+
}) : this.addEventListener(EventType.MQTT_CONNECT, (res) => {
|
|
998
|
+
this.client.subscribe(topic, { qos: 1 }, (error, e) => {
|
|
999
|
+
error instanceof Error ? console.error("订阅失败==>" + topic, error) : (this.topics = ArrayUtil.union(this.topics, topic), console.log("订阅成功==>" + topic));
|
|
668
1000
|
});
|
|
669
|
-
})
|
|
1001
|
+
});
|
|
1002
|
+
return this;
|
|
670
1003
|
}
|
|
671
|
-
unsubscribe(
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
1004
|
+
unsubscribe(topic) {
|
|
1005
|
+
this.client.unsubscribe(topic, { qos: 1 }, (error, res) => {
|
|
1006
|
+
if (error instanceof Error) {
|
|
1007
|
+
console.error(`取消订阅失败==>${topic}`, error);
|
|
1008
|
+
} else {
|
|
1009
|
+
this.topics = ArrayUtil.difference(this.topics, topic);
|
|
1010
|
+
console.log(`取消订阅成功==>${topic}`);
|
|
1011
|
+
}
|
|
1012
|
+
});
|
|
1013
|
+
return this;
|
|
675
1014
|
}
|
|
676
1015
|
unsubscribeAll() {
|
|
677
1016
|
this.unsubscribe(this.topics);
|
|
678
1017
|
}
|
|
679
1018
|
unconnect() {
|
|
680
|
-
this.client.end()
|
|
1019
|
+
this.client.end();
|
|
1020
|
+
this.client = null;
|
|
1021
|
+
this.dispatchEvent({ type: EventType.MQTT_CLOSE, message: null });
|
|
1022
|
+
console.log("断开mqtt成功==>" + this.url);
|
|
681
1023
|
}
|
|
682
1024
|
};
|
|
683
1025
|
/**
|
|
684
1026
|
* Creates an instance of MqttClient.
|
|
685
1027
|
* @param {*} config mqtt实例参数
|
|
686
1028
|
*/
|
|
687
|
-
|
|
1029
|
+
__publicField(_MqttClient, "defaultContext", {
|
|
688
1030
|
MQTT_USERNAME: "iRVMS-WEB",
|
|
689
1031
|
MQTT_PASSWORD: "novasky888",
|
|
690
|
-
MQTT_SERVICE: `ws://${window.document.domain}:20007/mqtt`,
|
|
691
1032
|
MQTT_TIMEOUTM: 2e4
|
|
692
1033
|
});
|
|
693
|
-
let
|
|
694
|
-
const
|
|
1034
|
+
let MqttClient = _MqttClient;
|
|
1035
|
+
const _Storage = class _Storage {
|
|
1036
|
+
/**
|
|
1037
|
+
* 将键值对存储到localStorage中
|
|
1038
|
+
*
|
|
1039
|
+
* @param key 键名
|
|
1040
|
+
* @param value 值,默认为null
|
|
1041
|
+
* @param options 存储选项,可选参数
|
|
1042
|
+
* @param options.expires 过期时间,单位为毫秒,默认为null
|
|
1043
|
+
*/
|
|
1044
|
+
static set(key, value = null, options = {}) {
|
|
1045
|
+
var query_key = this._getPrefixedKey(key, options);
|
|
1046
|
+
try {
|
|
1047
|
+
const { expires } = options;
|
|
1048
|
+
const data = { data: value };
|
|
1049
|
+
if (expires) {
|
|
1050
|
+
data.expires = expires;
|
|
1051
|
+
}
|
|
1052
|
+
localStorage.setItem(query_key, JSON.stringify(data));
|
|
1053
|
+
} catch (e) {
|
|
1054
|
+
if (console) console.warn(`Storage didn't successfully save the '{"${key}": "${value}"}' pair, because the localStorage is full.`);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* 从localStorage中获取指定key的存储值
|
|
1059
|
+
*
|
|
1060
|
+
* @param key 存储键名
|
|
1061
|
+
* @param missing 当获取不到指定key的存储值时返回的默认值
|
|
1062
|
+
* @param options 其他配置选项
|
|
1063
|
+
* @returns 返回指定key的存储值,若获取不到则返回missing参数指定的默认值
|
|
1064
|
+
*/
|
|
1065
|
+
static get(key, missing, options) {
|
|
1066
|
+
var query_key = this._getPrefixedKey(key, options), value;
|
|
1067
|
+
try {
|
|
1068
|
+
value = JSON.parse(localStorage.getItem(query_key) || "");
|
|
1069
|
+
} catch (e) {
|
|
1070
|
+
if (localStorage[query_key]) {
|
|
1071
|
+
value = { data: localStorage.getItem(query_key) };
|
|
1072
|
+
} else {
|
|
1073
|
+
value = null;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
if (!value) {
|
|
1077
|
+
return missing;
|
|
1078
|
+
} else if (typeof value === "object" && typeof value.data !== "undefined") {
|
|
1079
|
+
const expires = value.expires;
|
|
1080
|
+
if (expires && Date.now() > expires) {
|
|
1081
|
+
return missing;
|
|
1082
|
+
}
|
|
1083
|
+
return value.data;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
static keys() {
|
|
1087
|
+
const keys = [];
|
|
1088
|
+
var allKeys = Object.keys(localStorage);
|
|
1089
|
+
if (_Storage.prefix.length === 0) {
|
|
1090
|
+
return allKeys;
|
|
1091
|
+
}
|
|
1092
|
+
allKeys.forEach(function(key) {
|
|
1093
|
+
if (key.indexOf(_Storage.prefix) !== -1) {
|
|
1094
|
+
keys.push(key.replace(_Storage.prefix, ""));
|
|
1095
|
+
}
|
|
1096
|
+
});
|
|
1097
|
+
return keys;
|
|
1098
|
+
}
|
|
1099
|
+
static getAll(includeKeys) {
|
|
1100
|
+
var keys = _Storage.keys();
|
|
1101
|
+
if (includeKeys) {
|
|
1102
|
+
const result = [];
|
|
1103
|
+
keys.forEach((key) => {
|
|
1104
|
+
if (includeKeys.includes(key)) {
|
|
1105
|
+
const tempObj = {};
|
|
1106
|
+
tempObj[key] = _Storage.get(key, null, null);
|
|
1107
|
+
result.push(tempObj);
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
return result;
|
|
1111
|
+
}
|
|
1112
|
+
return keys.map((key) => _Storage.get(key, null, null));
|
|
1113
|
+
}
|
|
1114
|
+
static remove(key, options) {
|
|
1115
|
+
var queryKey = this._getPrefixedKey(key, options);
|
|
1116
|
+
localStorage.removeItem(queryKey);
|
|
1117
|
+
}
|
|
1118
|
+
static clear(options) {
|
|
1119
|
+
if (_Storage.prefix.length) {
|
|
1120
|
+
this.keys().forEach((key) => {
|
|
1121
|
+
localStorage.removeItem(this._getPrefixedKey(key, options));
|
|
1122
|
+
});
|
|
1123
|
+
} else {
|
|
1124
|
+
localStorage.clear();
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
};
|
|
1128
|
+
__publicField(_Storage, "prefix", "");
|
|
1129
|
+
__publicField(_Storage, "_getPrefixedKey", function(key, options) {
|
|
1130
|
+
options = options || {};
|
|
1131
|
+
if (options.noPrefix) {
|
|
1132
|
+
return key;
|
|
1133
|
+
} else {
|
|
1134
|
+
return _Storage.prefix + key;
|
|
1135
|
+
}
|
|
1136
|
+
});
|
|
1137
|
+
let Storage = _Storage;
|
|
1138
|
+
const ImageUtil = {
|
|
695
1139
|
emptyImageUrl: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
|
|
696
1140
|
/**
|
|
697
1141
|
*
|
|
698
1142
|
* @param image image,类型可以是HTMLCanvasElement、ImageData
|
|
699
1143
|
* @returns
|
|
700
1144
|
*/
|
|
701
|
-
getURL(
|
|
702
|
-
let
|
|
703
|
-
if (/^data:/i.test(
|
|
704
|
-
return
|
|
705
|
-
|
|
706
|
-
if (
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
1145
|
+
getURL(image) {
|
|
1146
|
+
let _canvas;
|
|
1147
|
+
if (/^data:/i.test(image.src)) {
|
|
1148
|
+
return image.src;
|
|
1149
|
+
}
|
|
1150
|
+
if (typeof HTMLCanvasElement === "undefined") {
|
|
1151
|
+
return image.src;
|
|
1152
|
+
}
|
|
1153
|
+
let canvas;
|
|
1154
|
+
if (image instanceof HTMLCanvasElement) {
|
|
1155
|
+
canvas = image;
|
|
1156
|
+
} else {
|
|
1157
|
+
if (_canvas === void 0) _canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
|
1158
|
+
_canvas.width = image.width;
|
|
1159
|
+
_canvas.height = image.height;
|
|
1160
|
+
const context = _canvas.getContext("2d");
|
|
1161
|
+
if (context) {
|
|
1162
|
+
if (image instanceof ImageData) {
|
|
1163
|
+
context.putImageData(image, 0, 0);
|
|
1164
|
+
} else {
|
|
1165
|
+
context.drawImage(image, 0, 0, image.width, image.height);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
canvas = _canvas;
|
|
1169
|
+
}
|
|
1170
|
+
if (canvas.width > 2048 || canvas.height > 2048) {
|
|
1171
|
+
console.warn("ImageUtil.getDataURL: Image converted to jpg for performance reasons", image);
|
|
1172
|
+
return canvas.toDataURL("image/jpeg", 0.6);
|
|
1173
|
+
} else {
|
|
1174
|
+
return canvas.toDataURL("image/png");
|
|
712
1175
|
}
|
|
713
|
-
return n.width > 2048 || n.height > 2048 ? (console.warn("ImageUtil.getDataURL: Image converted to jpg for performance reasons", t), n.toDataURL("image/jpeg", 0.6)) : n.toDataURL("image/png");
|
|
714
1176
|
},
|
|
715
1177
|
/**
|
|
716
1178
|
* 将图片的URL转换为Base64编码
|
|
@@ -720,13 +1182,16 @@ const $ = {
|
|
|
720
1182
|
* @param height 图片的高度,默认为图片原始高度
|
|
721
1183
|
* @returns 返回Promise对象,解析后得到包含Base64编码数据的对象
|
|
722
1184
|
*/
|
|
723
|
-
getBase64(
|
|
724
|
-
return new Promise((
|
|
725
|
-
let
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
1185
|
+
getBase64(url) {
|
|
1186
|
+
return new Promise((resolve, reject) => {
|
|
1187
|
+
let image = new Image();
|
|
1188
|
+
image.setAttribute("crossOrigin", "Anonymous");
|
|
1189
|
+
image.src = url;
|
|
1190
|
+
image.onload = () => {
|
|
1191
|
+
let dataURL = this.getURL(image);
|
|
1192
|
+
resolve(dataURL);
|
|
1193
|
+
};
|
|
1194
|
+
image.onerror = reject;
|
|
730
1195
|
});
|
|
731
1196
|
},
|
|
732
1197
|
/**
|
|
@@ -735,13 +1200,17 @@ const $ = {
|
|
|
735
1200
|
* @param base64 base64编码字符串
|
|
736
1201
|
* @returns 返回一个对象,包含type(类型)、ext(扩展名)和data(数据)字段,如果解析失败则返回null
|
|
737
1202
|
*/
|
|
738
|
-
parseBase64(
|
|
739
|
-
let
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1203
|
+
parseBase64(base64) {
|
|
1204
|
+
let re = new RegExp("data:(?<type>.*?);base64,(?<data>.*)");
|
|
1205
|
+
let res = re.exec(base64);
|
|
1206
|
+
if (res && res.groups) {
|
|
1207
|
+
return {
|
|
1208
|
+
type: res.groups.type,
|
|
1209
|
+
ext: res.groups.type.split("/").slice(-1)[0],
|
|
1210
|
+
data: res.groups.data
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
return null;
|
|
745
1214
|
},
|
|
746
1215
|
/**
|
|
747
1216
|
* 复制图片到剪贴板
|
|
@@ -750,33 +1219,51 @@ const $ = {
|
|
|
750
1219
|
* @returns 无返回值
|
|
751
1220
|
* @throws 如果解析base64数据失败,则抛出异常
|
|
752
1221
|
*/
|
|
753
|
-
async copyImage(
|
|
1222
|
+
async copyImage(url) {
|
|
754
1223
|
try {
|
|
755
|
-
const
|
|
756
|
-
|
|
1224
|
+
const base64Result = await this.getBase64(url);
|
|
1225
|
+
const parsedBase64 = this.parseBase64(base64Result.dataURL);
|
|
1226
|
+
if (!parsedBase64) {
|
|
757
1227
|
throw new Error("Failed to parse base64 data.");
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
let
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
1228
|
+
}
|
|
1229
|
+
let type = parsedBase64.type;
|
|
1230
|
+
let bytes = atob(parsedBase64.data);
|
|
1231
|
+
let ab = new ArrayBuffer(bytes.length);
|
|
1232
|
+
let ua = new Uint8Array(ab);
|
|
1233
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
1234
|
+
ua[i] = bytes.charCodeAt(i);
|
|
1235
|
+
}
|
|
1236
|
+
let blob = new Blob([ab], { type });
|
|
1237
|
+
await navigator.clipboard.write([new ClipboardItem({ [type]: blob })]);
|
|
1238
|
+
} catch (error) {
|
|
1239
|
+
console.error("Failed to copy image to clipboard:", error);
|
|
765
1240
|
}
|
|
766
1241
|
}
|
|
767
|
-
}
|
|
1242
|
+
};
|
|
1243
|
+
const AjaxUtil = {
|
|
768
1244
|
/**
|
|
769
1245
|
* Get JSON data by jsonp
|
|
770
1246
|
* @param url - resource url
|
|
771
1247
|
* @param callback - callback function when completed
|
|
772
1248
|
*/
|
|
773
|
-
jsonp(
|
|
774
|
-
const
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
1249
|
+
jsonp(url, callback) {
|
|
1250
|
+
const name = "_jsonp_" + CommUtils.guid();
|
|
1251
|
+
const head = document.getElementsByTagName("head")[0];
|
|
1252
|
+
if (url.includes("?")) {
|
|
1253
|
+
url += "&callback=" + name;
|
|
1254
|
+
} else {
|
|
1255
|
+
url += "?callback=" + name;
|
|
1256
|
+
}
|
|
1257
|
+
let script = document.createElement("script");
|
|
1258
|
+
script.type = "text/javascript";
|
|
1259
|
+
script.src = url;
|
|
1260
|
+
window[name] = function(data) {
|
|
1261
|
+
callback(null, data);
|
|
1262
|
+
head.removeChild(script);
|
|
1263
|
+
script = null;
|
|
1264
|
+
delete window[name];
|
|
1265
|
+
};
|
|
1266
|
+
head.appendChild(script);
|
|
780
1267
|
},
|
|
781
1268
|
/**
|
|
782
1269
|
* Fetch remote resource by HTTP "GET" method
|
|
@@ -798,18 +1285,25 @@ const $ = {
|
|
|
798
1285
|
* }
|
|
799
1286
|
* );
|
|
800
1287
|
*/
|
|
801
|
-
get(
|
|
802
|
-
if (
|
|
803
|
-
const
|
|
804
|
-
|
|
1288
|
+
get(url, options, cb) {
|
|
1289
|
+
if (CommUtils.isFunction(options)) {
|
|
1290
|
+
const t = cb;
|
|
1291
|
+
cb = options;
|
|
1292
|
+
options = t;
|
|
805
1293
|
}
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
1294
|
+
const client = this._getClient(cb);
|
|
1295
|
+
client.open("GET", url, true);
|
|
1296
|
+
if (options) {
|
|
1297
|
+
for (const k in options.headers) {
|
|
1298
|
+
client.setRequestHeader(k, options.headers[k]);
|
|
1299
|
+
}
|
|
1300
|
+
client.withCredentials = options.credentials === "include";
|
|
1301
|
+
if (options["responseType"]) {
|
|
1302
|
+
client.responseType = options["responseType"];
|
|
1303
|
+
}
|
|
811
1304
|
}
|
|
812
|
-
|
|
1305
|
+
client.send(null);
|
|
1306
|
+
return client;
|
|
813
1307
|
},
|
|
814
1308
|
/**
|
|
815
1309
|
* Fetch remote resource by HTTP "POST" method
|
|
@@ -836,38 +1330,81 @@ const $ = {
|
|
|
836
1330
|
* }
|
|
837
1331
|
* );
|
|
838
1332
|
*/
|
|
839
|
-
post(
|
|
840
|
-
let
|
|
841
|
-
if (typeof
|
|
1333
|
+
post(url, options = {}, cb) {
|
|
1334
|
+
let postData;
|
|
1335
|
+
if (typeof url !== "string") {
|
|
1336
|
+
cb = options.cb;
|
|
1337
|
+
postData = options.postData;
|
|
1338
|
+
options = { ...options };
|
|
1339
|
+
delete options.cb;
|
|
1340
|
+
delete options.postData;
|
|
1341
|
+
url = options.url;
|
|
1342
|
+
} else {
|
|
1343
|
+
if (typeof options === "function") {
|
|
1344
|
+
cb = options;
|
|
1345
|
+
options = {};
|
|
1346
|
+
}
|
|
1347
|
+
postData = options.postData;
|
|
1348
|
+
}
|
|
1349
|
+
if (!cb) {
|
|
842
1350
|
throw new Error("Callback function is required");
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
1351
|
+
}
|
|
1352
|
+
const client = this._getClient(cb);
|
|
1353
|
+
client.open("POST", url, true);
|
|
1354
|
+
options.headers = options.headers || {};
|
|
1355
|
+
if (!options.headers["Content-Type"]) {
|
|
1356
|
+
options.headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
1357
|
+
}
|
|
1358
|
+
Object.keys(options.headers).forEach((key) => {
|
|
1359
|
+
client.setRequestHeader(key, options.headers[key]);
|
|
1360
|
+
});
|
|
1361
|
+
if (typeof postData !== "string") {
|
|
1362
|
+
postData = JSON.stringify(postData);
|
|
1363
|
+
}
|
|
1364
|
+
client.send(postData);
|
|
1365
|
+
return client;
|
|
847
1366
|
},
|
|
848
|
-
_wrapCallback(
|
|
1367
|
+
_wrapCallback(client, cb) {
|
|
849
1368
|
return function() {
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
1369
|
+
if (client.readyState === 4) {
|
|
1370
|
+
if (client.status === 200) {
|
|
1371
|
+
if (client.responseType === "arraybuffer") {
|
|
1372
|
+
const response = client.response;
|
|
1373
|
+
if (response.byteLength === 0) {
|
|
1374
|
+
cb(new Error("http status 200 returned without content."));
|
|
1375
|
+
} else {
|
|
1376
|
+
cb(null, {
|
|
1377
|
+
data: client.response,
|
|
1378
|
+
cacheControl: client.getResponseHeader("Cache-Control"),
|
|
1379
|
+
expires: client.getResponseHeader("Expires"),
|
|
1380
|
+
contentType: client.getResponseHeader("Content-Type")
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
} else {
|
|
1384
|
+
cb(null, client.responseText);
|
|
1385
|
+
}
|
|
1386
|
+
} else {
|
|
1387
|
+
cb(new Error(client.statusText + "," + client.status));
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
856
1390
|
};
|
|
857
1391
|
},
|
|
858
|
-
_getClient(
|
|
859
|
-
let
|
|
1392
|
+
_getClient(cb) {
|
|
1393
|
+
let client = null;
|
|
860
1394
|
try {
|
|
861
|
-
|
|
862
|
-
} catch {
|
|
1395
|
+
client = new XMLHttpRequest();
|
|
1396
|
+
} catch (e) {
|
|
863
1397
|
throw new Error("XMLHttpRequest not supported.");
|
|
864
1398
|
}
|
|
865
|
-
|
|
1399
|
+
if (client) {
|
|
1400
|
+
client.onreadystatechange = this._wrapCallback(client, cb);
|
|
1401
|
+
}
|
|
1402
|
+
return client;
|
|
866
1403
|
},
|
|
867
1404
|
/**
|
|
868
1405
|
* Fetch resource as arraybuffer.
|
|
869
1406
|
* @param {String} url - url
|
|
870
|
-
* @param {Object} [options=null] - options, same as
|
|
1407
|
+
* @param {Object} [options=null] - options, same as AjaxUtil.get
|
|
871
1408
|
* @param {Function} cb - callback function when completed.
|
|
872
1409
|
* @example
|
|
873
1410
|
* AjaxUtil.getArrayBuffer(
|
|
@@ -880,24 +1417,37 @@ const $ = {
|
|
|
880
1417
|
* }
|
|
881
1418
|
* );
|
|
882
1419
|
*/
|
|
883
|
-
getArrayBuffer(
|
|
884
|
-
if (
|
|
885
|
-
const
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
1420
|
+
getArrayBuffer(url, options, cb) {
|
|
1421
|
+
if (CommUtils.isFunction(options)) {
|
|
1422
|
+
const t = cb;
|
|
1423
|
+
cb = options;
|
|
1424
|
+
options = t;
|
|
1425
|
+
}
|
|
1426
|
+
if (!options) {
|
|
1427
|
+
options = {};
|
|
1428
|
+
}
|
|
1429
|
+
options["responseType"] = "arraybuffer";
|
|
1430
|
+
return this.get(url, options, cb);
|
|
1431
|
+
},
|
|
1432
|
+
getImage(img, url, options) {
|
|
1433
|
+
return this.getArrayBuffer(url, options, (err, imgData) => {
|
|
1434
|
+
if (err) {
|
|
1435
|
+
if (img.onerror) {
|
|
1436
|
+
img.onerror(err);
|
|
1437
|
+
}
|
|
1438
|
+
} else if (imgData) {
|
|
1439
|
+
const URL2 = window.URL || window.webkitURL;
|
|
1440
|
+
const onload = img.onload;
|
|
1441
|
+
img.onload = () => {
|
|
1442
|
+
if (onload) {
|
|
1443
|
+
onload();
|
|
1444
|
+
}
|
|
1445
|
+
URL2.revokeObjectURL(img.src);
|
|
898
1446
|
};
|
|
899
|
-
const
|
|
900
|
-
|
|
1447
|
+
const blob = new Blob([new Uint8Array(imgData.data)], { type: imgData.contentType });
|
|
1448
|
+
img.cacheControl = imgData.cacheControl;
|
|
1449
|
+
img.expires = imgData.expires;
|
|
1450
|
+
img.src = imgData.data.byteLength ? URL2.createObjectURL(blob) : ImageUtil.emptyImageUrl;
|
|
901
1451
|
}
|
|
902
1452
|
});
|
|
903
1453
|
},
|
|
@@ -920,26 +1470,44 @@ const $ = {
|
|
|
920
1470
|
* }
|
|
921
1471
|
* );
|
|
922
1472
|
*/
|
|
923
|
-
getJSON(
|
|
924
|
-
if (
|
|
925
|
-
const
|
|
926
|
-
|
|
1473
|
+
getJSON(url, options, cb) {
|
|
1474
|
+
if (CommUtils.isFunction(options)) {
|
|
1475
|
+
const t = cb;
|
|
1476
|
+
cb = options;
|
|
1477
|
+
options = t;
|
|
927
1478
|
}
|
|
928
|
-
const
|
|
929
|
-
const
|
|
930
|
-
|
|
1479
|
+
const callback = function(err, resp) {
|
|
1480
|
+
const data = resp ? ObjectUtil.parse(resp) : null;
|
|
1481
|
+
if (cb) {
|
|
1482
|
+
cb(err, data);
|
|
1483
|
+
}
|
|
931
1484
|
};
|
|
932
|
-
|
|
1485
|
+
if (options && options["jsonp"]) {
|
|
1486
|
+
return this.jsonp(url, callback);
|
|
1487
|
+
}
|
|
1488
|
+
return this.get(url, options, callback);
|
|
933
1489
|
}
|
|
934
|
-
}
|
|
1490
|
+
};
|
|
1491
|
+
const BrowserUtil = {
|
|
935
1492
|
/**
|
|
936
1493
|
* 获取浏览器类型
|
|
937
1494
|
*
|
|
938
1495
|
* @returns 返回浏览器类型字符串,可能的值为 'IE'、'Firefox'、'Chrome'、'Opera'、'Safari' 或 'Unknown'
|
|
939
1496
|
*/
|
|
940
1497
|
getExplorer() {
|
|
941
|
-
var
|
|
942
|
-
|
|
1498
|
+
var explorer = window.navigator.userAgent;
|
|
1499
|
+
if (explorer.indexOf("MSIE") >= 0 || /Trident\//.test(explorer)) {
|
|
1500
|
+
return "IE";
|
|
1501
|
+
} else if (explorer.indexOf("Firefox") >= 0) {
|
|
1502
|
+
return "Firefox";
|
|
1503
|
+
} else if (explorer.indexOf("Chrome") >= 0) {
|
|
1504
|
+
return "Chrome";
|
|
1505
|
+
} else if (explorer.indexOf("Opera") >= 0) {
|
|
1506
|
+
return "Opera";
|
|
1507
|
+
} else if (explorer.indexOf("Safari") >= 0 && explorer.indexOf("Chrome") === -1) {
|
|
1508
|
+
return "Safari";
|
|
1509
|
+
}
|
|
1510
|
+
return "Unknown";
|
|
943
1511
|
},
|
|
944
1512
|
/**
|
|
945
1513
|
* 检测操作系统类型
|
|
@@ -947,21 +1515,45 @@ const $ = {
|
|
|
947
1515
|
* @returns 返回操作系统类型字符串,可能的值有:'MS Windows'、'Apple mac'、'Linux'、'Unix'
|
|
948
1516
|
*/
|
|
949
1517
|
detectOS() {
|
|
950
|
-
let
|
|
951
|
-
const
|
|
952
|
-
|
|
1518
|
+
let os_type = "";
|
|
1519
|
+
const windows = navigator.userAgent.indexOf("Windows", 0) != -1 ? 1 : 0;
|
|
1520
|
+
const mac = navigator.userAgent.indexOf("mac", 0) != -1 ? 1 : 0;
|
|
1521
|
+
const linux = navigator.userAgent.indexOf("Linux", 0) != -1 ? 1 : 0;
|
|
1522
|
+
const unix = navigator.userAgent.indexOf("X11", 0) != -1 ? 1 : 0;
|
|
1523
|
+
if (windows) os_type = "MS Windows";
|
|
1524
|
+
else if (mac) os_type = "Apple mac";
|
|
1525
|
+
else if (linux) os_type = "Linux";
|
|
1526
|
+
else if (unix) os_type = "Unix";
|
|
1527
|
+
return os_type;
|
|
953
1528
|
},
|
|
954
1529
|
/**
|
|
955
1530
|
* 切换全屏状态
|
|
956
1531
|
*
|
|
957
1532
|
* @param status 是否全屏
|
|
958
1533
|
*/
|
|
959
|
-
switchFullScreen(
|
|
960
|
-
if (
|
|
961
|
-
const
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1534
|
+
switchFullScreen(status) {
|
|
1535
|
+
if (status) {
|
|
1536
|
+
const element = document.documentElement;
|
|
1537
|
+
if (element.requestFullscreen) {
|
|
1538
|
+
element.requestFullscreen();
|
|
1539
|
+
} else if ("msRequestFullscreen" in element) {
|
|
1540
|
+
element.msRequestFullscreen();
|
|
1541
|
+
} else if ("mozRequestFullScreen" in element) {
|
|
1542
|
+
element.mozRequestFullScreen();
|
|
1543
|
+
} else if ("webkitRequestFullscreen" in element) {
|
|
1544
|
+
element.webkitRequestFullscreen();
|
|
1545
|
+
}
|
|
1546
|
+
} else {
|
|
1547
|
+
if (document.exitFullscreen) {
|
|
1548
|
+
document.exitFullscreen();
|
|
1549
|
+
} else if ("msExitFullscreen" in document) {
|
|
1550
|
+
document.msExitFullscreen();
|
|
1551
|
+
} else if ("mozCancelFullScreen" in document) {
|
|
1552
|
+
document.mozCancelFullScreen();
|
|
1553
|
+
} else if ("webkitExitFullscreen" in document) {
|
|
1554
|
+
document.webkitExitFullscreen();
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
965
1557
|
},
|
|
966
1558
|
/**
|
|
967
1559
|
* 刷新缩放比例
|
|
@@ -969,11 +1561,20 @@ const $ = {
|
|
|
969
1561
|
* @returns 无返回值
|
|
970
1562
|
*/
|
|
971
1563
|
refreshScale() {
|
|
972
|
-
const
|
|
973
|
-
|
|
974
|
-
const
|
|
975
|
-
|
|
976
|
-
|
|
1564
|
+
const baseWidth = document.documentElement.clientWidth || 0;
|
|
1565
|
+
const baseHeight = document.documentElement.clientHeight || 0;
|
|
1566
|
+
const appElement = document.getElementById("app");
|
|
1567
|
+
if (!appElement) return;
|
|
1568
|
+
const appStyle = appElement.style;
|
|
1569
|
+
const realRatio = baseWidth / baseHeight;
|
|
1570
|
+
const designRatio = 16 / 9;
|
|
1571
|
+
let scaleRate = baseWidth / 1920;
|
|
1572
|
+
if (realRatio > designRatio) {
|
|
1573
|
+
scaleRate = baseHeight / 1080;
|
|
1574
|
+
}
|
|
1575
|
+
appStyle.transformOrigin = "left top";
|
|
1576
|
+
appStyle.transform = `scale(${scaleRate}) translateX(-49.99%)`;
|
|
1577
|
+
appStyle.width = `${baseWidth / scaleRate}px`;
|
|
977
1578
|
},
|
|
978
1579
|
/**
|
|
979
1580
|
* 获取HTML字体大小
|
|
@@ -981,35 +1582,28 @@ const $ = {
|
|
|
981
1582
|
* @returns 无返回值,该函数会直接修改HTML元素的字体大小
|
|
982
1583
|
*/
|
|
983
1584
|
getHtmlFontSize() {
|
|
984
|
-
const
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
var r = /* @__PURE__ */ new Date();
|
|
990
|
-
r.setTime(r.getTime() + n * 24 * 60 * 60 * 1e3), document.cookie = t + "=" + escape(e) + ";expires=" + r.toUTCString();
|
|
991
|
-
},
|
|
992
|
-
remove: function(t) {
|
|
993
|
-
var e = /* @__PURE__ */ new Date();
|
|
994
|
-
e.setTime(e.getTime() - 1);
|
|
995
|
-
var n = this.get(t);
|
|
996
|
-
n != null && (document.cookie = t + "=" + n + ";expires=" + e.toUTCString());
|
|
997
|
-
},
|
|
998
|
-
get: function(t) {
|
|
999
|
-
var e = document.cookie.match(new RegExp("(^| )" + t + "=([^;]*)(;|$)"));
|
|
1000
|
-
return e != null ? e[2] : "";
|
|
1585
|
+
const htmlwidth = document.documentElement.clientWidth || document.body.clientWidth;
|
|
1586
|
+
const htmlDom = document.querySelector("html");
|
|
1587
|
+
if (htmlDom) {
|
|
1588
|
+
htmlDom.style.fontSize = htmlwidth / 192 + "px";
|
|
1589
|
+
}
|
|
1001
1590
|
}
|
|
1002
|
-
}
|
|
1591
|
+
};
|
|
1592
|
+
const CoordsUtil = {
|
|
1003
1593
|
PI: 3.141592653589793,
|
|
1004
1594
|
XPI: 3.141592653589793 * 3e3 / 180,
|
|
1005
|
-
delta(
|
|
1006
|
-
const
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
let
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1595
|
+
delta(lat, lng) {
|
|
1596
|
+
const a = 6378245;
|
|
1597
|
+
const ee = 0.006693421622965943;
|
|
1598
|
+
let dLat = this.transformLat(lng - 105, lat - 35);
|
|
1599
|
+
let dLon = this.transformLon(lng - 105, lat - 35);
|
|
1600
|
+
const radLat = lat / 180 * this.PI;
|
|
1601
|
+
let magic = Math.sin(radLat);
|
|
1602
|
+
magic = 1 - ee * magic * magic;
|
|
1603
|
+
const sqrtMagic = Math.sqrt(magic);
|
|
1604
|
+
dLat = dLat * 180 / (a * (1 - ee) / (magic * sqrtMagic) * this.PI);
|
|
1605
|
+
dLon = dLon * 180 / (a / sqrtMagic * Math.cos(radLat) * this.PI);
|
|
1606
|
+
return { lat: dLat, lng: dLon };
|
|
1013
1607
|
},
|
|
1014
1608
|
/**
|
|
1015
1609
|
* 判断经纬度是否不在中国境内
|
|
@@ -1018,64 +1612,110 @@ const $ = {
|
|
|
1018
1612
|
* @param lat 纬度
|
|
1019
1613
|
* @returns 如果经纬度不在中国境内则返回true,否则返回false
|
|
1020
1614
|
*/
|
|
1021
|
-
outOfChina(
|
|
1022
|
-
|
|
1615
|
+
outOfChina(lng, lat) {
|
|
1616
|
+
if (lng < 72.004 || lng > 137.8347) {
|
|
1617
|
+
return true;
|
|
1618
|
+
}
|
|
1619
|
+
if (lat < 0.8293 || lat > 55.8271) {
|
|
1620
|
+
return true;
|
|
1621
|
+
}
|
|
1622
|
+
return false;
|
|
1023
1623
|
},
|
|
1024
1624
|
// WGS-84 to GCJ-02
|
|
1025
|
-
gcjEncrypt(
|
|
1026
|
-
if (this.outOfChina(
|
|
1027
|
-
return { lat:
|
|
1028
|
-
|
|
1029
|
-
|
|
1625
|
+
gcjEncrypt(wgsLat, wgsLon) {
|
|
1626
|
+
if (this.outOfChina(wgsLat, wgsLon)) {
|
|
1627
|
+
return { lat: wgsLat, lng: wgsLon };
|
|
1628
|
+
}
|
|
1629
|
+
const d = this.delta(wgsLat, wgsLon);
|
|
1630
|
+
return { lat: wgsLat + d.lat, lng: wgsLon + d.lng };
|
|
1030
1631
|
},
|
|
1031
1632
|
// GCJ-02 to WGS-84
|
|
1032
|
-
gcjDecrypt(
|
|
1033
|
-
if (this.outOfChina(
|
|
1034
|
-
return { lat:
|
|
1035
|
-
|
|
1036
|
-
|
|
1633
|
+
gcjDecrypt(gcjLat, gcjLon) {
|
|
1634
|
+
if (this.outOfChina(gcjLat, gcjLon)) {
|
|
1635
|
+
return { lat: gcjLat, lng: gcjLon };
|
|
1636
|
+
}
|
|
1637
|
+
const d = this.delta(gcjLat, gcjLon);
|
|
1638
|
+
return { lat: gcjLat - d.lat, lng: gcjLon - d.lng };
|
|
1037
1639
|
},
|
|
1038
1640
|
// GCJ-02 to WGS-84 exactly
|
|
1039
|
-
gcjDecryptExact(
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1641
|
+
gcjDecryptExact(gcjLat, gcjLon) {
|
|
1642
|
+
const initDelta = 0.01;
|
|
1643
|
+
const threshold = 1e-9;
|
|
1644
|
+
let dLat = initDelta;
|
|
1645
|
+
let dLon = initDelta;
|
|
1646
|
+
let mLat = gcjLat - dLat;
|
|
1647
|
+
let mLon = gcjLon - dLon;
|
|
1648
|
+
let pLat = gcjLat + dLat;
|
|
1649
|
+
let pLon = gcjLon + dLon;
|
|
1650
|
+
let wgsLat = 0;
|
|
1651
|
+
let wgsLon = 0;
|
|
1652
|
+
let i = 0;
|
|
1653
|
+
while (1) {
|
|
1654
|
+
wgsLat = (mLat + pLat) / 2;
|
|
1655
|
+
wgsLon = (mLon + pLon) / 2;
|
|
1656
|
+
const tmp = this.gcjEncrypt(wgsLat, wgsLon);
|
|
1657
|
+
dLat = tmp.lat - gcjLat;
|
|
1658
|
+
dLon = tmp.lng - gcjLon;
|
|
1659
|
+
if (Math.abs(dLat) < threshold && Math.abs(dLon) < threshold) {
|
|
1660
|
+
break;
|
|
1661
|
+
}
|
|
1662
|
+
if (dLat > 0) pLat = wgsLat;
|
|
1663
|
+
else mLat = wgsLat;
|
|
1664
|
+
if (dLon > 0) pLon = wgsLon;
|
|
1665
|
+
else mLon = wgsLon;
|
|
1666
|
+
if (++i > 1e4) break;
|
|
1045
1667
|
}
|
|
1046
|
-
return { lat:
|
|
1668
|
+
return { lat: wgsLat, lng: wgsLon };
|
|
1047
1669
|
},
|
|
1048
1670
|
// GCJ-02 to BD-09
|
|
1049
|
-
bdEncrypt(
|
|
1050
|
-
const
|
|
1051
|
-
|
|
1671
|
+
bdEncrypt(gcjLat, gcjLon) {
|
|
1672
|
+
const x = gcjLon;
|
|
1673
|
+
const y = gcjLat;
|
|
1674
|
+
const z = Math.sqrt(x * x + y * y) + 2e-5 * Math.sin(y * this.XPI);
|
|
1675
|
+
const theta = Math.atan2(y, x) + 3e-6 * Math.cos(x * this.XPI);
|
|
1676
|
+
const bdLon = z * Math.cos(theta) + 65e-4;
|
|
1677
|
+
const bdLat = z * Math.sin(theta) + 6e-3;
|
|
1678
|
+
return { lat: bdLat, lng: bdLon };
|
|
1052
1679
|
},
|
|
1053
1680
|
// BD-09 to GCJ-02
|
|
1054
|
-
bdDecrypt(
|
|
1055
|
-
const
|
|
1056
|
-
|
|
1681
|
+
bdDecrypt(bdLat, bdLon) {
|
|
1682
|
+
const x = bdLon - 65e-4;
|
|
1683
|
+
const y = bdLat - 6e-3;
|
|
1684
|
+
const z = Math.sqrt(x * x + y * y) - 2e-5 * Math.sin(y * this.XPI);
|
|
1685
|
+
const theta = Math.atan2(y, x) - 3e-6 * Math.cos(x * this.XPI);
|
|
1686
|
+
const gcjLon = z * Math.cos(theta);
|
|
1687
|
+
const gcjLat = z * Math.sin(theta);
|
|
1688
|
+
return { lat: gcjLat, lng: gcjLon };
|
|
1057
1689
|
},
|
|
1058
1690
|
// WGS-84 to Web mercator
|
|
1059
1691
|
// mercatorLat -> y mercatorLon -> x
|
|
1060
|
-
mercatorEncrypt(
|
|
1061
|
-
const
|
|
1062
|
-
let
|
|
1063
|
-
|
|
1692
|
+
mercatorEncrypt(wgsLat, wgsLon) {
|
|
1693
|
+
const x = wgsLon * 2003750834e-2 / 180;
|
|
1694
|
+
let y = Math.log(Math.tan((90 + wgsLat) * this.PI / 360)) / (this.PI / 180);
|
|
1695
|
+
y = y * 2003750834e-2 / 180;
|
|
1696
|
+
return { lat: y, lng: x };
|
|
1064
1697
|
},
|
|
1065
1698
|
// Web mercator to WGS-84
|
|
1066
1699
|
// mercatorLat -> y mercatorLon -> x
|
|
1067
|
-
mercatorDecrypt(
|
|
1068
|
-
const
|
|
1069
|
-
let
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
return
|
|
1700
|
+
mercatorDecrypt(mercatorLat, mercatorLon) {
|
|
1701
|
+
const x = mercatorLon / 2003750834e-2 * 180;
|
|
1702
|
+
let y = mercatorLat / 2003750834e-2 * 180;
|
|
1703
|
+
y = 180 / this.PI * (2 * Math.atan(Math.exp(y * this.PI / 180)) - this.PI / 2);
|
|
1704
|
+
return { lat: y, lng: x };
|
|
1705
|
+
},
|
|
1706
|
+
transformLat(x, y) {
|
|
1707
|
+
let ret = -100 + 2 * x + 3 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
|
1708
|
+
ret += (20 * Math.sin(6 * x * this.PI) + 20 * Math.sin(2 * x * this.PI)) * 2 / 3;
|
|
1709
|
+
ret += (20 * Math.sin(y * this.PI) + 40 * Math.sin(y / 3 * this.PI)) * 2 / 3;
|
|
1710
|
+
ret += (160 * Math.sin(y / 12 * this.PI) + 320 * Math.sin(y * this.PI / 30)) * 2 / 3;
|
|
1711
|
+
return ret;
|
|
1712
|
+
},
|
|
1713
|
+
transformLon(x, y) {
|
|
1714
|
+
let ret = 300 + x + 2 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
|
1715
|
+
ret += (20 * Math.sin(6 * x * this.PI) + 20 * Math.sin(2 * x * this.PI)) * 2 / 3;
|
|
1716
|
+
ret += (20 * Math.sin(x * this.PI) + 40 * Math.sin(x / 3 * this.PI)) * 2 / 3;
|
|
1717
|
+
ret += (150 * Math.sin(x / 12 * this.PI) + 300 * Math.sin(x / 30 * this.PI)) * 2 / 3;
|
|
1718
|
+
return ret;
|
|
1079
1719
|
},
|
|
1080
1720
|
/**
|
|
1081
1721
|
* 生成指定范围内的随机经纬度坐标
|
|
@@ -1084,30 +1724,43 @@ const $ = {
|
|
|
1084
1724
|
* @param max 最大坐标,包含属性 x 和 y,分别表示最大经度和最大纬度
|
|
1085
1725
|
* @returns 返回生成的随机经纬度坐标,包含属性 lat 和 lng,分别表示纬度和经度
|
|
1086
1726
|
*/
|
|
1087
|
-
random({ x:
|
|
1727
|
+
random({ x: minX, y: minY }, { x: maxX, y: maxY }) {
|
|
1088
1728
|
return {
|
|
1089
|
-
lat: Math.random() * (
|
|
1090
|
-
lng: Math.random() * (
|
|
1729
|
+
lat: Math.random() * (maxY - minY) + minY,
|
|
1730
|
+
lng: Math.random() * (maxX - minX) + minX
|
|
1091
1731
|
};
|
|
1092
1732
|
},
|
|
1093
|
-
deCompose(
|
|
1094
|
-
if (!Array.isArray(
|
|
1095
|
-
return
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1733
|
+
deCompose(arr, fn, context) {
|
|
1734
|
+
if (!Array.isArray(arr)) {
|
|
1735
|
+
return context ? fn.call(context, arr) : fn(arr);
|
|
1736
|
+
}
|
|
1737
|
+
const result = [];
|
|
1738
|
+
let p, pp;
|
|
1739
|
+
for (let i = 0, len = arr.length; i < len; i++) {
|
|
1740
|
+
p = arr[i];
|
|
1741
|
+
if (CommUtils.isNil(p)) {
|
|
1742
|
+
result.push(null);
|
|
1101
1743
|
continue;
|
|
1102
1744
|
}
|
|
1103
|
-
Array.isArray(
|
|
1745
|
+
if (Array.isArray(p)) {
|
|
1746
|
+
result.push(this.deCompose(p, fn, context));
|
|
1747
|
+
} else {
|
|
1748
|
+
pp = context ? fn.call(context, p) : fn(p);
|
|
1749
|
+
result.push(pp);
|
|
1750
|
+
}
|
|
1104
1751
|
}
|
|
1105
|
-
return
|
|
1752
|
+
return result;
|
|
1106
1753
|
}
|
|
1107
|
-
}
|
|
1754
|
+
};
|
|
1755
|
+
const ColorUtil = {
|
|
1108
1756
|
random() {
|
|
1109
|
-
let
|
|
1110
|
-
|
|
1757
|
+
let r = Math.floor(Math.random() * 256).toString(16);
|
|
1758
|
+
let g = Math.floor(Math.random() * 256).toString(16);
|
|
1759
|
+
let b = Math.floor(Math.random() * 256).toString(16);
|
|
1760
|
+
r = r.length === 1 ? "0" + r : r;
|
|
1761
|
+
g = g.length === 1 ? "0" + g : g;
|
|
1762
|
+
b = b.length === 1 ? "0" + b : b;
|
|
1763
|
+
return "#" + r + g + b;
|
|
1111
1764
|
},
|
|
1112
1765
|
/**
|
|
1113
1766
|
* 将RGB颜色值转换为十六进制颜色值
|
|
@@ -1115,9 +1768,9 @@ const $ = {
|
|
|
1115
1768
|
* @param rgb RGB颜色值数组,包含三个0-255之间的整数
|
|
1116
1769
|
* @returns 转换后的十六进制颜色值,以#开头
|
|
1117
1770
|
*/
|
|
1118
|
-
rgb2hex(
|
|
1119
|
-
var
|
|
1120
|
-
return
|
|
1771
|
+
rgb2hex(rgb) {
|
|
1772
|
+
var hex = "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1);
|
|
1773
|
+
return hex;
|
|
1121
1774
|
},
|
|
1122
1775
|
/**
|
|
1123
1776
|
* 将RGB颜色值转换为RGBA颜色值,并返回转换后的颜色值。
|
|
@@ -1125,9 +1778,9 @@ const $ = {
|
|
|
1125
1778
|
* @param rgbValue RGB颜色值,格式为"rgb(r, g, b)"。
|
|
1126
1779
|
* @returns 转换后的RGBA颜色值,格式为"rgba(r, g, b, 1)"。如果输入值不符合RGB格式,则返回原值。
|
|
1127
1780
|
*/
|
|
1128
|
-
rgbToRgba(
|
|
1129
|
-
const
|
|
1130
|
-
return
|
|
1781
|
+
rgbToRgba(rgbValue) {
|
|
1782
|
+
const rgb = /rgb\((\d+,\s*[\d]+,\s*[\d]+)\)/g.exec(rgbValue);
|
|
1783
|
+
return rgb ? `rgba(${rgb[1]}, 1)` : rgbValue;
|
|
1131
1784
|
},
|
|
1132
1785
|
/**
|
|
1133
1786
|
* 将十六进制颜色值转换为rgba格式的颜色值
|
|
@@ -1135,12 +1788,18 @@ const $ = {
|
|
|
1135
1788
|
* @param hexValue 十六进制颜色值,可带或不带#前缀,支持3位和6位表示
|
|
1136
1789
|
* @returns 返回rgba格式的颜色值,格式为rgba(r,g,b,1)
|
|
1137
1790
|
*/
|
|
1138
|
-
hexToRgba(
|
|
1139
|
-
const
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
const
|
|
1143
|
-
|
|
1791
|
+
hexToRgba(hexValue) {
|
|
1792
|
+
const rgxShort = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
|
1793
|
+
const hex = hexValue.replace(rgxShort, (m, r2, g2, b2) => r2 + r2 + g2 + g2 + b2 + b2);
|
|
1794
|
+
const rgx = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
|
|
1795
|
+
const rgb = rgx.exec(hex);
|
|
1796
|
+
if (!rgb) {
|
|
1797
|
+
return hexValue;
|
|
1798
|
+
}
|
|
1799
|
+
const r = parseInt(rgb[1], 16);
|
|
1800
|
+
const g = parseInt(rgb[2], 16);
|
|
1801
|
+
const b = parseInt(rgb[3], 16);
|
|
1802
|
+
return `rgba(${r},${g},${b},1)`;
|
|
1144
1803
|
},
|
|
1145
1804
|
/**
|
|
1146
1805
|
* 将 HSL 颜色值转换为 RGBA 颜色值
|
|
@@ -1148,45 +1807,59 @@ const $ = {
|
|
|
1148
1807
|
* @param hslValue HSL 颜色值字符串,格式为 "hsl(h, s%, l%)" 或 "hsla(h, s%, l%, a)",其中 h 为色相,s 为饱和度,l 为亮度,a 为透明度(可选)。
|
|
1149
1808
|
* @returns 转换后的 RGBA 颜色值字符串,格式为 "rgba(r, g, b, a)",其中 r、g、b 为红绿蓝分量,a 为透明度。若输入为空或无效,则返回 null。
|
|
1150
1809
|
*/
|
|
1151
|
-
hslToRgba(
|
|
1152
|
-
if (!
|
|
1810
|
+
hslToRgba(hslValue) {
|
|
1811
|
+
if (!hslValue) {
|
|
1153
1812
|
return null;
|
|
1154
|
-
|
|
1155
|
-
|
|
1813
|
+
}
|
|
1814
|
+
const hsl = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(hslValue) || /hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(hslValue);
|
|
1815
|
+
if (!hsl) {
|
|
1156
1816
|
return null;
|
|
1157
|
-
const n = parseInt(e[1], 10) / 360, r = parseInt(e[2], 10) / 100, i = parseInt(e[3], 10) / 100, o = e[4] ? parseFloat(e[4]) : 1;
|
|
1158
|
-
function a(h, d, f) {
|
|
1159
|
-
return f < 0 && (f += 1), f > 1 && (f -= 1), f < 1 / 6 ? h + (d - h) * 6 * f : f < 1 / 2 ? d : f < 2 / 3 ? h + (d - h) * (2 / 3 - f) * 6 : h;
|
|
1160
1817
|
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1818
|
+
const h = parseInt(hsl[1], 10) / 360;
|
|
1819
|
+
const s = parseInt(hsl[2], 10) / 100;
|
|
1820
|
+
const l = parseInt(hsl[3], 10) / 100;
|
|
1821
|
+
const a = hsl[4] ? parseFloat(hsl[4]) : 1;
|
|
1822
|
+
function hue2rgb(p, q, t) {
|
|
1823
|
+
if (t < 0) t += 1;
|
|
1824
|
+
if (t > 1) t -= 1;
|
|
1825
|
+
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
1826
|
+
if (t < 1 / 2) return q;
|
|
1827
|
+
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
1828
|
+
return p;
|
|
1829
|
+
}
|
|
1830
|
+
let r, g, b;
|
|
1831
|
+
if (s === 0) {
|
|
1832
|
+
r = g = b = l;
|
|
1833
|
+
} else {
|
|
1834
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
1835
|
+
const p = 2 * l - q;
|
|
1836
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
1837
|
+
g = hue2rgb(p, q, h);
|
|
1838
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
1167
1839
|
}
|
|
1168
|
-
return `rgba(${Math.round(
|
|
1840
|
+
return `rgba(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)},${a})`;
|
|
1169
1841
|
},
|
|
1170
|
-
isHex(
|
|
1171
|
-
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(
|
|
1842
|
+
isHex(a) {
|
|
1843
|
+
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(a);
|
|
1172
1844
|
},
|
|
1173
|
-
isRgb(
|
|
1174
|
-
return /^rgb/.test(
|
|
1845
|
+
isRgb(a) {
|
|
1846
|
+
return /^rgb/.test(a);
|
|
1175
1847
|
},
|
|
1176
|
-
isHsl(
|
|
1177
|
-
return /^hsl/.test(
|
|
1848
|
+
isHsl(a) {
|
|
1849
|
+
return /^hsl/.test(a);
|
|
1178
1850
|
},
|
|
1179
|
-
isColor(
|
|
1180
|
-
return this.isHex(
|
|
1851
|
+
isColor(a) {
|
|
1852
|
+
return this.isHex(a) || this.isRgb(a) || this.isHsl(a);
|
|
1181
1853
|
},
|
|
1182
|
-
colorToRgb(
|
|
1183
|
-
if (this.isRgb(
|
|
1184
|
-
if (this.isHex(
|
|
1185
|
-
if (this.isHsl(
|
|
1854
|
+
colorToRgb(val) {
|
|
1855
|
+
if (this.isRgb(val)) return this.rgbToRgba(val);
|
|
1856
|
+
if (this.isHex(val)) return this.hexToRgba(val);
|
|
1857
|
+
if (this.isHsl(val)) return this.hslToRgba(val);
|
|
1186
1858
|
}
|
|
1187
1859
|
};
|
|
1188
|
-
|
|
1189
|
-
|
|
1860
|
+
const myDate = Object.create(Date);
|
|
1861
|
+
myDate.prototype.format = function(fmt = "yyyy-MM-dd hh:mm:ss") {
|
|
1862
|
+
const o = {
|
|
1190
1863
|
"M+": this.getMonth() + 1,
|
|
1191
1864
|
// 月份
|
|
1192
1865
|
"d+": this.getDate(),
|
|
@@ -1204,48 +1877,51 @@ Date.prototype.format = function(t) {
|
|
|
1204
1877
|
S: this.getMilliseconds()
|
|
1205
1878
|
// 毫秒
|
|
1206
1879
|
};
|
|
1207
|
-
/(y+)/.test(
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1880
|
+
if (/(y+)/.test(fmt)) {
|
|
1881
|
+
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
|
|
1882
|
+
}
|
|
1883
|
+
for (const k in o) {
|
|
1884
|
+
if (new RegExp("(" + k + ")").test(fmt)) {
|
|
1885
|
+
const len = k.length === 1 ? 1 : Number(k.slice(1));
|
|
1886
|
+
fmt = fmt.replace(RegExp.$1, ("00" + o[k]).substr(("" + o[k]).length + len - (o[k] + "").length));
|
|
1212
1887
|
}
|
|
1213
|
-
|
|
1888
|
+
}
|
|
1889
|
+
return fmt;
|
|
1214
1890
|
};
|
|
1215
|
-
|
|
1216
|
-
const
|
|
1217
|
-
switch (
|
|
1891
|
+
myDate.prototype.addDate = function(interval, number) {
|
|
1892
|
+
const date = new Date(this);
|
|
1893
|
+
switch (interval) {
|
|
1218
1894
|
case "y":
|
|
1219
|
-
|
|
1895
|
+
date.setFullYear(this.getFullYear() + number);
|
|
1220
1896
|
break;
|
|
1221
1897
|
case "q":
|
|
1222
|
-
|
|
1898
|
+
date.setMonth(this.getMonth() + number * 3);
|
|
1223
1899
|
break;
|
|
1224
1900
|
case "M":
|
|
1225
|
-
|
|
1901
|
+
date.setMonth(this.getMonth() + number);
|
|
1226
1902
|
break;
|
|
1227
1903
|
case "w":
|
|
1228
|
-
|
|
1904
|
+
date.setDate(this.getDate() + number * 7);
|
|
1229
1905
|
break;
|
|
1230
1906
|
case "d":
|
|
1231
|
-
|
|
1907
|
+
date.setDate(this.getDate() + number);
|
|
1232
1908
|
break;
|
|
1233
1909
|
case "h":
|
|
1234
|
-
|
|
1910
|
+
date.setHours(this.getHours() + number);
|
|
1235
1911
|
break;
|
|
1236
1912
|
case "m":
|
|
1237
|
-
|
|
1913
|
+
date.setMinutes(this.getMinutes() + number);
|
|
1238
1914
|
break;
|
|
1239
1915
|
case "s":
|
|
1240
|
-
|
|
1916
|
+
date.setSeconds(this.getSeconds() + number);
|
|
1241
1917
|
break;
|
|
1242
1918
|
default:
|
|
1243
|
-
|
|
1919
|
+
date.setDate(this.getDate() + number);
|
|
1244
1920
|
break;
|
|
1245
1921
|
}
|
|
1246
|
-
return
|
|
1922
|
+
return date;
|
|
1247
1923
|
};
|
|
1248
|
-
const
|
|
1924
|
+
const DateUtil = {
|
|
1249
1925
|
lastMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth() - 1, 1),
|
|
1250
1926
|
thisMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), 1),
|
|
1251
1927
|
nextMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth() + 1, 1),
|
|
@@ -1255,28 +1931,30 @@ const X = {
|
|
|
1255
1931
|
lastDayDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() - 1),
|
|
1256
1932
|
thisDayDate: new Date((/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0)),
|
|
1257
1933
|
nextDayDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() + 1),
|
|
1258
|
-
parseDate(
|
|
1259
|
-
if (typeof
|
|
1260
|
-
var
|
|
1261
|
-
if (
|
|
1262
|
-
|
|
1934
|
+
parseDate(str) {
|
|
1935
|
+
if (typeof str == "string") {
|
|
1936
|
+
var results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) *$/);
|
|
1937
|
+
if (results && results.length > 3) return new Date(parseInt(results[1]), parseInt(results[2]) - 1, parseInt(results[3]));
|
|
1938
|
+
results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) +(\d{1,2}):(\d{1,2}):(\d{1,2}) *$/);
|
|
1939
|
+
if (results && results.length > 6)
|
|
1263
1940
|
return new Date(
|
|
1264
|
-
parseInt(
|
|
1265
|
-
parseInt(
|
|
1266
|
-
parseInt(
|
|
1267
|
-
parseInt(
|
|
1268
|
-
parseInt(
|
|
1269
|
-
parseInt(
|
|
1941
|
+
parseInt(results[1]),
|
|
1942
|
+
parseInt(results[2]) - 1,
|
|
1943
|
+
parseInt(results[3]),
|
|
1944
|
+
parseInt(results[4]),
|
|
1945
|
+
parseInt(results[5]),
|
|
1946
|
+
parseInt(results[6])
|
|
1270
1947
|
);
|
|
1271
|
-
|
|
1948
|
+
results = str.match(/^ *(\d{4})-(\d{1,2})-(\d{1,2}) +(\d{1,2}):(\d{1,2}):(\d{1,2})\.(\d{1,9}) *$/);
|
|
1949
|
+
if (results && results.length > 7)
|
|
1272
1950
|
return new Date(
|
|
1273
|
-
parseInt(
|
|
1274
|
-
parseInt(
|
|
1275
|
-
parseInt(
|
|
1276
|
-
parseInt(
|
|
1277
|
-
parseInt(
|
|
1278
|
-
parseInt(
|
|
1279
|
-
parseInt(
|
|
1951
|
+
parseInt(results[1]),
|
|
1952
|
+
parseInt(results[2]) - 1,
|
|
1953
|
+
parseInt(results[3]),
|
|
1954
|
+
parseInt(results[4]),
|
|
1955
|
+
parseInt(results[5]),
|
|
1956
|
+
parseInt(results[6]),
|
|
1957
|
+
parseInt(results[7])
|
|
1280
1958
|
);
|
|
1281
1959
|
}
|
|
1282
1960
|
return null;
|
|
@@ -1288,27 +1966,56 @@ const X = {
|
|
|
1288
1966
|
* @param endTime 结束时间,可以是字符串、数字或日期类型
|
|
1289
1967
|
* @returns 返回格式化后的时间间隔字符串,格式为"天数 天 小时 时 分钟 分 秒 秒"或"少于1秒"
|
|
1290
1968
|
*/
|
|
1291
|
-
formatDateInterval(
|
|
1292
|
-
const
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
const
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1969
|
+
formatDateInterval(startTime, endTime) {
|
|
1970
|
+
const dateCreateTime = new Date(startTime);
|
|
1971
|
+
const dateFinishTime = new Date(endTime);
|
|
1972
|
+
const dateInterval = dateFinishTime.getTime() - dateCreateTime.getTime();
|
|
1973
|
+
const days = Math.floor(dateInterval / (24 * 3600 * 1e3));
|
|
1974
|
+
const leave1 = dateInterval % (24 * 3600 * 1e3);
|
|
1975
|
+
const hours = Math.floor(leave1 / (3600 * 1e3));
|
|
1976
|
+
const leave2 = leave1 % (3600 * 1e3);
|
|
1977
|
+
const minutes = Math.floor(leave2 / (60 * 1e3));
|
|
1978
|
+
const leave3 = leave2 % (60 * 1e3);
|
|
1979
|
+
const seconds = Math.round(leave3 / 1e3);
|
|
1980
|
+
let intervalDes = "";
|
|
1981
|
+
if (days > 0) {
|
|
1982
|
+
intervalDes += days + "天";
|
|
1983
|
+
}
|
|
1984
|
+
if (hours > 0) {
|
|
1985
|
+
intervalDes += hours + "时";
|
|
1986
|
+
}
|
|
1987
|
+
if (minutes > 0) {
|
|
1988
|
+
intervalDes += minutes + "分";
|
|
1989
|
+
}
|
|
1990
|
+
if (seconds > 0) {
|
|
1991
|
+
intervalDes += seconds + "秒";
|
|
1992
|
+
}
|
|
1993
|
+
if (days === 0 && hours === 0 && minutes === 0 && seconds === 0) {
|
|
1994
|
+
intervalDes = "少于1秒";
|
|
1995
|
+
}
|
|
1996
|
+
return intervalDes;
|
|
1301
1997
|
},
|
|
1302
|
-
|
|
1998
|
+
formatterCounter(times) {
|
|
1999
|
+
const checked = function(j) {
|
|
2000
|
+
return (j > 10 ? "" : "0") + (j || 0);
|
|
2001
|
+
};
|
|
2002
|
+
const houres = checked(Math.floor(times / 3600));
|
|
2003
|
+
const level1 = times % 3600;
|
|
2004
|
+
const minutes = checked(Math.floor(level1 / 60));
|
|
2005
|
+
const leave2 = level1 % 60;
|
|
2006
|
+
const seconds = checked(Math.round(leave2));
|
|
2007
|
+
return `${houres}:${minutes}:${seconds}`;
|
|
2008
|
+
},
|
|
2009
|
+
sleep(d) {
|
|
1303
2010
|
}
|
|
1304
2011
|
};
|
|
1305
|
-
function
|
|
1306
|
-
return
|
|
2012
|
+
function trim(str) {
|
|
2013
|
+
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, "");
|
|
1307
2014
|
}
|
|
1308
|
-
function
|
|
1309
|
-
return
|
|
2015
|
+
function splitWords(str) {
|
|
2016
|
+
return trim(str).split(/\s+/);
|
|
1310
2017
|
}
|
|
1311
|
-
const
|
|
2018
|
+
const DomUtil = {
|
|
1312
2019
|
/**
|
|
1313
2020
|
* 获取元素的样式值
|
|
1314
2021
|
*
|
|
@@ -1316,14 +2023,15 @@ const V = {
|
|
|
1316
2023
|
* @param style 样式属性名称
|
|
1317
2024
|
* @returns 元素的样式值,如果获取不到则返回 null
|
|
1318
2025
|
*/
|
|
1319
|
-
getStyle(
|
|
1320
|
-
var
|
|
1321
|
-
let
|
|
1322
|
-
if (!
|
|
1323
|
-
const
|
|
1324
|
-
|
|
2026
|
+
getStyle(el, style) {
|
|
2027
|
+
var _a;
|
|
2028
|
+
let value = el.style[style];
|
|
2029
|
+
if (!value || value === "auto") {
|
|
2030
|
+
const css = (_a = document.defaultView) == null ? void 0 : _a.getComputedStyle(el, null);
|
|
2031
|
+
value = css ? css[style] : null;
|
|
2032
|
+
if (value === "auto") value = null;
|
|
1325
2033
|
}
|
|
1326
|
-
return
|
|
2034
|
+
return value;
|
|
1327
2035
|
},
|
|
1328
2036
|
/**
|
|
1329
2037
|
* 创建一个HTML元素
|
|
@@ -1333,45 +2041,56 @@ const V = {
|
|
|
1333
2041
|
* @param container 父容器,若传入,则新创建的元素会被添加到该容器中
|
|
1334
2042
|
* @returns 返回新创建的HTML元素
|
|
1335
2043
|
*/
|
|
1336
|
-
create(
|
|
1337
|
-
const
|
|
1338
|
-
|
|
2044
|
+
create(tagName, className, container) {
|
|
2045
|
+
const el = document.createElement(tagName);
|
|
2046
|
+
el.className = className || "";
|
|
2047
|
+
if (container) {
|
|
2048
|
+
container.appendChild(el);
|
|
2049
|
+
}
|
|
2050
|
+
return el;
|
|
1339
2051
|
},
|
|
1340
2052
|
/**
|
|
1341
2053
|
* 从父节点中移除指定元素。
|
|
1342
2054
|
*
|
|
1343
2055
|
* @param el 要移除的元素对象,必须包含parentNode属性。
|
|
1344
2056
|
*/
|
|
1345
|
-
remove(
|
|
1346
|
-
const
|
|
1347
|
-
|
|
2057
|
+
remove(el) {
|
|
2058
|
+
const parent = el.parentNode;
|
|
2059
|
+
if (parent) {
|
|
2060
|
+
parent.removeChild(el);
|
|
2061
|
+
}
|
|
1348
2062
|
},
|
|
1349
2063
|
/**
|
|
1350
2064
|
* 清空给定元素的子节点
|
|
1351
2065
|
*
|
|
1352
2066
|
* @param el 要清空子节点的元素,包含firstChild和removeChild属性
|
|
1353
2067
|
*/
|
|
1354
|
-
empty(
|
|
1355
|
-
|
|
1356
|
-
|
|
2068
|
+
empty(el) {
|
|
2069
|
+
while (el.firstChild) {
|
|
2070
|
+
el.removeChild(el.firstChild);
|
|
2071
|
+
}
|
|
1357
2072
|
},
|
|
1358
2073
|
/**
|
|
1359
2074
|
* 将元素移到父节点的最前面
|
|
1360
2075
|
*
|
|
1361
2076
|
* @param el 要移动的元素,需要包含 parentNode 属性
|
|
1362
2077
|
*/
|
|
1363
|
-
toFront(
|
|
1364
|
-
const
|
|
1365
|
-
|
|
2078
|
+
toFront(el) {
|
|
2079
|
+
const parent = el.parentNode;
|
|
2080
|
+
if (parent && parent.lastChild !== el) {
|
|
2081
|
+
parent.appendChild(el);
|
|
2082
|
+
}
|
|
1366
2083
|
},
|
|
1367
2084
|
/**
|
|
1368
2085
|
* 将元素移动到其父节点的最前面
|
|
1369
2086
|
*
|
|
1370
2087
|
* @param el 要移动的元素,需要包含parentNode属性
|
|
1371
2088
|
*/
|
|
1372
|
-
toBack(
|
|
1373
|
-
const
|
|
1374
|
-
|
|
2089
|
+
toBack(el) {
|
|
2090
|
+
const parent = el.parentNode;
|
|
2091
|
+
if (parent && parent.firstChild !== el) {
|
|
2092
|
+
parent.insertBefore(el, parent.firstChild);
|
|
2093
|
+
}
|
|
1375
2094
|
},
|
|
1376
2095
|
/**
|
|
1377
2096
|
* 获取元素的类名
|
|
@@ -1382,8 +2101,9 @@ const V = {
|
|
|
1382
2101
|
* @param el.className.baseVal 类名字符串
|
|
1383
2102
|
* @returns 返回元素的类名字符串
|
|
1384
2103
|
*/
|
|
1385
|
-
getClass(
|
|
1386
|
-
|
|
2104
|
+
getClass(el) {
|
|
2105
|
+
const shadowElement = (el == null ? void 0 : el.host) || el;
|
|
2106
|
+
return shadowElement.className.toString();
|
|
1387
2107
|
},
|
|
1388
2108
|
/**
|
|
1389
2109
|
* 判断元素是否包含指定类名
|
|
@@ -1392,12 +2112,13 @@ const V = {
|
|
|
1392
2112
|
* @param name 要判断的类名
|
|
1393
2113
|
* @returns 返回一个布尔值,表示元素是否包含指定类名
|
|
1394
2114
|
*/
|
|
1395
|
-
hasClass(
|
|
1396
|
-
var
|
|
1397
|
-
if ((
|
|
1398
|
-
return
|
|
1399
|
-
|
|
1400
|
-
|
|
2115
|
+
hasClass(el, name) {
|
|
2116
|
+
var _a;
|
|
2117
|
+
if ((_a = el.classList) == null ? void 0 : _a.contains(name)) {
|
|
2118
|
+
return true;
|
|
2119
|
+
}
|
|
2120
|
+
const className = this.getClass(el);
|
|
2121
|
+
return className.length > 0 && new RegExp(`(^|\\s)${name}(\\s|$)`).test(className);
|
|
1401
2122
|
},
|
|
1402
2123
|
/**
|
|
1403
2124
|
* 给指定的 HTML 元素添加类名
|
|
@@ -1405,14 +2126,15 @@ const V = {
|
|
|
1405
2126
|
* @param el 要添加类名的 HTML 元素
|
|
1406
2127
|
* @param name 要添加的类名,多个类名之间用空格分隔
|
|
1407
2128
|
*/
|
|
1408
|
-
addClass(
|
|
1409
|
-
if (
|
|
1410
|
-
const
|
|
1411
|
-
for (let
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
this.
|
|
2129
|
+
addClass(el, name) {
|
|
2130
|
+
if (el.classList !== void 0) {
|
|
2131
|
+
const classes = splitWords(name);
|
|
2132
|
+
for (let i = 0, len = classes.length; i < len; i++) {
|
|
2133
|
+
el.classList.add(classes[i]);
|
|
2134
|
+
}
|
|
2135
|
+
} else if (!this.hasClass(el, name)) {
|
|
2136
|
+
const className = this.getClass(el);
|
|
2137
|
+
this.setClass(el, (className ? className + " " : "") + name);
|
|
1416
2138
|
}
|
|
1417
2139
|
},
|
|
1418
2140
|
/**
|
|
@@ -1421,8 +2143,13 @@ const V = {
|
|
|
1421
2143
|
* @param el 要移除类名的元素
|
|
1422
2144
|
* @param name 要移除的类名,多个类名用空格分隔
|
|
1423
2145
|
*/
|
|
1424
|
-
removeClass(
|
|
1425
|
-
|
|
2146
|
+
removeClass(el, name) {
|
|
2147
|
+
if (el.classList !== void 0) {
|
|
2148
|
+
const classes = splitWords(name);
|
|
2149
|
+
classes.forEach((className) => el.classList.remove(className));
|
|
2150
|
+
} else {
|
|
2151
|
+
this.setClass(el, (" " + this.getClass(el) + " ").replace(" " + name + " ", " ").trim());
|
|
2152
|
+
}
|
|
1426
2153
|
},
|
|
1427
2154
|
/**
|
|
1428
2155
|
* 设置元素的 CSS 类名
|
|
@@ -1430,8 +2157,11 @@ const V = {
|
|
|
1430
2157
|
* @param el HTML 或 SVG 元素
|
|
1431
2158
|
* @param name 要设置的类名,多个类名之间用空格分隔
|
|
1432
2159
|
*/
|
|
1433
|
-
setClass(
|
|
1434
|
-
"classList" in
|
|
2160
|
+
setClass(el, name) {
|
|
2161
|
+
if ("classList" in el) {
|
|
2162
|
+
el.classList.value = "";
|
|
2163
|
+
name.split(" ").forEach((className) => el.classList.add(className));
|
|
2164
|
+
}
|
|
1435
2165
|
},
|
|
1436
2166
|
/**
|
|
1437
2167
|
* 从字符串中解析XML文档,并返回根节点
|
|
@@ -1439,18 +2169,22 @@ const V = {
|
|
|
1439
2169
|
* @param str 要解析的XML字符串
|
|
1440
2170
|
* @returns 解析后的XML文档的根节点
|
|
1441
2171
|
*/
|
|
1442
|
-
parseFromString(
|
|
1443
|
-
|
|
2172
|
+
parseFromString(str) {
|
|
2173
|
+
const parser = new DOMParser();
|
|
2174
|
+
const doc = parser.parseFromString(str, "text/xml");
|
|
2175
|
+
return doc.children[0];
|
|
1444
2176
|
}
|
|
1445
|
-
}
|
|
2177
|
+
};
|
|
2178
|
+
const TYPES = ["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon"];
|
|
2179
|
+
const GeoJsonUtil = {
|
|
1446
2180
|
/**
|
|
1447
2181
|
* 获取GeoJSON要素的几何类型
|
|
1448
2182
|
*
|
|
1449
2183
|
* @param feature GeoJSONFeature 类型的要素
|
|
1450
2184
|
* @returns 返回要素的几何类型,如果要素没有几何属性则返回 null
|
|
1451
2185
|
*/
|
|
1452
|
-
getGeoJsonType(
|
|
1453
|
-
return
|
|
2186
|
+
getGeoJsonType(feature) {
|
|
2187
|
+
return feature.geometry ? feature.geometry.type : null;
|
|
1454
2188
|
},
|
|
1455
2189
|
/**
|
|
1456
2190
|
* 判断给定的GeoJSON要素是否为有效的GeoJSON格式
|
|
@@ -1458,14 +2192,16 @@ const V = {
|
|
|
1458
2192
|
* @param feature 要判断的GeoJSON要素
|
|
1459
2193
|
* @returns 如果为有效的GeoJSON格式则返回true,否则返回false
|
|
1460
2194
|
*/
|
|
1461
|
-
isGeoJson(
|
|
1462
|
-
const
|
|
1463
|
-
if (
|
|
1464
|
-
for (let
|
|
1465
|
-
if (
|
|
1466
|
-
return
|
|
2195
|
+
isGeoJson(feature) {
|
|
2196
|
+
const type = this.getGeoJsonType(feature);
|
|
2197
|
+
if (type) {
|
|
2198
|
+
for (let i = 0, len = TYPES.length; i < len; i++) {
|
|
2199
|
+
if (TYPES[i] === type) {
|
|
2200
|
+
return true;
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
1467
2203
|
}
|
|
1468
|
-
return
|
|
2204
|
+
return false;
|
|
1469
2205
|
},
|
|
1470
2206
|
/**
|
|
1471
2207
|
* 判断是否为 GeoJSON 多边形
|
|
@@ -1473,9 +2209,12 @@ const V = {
|
|
|
1473
2209
|
* @param feature GeoJSONFeature 对象
|
|
1474
2210
|
* @returns 返回布尔值,表示是否为 GeoJSON 多边形
|
|
1475
2211
|
*/
|
|
1476
|
-
isGeoJsonPolygon(
|
|
1477
|
-
const
|
|
1478
|
-
|
|
2212
|
+
isGeoJsonPolygon(feature) {
|
|
2213
|
+
const type = this.getGeoJsonType(feature);
|
|
2214
|
+
if (type && (type === TYPES[4] || type === TYPES[5])) {
|
|
2215
|
+
return true;
|
|
2216
|
+
}
|
|
2217
|
+
return false;
|
|
1479
2218
|
},
|
|
1480
2219
|
/**
|
|
1481
2220
|
* 判断给定的 GeoJSONFeature 是否为 GeoJSON 线
|
|
@@ -1483,9 +2222,12 @@ const V = {
|
|
|
1483
2222
|
* @param feature GeoJSONFeature 对象
|
|
1484
2223
|
* @returns 是 GeoJSON 线返回 true,否则返回 false
|
|
1485
2224
|
*/
|
|
1486
|
-
isGeoJsonLine(
|
|
1487
|
-
const
|
|
1488
|
-
|
|
2225
|
+
isGeoJsonLine(feature) {
|
|
2226
|
+
const type = this.getGeoJsonType(feature);
|
|
2227
|
+
if (type && (type === TYPES[2] || type === TYPES[3])) {
|
|
2228
|
+
return true;
|
|
2229
|
+
}
|
|
2230
|
+
return false;
|
|
1489
2231
|
},
|
|
1490
2232
|
/**
|
|
1491
2233
|
* 判断是否为 GeoJSON 点类型
|
|
@@ -1493,9 +2235,12 @@ const V = {
|
|
|
1493
2235
|
* @param feature GeoJSONFeature 对象
|
|
1494
2236
|
* @returns 是点类型返回 true,否则返回 false
|
|
1495
2237
|
*/
|
|
1496
|
-
isGeoJsonPoint(
|
|
1497
|
-
const
|
|
1498
|
-
|
|
2238
|
+
isGeoJsonPoint(feature) {
|
|
2239
|
+
const type = this.getGeoJsonType(feature);
|
|
2240
|
+
if (type && (type === TYPES[0] || type === TYPES[1])) {
|
|
2241
|
+
return true;
|
|
2242
|
+
}
|
|
2243
|
+
return false;
|
|
1499
2244
|
},
|
|
1500
2245
|
/**
|
|
1501
2246
|
* 判断传入的 GeoJSONFeature 是否为 Multi 类型的 GeoJSON。
|
|
@@ -1503,9 +2248,14 @@ const V = {
|
|
|
1503
2248
|
* @param feature GeoJSONFeature 类型的参数,待判断是否为 Multi 类型的 GeoJSON。
|
|
1504
2249
|
* @returns 返回一个布尔值,如果传入的 GeoJSONFeature 是 Multi 类型的 GeoJSON,则返回 true,否则返回 false。
|
|
1505
2250
|
*/
|
|
1506
|
-
isGeoJsonMulti(
|
|
1507
|
-
const
|
|
1508
|
-
|
|
2251
|
+
isGeoJsonMulti(feature) {
|
|
2252
|
+
const type = this.getGeoJsonType(feature);
|
|
2253
|
+
if (type) {
|
|
2254
|
+
if (type.indexOf("Multi") > -1) {
|
|
2255
|
+
return true;
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
return false;
|
|
1509
2259
|
},
|
|
1510
2260
|
/**
|
|
1511
2261
|
* 获取GeoJSON要素的坐标数组
|
|
@@ -1513,8 +2263,8 @@ const V = {
|
|
|
1513
2263
|
* @param feature GeoJSONFeature对象
|
|
1514
2264
|
* @returns 返回一个包含坐标数组的数组,可以是二维、三维或四维数组
|
|
1515
2265
|
*/
|
|
1516
|
-
getGeoJsonCoordinates(
|
|
1517
|
-
return
|
|
2266
|
+
getGeoJsonCoordinates(feature) {
|
|
2267
|
+
return feature.geometry ? feature.geometry.coordinates : [];
|
|
1518
2268
|
},
|
|
1519
2269
|
/**
|
|
1520
2270
|
* 获取GeoJSON要素的中心点坐标
|
|
@@ -1523,42 +2273,64 @@ const V = {
|
|
|
1523
2273
|
* @param out 输出坐标对象,默认为null
|
|
1524
2274
|
* @returns 返回中心点坐标,如果无法获取则返回null
|
|
1525
2275
|
*/
|
|
1526
|
-
getGeoJsonCenter(
|
|
1527
|
-
const
|
|
1528
|
-
if (!
|
|
2276
|
+
getGeoJsonCenter(feature, out) {
|
|
2277
|
+
const type = this.getGeoJsonType(feature);
|
|
2278
|
+
if (!type || !feature.geometry) {
|
|
1529
2279
|
return null;
|
|
1530
|
-
|
|
1531
|
-
|
|
2280
|
+
}
|
|
2281
|
+
const geometry = feature.geometry;
|
|
2282
|
+
const coordinates = geometry.coordinates;
|
|
2283
|
+
if (!coordinates) {
|
|
1532
2284
|
return null;
|
|
1533
|
-
|
|
1534
|
-
|
|
2285
|
+
}
|
|
2286
|
+
let sumX = 0, sumY = 0, coordLen = 0;
|
|
2287
|
+
switch (type) {
|
|
1535
2288
|
case "Point": {
|
|
1536
|
-
|
|
2289
|
+
sumX = coordinates[0];
|
|
2290
|
+
sumY = coordinates[1];
|
|
2291
|
+
coordLen++;
|
|
1537
2292
|
break;
|
|
1538
2293
|
}
|
|
1539
2294
|
case "MultiPoint":
|
|
1540
2295
|
case "LineString": {
|
|
1541
|
-
for (let
|
|
1542
|
-
|
|
2296
|
+
for (let i = 0, len = coordinates.length; i < len; i++) {
|
|
2297
|
+
sumX += coordinates[i][0];
|
|
2298
|
+
sumY += coordinates[i][1];
|
|
2299
|
+
coordLen++;
|
|
2300
|
+
}
|
|
1543
2301
|
break;
|
|
1544
2302
|
}
|
|
1545
2303
|
case "MultiLineString":
|
|
1546
2304
|
case "Polygon": {
|
|
1547
|
-
for (let
|
|
1548
|
-
for (let
|
|
1549
|
-
|
|
2305
|
+
for (let i = 0, len = coordinates.length; i < len; i++) {
|
|
2306
|
+
for (let j = 0, len1 = coordinates[i].length; j < len1; j++) {
|
|
2307
|
+
sumX += coordinates[i][j][0];
|
|
2308
|
+
sumY += coordinates[i][j][1];
|
|
2309
|
+
coordLen++;
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
1550
2312
|
break;
|
|
1551
2313
|
}
|
|
1552
2314
|
case "MultiPolygon": {
|
|
1553
|
-
for (let
|
|
1554
|
-
for (let
|
|
1555
|
-
for (let
|
|
1556
|
-
|
|
2315
|
+
for (let i = 0, len = coordinates.length; i < len; i++) {
|
|
2316
|
+
for (let j = 0, len1 = coordinates[i].length; j < len1; j++) {
|
|
2317
|
+
for (let m = 0, len2 = coordinates[i][j].length; m < len2; m++) {
|
|
2318
|
+
sumX += coordinates[i][j][m][0];
|
|
2319
|
+
sumY += coordinates[i][j][m][1];
|
|
2320
|
+
coordLen++;
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
1557
2324
|
break;
|
|
1558
2325
|
}
|
|
1559
2326
|
}
|
|
1560
|
-
const
|
|
1561
|
-
|
|
2327
|
+
const x = sumX / coordLen, y = sumY / coordLen;
|
|
2328
|
+
if (out) {
|
|
2329
|
+
out.x = x;
|
|
2330
|
+
out.y = y;
|
|
2331
|
+
return out;
|
|
2332
|
+
}
|
|
2333
|
+
return { x, y };
|
|
1562
2334
|
},
|
|
1563
2335
|
/**
|
|
1564
2336
|
* 将一个包含多个点、线或面的 GeoJSON 特征对象拆分成多个独立的 GeoJSON 特征对象数组。
|
|
@@ -1566,42 +2338,48 @@ const V = {
|
|
|
1566
2338
|
* @param feature 包含多个点、线或面的 GeoJSON 特征对象
|
|
1567
2339
|
* @returns 返回一个 GeoJSON 特征对象数组,如果拆分失败则返回 null
|
|
1568
2340
|
*/
|
|
1569
|
-
spliteGeoJsonMulti(
|
|
1570
|
-
const
|
|
1571
|
-
if (!
|
|
2341
|
+
spliteGeoJsonMulti(feature) {
|
|
2342
|
+
const type = this.getGeoJsonType(feature);
|
|
2343
|
+
if (!type || !feature.geometry) {
|
|
1572
2344
|
return null;
|
|
1573
|
-
|
|
1574
|
-
|
|
2345
|
+
}
|
|
2346
|
+
const geometry = feature.geometry;
|
|
2347
|
+
const properties = feature.properties || {};
|
|
2348
|
+
const coordinates = geometry.coordinates;
|
|
2349
|
+
if (!coordinates) {
|
|
1575
2350
|
return null;
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
2351
|
+
}
|
|
2352
|
+
const features = [];
|
|
2353
|
+
let fType;
|
|
2354
|
+
switch (type) {
|
|
1579
2355
|
case "MultiPoint": {
|
|
1580
|
-
|
|
2356
|
+
fType = "Point";
|
|
1581
2357
|
break;
|
|
1582
2358
|
}
|
|
1583
2359
|
case "MultiLineString": {
|
|
1584
|
-
|
|
2360
|
+
fType = "LineString";
|
|
1585
2361
|
break;
|
|
1586
2362
|
}
|
|
1587
2363
|
case "MultiPolygon": {
|
|
1588
|
-
|
|
2364
|
+
fType = "Polygon";
|
|
1589
2365
|
break;
|
|
1590
2366
|
}
|
|
1591
2367
|
}
|
|
1592
|
-
if (
|
|
1593
|
-
for (let
|
|
1594
|
-
|
|
2368
|
+
if (fType) {
|
|
2369
|
+
for (let i = 0, len = coordinates.length; i < len; i++) {
|
|
2370
|
+
features.push({
|
|
1595
2371
|
type: "Feature",
|
|
1596
2372
|
geometry: {
|
|
1597
|
-
type:
|
|
1598
|
-
coordinates: i
|
|
2373
|
+
type: fType,
|
|
2374
|
+
coordinates: coordinates[i]
|
|
1599
2375
|
},
|
|
1600
|
-
properties
|
|
2376
|
+
properties
|
|
1601
2377
|
});
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
2378
|
+
}
|
|
2379
|
+
} else {
|
|
2380
|
+
features.push(feature);
|
|
2381
|
+
}
|
|
2382
|
+
return features;
|
|
1605
2383
|
},
|
|
1606
2384
|
/**
|
|
1607
2385
|
* 根据坐标数组生成GeoJSON要素
|
|
@@ -1610,30 +2388,35 @@ const V = {
|
|
|
1610
2388
|
* @returns GeoJSONFeature 生成的GeoJSON要素
|
|
1611
2389
|
* @throws Error 如果coordinates参数格式错误
|
|
1612
2390
|
*/
|
|
1613
|
-
getGeoJsonByCoordinates(
|
|
1614
|
-
if (!Array.isArray(
|
|
2391
|
+
getGeoJsonByCoordinates(coordinates) {
|
|
2392
|
+
if (!Array.isArray(coordinates)) {
|
|
1615
2393
|
throw Error("coordinates 参数格式错误");
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
else
|
|
2394
|
+
}
|
|
2395
|
+
let type;
|
|
2396
|
+
if (coordinates.length === 2 && typeof coordinates[0] === "number" && typeof coordinates[1] === "number") {
|
|
2397
|
+
type = "Point";
|
|
2398
|
+
} else if (Array.isArray(coordinates[0]) && coordinates[0].length === 2) {
|
|
2399
|
+
type = "LineString";
|
|
2400
|
+
} else if (Array.isArray(coordinates[0]) && Array.isArray(coordinates[0][0])) {
|
|
2401
|
+
const outerRing = coordinates[0];
|
|
2402
|
+
const isClosed = outerRing[0].join(",") === outerRing[outerRing.length - 1].join(",");
|
|
2403
|
+
if (isClosed) {
|
|
2404
|
+
type = "Polygon";
|
|
2405
|
+
} else if (coordinates.length > 1) {
|
|
2406
|
+
type = "MultiPolygon";
|
|
2407
|
+
} else {
|
|
1628
2408
|
throw Error("coordinates 参数格式错误");
|
|
1629
|
-
|
|
2409
|
+
}
|
|
2410
|
+
} else {
|
|
1630
2411
|
throw Error("coordinates 参数格式错误");
|
|
2412
|
+
}
|
|
1631
2413
|
return {
|
|
1632
2414
|
type: "Feature",
|
|
1633
|
-
geometry: { type
|
|
2415
|
+
geometry: { type, coordinates }
|
|
1634
2416
|
};
|
|
1635
2417
|
}
|
|
1636
|
-
}
|
|
2418
|
+
};
|
|
2419
|
+
const GeoUtil = {
|
|
1637
2420
|
toRadian: Math.PI / 180,
|
|
1638
2421
|
R: 6371393,
|
|
1639
2422
|
/**
|
|
@@ -1643,8 +2426,8 @@ const V = {
|
|
|
1643
2426
|
* @param lat 纬度值
|
|
1644
2427
|
* @returns 如果经纬度合法,返回true;否则返回false
|
|
1645
2428
|
*/
|
|
1646
|
-
isLnglat(
|
|
1647
|
-
return !isNaN(
|
|
2429
|
+
isLnglat(lng, lat) {
|
|
2430
|
+
return !isNaN(lng) && !isNaN(lat) && !!(+lat > -90 && +lat < 90 && +lng > -180 && +lng < 180);
|
|
1648
2431
|
},
|
|
1649
2432
|
/**
|
|
1650
2433
|
* 计算两哥平面坐标点间的距离
|
|
@@ -1653,8 +2436,8 @@ const V = {
|
|
|
1653
2436
|
* @param p2 坐标点2,包含x和y属性
|
|
1654
2437
|
* @returns 返回两点间的欧几里得距离
|
|
1655
2438
|
*/
|
|
1656
|
-
distance(
|
|
1657
|
-
return Math.sqrt(Math.pow(
|
|
2439
|
+
distance(p1, p2) {
|
|
2440
|
+
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
|
|
1658
2441
|
},
|
|
1659
2442
|
/**
|
|
1660
2443
|
* 计算两个经纬度点之间的距离
|
|
@@ -1663,10 +2446,18 @@ const V = {
|
|
|
1663
2446
|
* @param B 经纬度点B,包含lng(经度)和lat(纬度)两个属性
|
|
1664
2447
|
* @returns 返回两点之间的距离,单位为米
|
|
1665
2448
|
*/
|
|
1666
|
-
distanceByPoints(
|
|
1667
|
-
const { lng:
|
|
1668
|
-
|
|
1669
|
-
|
|
2449
|
+
distanceByPoints(A, B) {
|
|
2450
|
+
const { lng: lngA, lat: latA } = A;
|
|
2451
|
+
const { lng: lngB, lat: latB } = B;
|
|
2452
|
+
const earthR = 6371e3;
|
|
2453
|
+
const x = Math.cos(latA * Math.PI / 180) * Math.cos(latB * Math.PI / 180) * Math.cos((lngA - lngB) * Math.PI / 180);
|
|
2454
|
+
const y = Math.sin(latA * Math.PI / 180) * Math.sin(latB * Math.PI / 180);
|
|
2455
|
+
let s = x + y;
|
|
2456
|
+
if (s > 1) s = 1;
|
|
2457
|
+
if (s < -1) s = -1;
|
|
2458
|
+
const alpha = Math.acos(s);
|
|
2459
|
+
const distance = alpha * earthR;
|
|
2460
|
+
return distance;
|
|
1670
2461
|
},
|
|
1671
2462
|
/**
|
|
1672
2463
|
* 格式化经纬度为度分秒格式
|
|
@@ -1675,13 +2466,22 @@ const V = {
|
|
|
1675
2466
|
* @param lat 纬度
|
|
1676
2467
|
* @returns 返回格式化后的经纬度字符串,格式为:经度度分秒,纬度度分秒
|
|
1677
2468
|
*/
|
|
1678
|
-
formatLnglat(
|
|
1679
|
-
let
|
|
1680
|
-
function
|
|
1681
|
-
const
|
|
1682
|
-
|
|
2469
|
+
formatLnglat(lng, lat) {
|
|
2470
|
+
let res = "";
|
|
2471
|
+
function formatDegreeToDMS(valueInDegrees) {
|
|
2472
|
+
const degree = Math.floor(valueInDegrees);
|
|
2473
|
+
const minutes = Math.floor((valueInDegrees - degree) * 60);
|
|
2474
|
+
const seconds = (valueInDegrees - degree) * 3600 - minutes * 60;
|
|
2475
|
+
return `${degree}°${minutes}′${seconds.toFixed(2)}″`;
|
|
2476
|
+
}
|
|
2477
|
+
if (this.isLnglat(lng, lat)) {
|
|
2478
|
+
res = formatDegreeToDMS(lng) + "," + formatDegreeToDMS(lat);
|
|
2479
|
+
} else if (!isNaN(lng)) {
|
|
2480
|
+
res = formatDegreeToDMS(lng);
|
|
2481
|
+
} else if (!isNaN(lat)) {
|
|
2482
|
+
res = formatDegreeToDMS(lat);
|
|
1683
2483
|
}
|
|
1684
|
-
return
|
|
2484
|
+
return res;
|
|
1685
2485
|
},
|
|
1686
2486
|
/**
|
|
1687
2487
|
* 将经纬度字符串转换为度
|
|
@@ -1690,20 +2490,24 @@ const V = {
|
|
|
1690
2490
|
* @param lat 纬度字符串
|
|
1691
2491
|
* @returns 转换后的经纬度对象
|
|
1692
2492
|
*/
|
|
1693
|
-
transformLnglat(
|
|
1694
|
-
function
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
2493
|
+
transformLnglat(lng, lat) {
|
|
2494
|
+
function dms2deg(dmsString) {
|
|
2495
|
+
const isNegative = /[sw]/i.test(dmsString);
|
|
2496
|
+
let factor = isNegative ? -1 : 1;
|
|
2497
|
+
const numericParts = dmsString.match(/[\d.]+/g) || [];
|
|
2498
|
+
let degrees = 0;
|
|
2499
|
+
for (let i = 0; i < numericParts.length; i++) {
|
|
2500
|
+
degrees += parseFloat(numericParts[i]) / factor;
|
|
2501
|
+
factor *= 60;
|
|
2502
|
+
}
|
|
2503
|
+
return degrees;
|
|
1701
2504
|
}
|
|
1702
|
-
if (
|
|
2505
|
+
if (lng && lat) {
|
|
1703
2506
|
return {
|
|
1704
|
-
lng:
|
|
1705
|
-
lat:
|
|
2507
|
+
lng: dms2deg(lng),
|
|
2508
|
+
lat: dms2deg(lat)
|
|
1706
2509
|
};
|
|
2510
|
+
}
|
|
1707
2511
|
},
|
|
1708
2512
|
/**
|
|
1709
2513
|
* 射线法判断点是否在多边形内
|
|
@@ -1712,19 +2516,24 @@ const V = {
|
|
|
1712
2516
|
* @param poly 多边形顶点数组,可以是字符串数组或对象数组
|
|
1713
2517
|
* @returns 返回字符串,表示点相对于多边形的位置:'in'表示在多边形内,'out'表示在多边形外,'on'表示在多边形上
|
|
1714
2518
|
*/
|
|
1715
|
-
rayCasting(
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
2519
|
+
rayCasting(p, poly) {
|
|
2520
|
+
var px = p.x, py = p.y, flag = false;
|
|
2521
|
+
for (var i = 0, l = poly.length, j = l - 1; i < l; j = i, i++) {
|
|
2522
|
+
var sx = poly[i].x, sy = poly[i].y, tx = poly[j].x, ty = poly[j].y;
|
|
2523
|
+
if (sx === px && sy === py || tx === px && ty === py) {
|
|
1719
2524
|
return "on";
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
2525
|
+
}
|
|
2526
|
+
if (sy < py && ty >= py || sy >= py && ty < py) {
|
|
2527
|
+
var x = sx + (py - sy) * (tx - sx) / (ty - sy);
|
|
2528
|
+
if (x === px) {
|
|
1723
2529
|
return "on";
|
|
1724
|
-
|
|
2530
|
+
}
|
|
2531
|
+
if (x > px) {
|
|
2532
|
+
flag = !flag;
|
|
2533
|
+
}
|
|
1725
2534
|
}
|
|
1726
2535
|
}
|
|
1727
|
-
return
|
|
2536
|
+
return flag ? "in" : "out";
|
|
1728
2537
|
},
|
|
1729
2538
|
/**
|
|
1730
2539
|
* 旋转点
|
|
@@ -1734,9 +2543,10 @@ const V = {
|
|
|
1734
2543
|
* @param θ 旋转角度(顺时针旋转为正)
|
|
1735
2544
|
* @returns 旋转后点坐标
|
|
1736
2545
|
*/
|
|
1737
|
-
rotatePoint(
|
|
1738
|
-
const
|
|
1739
|
-
|
|
2546
|
+
rotatePoint(p1, p2, θ) {
|
|
2547
|
+
const x = (p1.x - p2.x) * Math.cos(Math.PI / 180 * -θ) - (p1.y - p2.y) * Math.sin(Math.PI / 180 * -θ) + p2.x;
|
|
2548
|
+
const y = (p1.x - p2.x) * Math.sin(Math.PI / 180 * -θ) + (p1.y - p2.y) * Math.cos(Math.PI / 180 * -θ) + p2.y;
|
|
2549
|
+
return { x, y };
|
|
1740
2550
|
},
|
|
1741
2551
|
/**
|
|
1742
2552
|
* 根据两个平面坐标点计算方位角和距离
|
|
@@ -1745,9 +2555,15 @@ const V = {
|
|
|
1745
2555
|
* @param p2 第二个点的坐标对象
|
|
1746
2556
|
* @returns 返回一个对象,包含angle和distance属性,分别表示两点之间的角度(以度为单位,取值范围为0~359)和距离
|
|
1747
2557
|
*/
|
|
1748
|
-
calcBearAndDis(
|
|
1749
|
-
const { x:
|
|
1750
|
-
|
|
2558
|
+
calcBearAndDis(p1, p2) {
|
|
2559
|
+
const { x: x1, y: y1 } = p1;
|
|
2560
|
+
const { x: x2, y: y2 } = p2;
|
|
2561
|
+
const dx = x2 - x1;
|
|
2562
|
+
const dy = y2 - y1;
|
|
2563
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
2564
|
+
const angleInRadians = Math.atan2(dy, dx);
|
|
2565
|
+
const angle = (angleInRadians * (180 / Math.PI) + 360 + 90) % 360;
|
|
2566
|
+
return { angle, distance };
|
|
1751
2567
|
},
|
|
1752
2568
|
/**
|
|
1753
2569
|
* 根据两个经纬度点计算方位角和距离
|
|
@@ -1756,11 +2572,19 @@ const V = {
|
|
|
1756
2572
|
* @param latlng2 第二个经纬度点
|
|
1757
2573
|
* @returns 包含方位角和距离的对象
|
|
1758
2574
|
*/
|
|
1759
|
-
calcBearAndDisByPoints(
|
|
1760
|
-
var
|
|
2575
|
+
calcBearAndDisByPoints(latlng1, latlng2) {
|
|
2576
|
+
var f1 = latlng1.lat * 1, l1 = latlng1.lng * 1, f2 = latlng2.lat * 1, l2 = latlng2.lng * 1;
|
|
2577
|
+
var y = Math.sin((l2 - l1) * this.toRadian) * Math.cos(f2 * this.toRadian);
|
|
2578
|
+
var x = Math.cos(f1 * this.toRadian) * Math.sin(f2 * this.toRadian) - Math.sin(f1 * this.toRadian) * Math.cos(f2 * this.toRadian) * Math.cos((l2 - l1) * this.toRadian);
|
|
2579
|
+
var angle = Math.atan2(y, x) * (180 / Math.PI);
|
|
2580
|
+
var deltaF = (f2 - f1) * this.toRadian;
|
|
2581
|
+
var deltaL = (l2 - l1) * this.toRadian;
|
|
2582
|
+
var a = Math.sin(deltaF / 2) * Math.sin(deltaF / 2) + Math.cos(f1 * this.toRadian) * Math.cos(f2 * this.toRadian) * Math.sin(deltaL / 2) * Math.sin(deltaL / 2);
|
|
2583
|
+
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
2584
|
+
var distance = this.R * c;
|
|
1761
2585
|
return {
|
|
1762
|
-
angle
|
|
1763
|
-
distance
|
|
2586
|
+
angle,
|
|
2587
|
+
distance
|
|
1764
2588
|
};
|
|
1765
2589
|
},
|
|
1766
2590
|
/**
|
|
@@ -1771,15 +2595,20 @@ const V = {
|
|
|
1771
2595
|
* @param p2 线段终点P2的坐标
|
|
1772
2596
|
* @returns 点P到线段P1P2的最短距离
|
|
1773
2597
|
*/
|
|
1774
|
-
distanceToSegment(
|
|
1775
|
-
const
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
2598
|
+
distanceToSegment(p, p1, p2) {
|
|
2599
|
+
const x = p.x, y = p.y, x1 = p1.x, y1 = p1.y, x2 = p2.x, y2 = p2.y;
|
|
2600
|
+
const cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);
|
|
2601
|
+
if (cross <= 0) {
|
|
2602
|
+
return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
|
|
2603
|
+
}
|
|
2604
|
+
const d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
|
|
2605
|
+
if (cross >= d2) {
|
|
2606
|
+
return Math.sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
|
|
2607
|
+
}
|
|
2608
|
+
const r = cross / d2;
|
|
2609
|
+
const px = x1 + (x2 - x1) * r;
|
|
2610
|
+
const py = y1 + (y2 - y1) * r;
|
|
2611
|
+
return Math.sqrt((x - px) * (x - px) + (y - py) * (y - py));
|
|
1783
2612
|
},
|
|
1784
2613
|
/**
|
|
1785
2614
|
* 根据给定的经纬度、角度和距离计算新的经纬度点
|
|
@@ -1789,13 +2618,16 @@ const V = {
|
|
|
1789
2618
|
* @param distance 距离值,单位为米,表示从当前点出发的距离
|
|
1790
2619
|
* @returns 返回计算后的新经纬度点,类型为{lat: number, lng: number}
|
|
1791
2620
|
*/
|
|
1792
|
-
calcPointByBearAndDis(
|
|
1793
|
-
const
|
|
1794
|
-
|
|
1795
|
-
const
|
|
2621
|
+
calcPointByBearAndDis(latlng, angle, distance) {
|
|
2622
|
+
const sLat = MathUtils.deg2Rad(latlng.lat * 1);
|
|
2623
|
+
const sLng = MathUtils.deg2Rad(latlng.lng * 1);
|
|
2624
|
+
const d = distance / this.R;
|
|
2625
|
+
angle = MathUtils.deg2Rad(angle);
|
|
2626
|
+
const lat = Math.asin(Math.sin(sLat) * Math.cos(d) + Math.cos(sLat) * Math.sin(d) * Math.cos(angle));
|
|
2627
|
+
const lon = sLng + Math.atan2(Math.sin(angle) * Math.sin(d) * Math.cos(sLat), Math.cos(d) - Math.sin(sLat) * Math.sin(lat));
|
|
1796
2628
|
return {
|
|
1797
|
-
lat:
|
|
1798
|
-
lng:
|
|
2629
|
+
lat: MathUtils.rad2Deg(lat),
|
|
2630
|
+
lng: MathUtils.rad2Deg(lon)
|
|
1799
2631
|
};
|
|
1800
2632
|
},
|
|
1801
2633
|
/**
|
|
@@ -1805,11 +2637,11 @@ const V = {
|
|
|
1805
2637
|
* @param y 墨卡托坐标的y值
|
|
1806
2638
|
* @returns 返回包含转换后的经度lng和纬度lat的对象
|
|
1807
2639
|
*/
|
|
1808
|
-
mercatorTolonlat(
|
|
1809
|
-
const
|
|
1810
|
-
var
|
|
1811
|
-
const
|
|
1812
|
-
return { lng
|
|
2640
|
+
mercatorTolonlat(x, y) {
|
|
2641
|
+
const lng = x / 2003750834e-2 * 180;
|
|
2642
|
+
var mmy = y / 2003750834e-2 * 180;
|
|
2643
|
+
const lat = 180 / Math.PI * (2 * Math.atan(Math.exp(mmy * Math.PI / 180)) - Math.PI / 2);
|
|
2644
|
+
return { lng, lat };
|
|
1813
2645
|
},
|
|
1814
2646
|
/**
|
|
1815
2647
|
* 将经纬度坐标转换为墨卡托坐标
|
|
@@ -1818,12 +2650,12 @@ const V = {
|
|
|
1818
2650
|
* @param lat 纬度值
|
|
1819
2651
|
* @returns 墨卡托坐标对象,包含x和y属性
|
|
1820
2652
|
*/
|
|
1821
|
-
lonlatToMercator(
|
|
1822
|
-
var
|
|
1823
|
-
const
|
|
1824
|
-
var
|
|
1825
|
-
const
|
|
1826
|
-
return { x
|
|
2653
|
+
lonlatToMercator(lng, lat) {
|
|
2654
|
+
var earthRad = 6378137;
|
|
2655
|
+
const x = lng * Math.PI / 180 * earthRad;
|
|
2656
|
+
var a = lat * Math.PI / 180;
|
|
2657
|
+
const y = earthRad / 2 * Math.log((1 + Math.sin(a)) / (1 - Math.sin(a)));
|
|
2658
|
+
return { x, y };
|
|
1827
2659
|
},
|
|
1828
2660
|
/**
|
|
1829
2661
|
* 根据百分比获取坐标
|
|
@@ -1833,23 +2665,28 @@ const V = {
|
|
|
1833
2665
|
* @param percent 百分比,取值范围0-1
|
|
1834
2666
|
* @returns 返回插值后的坐标
|
|
1835
2667
|
*/
|
|
1836
|
-
interpolate({ x:
|
|
1837
|
-
const
|
|
1838
|
-
return { x:
|
|
2668
|
+
interpolate({ x: x1, y: y1, z: z1 = 0 }, { x: x2, y: y2, z: z2 = 0 }, percent) {
|
|
2669
|
+
const dx = x2 - x1, dy = y2 - y1, dz = z2 - z1;
|
|
2670
|
+
return { x: x1 + dx * percent, y: y1 + dy * percent, z: z1 + dz * percent };
|
|
1839
2671
|
}
|
|
1840
|
-
}
|
|
2672
|
+
};
|
|
2673
|
+
const FileUtil = {
|
|
1841
2674
|
/**
|
|
1842
2675
|
* 将Base64编码的字符串转换为Blob对象
|
|
1843
2676
|
*
|
|
1844
2677
|
* @param data Base64编码的字符串
|
|
1845
2678
|
* @returns 转换后的Blob对象
|
|
1846
2679
|
*/
|
|
1847
|
-
convertBase64ToBlob(
|
|
1848
|
-
const
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
2680
|
+
convertBase64ToBlob(data) {
|
|
2681
|
+
const mimeString = data.split(",")[0].split(":")[1].split(";")[0];
|
|
2682
|
+
const byteCharacters = atob(data.split(",")[1]);
|
|
2683
|
+
const byteNumbers = new Array(byteCharacters.length);
|
|
2684
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
2685
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
2686
|
+
}
|
|
2687
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
2688
|
+
const blob = new Blob([byteArray], { type: mimeString });
|
|
2689
|
+
return blob;
|
|
1853
2690
|
},
|
|
1854
2691
|
/**
|
|
1855
2692
|
* 将图片的URL转换为Base64编码
|
|
@@ -1866,11 +2703,17 @@ const V = {
|
|
|
1866
2703
|
* @param filename 文件的名称
|
|
1867
2704
|
* @returns 返回文件对象
|
|
1868
2705
|
*/
|
|
1869
|
-
convertBase64ToFile(
|
|
1870
|
-
const
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
2706
|
+
convertBase64ToFile(dataurl, filename) {
|
|
2707
|
+
const arr = dataurl.split(",");
|
|
2708
|
+
const mimeMatch = arr[0].match(/:(.*?);/);
|
|
2709
|
+
const mime = mimeMatch ? mimeMatch[1] : "image/png";
|
|
2710
|
+
const bstr = atob(arr[1]);
|
|
2711
|
+
const u8arr = new Uint8Array(bstr.length);
|
|
2712
|
+
for (let i = 0; i < bstr.length; i++) {
|
|
2713
|
+
u8arr[i] = bstr.charCodeAt(i);
|
|
2714
|
+
}
|
|
2715
|
+
const file = new File([u8arr], filename, { type: mime });
|
|
2716
|
+
return file;
|
|
1874
2717
|
},
|
|
1875
2718
|
/**
|
|
1876
2719
|
* 从文件下载数据
|
|
@@ -1878,22 +2721,27 @@ const V = {
|
|
|
1878
2721
|
* @param data 要下载的数据,可以是字符串数组、BlobPart 或 MediaSource
|
|
1879
2722
|
* @param saveName 下载后文件的保存名称
|
|
1880
2723
|
*/
|
|
1881
|
-
downloadFromFile(
|
|
1882
|
-
if (typeof
|
|
1883
|
-
if (
|
|
1884
|
-
|
|
1885
|
-
else {
|
|
1886
|
-
const
|
|
1887
|
-
|
|
2724
|
+
downloadFromFile(data, saveName) {
|
|
2725
|
+
if (typeof data == "object") {
|
|
2726
|
+
if (data instanceof Blob) {
|
|
2727
|
+
data = URL.createObjectURL(data);
|
|
2728
|
+
} else {
|
|
2729
|
+
const str = JSON.stringify(data);
|
|
2730
|
+
const blob = new Blob([str], { type: "text/json" });
|
|
2731
|
+
data = window.URL.createObjectURL(blob);
|
|
1888
2732
|
}
|
|
1889
|
-
else if (typeof
|
|
1890
|
-
const
|
|
1891
|
-
|
|
2733
|
+
} else if (typeof data == "string" && data.indexOf("http") === -1) {
|
|
2734
|
+
const blob = new Blob([data], { type: "text/json" });
|
|
2735
|
+
data = window.URL.createObjectURL(blob);
|
|
1892
2736
|
}
|
|
1893
|
-
var
|
|
1894
|
-
|
|
2737
|
+
var link = document.createElement("a");
|
|
2738
|
+
link.href = data;
|
|
2739
|
+
link.download = saveName || "";
|
|
2740
|
+
link.click();
|
|
2741
|
+
window.URL.revokeObjectURL(link.href);
|
|
1895
2742
|
}
|
|
1896
|
-
}
|
|
2743
|
+
};
|
|
2744
|
+
const OptimizeUtil = {
|
|
1897
2745
|
/**
|
|
1898
2746
|
* 防抖函数,在指定的等待时间内,如果连续触发事件,则只在最后一次触发后执行函数。适用于像搜索输入框这种需要用户停止输入后才调用的场景
|
|
1899
2747
|
*
|
|
@@ -1902,16 +2750,35 @@ const V = {
|
|
|
1902
2750
|
* @param immediate 是否立即执行函数,默认为true。
|
|
1903
2751
|
* @returns 返回防抖后的函数。
|
|
1904
2752
|
*/
|
|
1905
|
-
debounce(
|
|
1906
|
-
let
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
2753
|
+
debounce(func, wait, immediate = true) {
|
|
2754
|
+
let timeout = null;
|
|
2755
|
+
let args;
|
|
2756
|
+
let timestamp;
|
|
2757
|
+
let result;
|
|
2758
|
+
const later = () => {
|
|
2759
|
+
const last = Date.now() - timestamp;
|
|
2760
|
+
if (last < wait && last > 0) {
|
|
2761
|
+
timeout = setTimeout(later, wait - last);
|
|
2762
|
+
} else {
|
|
2763
|
+
timeout = null;
|
|
2764
|
+
if (!immediate) {
|
|
2765
|
+
result = func.apply(this, args);
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
1910
2768
|
};
|
|
1911
|
-
return (...
|
|
1912
|
-
|
|
1913
|
-
const
|
|
1914
|
-
|
|
2769
|
+
return (...args2) => {
|
|
2770
|
+
timestamp = Date.now();
|
|
2771
|
+
const callNow = immediate && !timeout;
|
|
2772
|
+
if (!timeout) {
|
|
2773
|
+
timeout = setTimeout(later, wait);
|
|
2774
|
+
}
|
|
2775
|
+
if (callNow) {
|
|
2776
|
+
result = func.apply(this, args2);
|
|
2777
|
+
if (!timeout) {
|
|
2778
|
+
args2 = null;
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
return result;
|
|
1915
2782
|
};
|
|
1916
2783
|
},
|
|
1917
2784
|
/**
|
|
@@ -1922,15 +2789,24 @@ const V = {
|
|
|
1922
2789
|
* @param type 节流类型,1表示时间戳方式,2表示定时器方式
|
|
1923
2790
|
* @returns 返回一个新的函数,该函数在节流控制下执行传入的函数
|
|
1924
2791
|
*/
|
|
1925
|
-
throttle(
|
|
1926
|
-
let
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
2792
|
+
throttle(func, wait, type = 1) {
|
|
2793
|
+
let previous = 0;
|
|
2794
|
+
let timeout = null;
|
|
2795
|
+
return (...args) => {
|
|
2796
|
+
if (type === 1) {
|
|
2797
|
+
const now = Date.now();
|
|
2798
|
+
if (now - previous >= wait) {
|
|
2799
|
+
func.apply(this, args);
|
|
2800
|
+
previous = now;
|
|
2801
|
+
}
|
|
2802
|
+
} else if (type === 2) {
|
|
2803
|
+
if (!timeout) {
|
|
2804
|
+
timeout = setTimeout(() => {
|
|
2805
|
+
timeout = null;
|
|
2806
|
+
func.apply(this, args);
|
|
2807
|
+
}, wait);
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
1934
2810
|
};
|
|
1935
2811
|
},
|
|
1936
2812
|
/**
|
|
@@ -1939,15 +2815,16 @@ const V = {
|
|
|
1939
2815
|
* @param fn 传入待缓存的函数
|
|
1940
2816
|
* @returns 返回缓存后的函数
|
|
1941
2817
|
*/
|
|
1942
|
-
memoize(
|
|
1943
|
-
const
|
|
1944
|
-
return (...
|
|
1945
|
-
const
|
|
1946
|
-
if (
|
|
1947
|
-
return
|
|
1948
|
-
{
|
|
1949
|
-
const
|
|
1950
|
-
|
|
2818
|
+
memoize(fn) {
|
|
2819
|
+
const cache = /* @__PURE__ */ new Map();
|
|
2820
|
+
return (...args) => {
|
|
2821
|
+
const argsString = JSON.stringify(args);
|
|
2822
|
+
if (cache.has(argsString)) {
|
|
2823
|
+
return cache.get(argsString);
|
|
2824
|
+
} else {
|
|
2825
|
+
const result = fn.apply(this, args);
|
|
2826
|
+
cache.set(argsString, result);
|
|
2827
|
+
return result;
|
|
1951
2828
|
}
|
|
1952
2829
|
};
|
|
1953
2830
|
},
|
|
@@ -1958,13 +2835,33 @@ const V = {
|
|
|
1958
2835
|
* @param frequency 每次调用函数之间的时间间隔,单位为毫秒,默认为500毫秒。
|
|
1959
2836
|
* @param duration 函数递归调用的总时长,单位为毫秒,默认为5000毫秒。
|
|
1960
2837
|
*/
|
|
1961
|
-
recurve(
|
|
1962
|
-
let
|
|
2838
|
+
recurve(fun, frequency = 500, duration = 5e3) {
|
|
2839
|
+
let timer = 0;
|
|
1963
2840
|
setTimeout(() => {
|
|
1964
|
-
|
|
1965
|
-
|
|
2841
|
+
timer++;
|
|
2842
|
+
if (timer < Math.floor(duration / frequency)) {
|
|
2843
|
+
fun.call(this);
|
|
2844
|
+
setTimeout(this.recurve.bind(this, fun, frequency, duration), frequency);
|
|
2845
|
+
}
|
|
2846
|
+
}, frequency);
|
|
2847
|
+
},
|
|
2848
|
+
/**
|
|
2849
|
+
* 确保函数只被调用一次
|
|
2850
|
+
*
|
|
2851
|
+
* @param func 要被调用的函数
|
|
2852
|
+
* @returns 返回一个新的函数,该函数在被首次调用时会执行传入的函数,之后再次调用将不再执行
|
|
2853
|
+
*/
|
|
2854
|
+
once(func) {
|
|
2855
|
+
let called = false;
|
|
2856
|
+
return function(...args) {
|
|
2857
|
+
if (!called) {
|
|
2858
|
+
called = true;
|
|
2859
|
+
return func(...args);
|
|
2860
|
+
}
|
|
2861
|
+
};
|
|
1966
2862
|
}
|
|
1967
|
-
}
|
|
2863
|
+
};
|
|
2864
|
+
const StringUtil = {
|
|
1968
2865
|
/**
|
|
1969
2866
|
* 校验字符串是否符合指定类型
|
|
1970
2867
|
*
|
|
@@ -1989,44 +2886,44 @@ const V = {
|
|
|
1989
2886
|
* - 'HTML': HTML标记
|
|
1990
2887
|
* @returns 校验结果,符合返回true,否则返回false
|
|
1991
2888
|
*/
|
|
1992
|
-
checkStr(
|
|
1993
|
-
switch (
|
|
2889
|
+
checkStr(str, type) {
|
|
2890
|
+
switch (type) {
|
|
1994
2891
|
case "phone":
|
|
1995
|
-
return /^1[3|4|5|6|7|8|9][0-9]{9}$/.test(
|
|
2892
|
+
return /^1[3|4|5|6|7|8|9][0-9]{9}$/.test(str);
|
|
1996
2893
|
case "tel":
|
|
1997
|
-
return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(
|
|
2894
|
+
return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);
|
|
1998
2895
|
case "card":
|
|
1999
|
-
return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(
|
|
2896
|
+
return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(str);
|
|
2000
2897
|
case "pwd":
|
|
2001
|
-
return /^[a-zA-Z]\w{5,17}$/.test(
|
|
2898
|
+
return /^[a-zA-Z]\w{5,17}$/.test(str);
|
|
2002
2899
|
case "postal":
|
|
2003
|
-
return /[1-9]\d{5}(?!\d)/.test(
|
|
2900
|
+
return /[1-9]\d{5}(?!\d)/.test(str);
|
|
2004
2901
|
case "QQ":
|
|
2005
|
-
return /^[1-9][0-9]{4,9}$/.test(
|
|
2902
|
+
return /^[1-9][0-9]{4,9}$/.test(str);
|
|
2006
2903
|
case "email":
|
|
2007
|
-
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(
|
|
2904
|
+
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
|
|
2008
2905
|
case "money":
|
|
2009
|
-
return /^\d*(?:\.\d{0,2})?$/.test(
|
|
2906
|
+
return /^\d*(?:\.\d{0,2})?$/.test(str);
|
|
2010
2907
|
case "URL":
|
|
2011
|
-
return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(
|
|
2908
|
+
return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(str);
|
|
2012
2909
|
case "IP":
|
|
2013
|
-
return /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/.test(
|
|
2910
|
+
return /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/.test(str);
|
|
2014
2911
|
case "date":
|
|
2015
|
-
return /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/.test(
|
|
2912
|
+
return /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/.test(str) || /^(\d{4})\-(\d{2})\-(\d{2})$/.test(str);
|
|
2016
2913
|
case "number":
|
|
2017
|
-
return /^[0-9]$/.test(
|
|
2914
|
+
return /^[0-9]$/.test(str);
|
|
2018
2915
|
case "english":
|
|
2019
|
-
return /^[a-zA-Z]+$/.test(
|
|
2916
|
+
return /^[a-zA-Z]+$/.test(str);
|
|
2020
2917
|
case "chinese":
|
|
2021
|
-
return /^[\u4E00-\u9FA5]+$/.test(
|
|
2918
|
+
return /^[\u4E00-\u9FA5]+$/.test(str);
|
|
2022
2919
|
case "lower":
|
|
2023
|
-
return /^[a-z]+$/.test(
|
|
2920
|
+
return /^[a-z]+$/.test(str);
|
|
2024
2921
|
case "upper":
|
|
2025
|
-
return /^[A-Z]+$/.test(
|
|
2922
|
+
return /^[A-Z]+$/.test(str);
|
|
2026
2923
|
case "HTML":
|
|
2027
|
-
return /<("[^"]*"|'[^']*'|[^'">])*>/.test(
|
|
2924
|
+
return /<("[^"]*"|'[^']*'|[^'">])*>/.test(str);
|
|
2028
2925
|
default:
|
|
2029
|
-
return
|
|
2926
|
+
return true;
|
|
2030
2927
|
}
|
|
2031
2928
|
},
|
|
2032
2929
|
/**
|
|
@@ -2041,26 +2938,31 @@ const V = {
|
|
|
2041
2938
|
* 5:全部小写
|
|
2042
2939
|
* @returns 转换后的字符串
|
|
2043
2940
|
*/
|
|
2044
|
-
changeCase(
|
|
2045
|
-
|
|
2941
|
+
changeCase(str, type) {
|
|
2942
|
+
type = type || 4;
|
|
2943
|
+
switch (type) {
|
|
2046
2944
|
case 1:
|
|
2047
|
-
return
|
|
2048
|
-
return
|
|
2945
|
+
return str.replace(/\b\w+\b/g, function(word) {
|
|
2946
|
+
return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase();
|
|
2049
2947
|
});
|
|
2050
2948
|
case 2:
|
|
2051
|
-
return
|
|
2052
|
-
return
|
|
2949
|
+
return str.replace(/\b\w+\b/g, function(word) {
|
|
2950
|
+
return word.substring(0, 1).toLowerCase() + word.substring(1).toUpperCase();
|
|
2053
2951
|
});
|
|
2054
2952
|
case 3:
|
|
2055
|
-
return
|
|
2056
|
-
|
|
2953
|
+
return str.split("").map(function(word) {
|
|
2954
|
+
if (/[a-z]/.test(word)) {
|
|
2955
|
+
return word.toUpperCase();
|
|
2956
|
+
} else {
|
|
2957
|
+
return word.toLowerCase();
|
|
2958
|
+
}
|
|
2057
2959
|
}).join("");
|
|
2058
2960
|
case 4:
|
|
2059
|
-
return
|
|
2961
|
+
return str.toUpperCase();
|
|
2060
2962
|
case 5:
|
|
2061
|
-
return
|
|
2963
|
+
return str.toLowerCase();
|
|
2062
2964
|
default:
|
|
2063
|
-
return
|
|
2965
|
+
return str;
|
|
2064
2966
|
}
|
|
2065
2967
|
},
|
|
2066
2968
|
/**
|
|
@@ -2070,17 +2972,18 @@ const V = {
|
|
|
2070
2972
|
* @param args 可变参数列表,支持 Object、Array 类型和任意其他类型,若为 null 或 undefined,则按类型默认转换为 '{}'、'[]' 或 ''
|
|
2071
2973
|
* @returns 返回生成的新字符串
|
|
2072
2974
|
*/
|
|
2073
|
-
tag(
|
|
2074
|
-
|
|
2075
|
-
switch (
|
|
2975
|
+
tag(strArray, ...args) {
|
|
2976
|
+
args = args.map((val) => {
|
|
2977
|
+
switch (CommUtils.getDataType(val)) {
|
|
2076
2978
|
case "Object":
|
|
2077
|
-
return
|
|
2979
|
+
return val || "{}";
|
|
2078
2980
|
case "Array":
|
|
2079
|
-
return
|
|
2981
|
+
return val || "[]";
|
|
2080
2982
|
default:
|
|
2081
|
-
return
|
|
2983
|
+
return val || "";
|
|
2082
2984
|
}
|
|
2083
|
-
})
|
|
2985
|
+
});
|
|
2986
|
+
return strArray.reduce((prev, next, index) => `${prev}${args[index - 1]}${next}`);
|
|
2084
2987
|
},
|
|
2085
2988
|
/**
|
|
2086
2989
|
* 计算字符串的字节长度
|
|
@@ -2088,8 +2991,8 @@ const V = {
|
|
|
2088
2991
|
* @param str 需要计算字节长度的字符串
|
|
2089
2992
|
* @returns 返回字符串的字节长度
|
|
2090
2993
|
*/
|
|
2091
|
-
getByteLength(
|
|
2092
|
-
return
|
|
2994
|
+
getByteLength(str) {
|
|
2995
|
+
return str.replace(/[\u0391-\uFFE5]/g, "aa").length;
|
|
2093
2996
|
},
|
|
2094
2997
|
/**
|
|
2095
2998
|
* 截取字符串中指定字节长度的子串
|
|
@@ -2099,112 +3002,39 @@ const V = {
|
|
|
2099
3002
|
* @param n 截取字节长度
|
|
2100
3003
|
* @returns 返回截取后的子串
|
|
2101
3004
|
*/
|
|
2102
|
-
subStringByte(
|
|
3005
|
+
subStringByte(str, start, n) {
|
|
2103
3006
|
var r = /[^\x00-\xff]/g;
|
|
2104
|
-
if (
|
|
2105
|
-
return
|
|
2106
|
-
for (var i = Math.floor(n / 2), o = i; o < t.length; o++) {
|
|
2107
|
-
let a = t.substring(e, o);
|
|
2108
|
-
if (a.replace(r, "mm").length >= n)
|
|
2109
|
-
return a;
|
|
2110
|
-
}
|
|
2111
|
-
return t;
|
|
2112
|
-
},
|
|
2113
|
-
/**
|
|
2114
|
-
* 将值转换为字符串
|
|
2115
|
-
*
|
|
2116
|
-
* @param value 要转换的值
|
|
2117
|
-
* @returns 转换后的字符串,如果值为空,则返回空字符串
|
|
2118
|
-
*/
|
|
2119
|
-
asString(t) {
|
|
2120
|
-
if (M.isEmpty(t))
|
|
2121
|
-
return "";
|
|
2122
|
-
switch (M.getDataType(t)) {
|
|
2123
|
-
case "Object":
|
|
2124
|
-
case "Array":
|
|
2125
|
-
return JSON.stringify(t);
|
|
2126
|
-
default:
|
|
2127
|
-
return t;
|
|
2128
|
-
}
|
|
2129
|
-
},
|
|
2130
|
-
replaceAll(t, e, n) {
|
|
2131
|
-
if (!t)
|
|
2132
|
-
return t;
|
|
2133
|
-
for (; t.indexOf(e) > -1; )
|
|
2134
|
-
t = t.replace(e, n);
|
|
2135
|
-
return t;
|
|
2136
|
-
}
|
|
2137
|
-
}, p = class p {
|
|
2138
|
-
static set(e, n = null, r = null) {
|
|
2139
|
-
var i = this._getPrefixedKey(e, r);
|
|
2140
|
-
try {
|
|
2141
|
-
localStorage.setItem(i, JSON.stringify({ data: n }));
|
|
2142
|
-
} catch {
|
|
2143
|
-
console && console.warn("StoreUtil didn't successfully save the '{" + e + ": " + n + "}' pair, because the localStorage is full.");
|
|
2144
|
-
}
|
|
2145
|
-
}
|
|
2146
|
-
static get(e, n, r) {
|
|
2147
|
-
var i = this._getPrefixedKey(e, r), o;
|
|
2148
|
-
try {
|
|
2149
|
-
o = JSON.parse(localStorage.getItem(i) || "");
|
|
2150
|
-
} catch {
|
|
2151
|
-
localStorage[i] ? o = { data: localStorage.getItem(i) } : o = null;
|
|
3007
|
+
if (str.replace(r, "mm").length <= n) {
|
|
3008
|
+
return str;
|
|
2152
3009
|
}
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
const e = [];
|
|
2160
|
-
var n = Object.keys(localStorage);
|
|
2161
|
-
return p.prefix.length === 0 ? n : (n.forEach(function(r) {
|
|
2162
|
-
r.indexOf(p.prefix) !== -1 && e.push(r.replace(p.prefix, ""));
|
|
2163
|
-
}), e);
|
|
2164
|
-
}
|
|
2165
|
-
static getAll(e) {
|
|
2166
|
-
var n = p.keys();
|
|
2167
|
-
if (e) {
|
|
2168
|
-
const r = [];
|
|
2169
|
-
return n.forEach((i) => {
|
|
2170
|
-
if (e.includes(i)) {
|
|
2171
|
-
const o = {};
|
|
2172
|
-
o[i] = p.get(i, null, null), r.push(o);
|
|
2173
|
-
}
|
|
2174
|
-
}), r;
|
|
3010
|
+
var m = Math.floor(n / 2);
|
|
3011
|
+
for (var i = m; i < str.length; i++) {
|
|
3012
|
+
let sub = str.substring(start, i);
|
|
3013
|
+
if (sub.replace(r, "mm").length >= n) {
|
|
3014
|
+
return sub;
|
|
3015
|
+
}
|
|
2175
3016
|
}
|
|
2176
|
-
return
|
|
2177
|
-
}
|
|
2178
|
-
static remove(e, n) {
|
|
2179
|
-
var r = this._getPrefixedKey(e, n);
|
|
2180
|
-
localStorage.removeItem(r);
|
|
2181
|
-
}
|
|
2182
|
-
static clear(e) {
|
|
2183
|
-
p.prefix.length ? this.keys().forEach((n) => {
|
|
2184
|
-
localStorage.removeItem(this._getPrefixedKey(n, e));
|
|
2185
|
-
}) : localStorage.clear();
|
|
3017
|
+
return str;
|
|
2186
3018
|
}
|
|
2187
3019
|
};
|
|
2188
|
-
|
|
2189
|
-
return n = n || {}, n.noPrefix ? e : p.prefix + e;
|
|
2190
|
-
});
|
|
2191
|
-
let I = p;
|
|
2192
|
-
const rt = {
|
|
3020
|
+
const UrlUtil = {
|
|
2193
3021
|
/**
|
|
2194
3022
|
* 将json对象转换为查询字符串
|
|
2195
3023
|
*
|
|
2196
3024
|
* @param json 待转换的json对象
|
|
2197
3025
|
* @returns 转换后的查询字符串
|
|
2198
3026
|
*/
|
|
2199
|
-
json2Query(
|
|
2200
|
-
var
|
|
2201
|
-
for (var
|
|
2202
|
-
if (
|
|
2203
|
-
var
|
|
2204
|
-
|
|
3027
|
+
json2Query(json) {
|
|
3028
|
+
var tempArr = [];
|
|
3029
|
+
for (var i in json) {
|
|
3030
|
+
if (json.hasOwnProperty(i)) {
|
|
3031
|
+
var key = i;
|
|
3032
|
+
var value = json[i];
|
|
3033
|
+
tempArr.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
|
|
2205
3034
|
}
|
|
2206
|
-
|
|
2207
|
-
|
|
3035
|
+
}
|
|
3036
|
+
var urlParamsStr = tempArr.join("&");
|
|
3037
|
+
return urlParamsStr;
|
|
2208
3038
|
},
|
|
2209
3039
|
/**
|
|
2210
3040
|
* 从 URL 中解析出查询参数和哈希参数,并以对象的形式返回
|
|
@@ -2213,54 +3043,60 @@ const rt = {
|
|
|
2213
3043
|
* @param needDecode 是否需要解码参数值,默认为 true
|
|
2214
3044
|
* @returns 返回一个包含解析后参数的对象,其中键为参数名,值为参数值
|
|
2215
3045
|
*/
|
|
2216
|
-
query2Json(
|
|
2217
|
-
const
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
3046
|
+
query2Json(href = window.location.href, needDecode = true) {
|
|
3047
|
+
const reg = /([^&=]+)=([\w\W]*?)(&|$|#)/g;
|
|
3048
|
+
const { search, hash } = new URL(href);
|
|
3049
|
+
const args = [search, hash];
|
|
3050
|
+
let obj = {};
|
|
3051
|
+
for (let i = 0; i < args.length; i++) {
|
|
3052
|
+
const str = args[i];
|
|
3053
|
+
if (str) {
|
|
3054
|
+
const s = str.replace(/#|\//g, "");
|
|
3055
|
+
const arr = s.split("?");
|
|
3056
|
+
if (arr.length > 1) {
|
|
3057
|
+
for (let j = 1; j < arr.length; j++) {
|
|
3058
|
+
let res;
|
|
3059
|
+
while (res = reg.exec(arr[j])) {
|
|
3060
|
+
obj[res[1]] = needDecode ? decodeURIComponent(res[2]) : res[2];
|
|
3061
|
+
}
|
|
2228
3062
|
}
|
|
3063
|
+
}
|
|
2229
3064
|
}
|
|
2230
3065
|
}
|
|
2231
|
-
return
|
|
3066
|
+
return obj;
|
|
2232
3067
|
}
|
|
2233
3068
|
};
|
|
2234
3069
|
export {
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
3070
|
+
AjaxUtil,
|
|
3071
|
+
ArrayUtil,
|
|
3072
|
+
AudioPlayer,
|
|
3073
|
+
BrowserUtil,
|
|
3074
|
+
CanvasDrawer,
|
|
3075
|
+
ColorUtil,
|
|
3076
|
+
Cookie,
|
|
3077
|
+
CoordsUtil,
|
|
3078
|
+
DateUtil,
|
|
3079
|
+
DomUtil,
|
|
3080
|
+
ErrorType,
|
|
3081
|
+
EventDispatcher,
|
|
3082
|
+
EventType,
|
|
3083
|
+
FileUtil,
|
|
3084
|
+
GeoJsonUtil,
|
|
3085
|
+
GeoUtil,
|
|
3086
|
+
GraphicType,
|
|
3087
|
+
HashMap,
|
|
3088
|
+
ImageUtil,
|
|
3089
|
+
LayerType,
|
|
3090
|
+
LineSymbol,
|
|
3091
|
+
MathUtils as MathUtil,
|
|
3092
|
+
MeasureMode,
|
|
3093
|
+
MqttClient,
|
|
3094
|
+
ObjectState,
|
|
3095
|
+
ObjectUtil,
|
|
3096
|
+
OptimizeUtil,
|
|
3097
|
+
Storage,
|
|
3098
|
+
StringUtil,
|
|
3099
|
+
UrlUtil,
|
|
3100
|
+
CommUtils as Util,
|
|
3101
|
+
WebSocketClient
|
|
2266
3102
|
};
|