gis-common 4.1.8 → 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/EventDispatcher.d.ts +1 -1
- package/dist/core/MqttClient.d.ts +33 -0
- package/dist/core/Storage.d.ts +28 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/gis-common.es.js +2011 -1081
- package/dist/gis-common.umd.js +1 -1
- package/dist/utils/AjaxUtil.d.ts +7 -7
- package/dist/utils/ArrayUtil.d.ts +2 -3
- package/dist/utils/CommUtil.d.ts +36 -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 +5 -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,15 +1,123 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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) {
|
|
7
95
|
/**
|
|
8
96
|
* Creates an instance of AudioPlayer.
|
|
9
97
|
* @param {*} url
|
|
10
98
|
*/
|
|
11
|
-
|
|
12
|
-
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);
|
|
13
121
|
}
|
|
14
122
|
play() {
|
|
15
123
|
!this.muted && this.audio.play();
|
|
@@ -23,18 +131,44 @@ class F {
|
|
|
23
131
|
/**
|
|
24
132
|
* @description 设置静音状态,如果静音,autoplay属性将失效
|
|
25
133
|
*/
|
|
26
|
-
set muted(
|
|
27
|
-
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
|
+
}
|
|
28
162
|
}
|
|
29
163
|
}
|
|
30
|
-
const
|
|
164
|
+
const MathUtils = {
|
|
31
165
|
DEG2RAD: Math.PI / 180,
|
|
32
166
|
RAD2DEG: 180 / Math.PI,
|
|
33
|
-
randInt(
|
|
34
|
-
return
|
|
167
|
+
randInt(low, high) {
|
|
168
|
+
return low + Math.floor(Math.random() * (high - low + 1));
|
|
35
169
|
},
|
|
36
|
-
randFloat(
|
|
37
|
-
return
|
|
170
|
+
randFloat(low, high) {
|
|
171
|
+
return low + Math.random() * (high - low);
|
|
38
172
|
},
|
|
39
173
|
/**
|
|
40
174
|
* 角度转弧度
|
|
@@ -42,17 +176,8 @@ const m = {
|
|
|
42
176
|
* @param {*} degrees
|
|
43
177
|
* @returns {*}
|
|
44
178
|
*/
|
|
45
|
-
|
|
46
|
-
return
|
|
47
|
-
},
|
|
48
|
-
/**
|
|
49
|
-
* 角度转弧度
|
|
50
|
-
*
|
|
51
|
-
* @param {*} degrees
|
|
52
|
-
* @returns {*}
|
|
53
|
-
*/
|
|
54
|
-
toRadians(t) {
|
|
55
|
-
return t * this.DEG2RAD;
|
|
179
|
+
deg2Rad(degrees) {
|
|
180
|
+
return degrees * this.DEG2RAD;
|
|
56
181
|
},
|
|
57
182
|
/**
|
|
58
183
|
* 弧度转角度
|
|
@@ -60,57 +185,43 @@ const m = {
|
|
|
60
185
|
* @param {*} radians
|
|
61
186
|
* @returns {*}
|
|
62
187
|
*/
|
|
63
|
-
|
|
64
|
-
return
|
|
188
|
+
rad2Deg(radians) {
|
|
189
|
+
return radians * this.RAD2DEG;
|
|
65
190
|
},
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
*
|
|
69
|
-
* @param {*} radians
|
|
70
|
-
* @returns {*}
|
|
71
|
-
*/
|
|
72
|
-
toDegrees(t) {
|
|
73
|
-
return t * this.RAD2DEG;
|
|
74
|
-
},
|
|
75
|
-
formatFloat(t, e = 2) {
|
|
76
|
-
return Math.round(t * Math.pow(10, e)) / Math.pow(10, e);
|
|
77
|
-
},
|
|
78
|
-
/**
|
|
79
|
-
* 根据给定值返回指定的最小值和最大值之间的最小值
|
|
80
|
-
*
|
|
81
|
-
* @param val 给定的数值
|
|
82
|
-
* @param min 最小值
|
|
83
|
-
* @param max 最大值
|
|
84
|
-
* @returns 返回限制后的数值
|
|
85
|
-
*/
|
|
86
|
-
minMax(t, e, n) {
|
|
87
|
-
return Math.min(Math.max(t, e), n);
|
|
191
|
+
round(value, n = 2) {
|
|
192
|
+
return Math.round(value * Math.pow(10, n)) / Math.pow(10, n);
|
|
88
193
|
},
|
|
89
194
|
/**
|
|
90
|
-
*
|
|
195
|
+
* 将数值限制在指定范围内
|
|
91
196
|
*
|
|
92
|
-
* @param val
|
|
197
|
+
* @param val 需要限制的数值
|
|
93
198
|
* @param min 最小值
|
|
94
199
|
* @param max 最大值
|
|
95
200
|
* @returns 返回限制后的数值
|
|
96
201
|
*/
|
|
97
|
-
|
|
98
|
-
return Math.
|
|
202
|
+
clamp(val, min, max) {
|
|
203
|
+
return Math.min(Math.max(val, min), max);
|
|
99
204
|
}
|
|
100
205
|
};
|
|
101
|
-
class
|
|
102
|
-
constructor(
|
|
103
|
-
|
|
104
|
-
if (typeof
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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 {
|
|
111
220
|
throw new Error("getContext is not available on this element");
|
|
112
|
-
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
113
223
|
throw new Error("Element is not an HTMLElement");
|
|
224
|
+
}
|
|
114
225
|
}
|
|
115
226
|
/**
|
|
116
227
|
* 绘制线条
|
|
@@ -120,12 +231,18 @@ class B {
|
|
|
120
231
|
* @param options 绘制选项,包括线条宽度和颜色
|
|
121
232
|
* @throws 当画布上下文不存在时抛出错误
|
|
122
233
|
*/
|
|
123
|
-
drawLine({ x:
|
|
124
|
-
if (!this.context)
|
|
234
|
+
drawLine({ x: startX, y: startY }, { x: endX, y: endY }, options = {}) {
|
|
235
|
+
if (!this.context) {
|
|
125
236
|
throw new Error("Canvas context is null or undefined");
|
|
237
|
+
}
|
|
126
238
|
this.context.beginPath();
|
|
127
|
-
const
|
|
128
|
-
|
|
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();
|
|
129
246
|
}
|
|
130
247
|
/**
|
|
131
248
|
* 绘制圆弧
|
|
@@ -140,67 +257,107 @@ class B {
|
|
|
140
257
|
* @param bgColor 背景颜色
|
|
141
258
|
* @throws 当Canvas context为null或undefined时抛出错误
|
|
142
259
|
*/
|
|
143
|
-
drawArc({ x
|
|
144
|
-
if (!this.context)
|
|
260
|
+
drawArc({ x, y }, radius, startAngle, endAngle, anticlockwise, isFill, bgColor) {
|
|
261
|
+
if (!this.context) {
|
|
145
262
|
throw new Error("Canvas context is null or undefined");
|
|
146
|
-
|
|
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
|
+
}
|
|
147
275
|
}
|
|
148
|
-
static createCanvas(
|
|
149
|
-
let
|
|
150
|
-
if (typeof document
|
|
151
|
-
|
|
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
|
+
}
|
|
152
288
|
}
|
|
153
289
|
}
|
|
154
|
-
class
|
|
290
|
+
class EventDispatcher {
|
|
155
291
|
constructor() {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
292
|
+
__publicField(this, "_listeners");
|
|
293
|
+
__publicField(this, "_mutex", {});
|
|
294
|
+
__publicField(this, "_context");
|
|
159
295
|
}
|
|
160
|
-
addEventListener(
|
|
161
|
-
this._listeners === void 0
|
|
162
|
-
|
|
163
|
-
|
|
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;
|
|
164
311
|
}
|
|
165
|
-
hasEventListener(
|
|
166
|
-
if (this._listeners === null || this._listeners === void 0) return
|
|
167
|
-
const
|
|
168
|
-
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;
|
|
169
316
|
}
|
|
170
|
-
removeEventListener(
|
|
317
|
+
removeEventListener(type, listener) {
|
|
171
318
|
if (this._listeners === void 0) return;
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
+
}
|
|
176
329
|
}
|
|
177
330
|
}
|
|
178
|
-
dispatchEvent(
|
|
331
|
+
dispatchEvent(event) {
|
|
179
332
|
if (this._listeners === void 0) return;
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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);
|
|
188
342
|
return;
|
|
189
343
|
}
|
|
190
344
|
}
|
|
191
|
-
for (let i = 0,
|
|
192
|
-
const
|
|
193
|
-
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
|
+
}
|
|
194
350
|
}
|
|
195
351
|
}
|
|
196
352
|
}
|
|
197
353
|
removeAllListener() {
|
|
198
354
|
this._mutex = {};
|
|
199
|
-
for (const
|
|
200
|
-
this._listeners[
|
|
355
|
+
for (const key in this._listeners) {
|
|
356
|
+
this._listeners[key] = [];
|
|
357
|
+
}
|
|
201
358
|
}
|
|
202
359
|
}
|
|
203
|
-
class
|
|
360
|
+
class HashMap extends Map {
|
|
204
361
|
isEmpty() {
|
|
205
362
|
return this.size === 0;
|
|
206
363
|
}
|
|
@@ -216,109 +373,183 @@ class x extends Map {
|
|
|
216
373
|
fromEntries() {
|
|
217
374
|
}
|
|
218
375
|
}
|
|
219
|
-
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
Array.isArray(
|
|
223
|
-
|
|
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;
|
|
224
384
|
};
|
|
225
|
-
class
|
|
226
|
-
constructor(
|
|
385
|
+
class WebSocketClient extends EventDispatcher {
|
|
386
|
+
constructor(url = "ws://127.0.0.1:10088") {
|
|
227
387
|
super();
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
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);
|
|
234
398
|
}
|
|
235
399
|
connect() {
|
|
236
|
-
|
|
400
|
+
this.disconnect();
|
|
401
|
+
if (this.url) {
|
|
237
402
|
try {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
n.connectStatus = !0, n.dispatchEvent({
|
|
247
|
-
type: R.WEB_SOCKET_MESSAGE,
|
|
248
|
-
message: r
|
|
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
|
|
249
411
|
});
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
412
|
+
};
|
|
413
|
+
this.client.onmessage = function(message) {
|
|
414
|
+
self.connectStatus = true;
|
|
415
|
+
self.dispatchEvent({
|
|
416
|
+
type: EventType.WEB_SOCKET_MESSAGE,
|
|
417
|
+
message
|
|
254
418
|
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
419
|
+
};
|
|
420
|
+
this.client.onclose = function(message) {
|
|
421
|
+
self.dispatchEvent({
|
|
422
|
+
type: EventType.WEB_SOCKET_CLOSE,
|
|
423
|
+
message
|
|
259
424
|
});
|
|
260
|
-
}
|
|
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
|
+
}
|
|
261
434
|
}
|
|
262
|
-
} catch (
|
|
263
|
-
console.error("创建ws连接失败" + this.url + ":" +
|
|
435
|
+
} catch (ex) {
|
|
436
|
+
console.error("创建ws连接失败" + this.url + ":" + ex);
|
|
264
437
|
}
|
|
438
|
+
}
|
|
265
439
|
}
|
|
266
440
|
disconnect() {
|
|
267
|
-
if (this.client)
|
|
441
|
+
if (this.client) {
|
|
268
442
|
try {
|
|
269
|
-
console.log("ws断开连接" + this.url)
|
|
270
|
-
|
|
443
|
+
console.log("ws断开连接" + this.url);
|
|
444
|
+
this.client.close();
|
|
445
|
+
this.client = null;
|
|
446
|
+
} catch (ex) {
|
|
271
447
|
this.client = null;
|
|
272
448
|
}
|
|
449
|
+
}
|
|
273
450
|
}
|
|
274
|
-
connCheckStatus(
|
|
275
|
-
this.checkTimes >
|
|
276
|
-
|
|
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);
|
|
277
459
|
}, 2e3);
|
|
278
460
|
}
|
|
279
|
-
send(
|
|
280
|
-
|
|
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;
|
|
281
468
|
}
|
|
282
469
|
heartbeat() {
|
|
283
470
|
setTimeout(() => {
|
|
284
|
-
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);
|
|
285
476
|
}, 1e3);
|
|
286
477
|
}
|
|
287
478
|
}
|
|
288
|
-
const
|
|
479
|
+
const CommUtils = {
|
|
289
480
|
/**
|
|
290
481
|
* 获取数据类型
|
|
291
482
|
*
|
|
292
483
|
* @param data 待判断的数据
|
|
293
484
|
* @returns 返回数据类型字符串
|
|
294
485
|
*/
|
|
295
|
-
getDataType(
|
|
296
|
-
return Object.prototype.toString.call(
|
|
486
|
+
getDataType(data) {
|
|
487
|
+
return Object.prototype.toString.call(data).slice(8, -1);
|
|
297
488
|
},
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
489
|
+
asArray(obj) {
|
|
490
|
+
return this.isEmpty(obj) ? [] : Array.isArray(obj) ? obj : [obj];
|
|
491
|
+
},
|
|
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
|
+
}
|
|
513
|
+
},
|
|
514
|
+
/**
|
|
515
|
+
* 判断传入的值是否为空
|
|
516
|
+
*
|
|
517
|
+
* @param value 待判断的值
|
|
518
|
+
* @returns 返回布尔值,表示是否为空
|
|
519
|
+
*/
|
|
520
|
+
isEmpty(value) {
|
|
521
|
+
if (value == null) {
|
|
522
|
+
return true;
|
|
523
|
+
}
|
|
524
|
+
const type = this.getDataType(value);
|
|
525
|
+
switch (type) {
|
|
302
526
|
case "String":
|
|
303
|
-
return
|
|
527
|
+
return value.trim() === "";
|
|
304
528
|
case "Array":
|
|
305
|
-
return !
|
|
529
|
+
return !value.length;
|
|
306
530
|
case "Object":
|
|
307
|
-
return !Object.keys(
|
|
531
|
+
return !Object.keys(value).length;
|
|
308
532
|
case "Boolean":
|
|
309
|
-
return !
|
|
533
|
+
return !value;
|
|
310
534
|
default:
|
|
311
|
-
return
|
|
535
|
+
return false;
|
|
312
536
|
}
|
|
313
537
|
},
|
|
314
|
-
isNotEmpty(
|
|
315
|
-
return !this.isEmpty(
|
|
538
|
+
isNotEmpty(val) {
|
|
539
|
+
return !this.isEmpty(val);
|
|
316
540
|
},
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
541
|
+
/**
|
|
542
|
+
* 将JSON对象转换为FormData对象
|
|
543
|
+
*
|
|
544
|
+
* @param json 待转换的JSON对象,其属性值为字符串或Blob类型
|
|
545
|
+
* @returns 转换后的FormData对象
|
|
546
|
+
*/
|
|
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;
|
|
322
553
|
},
|
|
323
554
|
/**
|
|
324
555
|
* 生成GUID
|
|
@@ -326,10 +557,10 @@ const y = {
|
|
|
326
557
|
* @returns 返回一个由8个16进制数组成的GUID字符串
|
|
327
558
|
*/
|
|
328
559
|
guid() {
|
|
329
|
-
const
|
|
560
|
+
const S4 = function() {
|
|
330
561
|
return ((1 + Math.random()) * 65536 | 0).toString(16).substring(1);
|
|
331
562
|
};
|
|
332
|
-
return
|
|
563
|
+
return S4() + S4() + S4() + S4() + S4() + S4() + S4() + S4();
|
|
333
564
|
},
|
|
334
565
|
/**
|
|
335
566
|
* 将参数进行解码并返回解码后的字符串
|
|
@@ -337,18 +568,23 @@ const y = {
|
|
|
337
568
|
* @param args 参数
|
|
338
569
|
* @returns 解码后的字符串
|
|
339
570
|
*/
|
|
340
|
-
decodeDict(...
|
|
341
|
-
let
|
|
342
|
-
if (
|
|
343
|
-
const
|
|
344
|
-
for (let
|
|
345
|
-
const
|
|
346
|
-
|
|
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
|
+
}
|
|
580
|
+
}
|
|
581
|
+
if (!res && args.length % 2 === 0) {
|
|
582
|
+
res = args[args.length - 1];
|
|
347
583
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
return
|
|
584
|
+
} else {
|
|
585
|
+
res = args[0];
|
|
586
|
+
}
|
|
587
|
+
return res;
|
|
352
588
|
},
|
|
353
589
|
/**
|
|
354
590
|
* 将一个或多个对象的所有可枚举属性复制到目标对象。
|
|
@@ -357,14 +593,15 @@ const y = {
|
|
|
357
593
|
* @param args 一个或多个源对象,用于提供要复制的属性。
|
|
358
594
|
* @returns 返回目标对象,包含所有复制的属性。
|
|
359
595
|
*/
|
|
360
|
-
extend(
|
|
361
|
-
let
|
|
362
|
-
for (
|
|
363
|
-
|
|
364
|
-
for (
|
|
365
|
-
|
|
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
|
+
}
|
|
366
603
|
}
|
|
367
|
-
return
|
|
604
|
+
return dest;
|
|
368
605
|
},
|
|
369
606
|
/**
|
|
370
607
|
* 将扁平化数组转换为树形结构数组
|
|
@@ -375,34 +612,55 @@ const y = {
|
|
|
375
612
|
* @param childrenPropertyName 树形结构中标识子节点的字段名,默认为'children'
|
|
376
613
|
* @returns 转换后的树形结构数组
|
|
377
614
|
*/
|
|
378
|
-
convertToTree2(
|
|
379
|
-
const
|
|
380
|
-
function
|
|
381
|
-
const
|
|
382
|
-
|
|
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
|
+
}
|
|
383
627
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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;
|
|
387
635
|
},
|
|
388
636
|
/**
|
|
389
637
|
* 异步加载script
|
|
390
638
|
*
|
|
391
639
|
* @param {*} url
|
|
392
640
|
*/
|
|
393
|
-
asyncLoadScript(
|
|
394
|
-
return new Promise((
|
|
641
|
+
asyncLoadScript(url) {
|
|
642
|
+
return new Promise((resolve, reject) => {
|
|
395
643
|
try {
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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);
|
|
406
664
|
}
|
|
407
665
|
});
|
|
408
666
|
},
|
|
@@ -412,12 +670,16 @@ const y = {
|
|
|
412
670
|
* @param urls 样式文件URL数组
|
|
413
671
|
* @returns 无返回值
|
|
414
672
|
*/
|
|
415
|
-
loadStyle(
|
|
416
|
-
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
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);
|
|
421
683
|
});
|
|
422
684
|
},
|
|
423
685
|
/**
|
|
@@ -428,13 +690,17 @@ const y = {
|
|
|
428
690
|
* @returns 替换后的字符串
|
|
429
691
|
* @throws 当对象中没有找到与占位符对应的值时,抛出错误
|
|
430
692
|
*/
|
|
431
|
-
template(
|
|
432
|
-
const
|
|
433
|
-
return
|
|
434
|
-
const
|
|
435
|
-
if (
|
|
436
|
-
throw new Error(`${
|
|
437
|
-
|
|
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
|
+
}
|
|
438
704
|
});
|
|
439
705
|
},
|
|
440
706
|
/**
|
|
@@ -443,18 +709,32 @@ const y = {
|
|
|
443
709
|
* @param data 待处理的对象
|
|
444
710
|
* @returns 返回处理后的对象
|
|
445
711
|
*/
|
|
446
|
-
deleteEmptyProperty(
|
|
712
|
+
deleteEmptyProperty(data) {
|
|
447
713
|
return Object.fromEntries(
|
|
448
|
-
Object.keys(
|
|
714
|
+
Object.keys(data).filter((d) => !this.isEmpty(data[d])).map((i) => [i, data[i]])
|
|
449
715
|
);
|
|
450
716
|
},
|
|
451
|
-
deepAssign(
|
|
452
|
-
(typeof
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
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;
|
|
458
738
|
},
|
|
459
739
|
/**
|
|
460
740
|
* 复制文本到剪贴板
|
|
@@ -462,67 +742,437 @@ const y = {
|
|
|
462
742
|
* @param text 要复制的文本
|
|
463
743
|
* @returns 返回一个Promise,表示复制操作的结果
|
|
464
744
|
*/
|
|
465
|
-
handleCopyValue(
|
|
466
|
-
if (navigator.clipboard && window.isSecureContext)
|
|
467
|
-
return navigator.clipboard.writeText(
|
|
468
|
-
{
|
|
469
|
-
const
|
|
470
|
-
|
|
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) => {
|
|
471
758
|
try {
|
|
472
|
-
document.execCommand("copy")
|
|
473
|
-
|
|
474
|
-
|
|
759
|
+
document.execCommand("copy");
|
|
760
|
+
resolve();
|
|
761
|
+
} catch (error) {
|
|
762
|
+
reject(new Error("copy failed"));
|
|
475
763
|
} finally {
|
|
476
|
-
|
|
764
|
+
textArea.remove();
|
|
477
765
|
}
|
|
478
766
|
});
|
|
479
767
|
}
|
|
480
768
|
},
|
|
481
|
-
isArray(
|
|
482
|
-
return Array.isArray(
|
|
769
|
+
isArray(a) {
|
|
770
|
+
return Array.isArray(a);
|
|
483
771
|
},
|
|
484
|
-
isObject(
|
|
485
|
-
return Object.prototype.toString.call(
|
|
772
|
+
isObject(a) {
|
|
773
|
+
return Object.prototype.toString.call(a).indexOf("Object") > -1;
|
|
486
774
|
},
|
|
487
|
-
isNil(
|
|
488
|
-
return
|
|
775
|
+
isNil(a) {
|
|
776
|
+
return a === void 0 || a === "undefined" || a === null || a === "null";
|
|
489
777
|
},
|
|
490
|
-
isNumber(
|
|
491
|
-
return typeof
|
|
778
|
+
isNumber(a) {
|
|
779
|
+
return typeof a === "number" && !isNaN(a) || typeof a === "string" && Number.isFinite(+a);
|
|
492
780
|
},
|
|
493
|
-
isFunction(
|
|
494
|
-
|
|
781
|
+
isFunction(obj) {
|
|
782
|
+
if (this.isNil(obj)) {
|
|
783
|
+
return false;
|
|
784
|
+
}
|
|
785
|
+
return typeof obj === "function" || obj.constructor !== null && obj.constructor === Function;
|
|
786
|
+
},
|
|
787
|
+
/**
|
|
788
|
+
* 判断传入参数是否为DOM元素
|
|
789
|
+
*
|
|
790
|
+
* @param a 待判断的参数
|
|
791
|
+
* @returns 返回布尔值,表示是否为DOM元素
|
|
792
|
+
*/
|
|
793
|
+
isElement(a) {
|
|
794
|
+
return typeof a === "object" && a.nodeType === 1;
|
|
795
|
+
},
|
|
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;
|
|
495
807
|
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
|
|
808
|
+
};
|
|
809
|
+
const ObjectUtil = {
|
|
810
|
+
deepClone(a) {
|
|
811
|
+
return structuredClone(a);
|
|
499
812
|
},
|
|
500
|
-
isEqual(
|
|
501
|
-
return JSON.stringify(
|
|
813
|
+
isEqual(a, b) {
|
|
814
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
502
815
|
},
|
|
503
|
-
parse(
|
|
504
|
-
|
|
816
|
+
parse(str) {
|
|
817
|
+
if (!str || !(typeof str === "string")) {
|
|
818
|
+
return str;
|
|
819
|
+
}
|
|
820
|
+
return JSON.parse(str);
|
|
821
|
+
}
|
|
822
|
+
};
|
|
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]);
|
|
832
|
+
};
|
|
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;
|
|
845
|
+
};
|
|
846
|
+
myArray.prototype.max = function() {
|
|
847
|
+
return Math.max.apply({}, this);
|
|
848
|
+
};
|
|
849
|
+
myArray.prototype.min = function() {
|
|
850
|
+
return Math.min.apply({}, this);
|
|
851
|
+
};
|
|
852
|
+
myArray.sum = function() {
|
|
853
|
+
return this.length > 0 ? this.reduce((prev = 0, curr = 0) => prev + curr) : 0;
|
|
854
|
+
};
|
|
855
|
+
myArray.avg = function() {
|
|
856
|
+
return this.length ? this.sum() / this.length : 0;
|
|
857
|
+
};
|
|
858
|
+
myArray.desc = function(f = (d) => d) {
|
|
859
|
+
return this.sort((n1, n2) => f(n2) - f(n1));
|
|
860
|
+
};
|
|
861
|
+
myArray.asc = function(f = (d) => d) {
|
|
862
|
+
return this.sort((n1, n2) => f(n1) - f(n2));
|
|
863
|
+
};
|
|
864
|
+
myArray.remove = function(obj) {
|
|
865
|
+
const i = this.indexOf(obj);
|
|
866
|
+
if (i > -1) {
|
|
867
|
+
this.splice(i, 1);
|
|
868
|
+
}
|
|
869
|
+
return this;
|
|
870
|
+
};
|
|
871
|
+
const ArrayUtil = {
|
|
872
|
+
/**
|
|
873
|
+
* 创建指定长度的数组,并返回其索引数组
|
|
874
|
+
*
|
|
875
|
+
* @param length 数组长度
|
|
876
|
+
* @returns 索引数组
|
|
877
|
+
*/
|
|
878
|
+
create(length) {
|
|
879
|
+
return [...new Array(length).keys()];
|
|
880
|
+
},
|
|
881
|
+
/**
|
|
882
|
+
* 合并多个数组,并去重
|
|
883
|
+
*
|
|
884
|
+
* @param args 需要合并的数组
|
|
885
|
+
* @returns 合并后的去重数组
|
|
886
|
+
*/
|
|
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;
|
|
895
|
+
},
|
|
896
|
+
/**
|
|
897
|
+
* 求多个数组的交集
|
|
898
|
+
*
|
|
899
|
+
* @param args 多个需要求交集的数组
|
|
900
|
+
* @returns 返回多个数组的交集数组
|
|
901
|
+
*/
|
|
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;
|
|
910
|
+
},
|
|
911
|
+
/**
|
|
912
|
+
* 将多个数组拼接为一个数组,并去除其中的空值。
|
|
913
|
+
*
|
|
914
|
+
* @param args 需要拼接的数组列表。
|
|
915
|
+
* @returns 拼接并去空后的数组。
|
|
916
|
+
*/
|
|
917
|
+
unionAll(...args) {
|
|
918
|
+
return [...args].flat().filter((d) => !!d);
|
|
919
|
+
},
|
|
920
|
+
/**
|
|
921
|
+
* 求差集
|
|
922
|
+
*
|
|
923
|
+
* @param args 任意个集合
|
|
924
|
+
* @returns 返回差集结果
|
|
925
|
+
*/
|
|
926
|
+
difference(...args) {
|
|
927
|
+
if (args.length === 0) return [];
|
|
928
|
+
return this.union(...args).filter((d) => !this.intersection(...args).includes(d));
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
const _MqttClient = class _MqttClient extends EventDispatcher {
|
|
932
|
+
constructor(url = `ws://${window.document.domain}:20007/mqtt`, config = {}) {
|
|
933
|
+
super();
|
|
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 = {
|
|
942
|
+
connectTimeout: this.context.MQTT_TIMEOUTM,
|
|
943
|
+
clientId: CommUtils.guid(),
|
|
944
|
+
username: this.context.MQTT_USERNAME,
|
|
945
|
+
password: this.context.MQTT_PASSWORD,
|
|
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 = [];
|
|
954
|
+
}
|
|
955
|
+
_onConnect() {
|
|
956
|
+
this.client.on("connect", () => {
|
|
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();
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
_onMessage() {
|
|
970
|
+
this.client.on("message", (topic, message) => {
|
|
971
|
+
let dataString = message;
|
|
972
|
+
let data = "";
|
|
973
|
+
if (message instanceof Uint8Array) {
|
|
974
|
+
dataString = message.toString();
|
|
975
|
+
}
|
|
976
|
+
try {
|
|
977
|
+
data = ObjectUtil.parse(dataString);
|
|
978
|
+
} catch (error) {
|
|
979
|
+
throw new Error(ErrorType.JSON_PARSE_ERROR);
|
|
980
|
+
}
|
|
981
|
+
this.dispatchEvent({
|
|
982
|
+
type: EventType.MQTT_MESSAGE,
|
|
983
|
+
message: { topic, data }
|
|
984
|
+
});
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
sendMsg(topic, msg) {
|
|
988
|
+
if (!this.client.connected) {
|
|
989
|
+
console.error("客户端未连接");
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
this.client.publish(topic, msg, { qos: 1, retain: true });
|
|
993
|
+
}
|
|
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));
|
|
1000
|
+
});
|
|
1001
|
+
});
|
|
1002
|
+
return this;
|
|
1003
|
+
}
|
|
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;
|
|
1014
|
+
}
|
|
1015
|
+
unsubscribeAll() {
|
|
1016
|
+
this.unsubscribe(this.topics);
|
|
1017
|
+
}
|
|
1018
|
+
unconnect() {
|
|
1019
|
+
this.client.end();
|
|
1020
|
+
this.client = null;
|
|
1021
|
+
this.dispatchEvent({ type: EventType.MQTT_CLOSE, message: null });
|
|
1022
|
+
console.log("断开mqtt成功==>" + this.url);
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
/**
|
|
1026
|
+
* Creates an instance of MqttClient.
|
|
1027
|
+
* @param {*} config mqtt实例参数
|
|
1028
|
+
*/
|
|
1029
|
+
__publicField(_MqttClient, "defaultContext", {
|
|
1030
|
+
MQTT_USERNAME: "iRVMS-WEB",
|
|
1031
|
+
MQTT_PASSWORD: "novasky888",
|
|
1032
|
+
MQTT_TIMEOUTM: 2e4
|
|
1033
|
+
});
|
|
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));
|
|
505
1113
|
}
|
|
506
|
-
|
|
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 = {
|
|
507
1139
|
emptyImageUrl: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
|
|
508
1140
|
/**
|
|
509
1141
|
*
|
|
510
1142
|
* @param image image,类型可以是HTMLCanvasElement、ImageData
|
|
511
1143
|
* @returns
|
|
512
1144
|
*/
|
|
513
|
-
getURL(
|
|
514
|
-
let
|
|
515
|
-
if (/^data:/i.test(
|
|
516
|
-
return
|
|
517
|
-
|
|
518
|
-
if (
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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");
|
|
524
1175
|
}
|
|
525
|
-
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");
|
|
526
1176
|
},
|
|
527
1177
|
/**
|
|
528
1178
|
* 将图片的URL转换为Base64编码
|
|
@@ -532,13 +1182,16 @@ const y = {
|
|
|
532
1182
|
* @param height 图片的高度,默认为图片原始高度
|
|
533
1183
|
* @returns 返回Promise对象,解析后得到包含Base64编码数据的对象
|
|
534
1184
|
*/
|
|
535
|
-
getBase64(
|
|
536
|
-
return new Promise((
|
|
537
|
-
let
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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;
|
|
542
1195
|
});
|
|
543
1196
|
},
|
|
544
1197
|
/**
|
|
@@ -547,13 +1200,17 @@ const y = {
|
|
|
547
1200
|
* @param base64 base64编码字符串
|
|
548
1201
|
* @returns 返回一个对象,包含type(类型)、ext(扩展名)和data(数据)字段,如果解析失败则返回null
|
|
549
1202
|
*/
|
|
550
|
-
parseBase64(
|
|
551
|
-
let
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
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;
|
|
557
1214
|
},
|
|
558
1215
|
/**
|
|
559
1216
|
* 复制图片到剪贴板
|
|
@@ -562,33 +1219,51 @@ const y = {
|
|
|
562
1219
|
* @returns 无返回值
|
|
563
1220
|
* @throws 如果解析base64数据失败,则抛出异常
|
|
564
1221
|
*/
|
|
565
|
-
async copyImage(
|
|
1222
|
+
async copyImage(url) {
|
|
566
1223
|
try {
|
|
567
|
-
const
|
|
568
|
-
|
|
1224
|
+
const base64Result = await this.getBase64(url);
|
|
1225
|
+
const parsedBase64 = this.parseBase64(base64Result.dataURL);
|
|
1226
|
+
if (!parsedBase64) {
|
|
569
1227
|
throw new Error("Failed to parse base64 data.");
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
let
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
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);
|
|
577
1240
|
}
|
|
578
1241
|
}
|
|
579
|
-
}
|
|
1242
|
+
};
|
|
1243
|
+
const AjaxUtil = {
|
|
580
1244
|
/**
|
|
581
1245
|
* Get JSON data by jsonp
|
|
582
1246
|
* @param url - resource url
|
|
583
1247
|
* @param callback - callback function when completed
|
|
584
1248
|
*/
|
|
585
|
-
jsonp(
|
|
586
|
-
const
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
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);
|
|
592
1267
|
},
|
|
593
1268
|
/**
|
|
594
1269
|
* Fetch remote resource by HTTP "GET" method
|
|
@@ -610,18 +1285,25 @@ const y = {
|
|
|
610
1285
|
* }
|
|
611
1286
|
* );
|
|
612
1287
|
*/
|
|
613
|
-
get(
|
|
614
|
-
if (
|
|
615
|
-
const
|
|
616
|
-
|
|
1288
|
+
get(url, options, cb) {
|
|
1289
|
+
if (CommUtils.isFunction(options)) {
|
|
1290
|
+
const t = cb;
|
|
1291
|
+
cb = options;
|
|
1292
|
+
options = t;
|
|
617
1293
|
}
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
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
|
+
}
|
|
623
1304
|
}
|
|
624
|
-
|
|
1305
|
+
client.send(null);
|
|
1306
|
+
return client;
|
|
625
1307
|
},
|
|
626
1308
|
/**
|
|
627
1309
|
* Fetch remote resource by HTTP "POST" method
|
|
@@ -648,38 +1330,81 @@ const y = {
|
|
|
648
1330
|
* }
|
|
649
1331
|
* );
|
|
650
1332
|
*/
|
|
651
|
-
post(
|
|
652
|
-
let
|
|
653
|
-
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) {
|
|
654
1350
|
throw new Error("Callback function is required");
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
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;
|
|
659
1366
|
},
|
|
660
|
-
_wrapCallback(
|
|
1367
|
+
_wrapCallback(client, cb) {
|
|
661
1368
|
return function() {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
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
|
+
}
|
|
668
1390
|
};
|
|
669
1391
|
},
|
|
670
|
-
_getClient(
|
|
671
|
-
let
|
|
1392
|
+
_getClient(cb) {
|
|
1393
|
+
let client = null;
|
|
672
1394
|
try {
|
|
673
|
-
|
|
674
|
-
} catch {
|
|
1395
|
+
client = new XMLHttpRequest();
|
|
1396
|
+
} catch (e) {
|
|
675
1397
|
throw new Error("XMLHttpRequest not supported.");
|
|
676
1398
|
}
|
|
677
|
-
|
|
1399
|
+
if (client) {
|
|
1400
|
+
client.onreadystatechange = this._wrapCallback(client, cb);
|
|
1401
|
+
}
|
|
1402
|
+
return client;
|
|
678
1403
|
},
|
|
679
1404
|
/**
|
|
680
1405
|
* Fetch resource as arraybuffer.
|
|
681
1406
|
* @param {String} url - url
|
|
682
|
-
* @param {Object} [options=null] - options, same as
|
|
1407
|
+
* @param {Object} [options=null] - options, same as AjaxUtil.get
|
|
683
1408
|
* @param {Function} cb - callback function when completed.
|
|
684
1409
|
* @example
|
|
685
1410
|
* AjaxUtil.getArrayBuffer(
|
|
@@ -692,24 +1417,37 @@ const y = {
|
|
|
692
1417
|
* }
|
|
693
1418
|
* );
|
|
694
1419
|
*/
|
|
695
|
-
getArrayBuffer(
|
|
696
|
-
if (
|
|
697
|
-
const
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
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);
|
|
710
1446
|
};
|
|
711
|
-
const
|
|
712
|
-
|
|
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;
|
|
713
1451
|
}
|
|
714
1452
|
});
|
|
715
1453
|
},
|
|
@@ -732,121 +1470,44 @@ const y = {
|
|
|
732
1470
|
* }
|
|
733
1471
|
* );
|
|
734
1472
|
*/
|
|
735
|
-
getJSON(
|
|
736
|
-
if (
|
|
737
|
-
const
|
|
738
|
-
|
|
1473
|
+
getJSON(url, options, cb) {
|
|
1474
|
+
if (CommUtils.isFunction(options)) {
|
|
1475
|
+
const t = cb;
|
|
1476
|
+
cb = options;
|
|
1477
|
+
options = t;
|
|
739
1478
|
}
|
|
740
|
-
const
|
|
741
|
-
const
|
|
742
|
-
|
|
1479
|
+
const callback = function(err, resp) {
|
|
1480
|
+
const data = resp ? ObjectUtil.parse(resp) : null;
|
|
1481
|
+
if (cb) {
|
|
1482
|
+
cb(err, data);
|
|
1483
|
+
}
|
|
743
1484
|
};
|
|
744
|
-
|
|
1485
|
+
if (options && options["jsonp"]) {
|
|
1486
|
+
return this.jsonp(url, callback);
|
|
1487
|
+
}
|
|
1488
|
+
return this.get(url, options, callback);
|
|
745
1489
|
}
|
|
746
1490
|
};
|
|
747
|
-
|
|
748
|
-
var e = {};
|
|
749
|
-
return this.forEach(function(n) {
|
|
750
|
-
var r = JSON.stringify(t(n));
|
|
751
|
-
e[r] = e[r] || [], e[r].push(n);
|
|
752
|
-
}), Object.keys(e).map((n) => e[n]);
|
|
753
|
-
};
|
|
754
|
-
Array.prototype.distinct = function(t = (e) => e) {
|
|
755
|
-
const e = [], n = {};
|
|
756
|
-
return this.forEach((r) => {
|
|
757
|
-
const s = t(r), i = String(s);
|
|
758
|
-
n[i] || (n[i] = !0, e.push(r));
|
|
759
|
-
}), e;
|
|
760
|
-
};
|
|
761
|
-
Array.prototype.max = function() {
|
|
762
|
-
return Math.max.apply({}, this);
|
|
763
|
-
};
|
|
764
|
-
Array.prototype.min = function() {
|
|
765
|
-
return Math.min.apply({}, this);
|
|
766
|
-
};
|
|
767
|
-
Array.prototype.sum = function() {
|
|
768
|
-
return this.length > 0 ? this.reduce((t = 0, e = 0) => t + e) : 0;
|
|
769
|
-
};
|
|
770
|
-
Array.prototype.avg = function() {
|
|
771
|
-
return this.length ? this.sum() / this.length : 0;
|
|
772
|
-
};
|
|
773
|
-
Array.prototype.desc = function(t = (e) => e) {
|
|
774
|
-
return this.sort((e, n) => t(n) - t(e));
|
|
775
|
-
};
|
|
776
|
-
Array.prototype.asc = function(t = (e) => e) {
|
|
777
|
-
return this.sort((e, n) => t(e) - t(n));
|
|
778
|
-
};
|
|
779
|
-
Array.prototype.remove = function(t) {
|
|
780
|
-
const e = this.indexOf(t);
|
|
781
|
-
return e > -1 && this.splice(e, 1), this;
|
|
782
|
-
};
|
|
783
|
-
Array.prototype.clear = function() {
|
|
784
|
-
return this.length = 0, this;
|
|
785
|
-
};
|
|
786
|
-
const G = {
|
|
787
|
-
asArray(t) {
|
|
788
|
-
return y.isEmpty(t) ? [] : Array.isArray(t) ? t : [t];
|
|
789
|
-
},
|
|
790
|
-
/**
|
|
791
|
-
* 创建指定长度的数组,并返回其索引数组
|
|
792
|
-
*
|
|
793
|
-
* @param length 数组长度
|
|
794
|
-
* @returns 索引数组
|
|
795
|
-
*/
|
|
796
|
-
create(t) {
|
|
797
|
-
return [...new Array(t).keys()];
|
|
798
|
-
},
|
|
799
|
-
/**
|
|
800
|
-
* 合并多个数组,并去重
|
|
801
|
-
*
|
|
802
|
-
* @param args 需要合并的数组
|
|
803
|
-
* @returns 合并后的去重数组
|
|
804
|
-
*/
|
|
805
|
-
union(...t) {
|
|
806
|
-
let e = [];
|
|
807
|
-
return t.forEach((n) => {
|
|
808
|
-
Array.isArray(n) && (e = e.concat(n.filter((r) => !e.includes(r))));
|
|
809
|
-
}), e;
|
|
810
|
-
},
|
|
811
|
-
/**
|
|
812
|
-
* 求多个数组的交集
|
|
813
|
-
*
|
|
814
|
-
* @param args 多个需要求交集的数组
|
|
815
|
-
* @returns 返回多个数组的交集数组
|
|
816
|
-
*/
|
|
817
|
-
intersection(...t) {
|
|
818
|
-
let e = t[0] || [];
|
|
819
|
-
return t.forEach((n) => {
|
|
820
|
-
Array.isArray(n) && (e = e.filter((r) => n.includes(r)));
|
|
821
|
-
}), e;
|
|
822
|
-
},
|
|
823
|
-
/**
|
|
824
|
-
* 将多个数组拼接为一个数组,并去除其中的空值。
|
|
825
|
-
*
|
|
826
|
-
* @param args 需要拼接的数组列表。
|
|
827
|
-
* @returns 拼接并去空后的数组。
|
|
828
|
-
*/
|
|
829
|
-
unionAll(...t) {
|
|
830
|
-
return [...t].flat().filter((e) => !!e);
|
|
831
|
-
},
|
|
832
|
-
/**
|
|
833
|
-
* 求差集
|
|
834
|
-
*
|
|
835
|
-
* @param args 任意个集合
|
|
836
|
-
* @returns 返回差集结果
|
|
837
|
-
*/
|
|
838
|
-
difference(...t) {
|
|
839
|
-
return this.union(...t).filter((e) => !this.intersection(...t).includes(e));
|
|
840
|
-
}
|
|
841
|
-
}, J = {
|
|
1491
|
+
const BrowserUtil = {
|
|
842
1492
|
/**
|
|
843
1493
|
* 获取浏览器类型
|
|
844
1494
|
*
|
|
845
1495
|
* @returns 返回浏览器类型字符串,可能的值为 'IE'、'Firefox'、'Chrome'、'Opera'、'Safari' 或 'Unknown'
|
|
846
1496
|
*/
|
|
847
1497
|
getExplorer() {
|
|
848
|
-
var
|
|
849
|
-
|
|
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";
|
|
850
1511
|
},
|
|
851
1512
|
/**
|
|
852
1513
|
* 检测操作系统类型
|
|
@@ -854,21 +1515,45 @@ const G = {
|
|
|
854
1515
|
* @returns 返回操作系统类型字符串,可能的值有:'MS Windows'、'Apple mac'、'Linux'、'Unix'
|
|
855
1516
|
*/
|
|
856
1517
|
detectOS() {
|
|
857
|
-
let
|
|
858
|
-
const
|
|
859
|
-
|
|
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;
|
|
860
1528
|
},
|
|
861
1529
|
/**
|
|
862
1530
|
* 切换全屏状态
|
|
863
1531
|
*
|
|
864
1532
|
* @param status 是否全屏
|
|
865
1533
|
*/
|
|
866
|
-
switchFullScreen(
|
|
867
|
-
if (
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
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
|
+
}
|
|
872
1557
|
},
|
|
873
1558
|
/**
|
|
874
1559
|
* 刷新缩放比例
|
|
@@ -876,11 +1561,20 @@ const G = {
|
|
|
876
1561
|
* @returns 无返回值
|
|
877
1562
|
*/
|
|
878
1563
|
refreshScale() {
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
const
|
|
882
|
-
|
|
883
|
-
|
|
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`;
|
|
884
1578
|
},
|
|
885
1579
|
/**
|
|
886
1580
|
* 获取HTML字体大小
|
|
@@ -888,35 +1582,28 @@ const G = {
|
|
|
888
1582
|
* @returns 无返回值,该函数会直接修改HTML元素的字体大小
|
|
889
1583
|
*/
|
|
890
1584
|
getHtmlFontSize() {
|
|
891
|
-
const
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
var r = /* @__PURE__ */ new Date();
|
|
897
|
-
r.setTime(r.getTime() + n * 24 * 60 * 60 * 1e3), document.cookie = t + "=" + escape(e) + ";expires=" + r.toUTCString();
|
|
898
|
-
},
|
|
899
|
-
remove: function(t) {
|
|
900
|
-
var e = /* @__PURE__ */ new Date();
|
|
901
|
-
e.setTime(e.getTime() - 1);
|
|
902
|
-
var n = this.get(t);
|
|
903
|
-
n != null && (document.cookie = t + "=" + n + ";expires=" + e.toUTCString());
|
|
904
|
-
},
|
|
905
|
-
get: function(t) {
|
|
906
|
-
var e = document.cookie.match(new RegExp("(^| )" + t + "=([^;]*)(;|$)"));
|
|
907
|
-
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
|
+
}
|
|
908
1590
|
}
|
|
909
|
-
}
|
|
1591
|
+
};
|
|
1592
|
+
const CoordsUtil = {
|
|
910
1593
|
PI: 3.141592653589793,
|
|
911
1594
|
XPI: 3.141592653589793 * 3e3 / 180,
|
|
912
|
-
delta(
|
|
913
|
-
const
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
let
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
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 };
|
|
920
1607
|
},
|
|
921
1608
|
/**
|
|
922
1609
|
* 判断经纬度是否不在中国境内
|
|
@@ -925,64 +1612,110 @@ const G = {
|
|
|
925
1612
|
* @param lat 纬度
|
|
926
1613
|
* @returns 如果经纬度不在中国境内则返回true,否则返回false
|
|
927
1614
|
*/
|
|
928
|
-
outOfChina(
|
|
929
|
-
|
|
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;
|
|
930
1623
|
},
|
|
931
1624
|
// WGS-84 to GCJ-02
|
|
932
|
-
gcjEncrypt(
|
|
933
|
-
if (this.outOfChina(
|
|
934
|
-
return { lat:
|
|
935
|
-
|
|
936
|
-
|
|
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 };
|
|
937
1631
|
},
|
|
938
1632
|
// GCJ-02 to WGS-84
|
|
939
|
-
gcjDecrypt(
|
|
940
|
-
if (this.outOfChina(
|
|
941
|
-
return { lat:
|
|
942
|
-
|
|
943
|
-
|
|
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 };
|
|
944
1639
|
},
|
|
945
1640
|
// GCJ-02 to WGS-84 exactly
|
|
946
|
-
gcjDecryptExact(
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
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;
|
|
952
1667
|
}
|
|
953
|
-
return { lat:
|
|
1668
|
+
return { lat: wgsLat, lng: wgsLon };
|
|
954
1669
|
},
|
|
955
1670
|
// GCJ-02 to BD-09
|
|
956
|
-
bdEncrypt(
|
|
957
|
-
const
|
|
958
|
-
|
|
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 };
|
|
959
1679
|
},
|
|
960
1680
|
// BD-09 to GCJ-02
|
|
961
|
-
bdDecrypt(
|
|
962
|
-
const
|
|
963
|
-
|
|
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 };
|
|
964
1689
|
},
|
|
965
1690
|
// WGS-84 to Web mercator
|
|
966
1691
|
// mercatorLat -> y mercatorLon -> x
|
|
967
|
-
mercatorEncrypt(
|
|
968
|
-
const
|
|
969
|
-
let
|
|
970
|
-
|
|
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 };
|
|
971
1697
|
},
|
|
972
1698
|
// Web mercator to WGS-84
|
|
973
1699
|
// mercatorLat -> y mercatorLon -> x
|
|
974
|
-
mercatorDecrypt(
|
|
975
|
-
const
|
|
976
|
-
let
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
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;
|
|
986
1719
|
},
|
|
987
1720
|
/**
|
|
988
1721
|
* 生成指定范围内的随机经纬度坐标
|
|
@@ -991,30 +1724,43 @@ const G = {
|
|
|
991
1724
|
* @param max 最大坐标,包含属性 x 和 y,分别表示最大经度和最大纬度
|
|
992
1725
|
* @returns 返回生成的随机经纬度坐标,包含属性 lat 和 lng,分别表示纬度和经度
|
|
993
1726
|
*/
|
|
994
|
-
random({ x:
|
|
1727
|
+
random({ x: minX, y: minY }, { x: maxX, y: maxY }) {
|
|
995
1728
|
return {
|
|
996
|
-
lat: Math.random() * (
|
|
997
|
-
lng: Math.random() * (
|
|
1729
|
+
lat: Math.random() * (maxY - minY) + minY,
|
|
1730
|
+
lng: Math.random() * (maxX - minX) + minX
|
|
998
1731
|
};
|
|
999
1732
|
},
|
|
1000
|
-
deCompose(
|
|
1001
|
-
if (!Array.isArray(
|
|
1002
|
-
return
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
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);
|
|
1008
1743
|
continue;
|
|
1009
1744
|
}
|
|
1010
|
-
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
|
+
}
|
|
1011
1751
|
}
|
|
1012
|
-
return
|
|
1752
|
+
return result;
|
|
1013
1753
|
}
|
|
1014
|
-
}
|
|
1754
|
+
};
|
|
1755
|
+
const ColorUtil = {
|
|
1015
1756
|
random() {
|
|
1016
|
-
let
|
|
1017
|
-
|
|
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;
|
|
1018
1764
|
},
|
|
1019
1765
|
/**
|
|
1020
1766
|
* 将RGB颜色值转换为十六进制颜色值
|
|
@@ -1022,9 +1768,9 @@ const G = {
|
|
|
1022
1768
|
* @param rgb RGB颜色值数组,包含三个0-255之间的整数
|
|
1023
1769
|
* @returns 转换后的十六进制颜色值,以#开头
|
|
1024
1770
|
*/
|
|
1025
|
-
rgb2hex(
|
|
1026
|
-
var
|
|
1027
|
-
return
|
|
1771
|
+
rgb2hex(rgb) {
|
|
1772
|
+
var hex = "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1);
|
|
1773
|
+
return hex;
|
|
1028
1774
|
},
|
|
1029
1775
|
/**
|
|
1030
1776
|
* 将RGB颜色值转换为RGBA颜色值,并返回转换后的颜色值。
|
|
@@ -1032,9 +1778,9 @@ const G = {
|
|
|
1032
1778
|
* @param rgbValue RGB颜色值,格式为"rgb(r, g, b)"。
|
|
1033
1779
|
* @returns 转换后的RGBA颜色值,格式为"rgba(r, g, b, 1)"。如果输入值不符合RGB格式,则返回原值。
|
|
1034
1780
|
*/
|
|
1035
|
-
rgbToRgba(
|
|
1036
|
-
const
|
|
1037
|
-
return
|
|
1781
|
+
rgbToRgba(rgbValue) {
|
|
1782
|
+
const rgb = /rgb\((\d+,\s*[\d]+,\s*[\d]+)\)/g.exec(rgbValue);
|
|
1783
|
+
return rgb ? `rgba(${rgb[1]}, 1)` : rgbValue;
|
|
1038
1784
|
},
|
|
1039
1785
|
/**
|
|
1040
1786
|
* 将十六进制颜色值转换为rgba格式的颜色值
|
|
@@ -1042,12 +1788,18 @@ const G = {
|
|
|
1042
1788
|
* @param hexValue 十六进制颜色值,可带或不带#前缀,支持3位和6位表示
|
|
1043
1789
|
* @returns 返回rgba格式的颜色值,格式为rgba(r,g,b,1)
|
|
1044
1790
|
*/
|
|
1045
|
-
hexToRgba(
|
|
1046
|
-
const
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
const
|
|
1050
|
-
|
|
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)`;
|
|
1051
1803
|
},
|
|
1052
1804
|
/**
|
|
1053
1805
|
* 将 HSL 颜色值转换为 RGBA 颜色值
|
|
@@ -1055,45 +1807,59 @@ const G = {
|
|
|
1055
1807
|
* @param hslValue HSL 颜色值字符串,格式为 "hsl(h, s%, l%)" 或 "hsla(h, s%, l%, a)",其中 h 为色相,s 为饱和度,l 为亮度,a 为透明度(可选)。
|
|
1056
1808
|
* @returns 转换后的 RGBA 颜色值字符串,格式为 "rgba(r, g, b, a)",其中 r、g、b 为红绿蓝分量,a 为透明度。若输入为空或无效,则返回 null。
|
|
1057
1809
|
*/
|
|
1058
|
-
hslToRgba(
|
|
1059
|
-
if (!
|
|
1810
|
+
hslToRgba(hslValue) {
|
|
1811
|
+
if (!hslValue) {
|
|
1060
1812
|
return null;
|
|
1061
|
-
|
|
1062
|
-
|
|
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) {
|
|
1063
1816
|
return null;
|
|
1064
|
-
const n = parseInt(e[1], 10) / 360, r = parseInt(e[2], 10) / 100, s = parseInt(e[3], 10) / 100, i = e[4] ? parseFloat(e[4]) : 1;
|
|
1065
|
-
function a(c, u, f) {
|
|
1066
|
-
return f < 0 && (f += 1), f > 1 && (f -= 1), f < 1 / 6 ? c + (u - c) * 6 * f : f < 1 / 2 ? u : f < 2 / 3 ? c + (u - c) * (2 / 3 - f) * 6 : c;
|
|
1067
1817
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
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);
|
|
1074
1839
|
}
|
|
1075
|
-
return `rgba(${Math.round(
|
|
1840
|
+
return `rgba(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)},${a})`;
|
|
1076
1841
|
},
|
|
1077
|
-
isHex(
|
|
1078
|
-
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);
|
|
1079
1844
|
},
|
|
1080
|
-
isRgb(
|
|
1081
|
-
return /^rgb/.test(
|
|
1845
|
+
isRgb(a) {
|
|
1846
|
+
return /^rgb/.test(a);
|
|
1082
1847
|
},
|
|
1083
|
-
isHsl(
|
|
1084
|
-
return /^hsl/.test(
|
|
1848
|
+
isHsl(a) {
|
|
1849
|
+
return /^hsl/.test(a);
|
|
1085
1850
|
},
|
|
1086
|
-
isColor(
|
|
1087
|
-
return this.isHex(
|
|
1851
|
+
isColor(a) {
|
|
1852
|
+
return this.isHex(a) || this.isRgb(a) || this.isHsl(a);
|
|
1088
1853
|
},
|
|
1089
|
-
colorToRgb(
|
|
1090
|
-
if (this.isRgb(
|
|
1091
|
-
if (this.isHex(
|
|
1092
|
-
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);
|
|
1093
1858
|
}
|
|
1094
1859
|
};
|
|
1095
|
-
|
|
1096
|
-
|
|
1860
|
+
const myDate = Object.create(Date);
|
|
1861
|
+
myDate.prototype.format = function(fmt = "yyyy-MM-dd hh:mm:ss") {
|
|
1862
|
+
const o = {
|
|
1097
1863
|
"M+": this.getMonth() + 1,
|
|
1098
1864
|
// 月份
|
|
1099
1865
|
"d+": this.getDate(),
|
|
@@ -1111,48 +1877,51 @@ Date.prototype.format = function(t) {
|
|
|
1111
1877
|
S: this.getMilliseconds()
|
|
1112
1878
|
// 毫秒
|
|
1113
1879
|
};
|
|
1114
|
-
/(y+)/.test(
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
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));
|
|
1119
1887
|
}
|
|
1120
|
-
|
|
1888
|
+
}
|
|
1889
|
+
return fmt;
|
|
1121
1890
|
};
|
|
1122
|
-
|
|
1123
|
-
const
|
|
1124
|
-
switch (
|
|
1891
|
+
myDate.prototype.addDate = function(interval, number) {
|
|
1892
|
+
const date = new Date(this);
|
|
1893
|
+
switch (interval) {
|
|
1125
1894
|
case "y":
|
|
1126
|
-
|
|
1895
|
+
date.setFullYear(this.getFullYear() + number);
|
|
1127
1896
|
break;
|
|
1128
1897
|
case "q":
|
|
1129
|
-
|
|
1898
|
+
date.setMonth(this.getMonth() + number * 3);
|
|
1130
1899
|
break;
|
|
1131
1900
|
case "M":
|
|
1132
|
-
|
|
1901
|
+
date.setMonth(this.getMonth() + number);
|
|
1133
1902
|
break;
|
|
1134
1903
|
case "w":
|
|
1135
|
-
|
|
1904
|
+
date.setDate(this.getDate() + number * 7);
|
|
1136
1905
|
break;
|
|
1137
1906
|
case "d":
|
|
1138
|
-
|
|
1907
|
+
date.setDate(this.getDate() + number);
|
|
1139
1908
|
break;
|
|
1140
1909
|
case "h":
|
|
1141
|
-
|
|
1910
|
+
date.setHours(this.getHours() + number);
|
|
1142
1911
|
break;
|
|
1143
1912
|
case "m":
|
|
1144
|
-
|
|
1913
|
+
date.setMinutes(this.getMinutes() + number);
|
|
1145
1914
|
break;
|
|
1146
1915
|
case "s":
|
|
1147
|
-
|
|
1916
|
+
date.setSeconds(this.getSeconds() + number);
|
|
1148
1917
|
break;
|
|
1149
1918
|
default:
|
|
1150
|
-
|
|
1919
|
+
date.setDate(this.getDate() + number);
|
|
1151
1920
|
break;
|
|
1152
1921
|
}
|
|
1153
|
-
return
|
|
1922
|
+
return date;
|
|
1154
1923
|
};
|
|
1155
|
-
const
|
|
1924
|
+
const DateUtil = {
|
|
1156
1925
|
lastMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth() - 1, 1),
|
|
1157
1926
|
thisMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), 1),
|
|
1158
1927
|
nextMonthDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth() + 1, 1),
|
|
@@ -1162,28 +1931,30 @@ const W = {
|
|
|
1162
1931
|
lastDayDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() - 1),
|
|
1163
1932
|
thisDayDate: new Date((/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0)),
|
|
1164
1933
|
nextDayDate: new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), (/* @__PURE__ */ new Date()).getDate() + 1),
|
|
1165
|
-
parseDate(
|
|
1166
|
-
if (typeof
|
|
1167
|
-
var
|
|
1168
|
-
if (
|
|
1169
|
-
|
|
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)
|
|
1170
1940
|
return new Date(
|
|
1171
|
-
parseInt(
|
|
1172
|
-
parseInt(
|
|
1173
|
-
parseInt(
|
|
1174
|
-
parseInt(
|
|
1175
|
-
parseInt(
|
|
1176
|
-
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])
|
|
1177
1947
|
);
|
|
1178
|
-
|
|
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)
|
|
1179
1950
|
return new Date(
|
|
1180
|
-
parseInt(
|
|
1181
|
-
parseInt(
|
|
1182
|
-
parseInt(
|
|
1183
|
-
parseInt(
|
|
1184
|
-
parseInt(
|
|
1185
|
-
parseInt(
|
|
1186
|
-
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])
|
|
1187
1958
|
);
|
|
1188
1959
|
}
|
|
1189
1960
|
return null;
|
|
@@ -1195,27 +1966,56 @@ const W = {
|
|
|
1195
1966
|
* @param endTime 结束时间,可以是字符串、数字或日期类型
|
|
1196
1967
|
* @returns 返回格式化后的时间间隔字符串,格式为"天数 天 小时 时 分钟 分 秒 秒"或"少于1秒"
|
|
1197
1968
|
*/
|
|
1198
|
-
formatDateInterval(
|
|
1199
|
-
const
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
const
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
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;
|
|
1208
1997
|
},
|
|
1209
|
-
|
|
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) {
|
|
1210
2010
|
}
|
|
1211
2011
|
};
|
|
1212
|
-
function
|
|
1213
|
-
return
|
|
2012
|
+
function trim(str) {
|
|
2013
|
+
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, "");
|
|
1214
2014
|
}
|
|
1215
|
-
function
|
|
1216
|
-
return
|
|
2015
|
+
function splitWords(str) {
|
|
2016
|
+
return trim(str).split(/\s+/);
|
|
1217
2017
|
}
|
|
1218
|
-
const
|
|
2018
|
+
const DomUtil = {
|
|
1219
2019
|
/**
|
|
1220
2020
|
* 获取元素的样式值
|
|
1221
2021
|
*
|
|
@@ -1223,14 +2023,15 @@ const K = {
|
|
|
1223
2023
|
* @param style 样式属性名称
|
|
1224
2024
|
* @returns 元素的样式值,如果获取不到则返回 null
|
|
1225
2025
|
*/
|
|
1226
|
-
getStyle(
|
|
1227
|
-
var
|
|
1228
|
-
let
|
|
1229
|
-
if (!
|
|
1230
|
-
const
|
|
1231
|
-
|
|
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;
|
|
1232
2033
|
}
|
|
1233
|
-
return
|
|
2034
|
+
return value;
|
|
1234
2035
|
},
|
|
1235
2036
|
/**
|
|
1236
2037
|
* 创建一个HTML元素
|
|
@@ -1240,45 +2041,56 @@ const K = {
|
|
|
1240
2041
|
* @param container 父容器,若传入,则新创建的元素会被添加到该容器中
|
|
1241
2042
|
* @returns 返回新创建的HTML元素
|
|
1242
2043
|
*/
|
|
1243
|
-
create(
|
|
1244
|
-
const
|
|
1245
|
-
|
|
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;
|
|
1246
2051
|
},
|
|
1247
2052
|
/**
|
|
1248
2053
|
* 从父节点中移除指定元素。
|
|
1249
2054
|
*
|
|
1250
2055
|
* @param el 要移除的元素对象,必须包含parentNode属性。
|
|
1251
2056
|
*/
|
|
1252
|
-
remove(
|
|
1253
|
-
const
|
|
1254
|
-
|
|
2057
|
+
remove(el) {
|
|
2058
|
+
const parent = el.parentNode;
|
|
2059
|
+
if (parent) {
|
|
2060
|
+
parent.removeChild(el);
|
|
2061
|
+
}
|
|
1255
2062
|
},
|
|
1256
2063
|
/**
|
|
1257
2064
|
* 清空给定元素的子节点
|
|
1258
2065
|
*
|
|
1259
2066
|
* @param el 要清空子节点的元素,包含firstChild和removeChild属性
|
|
1260
2067
|
*/
|
|
1261
|
-
empty(
|
|
1262
|
-
|
|
1263
|
-
|
|
2068
|
+
empty(el) {
|
|
2069
|
+
while (el.firstChild) {
|
|
2070
|
+
el.removeChild(el.firstChild);
|
|
2071
|
+
}
|
|
1264
2072
|
},
|
|
1265
2073
|
/**
|
|
1266
2074
|
* 将元素移到父节点的最前面
|
|
1267
2075
|
*
|
|
1268
2076
|
* @param el 要移动的元素,需要包含 parentNode 属性
|
|
1269
2077
|
*/
|
|
1270
|
-
toFront(
|
|
1271
|
-
const
|
|
1272
|
-
|
|
2078
|
+
toFront(el) {
|
|
2079
|
+
const parent = el.parentNode;
|
|
2080
|
+
if (parent && parent.lastChild !== el) {
|
|
2081
|
+
parent.appendChild(el);
|
|
2082
|
+
}
|
|
1273
2083
|
},
|
|
1274
2084
|
/**
|
|
1275
2085
|
* 将元素移动到其父节点的最前面
|
|
1276
2086
|
*
|
|
1277
2087
|
* @param el 要移动的元素,需要包含parentNode属性
|
|
1278
2088
|
*/
|
|
1279
|
-
toBack(
|
|
1280
|
-
const
|
|
1281
|
-
|
|
2089
|
+
toBack(el) {
|
|
2090
|
+
const parent = el.parentNode;
|
|
2091
|
+
if (parent && parent.firstChild !== el) {
|
|
2092
|
+
parent.insertBefore(el, parent.firstChild);
|
|
2093
|
+
}
|
|
1282
2094
|
},
|
|
1283
2095
|
/**
|
|
1284
2096
|
* 获取元素的类名
|
|
@@ -1289,8 +2101,9 @@ const K = {
|
|
|
1289
2101
|
* @param el.className.baseVal 类名字符串
|
|
1290
2102
|
* @returns 返回元素的类名字符串
|
|
1291
2103
|
*/
|
|
1292
|
-
getClass(
|
|
1293
|
-
|
|
2104
|
+
getClass(el) {
|
|
2105
|
+
const shadowElement = (el == null ? void 0 : el.host) || el;
|
|
2106
|
+
return shadowElement.className.toString();
|
|
1294
2107
|
},
|
|
1295
2108
|
/**
|
|
1296
2109
|
* 判断元素是否包含指定类名
|
|
@@ -1299,12 +2112,13 @@ const K = {
|
|
|
1299
2112
|
* @param name 要判断的类名
|
|
1300
2113
|
* @returns 返回一个布尔值,表示元素是否包含指定类名
|
|
1301
2114
|
*/
|
|
1302
|
-
hasClass(
|
|
1303
|
-
var
|
|
1304
|
-
if ((
|
|
1305
|
-
return
|
|
1306
|
-
|
|
1307
|
-
|
|
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);
|
|
1308
2122
|
},
|
|
1309
2123
|
/**
|
|
1310
2124
|
* 给指定的 HTML 元素添加类名
|
|
@@ -1312,14 +2126,15 @@ const K = {
|
|
|
1312
2126
|
* @param el 要添加类名的 HTML 元素
|
|
1313
2127
|
* @param name 要添加的类名,多个类名之间用空格分隔
|
|
1314
2128
|
*/
|
|
1315
|
-
addClass(
|
|
1316
|
-
if (
|
|
1317
|
-
const
|
|
1318
|
-
for (let
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
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);
|
|
1323
2138
|
}
|
|
1324
2139
|
},
|
|
1325
2140
|
/**
|
|
@@ -1328,8 +2143,13 @@ const K = {
|
|
|
1328
2143
|
* @param el 要移除类名的元素
|
|
1329
2144
|
* @param name 要移除的类名,多个类名用空格分隔
|
|
1330
2145
|
*/
|
|
1331
|
-
removeClass(
|
|
1332
|
-
|
|
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
|
+
}
|
|
1333
2153
|
},
|
|
1334
2154
|
/**
|
|
1335
2155
|
* 设置元素的 CSS 类名
|
|
@@ -1337,8 +2157,11 @@ const K = {
|
|
|
1337
2157
|
* @param el HTML 或 SVG 元素
|
|
1338
2158
|
* @param name 要设置的类名,多个类名之间用空格分隔
|
|
1339
2159
|
*/
|
|
1340
|
-
setClass(
|
|
1341
|
-
"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
|
+
}
|
|
1342
2165
|
},
|
|
1343
2166
|
/**
|
|
1344
2167
|
* 从字符串中解析XML文档,并返回根节点
|
|
@@ -1346,18 +2169,22 @@ const K = {
|
|
|
1346
2169
|
* @param str 要解析的XML字符串
|
|
1347
2170
|
* @returns 解析后的XML文档的根节点
|
|
1348
2171
|
*/
|
|
1349
|
-
parseFromString(
|
|
1350
|
-
|
|
2172
|
+
parseFromString(str) {
|
|
2173
|
+
const parser = new DOMParser();
|
|
2174
|
+
const doc = parser.parseFromString(str, "text/xml");
|
|
2175
|
+
return doc.children[0];
|
|
1351
2176
|
}
|
|
1352
|
-
}
|
|
2177
|
+
};
|
|
2178
|
+
const TYPES = ["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon"];
|
|
2179
|
+
const GeoJsonUtil = {
|
|
1353
2180
|
/**
|
|
1354
2181
|
* 获取GeoJSON要素的几何类型
|
|
1355
2182
|
*
|
|
1356
2183
|
* @param feature GeoJSONFeature 类型的要素
|
|
1357
2184
|
* @returns 返回要素的几何类型,如果要素没有几何属性则返回 null
|
|
1358
2185
|
*/
|
|
1359
|
-
getGeoJsonType(
|
|
1360
|
-
return
|
|
2186
|
+
getGeoJsonType(feature) {
|
|
2187
|
+
return feature.geometry ? feature.geometry.type : null;
|
|
1361
2188
|
},
|
|
1362
2189
|
/**
|
|
1363
2190
|
* 判断给定的GeoJSON要素是否为有效的GeoJSON格式
|
|
@@ -1365,14 +2192,16 @@ const K = {
|
|
|
1365
2192
|
* @param feature 要判断的GeoJSON要素
|
|
1366
2193
|
* @returns 如果为有效的GeoJSON格式则返回true,否则返回false
|
|
1367
2194
|
*/
|
|
1368
|
-
isGeoJson(
|
|
1369
|
-
const
|
|
1370
|
-
if (
|
|
1371
|
-
for (let
|
|
1372
|
-
if (
|
|
1373
|
-
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
|
+
}
|
|
1374
2203
|
}
|
|
1375
|
-
return
|
|
2204
|
+
return false;
|
|
1376
2205
|
},
|
|
1377
2206
|
/**
|
|
1378
2207
|
* 判断是否为 GeoJSON 多边形
|
|
@@ -1380,9 +2209,12 @@ const K = {
|
|
|
1380
2209
|
* @param feature GeoJSONFeature 对象
|
|
1381
2210
|
* @returns 返回布尔值,表示是否为 GeoJSON 多边形
|
|
1382
2211
|
*/
|
|
1383
|
-
isGeoJsonPolygon(
|
|
1384
|
-
const
|
|
1385
|
-
|
|
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;
|
|
1386
2218
|
},
|
|
1387
2219
|
/**
|
|
1388
2220
|
* 判断给定的 GeoJSONFeature 是否为 GeoJSON 线
|
|
@@ -1390,9 +2222,12 @@ const K = {
|
|
|
1390
2222
|
* @param feature GeoJSONFeature 对象
|
|
1391
2223
|
* @returns 是 GeoJSON 线返回 true,否则返回 false
|
|
1392
2224
|
*/
|
|
1393
|
-
isGeoJsonLine(
|
|
1394
|
-
const
|
|
1395
|
-
|
|
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;
|
|
1396
2231
|
},
|
|
1397
2232
|
/**
|
|
1398
2233
|
* 判断是否为 GeoJSON 点类型
|
|
@@ -1400,9 +2235,12 @@ const K = {
|
|
|
1400
2235
|
* @param feature GeoJSONFeature 对象
|
|
1401
2236
|
* @returns 是点类型返回 true,否则返回 false
|
|
1402
2237
|
*/
|
|
1403
|
-
isGeoJsonPoint(
|
|
1404
|
-
const
|
|
1405
|
-
|
|
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;
|
|
1406
2244
|
},
|
|
1407
2245
|
/**
|
|
1408
2246
|
* 判断传入的 GeoJSONFeature 是否为 Multi 类型的 GeoJSON。
|
|
@@ -1410,9 +2248,14 @@ const K = {
|
|
|
1410
2248
|
* @param feature GeoJSONFeature 类型的参数,待判断是否为 Multi 类型的 GeoJSON。
|
|
1411
2249
|
* @returns 返回一个布尔值,如果传入的 GeoJSONFeature 是 Multi 类型的 GeoJSON,则返回 true,否则返回 false。
|
|
1412
2250
|
*/
|
|
1413
|
-
isGeoJsonMulti(
|
|
1414
|
-
const
|
|
1415
|
-
|
|
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;
|
|
1416
2259
|
},
|
|
1417
2260
|
/**
|
|
1418
2261
|
* 获取GeoJSON要素的坐标数组
|
|
@@ -1420,8 +2263,8 @@ const K = {
|
|
|
1420
2263
|
* @param feature GeoJSONFeature对象
|
|
1421
2264
|
* @returns 返回一个包含坐标数组的数组,可以是二维、三维或四维数组
|
|
1422
2265
|
*/
|
|
1423
|
-
getGeoJsonCoordinates(
|
|
1424
|
-
return
|
|
2266
|
+
getGeoJsonCoordinates(feature) {
|
|
2267
|
+
return feature.geometry ? feature.geometry.coordinates : [];
|
|
1425
2268
|
},
|
|
1426
2269
|
/**
|
|
1427
2270
|
* 获取GeoJSON要素的中心点坐标
|
|
@@ -1430,42 +2273,64 @@ const K = {
|
|
|
1430
2273
|
* @param out 输出坐标对象,默认为null
|
|
1431
2274
|
* @returns 返回中心点坐标,如果无法获取则返回null
|
|
1432
2275
|
*/
|
|
1433
|
-
getGeoJsonCenter(
|
|
1434
|
-
const
|
|
1435
|
-
if (!
|
|
2276
|
+
getGeoJsonCenter(feature, out) {
|
|
2277
|
+
const type = this.getGeoJsonType(feature);
|
|
2278
|
+
if (!type || !feature.geometry) {
|
|
1436
2279
|
return null;
|
|
1437
|
-
|
|
1438
|
-
|
|
2280
|
+
}
|
|
2281
|
+
const geometry = feature.geometry;
|
|
2282
|
+
const coordinates = geometry.coordinates;
|
|
2283
|
+
if (!coordinates) {
|
|
1439
2284
|
return null;
|
|
1440
|
-
|
|
1441
|
-
|
|
2285
|
+
}
|
|
2286
|
+
let sumX = 0, sumY = 0, coordLen = 0;
|
|
2287
|
+
switch (type) {
|
|
1442
2288
|
case "Point": {
|
|
1443
|
-
|
|
2289
|
+
sumX = coordinates[0];
|
|
2290
|
+
sumY = coordinates[1];
|
|
2291
|
+
coordLen++;
|
|
1444
2292
|
break;
|
|
1445
2293
|
}
|
|
1446
2294
|
case "MultiPoint":
|
|
1447
2295
|
case "LineString": {
|
|
1448
|
-
for (let
|
|
1449
|
-
|
|
2296
|
+
for (let i = 0, len = coordinates.length; i < len; i++) {
|
|
2297
|
+
sumX += coordinates[i][0];
|
|
2298
|
+
sumY += coordinates[i][1];
|
|
2299
|
+
coordLen++;
|
|
2300
|
+
}
|
|
1450
2301
|
break;
|
|
1451
2302
|
}
|
|
1452
2303
|
case "MultiLineString":
|
|
1453
2304
|
case "Polygon": {
|
|
1454
|
-
for (let
|
|
1455
|
-
for (let
|
|
1456
|
-
|
|
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
|
+
}
|
|
1457
2312
|
break;
|
|
1458
2313
|
}
|
|
1459
2314
|
case "MultiPolygon": {
|
|
1460
|
-
for (let
|
|
1461
|
-
for (let
|
|
1462
|
-
for (let
|
|
1463
|
-
|
|
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
|
+
}
|
|
1464
2324
|
break;
|
|
1465
2325
|
}
|
|
1466
2326
|
}
|
|
1467
|
-
const
|
|
1468
|
-
|
|
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 };
|
|
1469
2334
|
},
|
|
1470
2335
|
/**
|
|
1471
2336
|
* 将一个包含多个点、线或面的 GeoJSON 特征对象拆分成多个独立的 GeoJSON 特征对象数组。
|
|
@@ -1473,42 +2338,48 @@ const K = {
|
|
|
1473
2338
|
* @param feature 包含多个点、线或面的 GeoJSON 特征对象
|
|
1474
2339
|
* @returns 返回一个 GeoJSON 特征对象数组,如果拆分失败则返回 null
|
|
1475
2340
|
*/
|
|
1476
|
-
spliteGeoJsonMulti(
|
|
1477
|
-
const
|
|
1478
|
-
if (!
|
|
2341
|
+
spliteGeoJsonMulti(feature) {
|
|
2342
|
+
const type = this.getGeoJsonType(feature);
|
|
2343
|
+
if (!type || !feature.geometry) {
|
|
1479
2344
|
return null;
|
|
1480
|
-
|
|
1481
|
-
|
|
2345
|
+
}
|
|
2346
|
+
const geometry = feature.geometry;
|
|
2347
|
+
const properties = feature.properties || {};
|
|
2348
|
+
const coordinates = geometry.coordinates;
|
|
2349
|
+
if (!coordinates) {
|
|
1482
2350
|
return null;
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
2351
|
+
}
|
|
2352
|
+
const features = [];
|
|
2353
|
+
let fType;
|
|
2354
|
+
switch (type) {
|
|
1486
2355
|
case "MultiPoint": {
|
|
1487
|
-
|
|
2356
|
+
fType = "Point";
|
|
1488
2357
|
break;
|
|
1489
2358
|
}
|
|
1490
2359
|
case "MultiLineString": {
|
|
1491
|
-
|
|
2360
|
+
fType = "LineString";
|
|
1492
2361
|
break;
|
|
1493
2362
|
}
|
|
1494
2363
|
case "MultiPolygon": {
|
|
1495
|
-
|
|
2364
|
+
fType = "Polygon";
|
|
1496
2365
|
break;
|
|
1497
2366
|
}
|
|
1498
2367
|
}
|
|
1499
|
-
if (
|
|
1500
|
-
for (let
|
|
1501
|
-
|
|
2368
|
+
if (fType) {
|
|
2369
|
+
for (let i = 0, len = coordinates.length; i < len; i++) {
|
|
2370
|
+
features.push({
|
|
1502
2371
|
type: "Feature",
|
|
1503
2372
|
geometry: {
|
|
1504
|
-
type:
|
|
1505
|
-
coordinates:
|
|
2373
|
+
type: fType,
|
|
2374
|
+
coordinates: coordinates[i]
|
|
1506
2375
|
},
|
|
1507
|
-
properties
|
|
2376
|
+
properties
|
|
1508
2377
|
});
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
2378
|
+
}
|
|
2379
|
+
} else {
|
|
2380
|
+
features.push(feature);
|
|
2381
|
+
}
|
|
2382
|
+
return features;
|
|
1512
2383
|
},
|
|
1513
2384
|
/**
|
|
1514
2385
|
* 根据坐标数组生成GeoJSON要素
|
|
@@ -1517,30 +2388,35 @@ const K = {
|
|
|
1517
2388
|
* @returns GeoJSONFeature 生成的GeoJSON要素
|
|
1518
2389
|
* @throws Error 如果coordinates参数格式错误
|
|
1519
2390
|
*/
|
|
1520
|
-
getGeoJsonByCoordinates(
|
|
1521
|
-
if (!Array.isArray(
|
|
2391
|
+
getGeoJsonByCoordinates(coordinates) {
|
|
2392
|
+
if (!Array.isArray(coordinates)) {
|
|
1522
2393
|
throw Error("coordinates 参数格式错误");
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
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 {
|
|
1535
2408
|
throw Error("coordinates 参数格式错误");
|
|
1536
|
-
|
|
2409
|
+
}
|
|
2410
|
+
} else {
|
|
1537
2411
|
throw Error("coordinates 参数格式错误");
|
|
2412
|
+
}
|
|
1538
2413
|
return {
|
|
1539
2414
|
type: "Feature",
|
|
1540
|
-
geometry: { type
|
|
2415
|
+
geometry: { type, coordinates }
|
|
1541
2416
|
};
|
|
1542
2417
|
}
|
|
1543
|
-
}
|
|
2418
|
+
};
|
|
2419
|
+
const GeoUtil = {
|
|
1544
2420
|
toRadian: Math.PI / 180,
|
|
1545
2421
|
R: 6371393,
|
|
1546
2422
|
/**
|
|
@@ -1550,8 +2426,8 @@ const K = {
|
|
|
1550
2426
|
* @param lat 纬度值
|
|
1551
2427
|
* @returns 如果经纬度合法,返回true;否则返回false
|
|
1552
2428
|
*/
|
|
1553
|
-
isLnglat(
|
|
1554
|
-
return !isNaN(
|
|
2429
|
+
isLnglat(lng, lat) {
|
|
2430
|
+
return !isNaN(lng) && !isNaN(lat) && !!(+lat > -90 && +lat < 90 && +lng > -180 && +lng < 180);
|
|
1555
2431
|
},
|
|
1556
2432
|
/**
|
|
1557
2433
|
* 计算两哥平面坐标点间的距离
|
|
@@ -1560,8 +2436,8 @@ const K = {
|
|
|
1560
2436
|
* @param p2 坐标点2,包含x和y属性
|
|
1561
2437
|
* @returns 返回两点间的欧几里得距离
|
|
1562
2438
|
*/
|
|
1563
|
-
distance(
|
|
1564
|
-
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));
|
|
1565
2441
|
},
|
|
1566
2442
|
/**
|
|
1567
2443
|
* 计算两个经纬度点之间的距离
|
|
@@ -1570,10 +2446,18 @@ const K = {
|
|
|
1570
2446
|
* @param B 经纬度点B,包含lng(经度)和lat(纬度)两个属性
|
|
1571
2447
|
* @returns 返回两点之间的距离,单位为米
|
|
1572
2448
|
*/
|
|
1573
|
-
distanceByPoints(
|
|
1574
|
-
const { lng:
|
|
1575
|
-
|
|
1576
|
-
|
|
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;
|
|
1577
2461
|
},
|
|
1578
2462
|
/**
|
|
1579
2463
|
* 格式化经纬度为度分秒格式
|
|
@@ -1582,13 +2466,22 @@ const K = {
|
|
|
1582
2466
|
* @param lat 纬度
|
|
1583
2467
|
* @returns 返回格式化后的经纬度字符串,格式为:经度度分秒,纬度度分秒
|
|
1584
2468
|
*/
|
|
1585
|
-
formatLnglat(
|
|
1586
|
-
let
|
|
1587
|
-
function
|
|
1588
|
-
const
|
|
1589
|
-
|
|
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);
|
|
1590
2483
|
}
|
|
1591
|
-
return
|
|
2484
|
+
return res;
|
|
1592
2485
|
},
|
|
1593
2486
|
/**
|
|
1594
2487
|
* 将经纬度字符串转换为度
|
|
@@ -1597,20 +2490,24 @@ const K = {
|
|
|
1597
2490
|
* @param lat 纬度字符串
|
|
1598
2491
|
* @returns 转换后的经纬度对象
|
|
1599
2492
|
*/
|
|
1600
|
-
transformLnglat(
|
|
1601
|
-
function
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
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;
|
|
1608
2504
|
}
|
|
1609
|
-
if (
|
|
2505
|
+
if (lng && lat) {
|
|
1610
2506
|
return {
|
|
1611
|
-
lng:
|
|
1612
|
-
lat:
|
|
2507
|
+
lng: dms2deg(lng),
|
|
2508
|
+
lat: dms2deg(lat)
|
|
1613
2509
|
};
|
|
2510
|
+
}
|
|
1614
2511
|
},
|
|
1615
2512
|
/**
|
|
1616
2513
|
* 射线法判断点是否在多边形内
|
|
@@ -1619,19 +2516,24 @@ const K = {
|
|
|
1619
2516
|
* @param poly 多边形顶点数组,可以是字符串数组或对象数组
|
|
1620
2517
|
* @returns 返回字符串,表示点相对于多边形的位置:'in'表示在多边形内,'out'表示在多边形外,'on'表示在多边形上
|
|
1621
2518
|
*/
|
|
1622
|
-
rayCasting(
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
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) {
|
|
1626
2524
|
return "on";
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
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) {
|
|
1630
2529
|
return "on";
|
|
1631
|
-
|
|
2530
|
+
}
|
|
2531
|
+
if (x > px) {
|
|
2532
|
+
flag = !flag;
|
|
2533
|
+
}
|
|
1632
2534
|
}
|
|
1633
2535
|
}
|
|
1634
|
-
return
|
|
2536
|
+
return flag ? "in" : "out";
|
|
1635
2537
|
},
|
|
1636
2538
|
/**
|
|
1637
2539
|
* 旋转点
|
|
@@ -1641,9 +2543,10 @@ const K = {
|
|
|
1641
2543
|
* @param θ 旋转角度(顺时针旋转为正)
|
|
1642
2544
|
* @returns 旋转后点坐标
|
|
1643
2545
|
*/
|
|
1644
|
-
rotatePoint(
|
|
1645
|
-
const
|
|
1646
|
-
|
|
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 };
|
|
1647
2550
|
},
|
|
1648
2551
|
/**
|
|
1649
2552
|
* 根据两个平面坐标点计算方位角和距离
|
|
@@ -1652,9 +2555,15 @@ const K = {
|
|
|
1652
2555
|
* @param p2 第二个点的坐标对象
|
|
1653
2556
|
* @returns 返回一个对象,包含angle和distance属性,分别表示两点之间的角度(以度为单位,取值范围为0~359)和距离
|
|
1654
2557
|
*/
|
|
1655
|
-
calcBearAndDis(
|
|
1656
|
-
const { x:
|
|
1657
|
-
|
|
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 };
|
|
1658
2567
|
},
|
|
1659
2568
|
/**
|
|
1660
2569
|
* 根据两个经纬度点计算方位角和距离
|
|
@@ -1663,11 +2572,19 @@ const K = {
|
|
|
1663
2572
|
* @param latlng2 第二个经纬度点
|
|
1664
2573
|
* @returns 包含方位角和距离的对象
|
|
1665
2574
|
*/
|
|
1666
|
-
calcBearAndDisByPoints(
|
|
1667
|
-
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;
|
|
1668
2585
|
return {
|
|
1669
|
-
angle
|
|
1670
|
-
distance
|
|
2586
|
+
angle,
|
|
2587
|
+
distance
|
|
1671
2588
|
};
|
|
1672
2589
|
},
|
|
1673
2590
|
/**
|
|
@@ -1678,15 +2595,20 @@ const K = {
|
|
|
1678
2595
|
* @param p2 线段终点P2的坐标
|
|
1679
2596
|
* @returns 点P到线段P1P2的最短距离
|
|
1680
2597
|
*/
|
|
1681
|
-
distanceToSegment(
|
|
1682
|
-
const
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
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));
|
|
1690
2612
|
},
|
|
1691
2613
|
/**
|
|
1692
2614
|
* 根据给定的经纬度、角度和距离计算新的经纬度点
|
|
@@ -1696,13 +2618,16 @@ const K = {
|
|
|
1696
2618
|
* @param distance 距离值,单位为米,表示从当前点出发的距离
|
|
1697
2619
|
* @returns 返回计算后的新经纬度点,类型为{lat: number, lng: number}
|
|
1698
2620
|
*/
|
|
1699
|
-
calcPointByBearAndDis(
|
|
1700
|
-
const
|
|
1701
|
-
|
|
1702
|
-
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));
|
|
1703
2628
|
return {
|
|
1704
|
-
lat:
|
|
1705
|
-
lng:
|
|
2629
|
+
lat: MathUtils.rad2Deg(lat),
|
|
2630
|
+
lng: MathUtils.rad2Deg(lon)
|
|
1706
2631
|
};
|
|
1707
2632
|
},
|
|
1708
2633
|
/**
|
|
@@ -1712,11 +2637,11 @@ const K = {
|
|
|
1712
2637
|
* @param y 墨卡托坐标的y值
|
|
1713
2638
|
* @returns 返回包含转换后的经度lng和纬度lat的对象
|
|
1714
2639
|
*/
|
|
1715
|
-
mercatorTolonlat(
|
|
1716
|
-
const
|
|
1717
|
-
var
|
|
1718
|
-
const
|
|
1719
|
-
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 };
|
|
1720
2645
|
},
|
|
1721
2646
|
/**
|
|
1722
2647
|
* 将经纬度坐标转换为墨卡托坐标
|
|
@@ -1725,12 +2650,12 @@ const K = {
|
|
|
1725
2650
|
* @param lat 纬度值
|
|
1726
2651
|
* @returns 墨卡托坐标对象,包含x和y属性
|
|
1727
2652
|
*/
|
|
1728
|
-
lonlatToMercator(
|
|
1729
|
-
var
|
|
1730
|
-
const
|
|
1731
|
-
var
|
|
1732
|
-
const
|
|
1733
|
-
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 };
|
|
1734
2659
|
},
|
|
1735
2660
|
/**
|
|
1736
2661
|
* 根据百分比获取坐标
|
|
@@ -1740,23 +2665,28 @@ const K = {
|
|
|
1740
2665
|
* @param percent 百分比,取值范围0-1
|
|
1741
2666
|
* @returns 返回插值后的坐标
|
|
1742
2667
|
*/
|
|
1743
|
-
interpolate({ x:
|
|
1744
|
-
const
|
|
1745
|
-
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 };
|
|
1746
2671
|
}
|
|
1747
|
-
}
|
|
2672
|
+
};
|
|
2673
|
+
const FileUtil = {
|
|
1748
2674
|
/**
|
|
1749
2675
|
* 将Base64编码的字符串转换为Blob对象
|
|
1750
2676
|
*
|
|
1751
2677
|
* @param data Base64编码的字符串
|
|
1752
2678
|
* @returns 转换后的Blob对象
|
|
1753
2679
|
*/
|
|
1754
|
-
convertBase64ToBlob(
|
|
1755
|
-
const
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
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;
|
|
1760
2690
|
},
|
|
1761
2691
|
/**
|
|
1762
2692
|
* 将图片的URL转换为Base64编码
|
|
@@ -1773,11 +2703,17 @@ const K = {
|
|
|
1773
2703
|
* @param filename 文件的名称
|
|
1774
2704
|
* @returns 返回文件对象
|
|
1775
2705
|
*/
|
|
1776
|
-
convertBase64ToFile(
|
|
1777
|
-
const
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
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;
|
|
1781
2717
|
},
|
|
1782
2718
|
/**
|
|
1783
2719
|
* 从文件下载数据
|
|
@@ -1785,22 +2721,27 @@ const K = {
|
|
|
1785
2721
|
* @param data 要下载的数据,可以是字符串数组、BlobPart 或 MediaSource
|
|
1786
2722
|
* @param saveName 下载后文件的保存名称
|
|
1787
2723
|
*/
|
|
1788
|
-
downloadFromFile(
|
|
1789
|
-
if (typeof
|
|
1790
|
-
if (
|
|
1791
|
-
|
|
1792
|
-
else {
|
|
1793
|
-
const
|
|
1794
|
-
|
|
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);
|
|
1795
2732
|
}
|
|
1796
|
-
else if (typeof
|
|
1797
|
-
const
|
|
1798
|
-
|
|
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);
|
|
1799
2736
|
}
|
|
1800
|
-
var
|
|
1801
|
-
|
|
2737
|
+
var link = document.createElement("a");
|
|
2738
|
+
link.href = data;
|
|
2739
|
+
link.download = saveName || "";
|
|
2740
|
+
link.click();
|
|
2741
|
+
window.URL.revokeObjectURL(link.href);
|
|
1802
2742
|
}
|
|
1803
|
-
}
|
|
2743
|
+
};
|
|
2744
|
+
const OptimizeUtil = {
|
|
1804
2745
|
/**
|
|
1805
2746
|
* 防抖函数,在指定的等待时间内,如果连续触发事件,则只在最后一次触发后执行函数。适用于像搜索输入框这种需要用户停止输入后才调用的场景
|
|
1806
2747
|
*
|
|
@@ -1809,16 +2750,35 @@ const K = {
|
|
|
1809
2750
|
* @param immediate 是否立即执行函数,默认为true。
|
|
1810
2751
|
* @returns 返回防抖后的函数。
|
|
1811
2752
|
*/
|
|
1812
|
-
debounce(
|
|
1813
|
-
let
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
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
|
+
}
|
|
1817
2768
|
};
|
|
1818
|
-
return (...
|
|
1819
|
-
|
|
1820
|
-
const
|
|
1821
|
-
|
|
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;
|
|
1822
2782
|
};
|
|
1823
2783
|
},
|
|
1824
2784
|
/**
|
|
@@ -1829,15 +2789,24 @@ const K = {
|
|
|
1829
2789
|
* @param type 节流类型,1表示时间戳方式,2表示定时器方式
|
|
1830
2790
|
* @returns 返回一个新的函数,该函数在节流控制下执行传入的函数
|
|
1831
2791
|
*/
|
|
1832
|
-
throttle(
|
|
1833
|
-
let
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
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
|
+
}
|
|
1841
2810
|
};
|
|
1842
2811
|
},
|
|
1843
2812
|
/**
|
|
@@ -1846,15 +2815,16 @@ const K = {
|
|
|
1846
2815
|
* @param fn 传入待缓存的函数
|
|
1847
2816
|
* @returns 返回缓存后的函数
|
|
1848
2817
|
*/
|
|
1849
|
-
memoize(
|
|
1850
|
-
const
|
|
1851
|
-
return (...
|
|
1852
|
-
const
|
|
1853
|
-
if (
|
|
1854
|
-
return
|
|
1855
|
-
{
|
|
1856
|
-
const
|
|
1857
|
-
|
|
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;
|
|
1858
2828
|
}
|
|
1859
2829
|
};
|
|
1860
2830
|
},
|
|
@@ -1865,13 +2835,33 @@ const K = {
|
|
|
1865
2835
|
* @param frequency 每次调用函数之间的时间间隔,单位为毫秒,默认为500毫秒。
|
|
1866
2836
|
* @param duration 函数递归调用的总时长,单位为毫秒,默认为5000毫秒。
|
|
1867
2837
|
*/
|
|
1868
|
-
recurve(
|
|
1869
|
-
let
|
|
2838
|
+
recurve(fun, frequency = 500, duration = 5e3) {
|
|
2839
|
+
let timer = 0;
|
|
1870
2840
|
setTimeout(() => {
|
|
1871
|
-
|
|
1872
|
-
|
|
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
|
+
};
|
|
1873
2862
|
}
|
|
1874
|
-
}
|
|
2863
|
+
};
|
|
2864
|
+
const StringUtil = {
|
|
1875
2865
|
/**
|
|
1876
2866
|
* 校验字符串是否符合指定类型
|
|
1877
2867
|
*
|
|
@@ -1896,44 +2886,44 @@ const K = {
|
|
|
1896
2886
|
* - 'HTML': HTML标记
|
|
1897
2887
|
* @returns 校验结果,符合返回true,否则返回false
|
|
1898
2888
|
*/
|
|
1899
|
-
checkStr(
|
|
1900
|
-
switch (
|
|
2889
|
+
checkStr(str, type) {
|
|
2890
|
+
switch (type) {
|
|
1901
2891
|
case "phone":
|
|
1902
|
-
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);
|
|
1903
2893
|
case "tel":
|
|
1904
|
-
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);
|
|
1905
2895
|
case "card":
|
|
1906
|
-
return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(
|
|
2896
|
+
return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(str);
|
|
1907
2897
|
case "pwd":
|
|
1908
|
-
return /^[a-zA-Z]\w{5,17}$/.test(
|
|
2898
|
+
return /^[a-zA-Z]\w{5,17}$/.test(str);
|
|
1909
2899
|
case "postal":
|
|
1910
|
-
return /[1-9]\d{5}(?!\d)/.test(
|
|
2900
|
+
return /[1-9]\d{5}(?!\d)/.test(str);
|
|
1911
2901
|
case "QQ":
|
|
1912
|
-
return /^[1-9][0-9]{4,9}$/.test(
|
|
2902
|
+
return /^[1-9][0-9]{4,9}$/.test(str);
|
|
1913
2903
|
case "email":
|
|
1914
|
-
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(
|
|
2904
|
+
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
|
|
1915
2905
|
case "money":
|
|
1916
|
-
return /^\d*(?:\.\d{0,2})?$/.test(
|
|
2906
|
+
return /^\d*(?:\.\d{0,2})?$/.test(str);
|
|
1917
2907
|
case "URL":
|
|
1918
|
-
return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(
|
|
2908
|
+
return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(str);
|
|
1919
2909
|
case "IP":
|
|
1920
|
-
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);
|
|
1921
2911
|
case "date":
|
|
1922
|
-
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);
|
|
1923
2913
|
case "number":
|
|
1924
|
-
return /^[0-9]$/.test(
|
|
2914
|
+
return /^[0-9]$/.test(str);
|
|
1925
2915
|
case "english":
|
|
1926
|
-
return /^[a-zA-Z]+$/.test(
|
|
2916
|
+
return /^[a-zA-Z]+$/.test(str);
|
|
1927
2917
|
case "chinese":
|
|
1928
|
-
return /^[\u4E00-\u9FA5]+$/.test(
|
|
2918
|
+
return /^[\u4E00-\u9FA5]+$/.test(str);
|
|
1929
2919
|
case "lower":
|
|
1930
|
-
return /^[a-z]+$/.test(
|
|
2920
|
+
return /^[a-z]+$/.test(str);
|
|
1931
2921
|
case "upper":
|
|
1932
|
-
return /^[A-Z]+$/.test(
|
|
2922
|
+
return /^[A-Z]+$/.test(str);
|
|
1933
2923
|
case "HTML":
|
|
1934
|
-
return /<("[^"]*"|'[^']*'|[^'">])*>/.test(
|
|
2924
|
+
return /<("[^"]*"|'[^']*'|[^'">])*>/.test(str);
|
|
1935
2925
|
default:
|
|
1936
|
-
return
|
|
2926
|
+
return true;
|
|
1937
2927
|
}
|
|
1938
2928
|
},
|
|
1939
2929
|
/**
|
|
@@ -1948,26 +2938,31 @@ const K = {
|
|
|
1948
2938
|
* 5:全部小写
|
|
1949
2939
|
* @returns 转换后的字符串
|
|
1950
2940
|
*/
|
|
1951
|
-
changeCase(
|
|
1952
|
-
|
|
2941
|
+
changeCase(str, type) {
|
|
2942
|
+
type = type || 4;
|
|
2943
|
+
switch (type) {
|
|
1953
2944
|
case 1:
|
|
1954
|
-
return
|
|
1955
|
-
return
|
|
2945
|
+
return str.replace(/\b\w+\b/g, function(word) {
|
|
2946
|
+
return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase();
|
|
1956
2947
|
});
|
|
1957
2948
|
case 2:
|
|
1958
|
-
return
|
|
1959
|
-
return
|
|
2949
|
+
return str.replace(/\b\w+\b/g, function(word) {
|
|
2950
|
+
return word.substring(0, 1).toLowerCase() + word.substring(1).toUpperCase();
|
|
1960
2951
|
});
|
|
1961
2952
|
case 3:
|
|
1962
|
-
return
|
|
1963
|
-
|
|
2953
|
+
return str.split("").map(function(word) {
|
|
2954
|
+
if (/[a-z]/.test(word)) {
|
|
2955
|
+
return word.toUpperCase();
|
|
2956
|
+
} else {
|
|
2957
|
+
return word.toLowerCase();
|
|
2958
|
+
}
|
|
1964
2959
|
}).join("");
|
|
1965
2960
|
case 4:
|
|
1966
|
-
return
|
|
2961
|
+
return str.toUpperCase();
|
|
1967
2962
|
case 5:
|
|
1968
|
-
return
|
|
2963
|
+
return str.toLowerCase();
|
|
1969
2964
|
default:
|
|
1970
|
-
return
|
|
2965
|
+
return str;
|
|
1971
2966
|
}
|
|
1972
2967
|
},
|
|
1973
2968
|
/**
|
|
@@ -1977,17 +2972,18 @@ const K = {
|
|
|
1977
2972
|
* @param args 可变参数列表,支持 Object、Array 类型和任意其他类型,若为 null 或 undefined,则按类型默认转换为 '{}'、'[]' 或 ''
|
|
1978
2973
|
* @returns 返回生成的新字符串
|
|
1979
2974
|
*/
|
|
1980
|
-
tag(
|
|
1981
|
-
|
|
1982
|
-
switch (
|
|
2975
|
+
tag(strArray, ...args) {
|
|
2976
|
+
args = args.map((val) => {
|
|
2977
|
+
switch (CommUtils.getDataType(val)) {
|
|
1983
2978
|
case "Object":
|
|
1984
|
-
return
|
|
2979
|
+
return val || "{}";
|
|
1985
2980
|
case "Array":
|
|
1986
|
-
return
|
|
2981
|
+
return val || "[]";
|
|
1987
2982
|
default:
|
|
1988
|
-
return
|
|
2983
|
+
return val || "";
|
|
1989
2984
|
}
|
|
1990
|
-
})
|
|
2985
|
+
});
|
|
2986
|
+
return strArray.reduce((prev, next, index) => `${prev}${args[index - 1]}${next}`);
|
|
1991
2987
|
},
|
|
1992
2988
|
/**
|
|
1993
2989
|
* 计算字符串的字节长度
|
|
@@ -1995,8 +2991,8 @@ const K = {
|
|
|
1995
2991
|
* @param str 需要计算字节长度的字符串
|
|
1996
2992
|
* @returns 返回字符串的字节长度
|
|
1997
2993
|
*/
|
|
1998
|
-
getByteLength(
|
|
1999
|
-
return
|
|
2994
|
+
getByteLength(str) {
|
|
2995
|
+
return str.replace(/[\u0391-\uFFE5]/g, "aa").length;
|
|
2000
2996
|
},
|
|
2001
2997
|
/**
|
|
2002
2998
|
* 截取字符串中指定字节长度的子串
|
|
@@ -2006,112 +3002,39 @@ const K = {
|
|
|
2006
3002
|
* @param n 截取字节长度
|
|
2007
3003
|
* @returns 返回截取后的子串
|
|
2008
3004
|
*/
|
|
2009
|
-
subStringByte(
|
|
3005
|
+
subStringByte(str, start, n) {
|
|
2010
3006
|
var r = /[^\x00-\xff]/g;
|
|
2011
|
-
if (
|
|
2012
|
-
return
|
|
2013
|
-
for (var s = Math.floor(n / 2), i = s; i < t.length; i++) {
|
|
2014
|
-
let a = t.substring(e, i);
|
|
2015
|
-
if (a.replace(r, "mm").length >= n)
|
|
2016
|
-
return a;
|
|
3007
|
+
if (str.replace(r, "mm").length <= n) {
|
|
3008
|
+
return str;
|
|
2017
3009
|
}
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
* @returns 转换后的字符串,如果值为空,则返回空字符串
|
|
2025
|
-
*/
|
|
2026
|
-
asString(t) {
|
|
2027
|
-
if (y.isEmpty(t))
|
|
2028
|
-
return "";
|
|
2029
|
-
switch (y.getDataType(t)) {
|
|
2030
|
-
case "Object":
|
|
2031
|
-
case "Array":
|
|
2032
|
-
return JSON.stringify(t);
|
|
2033
|
-
default:
|
|
2034
|
-
return t;
|
|
2035
|
-
}
|
|
2036
|
-
},
|
|
2037
|
-
replaceAll(t, e, n) {
|
|
2038
|
-
if (!t)
|
|
2039
|
-
return t;
|
|
2040
|
-
for (; t.indexOf(e) > -1; )
|
|
2041
|
-
t = t.replace(e, n);
|
|
2042
|
-
return t;
|
|
2043
|
-
}
|
|
2044
|
-
}, g = class g {
|
|
2045
|
-
static set(e, n = null, r = null) {
|
|
2046
|
-
var s = this._getPrefixedKey(e, r);
|
|
2047
|
-
try {
|
|
2048
|
-
localStorage.setItem(s, JSON.stringify({ data: n }));
|
|
2049
|
-
} catch {
|
|
2050
|
-
console && console.warn("StoreUtil didn't successfully save the '{" + e + ": " + n + "}' pair, because the localStorage is full.");
|
|
2051
|
-
}
|
|
2052
|
-
}
|
|
2053
|
-
static get(e, n, r) {
|
|
2054
|
-
var s = this._getPrefixedKey(e, r), i;
|
|
2055
|
-
try {
|
|
2056
|
-
i = JSON.parse(localStorage.getItem(s) || "");
|
|
2057
|
-
} catch {
|
|
2058
|
-
localStorage[s] ? i = { data: localStorage.getItem(s) } : i = null;
|
|
2059
|
-
}
|
|
2060
|
-
if (i) {
|
|
2061
|
-
if (typeof i == "object" && typeof i.data < "u")
|
|
2062
|
-
return i.data;
|
|
2063
|
-
} else return n;
|
|
2064
|
-
}
|
|
2065
|
-
static keys() {
|
|
2066
|
-
const e = [];
|
|
2067
|
-
var n = Object.keys(localStorage);
|
|
2068
|
-
return g.prefix.length === 0 ? n : (n.forEach(function(r) {
|
|
2069
|
-
r.indexOf(g.prefix) !== -1 && e.push(r.replace(g.prefix, ""));
|
|
2070
|
-
}), e);
|
|
2071
|
-
}
|
|
2072
|
-
static getAll(e) {
|
|
2073
|
-
var n = g.keys();
|
|
2074
|
-
if (e) {
|
|
2075
|
-
const r = [];
|
|
2076
|
-
return n.forEach((s) => {
|
|
2077
|
-
if (e.includes(s)) {
|
|
2078
|
-
const i = {};
|
|
2079
|
-
i[s] = g.get(s, null, null), r.push(i);
|
|
2080
|
-
}
|
|
2081
|
-
}), 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
|
+
}
|
|
2082
3016
|
}
|
|
2083
|
-
return
|
|
2084
|
-
}
|
|
2085
|
-
static remove(e, n) {
|
|
2086
|
-
var r = this._getPrefixedKey(e, n);
|
|
2087
|
-
localStorage.removeItem(r);
|
|
2088
|
-
}
|
|
2089
|
-
static clear(e) {
|
|
2090
|
-
g.prefix.length ? this.keys().forEach((n) => {
|
|
2091
|
-
localStorage.removeItem(this._getPrefixedKey(n, e));
|
|
2092
|
-
}) : localStorage.clear();
|
|
3017
|
+
return str;
|
|
2093
3018
|
}
|
|
2094
3019
|
};
|
|
2095
|
-
|
|
2096
|
-
return n = n || {}, n.noPrefix ? e : g.prefix + e;
|
|
2097
|
-
});
|
|
2098
|
-
let S = g;
|
|
2099
|
-
const Z = {
|
|
3020
|
+
const UrlUtil = {
|
|
2100
3021
|
/**
|
|
2101
3022
|
* 将json对象转换为查询字符串
|
|
2102
3023
|
*
|
|
2103
3024
|
* @param json 待转换的json对象
|
|
2104
3025
|
* @returns 转换后的查询字符串
|
|
2105
3026
|
*/
|
|
2106
|
-
json2Query(
|
|
2107
|
-
var
|
|
2108
|
-
for (var
|
|
2109
|
-
if (
|
|
2110
|
-
var
|
|
2111
|
-
|
|
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));
|
|
2112
3034
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
3035
|
+
}
|
|
3036
|
+
var urlParamsStr = tempArr.join("&");
|
|
3037
|
+
return urlParamsStr;
|
|
2115
3038
|
},
|
|
2116
3039
|
/**
|
|
2117
3040
|
* 从 URL 中解析出查询参数和哈希参数,并以对象的形式返回
|
|
@@ -2120,53 +3043,60 @@ const Z = {
|
|
|
2120
3043
|
* @param needDecode 是否需要解码参数值,默认为 true
|
|
2121
3044
|
* @returns 返回一个包含解析后参数的对象,其中键为参数名,值为参数值
|
|
2122
3045
|
*/
|
|
2123
|
-
query2Json(
|
|
2124
|
-
const
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
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
|
+
}
|
|
2135
3062
|
}
|
|
3063
|
+
}
|
|
2136
3064
|
}
|
|
2137
3065
|
}
|
|
2138
|
-
return
|
|
3066
|
+
return obj;
|
|
2139
3067
|
}
|
|
2140
3068
|
};
|
|
2141
3069
|
export {
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
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
|
|
2172
3102
|
};
|