gis-common 4.2.1 → 4.2.3

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