zhihao-ui 1.2.65 → 1.3.0

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.
Files changed (99) hide show
  1. package/dist/es/{BaseInfo-VzgiaCKn.js → BaseInfo-DP7wB6Hy.js} +1 -1
  2. package/dist/es/{BaseItem-BtsARxvz.js → BaseItem-zKXAWw6X.js} +3 -3
  3. package/dist/es/{Button-Dw3i74l2.js → Button-D71UFKe2.js} +2 -2
  4. package/dist/es/DatePicker-ByaPDV8a.js +57 -0
  5. package/dist/es/{DetailHeader-C5LjDuTv.js → DetailHeader-BvwqbiHO.js} +3 -3
  6. package/dist/es/{DetailSubTitle-ak2l4HyV.js → DetailSubTitle-Brh4lgY7.js} +2 -2
  7. package/dist/es/{Dialog-Cw3E3ZU6.js → Dialog-Dfj9XSbZ.js} +3 -3
  8. package/dist/es/{DiyDataTable-Cgqys5z_.js → DiyDataTable-CyinC7X9.js} +4 -4
  9. package/dist/es/{EditInfoPair-8SWkyWJC.js → EditInfoPair-Bh8ExT4y.js} +3 -3
  10. package/dist/es/{FileWrapper-BKxBr28L.js → FileWrapper-Cr7F-CIS.js} +4 -4
  11. package/dist/es/{Grid-C8tYH4s7.js → Grid-CzmdTj41.js} +2 -2
  12. package/dist/es/{InfoPair-C3obQrjB.js → InfoPair-wZg9g-ul.js} +3 -3
  13. package/dist/es/{Input-C3HDYWCC.js → Input-DRtonb3d.js} +3 -3
  14. package/dist/es/{Loading-DfL7OJvd.js → Loading-CujO-NlL.js} +2 -2
  15. package/dist/es/Map-mRzxeRp6.js +1877 -0
  16. package/dist/es/{MessageBox-ByLWEDby.js → MessageBox-CRUoKQsc.js} +2 -2
  17. package/dist/es/{MoneyInput-CxngoHAe.js → MoneyInput-D1u6lU9a.js} +7 -7
  18. package/dist/es/{PageHeadPanel-d3ponlDx.js → PageHeadPanel-COhIV995.js} +2 -2
  19. package/dist/es/{Table-BufcZ4Wy.js → Table-BFbxIF3i.js} +5 -5
  20. package/dist/es/{ToolTips-D0FAOOvm.js → ToolTips-DNojIdT8.js} +7 -7
  21. package/dist/es/index.js +60 -74
  22. package/dist/es/{utils-BSQSj8Ii.js → utils-CVU4so-2.js} +1 -1
  23. package/dist/es/{vendor-DaYdW1_n.js → vendor-Cx2Ws2_l.js} +21548 -25505
  24. package/dist/index.css +1 -1
  25. package/dist/types/components/Map/components/zoomControl.vue.d.ts +1 -9
  26. package/dist/types/components/Map/config/index.d.ts +69 -0
  27. package/dist/types/components/Map/function/carTrack.d.ts +18 -0
  28. package/dist/types/components/Map/function/drawLine.d.ts +19 -0
  29. package/dist/types/components/Map/function/drawPolygon.d.ts +13 -0
  30. package/dist/types/components/Map/function/label.d.ts +9 -0
  31. package/dist/types/components/Map/function/layers.d.ts +7 -0
  32. package/dist/types/components/Map/function/map.d.ts +10 -0
  33. package/dist/types/components/Map/function/port.d.ts +10 -0
  34. package/dist/types/components/Map/function/ship/index.d.ts +9 -0
  35. package/dist/types/components/Map/function/ship/label.d.ts +5 -0
  36. package/dist/types/components/Map/function/ship/style.d.ts +7 -0
  37. package/dist/types/components/Map/function/ship.d.ts +34 -0
  38. package/dist/types/components/Map/function/shipLabel.d.ts +25 -0
  39. package/dist/types/components/Map/function/shipOverlay.d.ts +12 -0
  40. package/dist/types/components/Map/function/shipTrack.d.ts +15 -0
  41. package/dist/types/components/Map/interface/{entity/queryLicenseResponse.d.ts → carTrack.d.ts} +1 -17
  42. package/dist/types/components/Map/interface/index.d.ts +6 -13
  43. package/dist/types/components/Map/interface/label.d.ts +27 -0
  44. package/dist/types/components/Map/interface/mapProps.d.ts +14 -0
  45. package/dist/types/components/Map/interface/{entity/shipInfoVo.d.ts → shipInfoVo.d.ts} +17 -15
  46. package/dist/types/components/Map/interface/{entity/shipTrack.d.ts → shipTrack.d.ts} +2 -1
  47. package/dist/types/components/Map/interface/wharfEntity.d.ts +20 -0
  48. package/dist/types/components/Map/meta/index.d.ts +17 -0
  49. package/dist/types/components/Map/meta/ship.d.ts +26 -0
  50. package/dist/types/components/Map/types.d.ts +1 -13
  51. package/dist/types/components/Map/utils/cursor.d.ts +2 -0
  52. package/dist/types/components/Map/utils/events.d.ts +2 -0
  53. package/dist/types/components/Map/utils/rbush.d.ts +13 -0
  54. package/dist/types/components/Map/utils/track.d.ts +1 -0
  55. package/dist/umd/index.css +1 -1
  56. package/dist/umd/index.umd.cjs +124 -588
  57. package/package.json +1 -1
  58. package/dist/es/DatePicker-BCvYHlC7.js +0 -73
  59. package/dist/es/Map-BpqtL7_q.js +0 -2528
  60. package/dist/types/components/Map/Map.vue.d.ts +0 -156
  61. package/dist/types/components/Map/components/copyright.vue.d.ts +0 -36
  62. package/dist/types/components/Map/components/measure.vue.d.ts +0 -23
  63. package/dist/types/components/Map/components/toolPanel.vue.d.ts +0 -40
  64. package/dist/types/components/Map/config.d.ts +0 -32
  65. package/dist/types/components/Map/enum/car.d.ts +0 -5
  66. package/dist/types/components/Map/enum/device.d.ts +0 -8
  67. package/dist/types/components/Map/enum/index.d.ts +0 -5
  68. package/dist/types/components/Map/enum/openLayers.d.ts +0 -10
  69. package/dist/types/components/Map/enum/ship.d.ts +0 -50
  70. package/dist/types/components/Map/index.d.ts +0 -439
  71. package/dist/types/components/Map/interface/common/BaseEntity.d.ts +0 -29
  72. package/dist/types/components/Map/interface/common/page.d.ts +0 -34
  73. package/dist/types/components/Map/interface/entity/dashboard.d.ts +0 -16
  74. package/dist/types/components/Map/interface/entity/map.d.ts +0 -36
  75. package/dist/types/components/Map/interface/entity/point.d.ts +0 -10
  76. package/dist/types/components/Map/interface/entity/render.d.ts +0 -57
  77. package/dist/types/components/Map/interface/entity/ship.d.ts +0 -361
  78. package/dist/types/components/Map/interface/entity/shipMapData.d.ts +0 -27
  79. package/dist/types/components/Map/interface/entity/shipMarker.d.ts +0 -8
  80. package/dist/types/components/Map/interface/entity/vehicle.d.ts +0 -345
  81. package/dist/types/components/Map/interface/vo/vehicleVo.d.ts +0 -20
  82. package/dist/types/components/Map/render/canvasRender/canvasRender.d.ts +0 -15
  83. package/dist/types/components/Map/render/canvasRender/geometry.d.ts +0 -22
  84. package/dist/types/components/Map/render/canvasRender/renderCustomOverlay.d.ts +0 -5
  85. package/dist/types/components/Map/render/canvasRender/renderPointStyle.d.ts +0 -10
  86. package/dist/types/components/Map/render/canvasRender/renderShipStyle.d.ts +0 -5
  87. package/dist/types/components/Map/render/canvasRender/renderTrackStyle.d.ts +0 -12
  88. package/dist/types/components/Map/render/canvasRender/renderTruckStyle.d.ts +0 -3
  89. package/dist/types/components/Map/render/drawPolygon.d.ts +0 -10
  90. package/dist/types/components/Map/render/renderDashboard.d.ts +0 -12
  91. package/dist/types/components/Map/render/renderMarker.d.ts +0 -7
  92. package/dist/types/components/Map/render/renderPoint.d.ts +0 -80
  93. package/dist/types/components/Map/render/renderShip.d.ts +0 -20
  94. package/dist/types/components/Map/render/renderTrack.d.ts +0 -12
  95. package/dist/types/components/Map/render/renderTruck.d.ts +0 -10
  96. package/dist/types/components/Map/utils/common.d.ts +0 -27
  97. package/dist/types/components/Map/utils/format.d.ts +0 -10
  98. package/dist/types/components/Map/utils/store.d.ts +0 -32
  99. package/dist/types/components/Map/utils/transform.d.ts +0 -44
@@ -0,0 +1,1877 @@
1
+ import { defineComponent, inject, openBlock, createElementBlock, ref, createElementVNode, provide, onMounted, Fragment, createVNode } from "vue";
2
+ import { S as ScaleLine$1, t as toLonLat, p as fromLonLat, T as Text, F as Fill, q as Style, r as getLength, s as TileLayer, X as XYZ, R as RBush$1, V as VectorSource, u as VectorLayer, v as debounce, w as Feature, P as Point, I as Icon, x as useDebounceFn, O as Overlay, h as hooks, L as LineString, y as Stroke, z as Polygon, C as CircleStyle, A as Polyline, B as buffer, D as transform, G as getVectorContext, H as DoubleClickZoom, J as merge, K as Draw, M as unByKey, N as getUid, Q as MultiPoint, U as getArea, W as Map$2, Y as View } from "./vendor-Cx2Ws2_l.js";
3
+ import { _ as _export_sfc } from "./Button-D71UFKe2.js";
4
+ import { w as withInstall } from "./utils-CVU4so-2.js";
5
+ const _hoisted_1$1 = { id: "scale-line-container" }, _sfc_main$2 = /* @__PURE__ */ defineComponent({
6
+ __name: "scaleLine",
7
+ setup(e, { expose: t }) {
8
+ const o = inject("mapInstance");
9
+ return t({
10
+ setScaleLine: (r) => {
11
+ var s;
12
+ r || (r = "metric");
13
+ const a = new ScaleLine$1({
14
+ units: r
15
+ }), i = document.getElementById("scale-line-container");
16
+ i && (a.setTarget(i), (s = o == null ? void 0 : o.value) == null || s.addControl(a));
17
+ }
18
+ }), (r, a) => (openBlock(), createElementBlock("div", _hoisted_1$1));
19
+ }
20
+ }), ScaleLine = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-3cec9b07"]]), mapInstance$1 = ref(), getInstall = () => mapInstance$1.value, setInstall = (e) => {
21
+ mapInstance$1.value = e;
22
+ }, getView = () => getInstall().getView(), getZoom = () => {
23
+ var e;
24
+ return (e = getView()) == null ? void 0 : e.getZoom();
25
+ }, setZoom = (e) => {
26
+ var t;
27
+ console.log(e), console.log("getView()", getView()), (t = getView()) == null || t.setZoom(e);
28
+ }, setCenter = (e, t) => {
29
+ var o;
30
+ (o = getView()) == null || o.setCenter(fromLonLat([e, t]));
31
+ }, getCenter = () => {
32
+ var t;
33
+ const e = (t = getView()) == null ? void 0 : t.getCenter();
34
+ return toLonLat(e);
35
+ }, _hoisted_1 = { class: "zoom" }, _sfc_main$1 = /* @__PURE__ */ defineComponent({
36
+ __name: "zoomControl",
37
+ setup(e) {
38
+ const t = inject("mapInstance"), o = () => {
39
+ if (t != null && t.value) {
40
+ const r = getZoom();
41
+ if (!r) return;
42
+ setZoom(r + 1);
43
+ }
44
+ }, n = () => {
45
+ if (t != null && t.value) {
46
+ const r = getZoom();
47
+ if (!r) return;
48
+ setZoom(r - 1);
49
+ }
50
+ };
51
+ return (r, a) => (openBlock(), createElementBlock("div", _hoisted_1, [
52
+ createElementVNode("div", {
53
+ class: "button big-button",
54
+ onClick: o
55
+ }, " + "),
56
+ createElementVNode("div", {
57
+ class: "button small-button",
58
+ onClick: n
59
+ }, " - ")
60
+ ]));
61
+ }
62
+ }), ZoomControl = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-7771507f"]]), CDN_URL = "https://static.zhihaoscm.cn/", TIAN_DI_TU_KEY = "a6e8f78974f2581f2ca00485b40c948f", MAP_ZOOM = {
63
+ // 地图默认层级
64
+ default: 13,
65
+ // 地图缩放最小层级
66
+ min: 3,
67
+ // 地图缩放最大层级
68
+ max: 18,
69
+ // 船形图标最小渲染层级
70
+ shipTriggleMin: 16,
71
+ // 船形图标最大渲染层级
72
+ shipModelMax: 18,
73
+ //根据原系统canvas图片转换svg长宽比例计算缩放值
74
+ scaleNum: 0.555
75
+ }, MAP_DEFAULT_CENTER = [114.84, 30.52], projection = {
76
+ // 经纬度 源数据 地理坐标 WGS84
77
+ data: "EPSG:4326",
78
+ // 墨卡托投影坐标 渲染坐标
79
+ mercator: "EPSG:3857"
80
+ }, formatLength = function(e, t) {
81
+ const n = getLength(e);
82
+ let r = "";
83
+ switch (t) {
84
+ case LENGTH_UNIT.M:
85
+ r = Math.round(n * 100) / 100 + " m";
86
+ break;
87
+ case LENGTH_UNIT.KM:
88
+ r = Math.round(n / 1e3 * 100) / 100 + " km";
89
+ break;
90
+ case LENGTH_UNIT.NM:
91
+ r = (Math.round(n / 1e3 * 100) / 100 / 1.852).toFixed(2) + " nm";
92
+ break;
93
+ }
94
+ return r;
95
+ }, equatorialCircumference = 2003750834e-2;
96
+ function lonLatToMercator(e) {
97
+ const t = e[0] * equatorialCircumference / 180;
98
+ let o = Math.log(Math.tan((90 + e[1]) * Math.PI / 360)) / (Math.PI / 180);
99
+ return o = o * equatorialCircumference / 180, [t, o];
100
+ }
101
+ function getIconFont$1(unicode = "") {
102
+ return unicode.indexOf("&") !== -1 && (unicode = unicode.replace("&", "&")), unicode.indexOf("&amp") !== -1 && (unicode = unicode.replace("&amp", "&")), eval('("' + unicode.replace("&#x", "\\u").replace(";", "") + '")');
103
+ }
104
+ const getIconStyle = (e) => {
105
+ const t = new Text({
106
+ font: "Normal 14px map-iconfont",
107
+ text: getIconFont$1(e),
108
+ fill: new Fill({ color: "#fff" }),
109
+ offsetY: -14
110
+ });
111
+ return new Style({
112
+ text: t,
113
+ zIndex: 100
114
+ });
115
+ }, adjustBounds = (e, t) => t.length === 2 ? [e[0] - t[0], e[1] - t[1], e[2] + t[0], e[3] + t[1]] : [e[0] + t[0], e[1] + t[1], e[2] + t[2], e[3] + t[3]], isOverlapping = (e, t) => e[0] <= t[2] && e[2] >= t[0] && e[1] <= t[3] && e[3] >= t[1], mercatorToLonLat = (e, t = "lonlat") => {
116
+ const o = { lon: 0, lat: 0 }, n = e[0] / equatorialCircumference * 180;
117
+ let r = e[1] / equatorialCircumference * 180;
118
+ return r = 180 / Math.PI * (2 * Math.atan(Math.exp(r * Math.PI / 180)) - Math.PI / 2), o.lon = n, o.lat = r, t === "lonlat" ? o : [n, r];
119
+ };
120
+ var BASE_MAP_LINK = ((e) => (e.vectorTile = `https://t0.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&TILEMATRIXSET=w&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIAN_DI_TU_KEY}`, e.vectorTileMark = `https://t0.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&TILEMATRIXSET=w&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIAN_DI_TU_KEY}`, e.satelliteImgTile = `https://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&TILEMATRIXSET=w&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIAN_DI_TU_KEY}`, e.satelliteImgTileMark = `https://t0.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&TILEMATRIXSET=w&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIAN_DI_TU_KEY}`, e.greenTile = `${CDN_URL}/map/tile/{z}/{x}/{y}.png`, e))(BASE_MAP_LINK || {}), LENGTH_UNIT = /* @__PURE__ */ ((e) => (e[e.M = 1] = "M", e[e.KM = 2] = "KM", e[e.NM = 3] = "NM", e))(LENGTH_UNIT || {});
121
+ const getLayers = () => {
122
+ var e;
123
+ return (e = getInstall()) == null ? void 0 : e.getLayers();
124
+ }, layerType = ref("vector"), getShowLayerType = () => layerType.value, setShowLayerType = (e) => {
125
+ layerType.value = e;
126
+ const t = getLayers();
127
+ t && t.getArray().forEach((o) => {
128
+ o.setVisible(o.className_ === e);
129
+ });
130
+ }, showGreenTile = ref(), getGreenTileVisible = () => showGreenTile.value, setGreenTileVisible = (e) => {
131
+ if (e !== showGreenTile.value) {
132
+ if (e) {
133
+ const t = getLayers();
134
+ if (!t.getArray().find((n) => n.className_ === "greenTile")) {
135
+ const n = new TileLayer({
136
+ source: new XYZ({ url: BASE_MAP_LINK.greenTile }),
137
+ visible: e,
138
+ zIndex: 2,
139
+ className: "greenTile"
140
+ });
141
+ t.push(n);
142
+ }
143
+ } else {
144
+ const t = getLayers(), o = t.getArray().find((n) => n.className_ === "greenTile");
145
+ o && t.remove(o);
146
+ }
147
+ showGreenTile.value = e;
148
+ }
149
+ }, pixelRatio$1 = window.devicePixelRatio || 1, labelFont$1 = `${12 * pixelRatio$1}px Arial`, collisionTree$1 = new RBush$1(), features = /* @__PURE__ */ new Map(), animationFrameIds$1 = /* @__PURE__ */ new Map(), labels$1 = /* @__PURE__ */ new Map();
150
+ let currentLabelId = null, metrics = { width: 0, height: 0, textWidth: 0 };
151
+ const options$1 = {
152
+ padding: 4,
153
+ iconSize: 12,
154
+ lineColor: "#fff",
155
+ blinkInterval: 500,
156
+ collisionPadding: 10
157
+ };
158
+ function getIconFont(unicode = "") {
159
+ return unicode.indexOf("&amp;") !== -1 && (unicode = unicode.replace("&amp;", "&")), unicode.indexOf("&amp") !== -1 && (unicode = unicode.replace("&amp", "&")), eval('("' + unicode.replace("&#x", "\\u").replace(";", "") + '")');
160
+ }
161
+ const getFeatureById = (e) => features.get(e), checkCollision$1 = (e) => {
162
+ const t = options$1.collisionPadding, o = {
163
+ minX: e[0] - t,
164
+ minY: e[1] - t,
165
+ maxX: e[2] + t,
166
+ maxY: e[3] + t
167
+ }, n = collisionTree$1.search(o);
168
+ return currentLabelId && n.length > 0 ? n.some((r) => r.id !== currentLabelId) : n.length > 0;
169
+ }, calculateTextMetrics$1 = (e, t, o) => {
170
+ var i;
171
+ e.font = "500 " + labelFont$1;
172
+ const n = e.measureText(t.name).width, r = o ? 12 * devicePixelRatio + 10 : 0, a = (((i = t.rightIcons) == null ? void 0 : i.length) || 0) * (options$1.iconSize * devicePixelRatio + 6);
173
+ return {
174
+ width: r + options$1.padding * 2 + n + a,
175
+ textWidth: n,
176
+ height: parseInt(labelFont$1) * 1.2
177
+ };
178
+ }, calculateBestPosition$1 = (e, t) => {
179
+ const o = [
180
+ { position: "right", alignment: "center" },
181
+ // 右侧居中
182
+ { position: "left", alignment: "center" },
183
+ // 左侧居中
184
+ { position: "top", alignment: "center" },
185
+ // 上方居中
186
+ { position: "bottom", alignment: "center" },
187
+ // 下方居中
188
+ { position: "right", alignment: "start" },
189
+ // 右侧顶部对齐
190
+ { position: "right", alignment: "end" },
191
+ // 右侧底部对齐
192
+ { position: "left", alignment: "start" },
193
+ // 左侧顶部对齐
194
+ { position: "left", alignment: "end" },
195
+ // 左侧底部对齐
196
+ { position: "top", alignment: "start" },
197
+ // 上方左侧对齐
198
+ { position: "top", alignment: "end" },
199
+ // 上方右侧对齐
200
+ { position: "bottom", alignment: "start" },
201
+ // 下方左侧对齐
202
+ { position: "bottom", alignment: "end" }
203
+ // 下方右侧对齐
204
+ ];
205
+ for (const { position: r, alignment: a } of o) {
206
+ const i = calculateBounds$1(e, r, a, t);
207
+ if (!checkCollision$1(i))
208
+ return {
209
+ bounds: i,
210
+ position: r,
211
+ connectionPoints: calculateConnectionPoints$1(e, i, r, a)
212
+ };
213
+ }
214
+ const n = calculateBounds$1(e, "right", "start", t);
215
+ return {
216
+ bounds: n,
217
+ position: "right",
218
+ connectionPoints: calculateConnectionPoints$1(e, n, "right", "start")
219
+ };
220
+ }, calculateConnectionPoints$1 = (e, t, o, n) => {
221
+ const [r, a, i, s] = t, d = [r + (i - r) / 2, a + (s - a) / 2];
222
+ switch (o) {
223
+ case "right":
224
+ return n === "center" ? { start: e, end: [r, d[1]] } : n === "start" ? { start: e, end: [r, a + 10] } : { start: e, end: [r, s - 10] };
225
+ case "left":
226
+ return n === "center" ? { start: e, end: [i, d[1]] } : n === "start" ? { start: e, end: [i, a + 10] } : { start: e, end: [i, s - 10] };
227
+ case "top":
228
+ return n === "center" ? { start: e, end: [d[0], s] } : n === "start" ? { start: e, end: [r + 10, s] } : { start: e, end: [i - 10, s] };
229
+ case "bottom":
230
+ return n === "center" ? { start: e, end: [d[0], a] } : n === "start" ? { start: e, end: [r + 10, a] } : { start: e, end: [i - 10, a] };
231
+ default:
232
+ return { start: e, end: [r, d[1]] };
233
+ }
234
+ }, calculateBounds$1 = (e, t, o, n, r = 30) => {
235
+ const [a, i] = e, { width: s, height: d } = n;
236
+ switch (t) {
237
+ case "right": {
238
+ const u = a + r;
239
+ let l;
240
+ return o === "center" ? l = i - d / 2 : o === "start" ? l = i : l = i - d, [u, l, u + s, l + d];
241
+ }
242
+ case "left": {
243
+ const u = a - s - r;
244
+ let l;
245
+ return o === "center" ? l = i - d / 2 : o === "start" ? l = i : l = i - d, [u, l, u + s, l + d];
246
+ }
247
+ case "top": {
248
+ const u = i - d - r;
249
+ let l;
250
+ return o === "center" ? l = a - s / 2 : o === "start" ? l = a : l = a - s, [l, u, l + s, u + d];
251
+ }
252
+ case "bottom": {
253
+ const u = i + r;
254
+ let l;
255
+ return o === "center" ? l = a - s / 2 : o === "start" ? l = a : l = a - s, [l, u, l + s, u + d];
256
+ }
257
+ default:
258
+ return [a + r, i - d / 2, a + s + r, i + d / 2];
259
+ }
260
+ }, updateCollisionTree = (e, t) => {
261
+ if (labels$1.has(e)) {
262
+ const o = labels$1.get(e);
263
+ collisionTree$1.remove({
264
+ minX: o.bounds[0] - options$1.collisionPadding,
265
+ minY: o.bounds[1] - options$1.collisionPadding,
266
+ maxX: o.bounds[2] + options$1.collisionPadding,
267
+ maxY: o.bounds[3] + options$1.collisionPadding,
268
+ id: e
269
+ });
270
+ }
271
+ collisionTree$1.insert({
272
+ minX: t.bounds[0] - options$1.collisionPadding,
273
+ minY: t.bounds[1] - options$1.collisionPadding,
274
+ maxX: t.bounds[2] + options$1.collisionPadding,
275
+ maxY: t.bounds[3] + options$1.collisionPadding,
276
+ id: e
277
+ }), labels$1.set(e, {
278
+ id: e,
279
+ bounds: t.bounds,
280
+ position: t.position,
281
+ connectionPoints: t.connectionPoints
282
+ });
283
+ }, drawConnectionLine$1 = (e, t, o) => {
284
+ e.save(), e.beginPath(), e.moveTo(...t), e.lineTo(...o), e.strokeStyle = options$1.lineColor, e.lineWidth = 1, e.stroke(), e.restore();
285
+ }, drawLabelBackground$1 = (e, t, o) => {
286
+ const n = createRoundedRectPath$1(t, metrics);
287
+ e.save(), e.fillStyle = o.blinking ? o.blinkingColor || "#FFF" : "rgba(255, 255, 255, 1)", e.fill(n), e.strokeStyle = options$1.lineColor, e.stroke(), e.restore();
288
+ }, drawLabelContent$1 = (e, t, o, n, r) => {
289
+ var u;
290
+ const a = options$1.padding, i = r ? 12 * devicePixelRatio + 6 : 0, [s, d] = [
291
+ t.bounds[0] + i + a,
292
+ // 关键修复点:基于原始bounds计算
293
+ t.bounds[1] + parseInt(labelFont$1)
294
+ ];
295
+ if (e.save(), e.fillStyle = n ? "#ffffff" : "#000000", e.font = `500 ${labelFont$1}`, e.fillText(o.name, s, d), (u = o.rightIcons) != null && u.length) {
296
+ const l = e.measureText(o.name).width, c = options$1.iconSize * pixelRatio$1;
297
+ e.font = `${c}px map-iconfont`, o.rightIcons.forEach((p, m) => {
298
+ const h = s + l + a + m * (c + 4), g = getIconFont(p);
299
+ g && e.fillText(g, h, d);
300
+ });
301
+ }
302
+ e.restore();
303
+ }, createRoundedRectPath$1 = (e, t) => {
304
+ const [o, n] = e, r = 0, a = new Path2D(), i = o + t.width + options$1.padding, s = n + t.height;
305
+ return a.moveTo(o + r, n), a.lineTo(i - r, n), a.quadraticCurveTo(i, n, i, n + r), a.lineTo(i, s - r), a.quadraticCurveTo(i, s, i - r, s), a.lineTo(o + r, s), a.quadraticCurveTo(o, s, o, s - r), a.lineTo(o, n + r), a.quadraticCurveTo(o, n, o + r, n), a.closePath(), a;
306
+ }, handleBlinkAnimation$1 = (e, t, o, n) => {
307
+ const r = n.blinkingColor || "#FF0";
308
+ clearAnimation$1(e, t);
309
+ const a = createRoundedRectPath$1(o.bounds, metrics);
310
+ let i = !1, s = 0;
311
+ const d = (u) => {
312
+ if (u - s > options$1.blinkInterval) {
313
+ s = u, e.save(), e.clip(a), e.clearRect(...o.bounds), e.fillStyle = i ? r : "rgba(255, 255, 255, 1)", e.fill(a);
314
+ const l = 12 * devicePixelRatio, c = o.bounds[0] + 4, p = o.bounds[1] + (o.bounds[3] - o.bounds[1] - l) / 2;
315
+ e.fillStyle = r, e.fillRect(c, p, l, l), drawLabelContent$1(
316
+ e,
317
+ o,
318
+ n,
319
+ i,
320
+ !0
321
+ ), i = !i, e.restore();
322
+ }
323
+ animationFrameIds$1.set(t, requestAnimationFrame(d));
324
+ };
325
+ animationFrameIds$1.set(t, requestAnimationFrame(d));
326
+ }, clearAll = () => {
327
+ clearAllAnimations(), collisionTree$1.clear(), labels$1.clear(), features.clear();
328
+ }, clearAllAnimations = () => {
329
+ animationFrameIds$1.forEach((e) => cancelAnimationFrame(e)), animationFrameIds$1.clear();
330
+ }, clearAnimation$1 = (e, t) => {
331
+ if (animationFrameIds$1.has(t)) {
332
+ cancelAnimationFrame(animationFrameIds$1.get(t)), animationFrameIds$1.delete(t);
333
+ const o = labels$1.get(t);
334
+ if (o) {
335
+ e.save();
336
+ const n = createRoundedRectPath$1(o.bounds, metrics);
337
+ e.fillStyle = "rgba(255, 255, 255, 1)", e.fill(n);
338
+ const r = getFeatureById(t);
339
+ r && drawLabelContent$1(
340
+ e,
341
+ { bounds: o.bounds },
342
+ // 需要传入对应feature(建议存储feature引用)
343
+ r,
344
+ !1,
345
+ r.blinking
346
+ ), e.restore();
347
+ }
348
+ }
349
+ }, createLabelRenderer$1 = (e, t, o) => {
350
+ currentLabelId = o.id, features.set(currentLabelId, o);
351
+ const n = o.blinking || !1;
352
+ metrics = calculateTextMetrics$1(e, o, n);
353
+ const r = calculateBestPosition$1(t, metrics);
354
+ console.log("labelPos", r), drawConnectionLine$1(e, r.connectionPoints.start, r.connectionPoints.end), drawLabelBackground$1(e, r.bounds, o), drawLabelContent$1(e, r, o, !1, n), n ? handleBlinkAnimation$1(e, currentLabelId, r, o) : clearAnimation$1(e, currentLabelId), updateCollisionTree(currentLabelId, r);
355
+ };
356
+ new RBush$1();
357
+ var SHIP_SAIL_STATUS = /* @__PURE__ */ ((e) => (e[e.发动机使用中 = 0] = "发动机使用中", e[e.锚泊 = 1] = "锚泊", e[e.未操作 = 2] = "未操作", e[e.操纵能力受限 = 3] = "操纵能力受限", e[e.吃水受限 = 4] = "吃水受限", e[e.系泊 = 5] = "系泊", e[e.搁浅 = 6] = "搁浅", e[e.从事捕捞 = 7] = "从事捕捞", e[e.航行中 = 8] = "航行中", e[e.留作将来修正导航状态 = 9] = "留作将来修正导航状态", e[e.高速船留用 = 10] = "高速船留用", e[e.机动船尾推作业 = 11] = "机动船尾推作业", e[e.机动船顶推或侧推作业 = 12] = "机动船顶推或侧推作业", e[e.飞翼船留用 = 13] = "飞翼船留用", e[e.现行的 = 14] = "现行的", e[e.未定义 = 15] = "未定义", e))(SHIP_SAIL_STATUS || {}), SHIP_DIRECT = /* @__PURE__ */ ((e) => (e.left = "left", e.right = "right", e.front = "front", e.up = "up", e.down = "down", e.back = "back", e))(SHIP_DIRECT || {});
358
+ const shipsSource$1 = new VectorSource(), shipsLayer$1 = new VectorLayer({
359
+ source: shipsSource$1,
360
+ className: "zh-map--ship-layer",
361
+ updateWhileInteracting: !1,
362
+ updateWhileAnimating: !1,
363
+ renderBuffer: 300,
364
+ zIndex: 101
365
+ });
366
+ let selectedShipId = "", selectedShip, selectedShipFeature$1 = null, hoveredShipId$1 = "", attentionShips$1 = {}, attentionShipsColor$1 = {}, isZooming = !1, lastZoomTime = 0, lastScale = 1;
367
+ const ZOOM_ANIMATION_DURATION = 300, config$2 = {
368
+ color: "#04C900"
369
+ }, isLayerOnMap = (e, t) => e.getLayers().getArray().includes(t);
370
+ debounce((e) => {
371
+ const t = getInstall();
372
+ if (!t) return;
373
+ isLayerOnMap(t, shipsLayer$1) || t.addLayer(shipsLayer$1), selectedShipFeature$1 = null, clearShipList$1(), selectedShipId && selectedShip && e.filter((r) => r.id === selectedShipId).length === 0 && e.push(selectedShip);
374
+ const o = [];
375
+ e.forEach((n) => {
376
+ const r = [];
377
+ n.existDevice && r.push("&#xe687;"), n.existMobile && r.push("&#xe688;"), n.existWaterGauge && r.push("&#xe686;");
378
+ const a = {
379
+ ...n,
380
+ name: n.cnname || "未命名船舶",
381
+ iconSize: 12,
382
+ leftIcons: [],
383
+ blinking: attentionShips$1[n.id] || !1,
384
+ blinkingColor: attentionShipsColor$1[n.id] || "",
385
+ rightIcons: r
386
+ }, i = new Feature({
387
+ geometry: new Point(fromLonLat([n.lon, n.lat])),
388
+ id: n.id,
389
+ shipId: n.id,
390
+ selected: selectedShipId === n.id || n.isSelected,
391
+ color: n.fill,
392
+ direct: getShipDirectPath$1(n),
393
+ hightlight: !1,
394
+ shipData: a
395
+ });
396
+ i.setId(n.id), i.setStyle(createShipStyle$1(i)), (selectedShipId === n.id || n.isSelected) && (selectedShipFeature$1 = i), o.push(i);
397
+ }), shipsSource$1.addFeatures(o);
398
+ }, 10);
399
+ function easeOutCubic(e) {
400
+ return 1 - Math.pow(1 - e, 3);
401
+ }
402
+ const getImageSizeAndScale = (e, t) => {
403
+ const o = getInstall(), n = Math.round(Number(o.getView().getZoom())), r = Date.now();
404
+ isZooming = r - lastZoomTime < ZOOM_ANIMATION_DURATION;
405
+ const a = n <= MAP_ZOOM.shipModelMax && n >= MAP_ZOOM.shipTriggleMin ? "ship" : "triangle";
406
+ let i = 0;
407
+ if (a === "ship") {
408
+ const s = getShipScale$1(e, t) + 0.1;
409
+ if (isZooming) {
410
+ const d = Math.min(1, (r - lastZoomTime) / ZOOM_ANIMATION_DURATION), u = easeOutCubic(d);
411
+ i = lastScale * (1 - u) + s * u;
412
+ } else
413
+ i = s;
414
+ }
415
+ return { type: a, scale: i };
416
+ }, createShipStyle$1 = (e) => {
417
+ const t = e.getProperties(), { selected: o, shipData: n } = t, { wid: r, len: a } = n, { scale: i, type: s } = getImageSizeAndScale(a, r);
418
+ e.set("lastScale", i, !0);
419
+ const u = [baseStyle(e)];
420
+ if (o) {
421
+ const c = generateSelectedSvg(i, s);
422
+ u.push(c);
423
+ }
424
+ const l = createLabelStyle$1();
425
+ return l && u.push(l), u;
426
+ }, baseStyle = (e) => {
427
+ const t = e.getProperties(), { len: o, wid: n, color: r, selected: a, hightlight: i, shipData: s, direct: d } = t, { blinkingColor: u } = s, { scale: l, type: c } = getImageSizeAndScale(o, n), p = (s.cog - 90 + 360) % 360;
428
+ return new Style({
429
+ image: new Icon({
430
+ src: generateSvg(c, a, i, u || r, d),
431
+ scale: l || MAP_ZOOM.scaleNum,
432
+ anchor: [0.5, 0.5],
433
+ rotation: p * Math.PI / 180,
434
+ rotateWithView: !1,
435
+ opacity: isZooming ? 0.8 : 1
436
+ }),
437
+ zIndex: 98
438
+ });
439
+ }, generateSelectedSvg = (e, t) => {
440
+ const o = t === "ship" ? 109 : 49, n = `<svg xmlns="http://www.w3.org/2000/svg" width="${o}" height="${o}" viewBox="0 0 49 49" fill="none">
441
+ <path d="M1.99982 46.9998L1.99982 1.99982L46.9998 1.99982L46.9998 46.9998L1.99982 46.9998Z" fill="#FF2424" fill-opacity="0.2"/>
442
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M19.9998 0.5V3.5L3.49976 3.5V20H0.499756V0.500002L19.9998 0.5ZM45.4998 3.5H28.9998V0.5H48.4998V20H45.4998V3.5ZM48.4998 29L48.4998 48.5H28.9998V45.5H45.4998L45.4998 29H48.4998ZM3.49976 45.5L3.49976 29H0.499756L0.499758 48.5L19.9998 48.5V45.5L3.49976 45.5Z" fill="#FF2424"/>
443
+ </svg>`;
444
+ return new Style({
445
+ image: new Icon({
446
+ src: `data:image/svg+xml;utf8,${encodeURIComponent(n)}`,
447
+ scale: e || MAP_ZOOM.scaleNum
448
+ }),
449
+ zIndex: 100
450
+ });
451
+ }, createLabelStyle$1 = () => new Style({
452
+ renderer: (e, t) => {
453
+ try {
454
+ e = e;
455
+ const o = t.context, n = t.feature.getProperties().shipData;
456
+ if (!n) return;
457
+ createLabelRenderer$1(o, e, n);
458
+ return;
459
+ } catch (o) {
460
+ console.error(o);
461
+ }
462
+ },
463
+ zIndex: 99
464
+ });
465
+ debounce((e, t, o) => {
466
+ const n = getInstall();
467
+ if (e && e.get("shipId")) {
468
+ const r = e.get("shipId"), a = e.get("shipId");
469
+ if (t === "click" && a && (handleShipSelected(a), o && o(a, !0)), t === "hover") {
470
+ hoveredShipId$1 && hoveredShipId$1 !== r && clearHoverHight$1(), hoveredShipId$1 = r, n.getTargetElement().style.cursor = r ? "pointer" : "";
471
+ const i = hoveredShipId$1 ? shipsSource$1.getFeatureById(hoveredShipId$1) : null;
472
+ i == null || i.set("hightlight", !0), i == null || i.setStyle(createShipStyle$1(i));
473
+ }
474
+ } else
475
+ n.getTargetElement().style.cursor = "", clearHoverHight$1();
476
+ }, 10);
477
+ const clearHoverHight$1 = () => {
478
+ const e = hoveredShipId$1 ? shipsSource$1.getFeatureById(hoveredShipId$1) : null;
479
+ hoveredShipId$1 = null, e == null || e.set("hightlight", !1), e == null || e.setStyle(createShipStyle$1(e));
480
+ }, handleShipSelected = useDebounceFn((e) => {
481
+ const t = selectedShipId ? shipsSource$1.getFeatureById(selectedShipId) : null;
482
+ if (selectedShipId = selectedShipId === e ? null : e, t && (t.set("selected", !1), t == null || t.setStyle(createShipStyle$1(t))), selectedShipId) {
483
+ const o = shipsSource$1.getFeatureById(selectedShipId);
484
+ o && (o.set("selected", !0), o == null || o.setStyle(createShipStyle$1(o)));
485
+ }
486
+ }, 50, { maxWait: 100 }), getShipDirectPath$1 = (e) => {
487
+ const { spd: t, hdg: o, cog: n } = e;
488
+ let r = "";
489
+ return t && o && n ? n - +o >= 3 ? r = SHIP_DIRECT.right : n - +o <= -3 ? r = SHIP_DIRECT.left : r = SHIP_DIRECT.front : r = SHIP_DIRECT.front, r;
490
+ };
491
+ function getShipScale$1(e, t) {
492
+ const o = getInstall(), n = 97, r = 20, i = 1 / o.getView().getResolution(), s = e * i / n, d = t * i / r;
493
+ return Math.max(s, d);
494
+ }
495
+ const handleShipChange = () => {
496
+ lastZoomTime = Date.now(), isZooming = !0;
497
+ const e = shipsSource$1.getFeatures();
498
+ e.length > 0 && (lastScale = e[0].get("lastScale") || 1), shipsLayer$1.changed(), console.log("changeRecation---changed");
499
+ }, generateSvg = (e, t, o, n, r) => `data:image/svg+xml;utf8,${encodeURIComponent(createSvgIcon(e, o, n, r))}`, createSvgIcon = (e, t, o, n) => {
500
+ switch (e) {
501
+ case "triangle":
502
+ return `<svg width="41" height="24" viewBox="0 0 41 24" fill="none" xmlns="http://www.w3.org/2000/svg">
503
+ <path d="M30.8843 12.6777L2.21343 21.7067C1.75559 21.8509 1.28947 21.509 1.28947 21.029L1.28947 2.97103C1.28947 2.49102 1.75558 2.14913 2.21342 2.29331L30.8843 11.3223C31.5471 11.531 31.5471 12.469 30.8843 12.6777Z"
504
+ fill="${o || config$2.color}" stroke="${t ? "#FF2424" : "black"}" stroke-width="${t ? "2" : "0.578947"}" />
505
+ <!--path船航向左边或者向前-->
506
+ ${n === SHIP_DIRECT.left && `<path d="M30 12L40 12L40 8" stroke="${t ? "#FF2424" : "black"}" stroke-width="2"/>`}
507
+ <!--path船航向右边-->
508
+ ${n === SHIP_DIRECT.right && `<path d="M30 12L40 12L40 16" stroke="${t ? "#FF2424" : "black"}" stroke-width="2"/>`}
509
+ <!--path黑线无左右-->
510
+ ${n === SHIP_DIRECT.front && `<path d="M30 12L40 12" stroke="${t ? "#FF2424" : "black"}" stroke-width="1.5"/>`}
511
+ </svg>
512
+ `;
513
+ case "ship":
514
+ return `<svg width="97" height="20" viewBox="0 0 97 20" fill="none" xmlns="http://www.w3.org/2000/svg">
515
+ <path d="M0.289474 17.3433L0.289474 2.65655C0.289474 2.28572 0.574654 1.97725 0.944343 1.9482L22.0544 0.289473L67.5204 0.289473C67.6295 0.289473 67.7372 0.314613 67.835 0.362943L86.0565 9.3629C86.5844 9.6236 86.5844 10.3763 86.0565 10.637L67.835 19.6371C67.7372 19.6854 67.6295 19.7105 67.5203 19.7105L22.0544 19.7105L0.944343 18.0517C0.574653 18.0226 0.289474 17.7142 0.289474 17.3433Z"
516
+ fill="${o || config$2.color}" stroke="${t ? "#FF2424" : "black"}" stroke-width="${t ? "2" : "0.578947"}"/>
517
+ ${n === SHIP_DIRECT.left && `<path d="M86 10L96 10L96 6" stroke="${t ? "#FF2424" : "black"}" stroke-width="1.5"/>`}
518
+ ${n === SHIP_DIRECT.right && `<path d="M86 10L96 10L96 14" stroke="${t ? "#FF2424" : "black"}" stroke-width="1.5"/>`}
519
+ ${n === SHIP_DIRECT.front && `<path d="M86 10L96 10" stroke="${t ? "#FF2424" : "black"}" stroke-width="1.5"/>`}
520
+ </svg>
521
+ `;
522
+ default:
523
+ return "";
524
+ }
525
+ }, clearShipList$1 = () => {
526
+ getInstall() && shipsSource$1 && (shipsSource$1.getFeatures().forEach((t) => {
527
+ var o;
528
+ (!selectedShipFeature$1 || t.get("shipData").shipId !== ((o = selectedShipFeature$1.get("shipData")) == null ? void 0 : o.id)) && shipsSource$1.removeFeature(t);
529
+ }), shipsSource$1 && shipsSource$1.clear(), clearAll());
530
+ }, getRightIcons = (e) => {
531
+ const t = [];
532
+ return e.existDevice && t.push("&#xe687;"), e.existMobile && t.push("&#xe688;"), e.existWaterGauge && t.push("&#xe686;"), t;
533
+ }, createLabelRenderer = (e, t, o) => {
534
+ if (console.log("createLabelRenderer"), !e) return;
535
+ const n = calculateTextMetrics(e, o), r = calculateBestPosition(t, n);
536
+ if (!r) return;
537
+ drawConnectionLine(e, t, r.connectionPoints.end), drawLabelBackground(e, r.bounds, o, n), drawLabelContent(e, o, r), o.get("blinking") || !1 ? handleBlinkAnimation(e, o, r, n) : clearAnimation(e, o, n);
538
+ }, pixelRatio = window.devicePixelRatio || 1, labelFont = `${12 * pixelRatio}px Arial`, options = {
539
+ padding: 4,
540
+ iconSize: 12,
541
+ lineColor: "#fff",
542
+ blinkInterval: 500,
543
+ collisionPadding: 10
544
+ }, calculateTextMetrics = (e, t) => {
545
+ var a;
546
+ e.font = `500 ${labelFont}`;
547
+ const o = e.measureText(t.get("name")).width, n = t.get("selected") ? 12 * devicePixelRatio + 10 : 0, r = (((a = t.get("rightIcons")) == null ? void 0 : a.length) || 0) * (options.iconSize * devicePixelRatio + 6);
548
+ return {
549
+ width: n + options.padding * 2 + o + r,
550
+ textWidth: o,
551
+ height: parseInt(labelFont) * 1.2
552
+ };
553
+ }, calculateBestPosition = (e, t) => {
554
+ const o = [
555
+ { position: "right", alignment: "center" },
556
+ // 右侧居中
557
+ { position: "left", alignment: "center" },
558
+ // 左侧居中
559
+ { position: "top", alignment: "center" },
560
+ // 上方居中
561
+ { position: "bottom", alignment: "center" },
562
+ // 下方居中
563
+ { position: "right", alignment: "start" },
564
+ // 右侧顶部对齐
565
+ { position: "right", alignment: "end" },
566
+ // 右侧底部对齐
567
+ { position: "left", alignment: "start" },
568
+ // 左侧顶部对齐
569
+ { position: "left", alignment: "end" },
570
+ // 左侧底部对齐
571
+ { position: "top", alignment: "start" },
572
+ // 上方左侧对齐
573
+ { position: "top", alignment: "end" },
574
+ // 上方右侧对齐
575
+ { position: "bottom", alignment: "start" },
576
+ // 下方左侧对齐
577
+ { position: "bottom", alignment: "end" }
578
+ // 下方右侧对齐
579
+ ];
580
+ for (const { position: n, alignment: r } of o) {
581
+ const a = calculateBounds(e, n, r, t);
582
+ if (!checkCollision(a))
583
+ return {
584
+ bounds: a,
585
+ position: n,
586
+ connectionPoints: calculateConnectionPoints(e, a, n, r)
587
+ };
588
+ }
589
+ }, calculateBounds = (e, t, o, n, r = 30) => {
590
+ const [a, i] = e, { width: s, height: d } = n;
591
+ switch (t) {
592
+ case "right": {
593
+ const u = a + r;
594
+ let l;
595
+ return o === "center" ? l = i - d / 2 : o === "start" ? l = i : l = i - d, [u, l, u + s, l + d];
596
+ }
597
+ case "left": {
598
+ const u = a - s - r;
599
+ let l;
600
+ return o === "center" ? l = i - d / 2 : o === "start" ? l = i : l = i - d, [u, l, u + s, l + d];
601
+ }
602
+ case "top": {
603
+ const u = i - d - r;
604
+ let l;
605
+ return o === "center" ? l = a - s / 2 : o === "start" ? l = a : l = a - s, [l, u, l + s, u + d];
606
+ }
607
+ case "bottom": {
608
+ const u = i + r;
609
+ let l;
610
+ return o === "center" ? l = a - s / 2 : o === "start" ? l = a : l = a - s, [l, u, l + s, u + d];
611
+ }
612
+ default:
613
+ return [a + r, i - d / 2, a + s + r, i + d / 2];
614
+ }
615
+ }, collisionTree = new RBush$1(), checkCollision = (e) => {
616
+ const t = options.collisionPadding, o = {
617
+ minX: e[0] - t,
618
+ minY: e[1] - t,
619
+ maxX: e[2] + t,
620
+ maxY: e[3] + t
621
+ };
622
+ return collisionTree.search(o).length > 0;
623
+ }, calculateConnectionPoints = (e, t, o, n) => {
624
+ const [r, a, i, s] = t, d = [r + (i - r) / 2, a + (s - a) / 2];
625
+ switch (o) {
626
+ case "right":
627
+ return n === "center" ? { start: e, end: [r, d[1]] } : n === "start" ? { start: e, end: [r, a + 10] } : { start: e, end: [r, s - 10] };
628
+ case "left":
629
+ return n === "center" ? { start: e, end: [i, d[1]] } : n === "start" ? { start: e, end: [i, a + 10] } : { start: e, end: [i, s - 10] };
630
+ case "top":
631
+ return n === "center" ? { start: e, end: [d[0], s] } : n === "start" ? { start: e, end: [r + 10, s] } : { start: e, end: [i - 10, s] };
632
+ case "bottom":
633
+ return n === "center" ? { start: e, end: [d[0], a] } : n === "start" ? { start: e, end: [r + 10, a] } : { start: e, end: [i - 10, a] };
634
+ default:
635
+ return { start: e, end: [r, d[1]] };
636
+ }
637
+ }, drawConnectionLine = (e, t, o) => {
638
+ e.save(), e.beginPath(), e.moveTo(...t), e.lineTo(...o), e.strokeStyle = options.lineColor, e.lineWidth = 1, e.stroke(), e.restore();
639
+ }, drawLabelBackground = (e, t, o, n) => {
640
+ const r = createRoundedRectPath(t, n);
641
+ e.save(), e.fillStyle = o.get("blinking") ? o.get("blinkingColor") || "#FFF" : "rgba(255, 255, 255, 1)", e.fill(r), e.strokeStyle = options.lineColor, e.stroke(), e.restore();
642
+ }, createRoundedRectPath = (e, t) => {
643
+ const [o, n] = e, r = 0, a = new Path2D(), i = o + t.width + options.padding, s = n + t.height;
644
+ return a.moveTo(o + r, n), a.lineTo(i - r, n), a.quadraticCurveTo(i, n, i, n + r), a.lineTo(i, s - r), a.quadraticCurveTo(i, s, i - r, s), a.lineTo(o + r, s), a.quadraticCurveTo(o, s, o, s - r), a.lineTo(o, n + r), a.quadraticCurveTo(o, n, o + r, n), a.closePath(), a;
645
+ }, drawLabelContent = (ctx, feature, labelPos) => {
646
+ const isSelected = feature.get("selected"), isHighlight = feature.get("isHighlight"), name = feature.get("name"), rightIcons = feature.get("rightIcons") || [], basePadding = options.padding, contentOffset = isSelected ? 12 * devicePixelRatio + 6 : 0, [x, y] = [
647
+ labelPos.bounds[0] + contentOffset + basePadding,
648
+ // 关键修复点:基于原始bounds计算
649
+ labelPos.bounds[1] + parseInt(labelFont)
650
+ ];
651
+ if (ctx.save(), ctx.fillStyle = isHighlight ? "#ffffff" : "#000000", ctx.font = `500 ${labelFont}`, ctx.fillText(name, x, y), rightIcons != null && rightIcons.length) {
652
+ const e = ctx.measureText(name).width, t = options.iconSize * pixelRatio;
653
+ ctx.font = `${t}px map-iconfont`, rightIcons.forEach((o, n) => {
654
+ const r = x + e + basePadding + n * (t + 4), a = getIconFont(o);
655
+ a && ctx.fillText(a, r, y);
656
+ });
657
+ }
658
+ ctx.restore();
659
+ function getIconFont(unicode = "") {
660
+ return unicode.indexOf("&amp;") !== -1 && (unicode = unicode.replace("&amp;", "&")), unicode.indexOf("&amp") !== -1 && (unicode = unicode.replace("&amp", "&")), eval('("' + unicode.replace("&#x", "\\u").replace(";", "") + '")');
661
+ }
662
+ }, animationFrameIds = /* @__PURE__ */ new Map(), labels = /* @__PURE__ */ new Map(), handleBlinkAnimation = (e, t, o, n) => {
663
+ const r = t.get("blinkingColor") || "#FF0";
664
+ clearAnimation(e, t, n);
665
+ const a = createRoundedRectPath(o.bounds, n);
666
+ let i = !1, s = 0;
667
+ const d = (u) => {
668
+ if (u - s > options.blinkInterval) {
669
+ s = u, e.save(), e.clip(a), e.clearRect(...o.bounds), e.fillStyle = i ? r : "rgba(255, 255, 255, 1)", e.fill(a);
670
+ const l = 12 * devicePixelRatio, c = o.bounds[0] + 4, p = o.bounds[1] + (o.bounds[3] - o.bounds[1] - l) / 2;
671
+ e.fillStyle = r, e.fillRect(c, p, l, l), drawLabelContent(
672
+ e,
673
+ t,
674
+ o
675
+ ), i = !i, e.restore();
676
+ }
677
+ animationFrameIds.set(t.get("id"), requestAnimationFrame(d));
678
+ };
679
+ animationFrameIds.set(t.get("id"), requestAnimationFrame(d));
680
+ }, clearAnimation = (e, t, o) => {
681
+ const n = t.get("id");
682
+ if (animationFrameIds.has(n)) {
683
+ cancelAnimationFrame(animationFrameIds.get(n)), animationFrameIds.delete(n);
684
+ const r = labels.get(n);
685
+ if (r) {
686
+ e.save();
687
+ const a = createRoundedRectPath(r.bounds, o);
688
+ e.fillStyle = "rgba(255, 255, 255, 1)", e.fill(a), t && drawLabelContent(
689
+ e,
690
+ t,
691
+ r
692
+ ), e.restore();
693
+ }
694
+ }
695
+ }, getShipDirectPath = (e) => {
696
+ const { spd: t, hdg: o, cog: n } = e;
697
+ return t ? o !== null && +o != 511 && n !== null ? n - +o >= 3 ? SHIP_DIRECT.right : n - +o <= -3 ? SHIP_DIRECT.left : SHIP_DIRECT.front : SHIP_DIRECT.front : "";
698
+ }, createShipStyle = (e) => {
699
+ const { selected: t } = e.getProperties(), o = getShipType(), n = getShipScale(e, o), r = [initShipStyle(e, n, o)];
700
+ return t && r.push(selectedShipStyle(n, o)), r.push(createLabelStyle(e)), r;
701
+ }, getShipType = () => {
702
+ const e = getZoom();
703
+ return e <= MAP_ZOOM.shipModelMax && e >= MAP_ZOOM.shipTriggleMin ? "ship" : "triangle";
704
+ }, getShipScale = (e, t) => {
705
+ if (t === "ship") {
706
+ const { shipData: o } = e.getProperties(), { len: n, wid: r } = o, a = 97, i = 20, d = 1 / getView().getResolution(), u = n * d / a, l = r * d / i;
707
+ return Math.max(u, l);
708
+ }
709
+ return 0;
710
+ }, initShipStyle = (e, t, o) => {
711
+ const { color: n, direct: r, isHighlight: a, shipData: i } = e.getProperties(), s = (i.cog - 90 + 360) % 360;
712
+ return new Style({
713
+ image: new Icon({
714
+ src: d(),
715
+ scale: t || MAP_ZOOM.scaleNum,
716
+ anchor: [0.5, 0.5],
717
+ rotation: s * Math.PI / 180,
718
+ rotateWithView: !1
719
+ })
720
+ });
721
+ function d() {
722
+ return `data:image/svg+xml;utf8,${encodeURIComponent(u())}`;
723
+ }
724
+ function u() {
725
+ switch (o) {
726
+ case "triangle":
727
+ return `<svg width="41" height="24" viewBox="0 0 41 24" fill="none" xmlns="http://www.w3.org/2000/svg">
728
+ <path d="M30.8843 12.6777L2.21343 21.7067C1.75559 21.8509 1.28947 21.509 1.28947 21.029L1.28947 2.97103C1.28947 2.49102 1.75558 2.14913 2.21342 2.29331L30.8843 11.3223C31.5471 11.531 31.5471 12.469 30.8843 12.6777Z"
729
+ fill="${n}" stroke="${a ? "#FF2424" : "black"}" stroke-width="${a ? "2" : "0.578947"}" />
730
+ <!--path船航向左边或者向前-->
731
+ ${r === SHIP_DIRECT.left && `<path d="M30 12L40 12L40 8" stroke="${a ? "#FF2424" : "black"}" stroke-width="2"/>`}
732
+ <!--path船航向右边-->
733
+ ${r === SHIP_DIRECT.right && `<path d="M30 12L40 12L40 16" stroke="${a ? "#FF2424" : "black"}" stroke-width="2"/>`}
734
+ <!--path黑线无左右-->
735
+ ${r === SHIP_DIRECT.front && `<path d="M30 12L40 12" stroke="${a ? "#FF2424" : "black"}" stroke-width="1.5"/>`}
736
+ </svg>
737
+ `;
738
+ case "ship":
739
+ return `<svg width="97" height="20" viewBox="0 0 97 20" fill="none" xmlns="http://www.w3.org/2000/svg">
740
+ <path d="M0.289474 17.3433L0.289474 2.65655C0.289474 2.28572 0.574654 1.97725 0.944343 1.9482L22.0544 0.289473L67.5204 0.289473C67.6295 0.289473 67.7372 0.314613 67.835 0.362943L86.0565 9.3629C86.5844 9.6236 86.5844 10.3763 86.0565 10.637L67.835 19.6371C67.7372 19.6854 67.6295 19.7105 67.5203 19.7105L22.0544 19.7105L0.944343 18.0517C0.574653 18.0226 0.289474 17.7142 0.289474 17.3433Z"
741
+ fill="${n}" stroke="${a ? "#FF2424" : "black"}" stroke-width="${a ? "4" : "0.578947"}"/>
742
+ ${r === SHIP_DIRECT.left && `<path d="M86 10L96 10L96 6" stroke="${a ? "#FF2424" : "black"}" stroke-width="1.5"/>`}
743
+ ${r === SHIP_DIRECT.right && `<path d="M86 10L96 10L96 14" stroke="${a ? "#FF2424" : "black"}" stroke-width="1.5"/>`}
744
+ ${r === SHIP_DIRECT.front && `<path d="M86 10L96 10" stroke="${a ? "#FF2424" : "black"}" stroke-width="1.5"/>`}
745
+ </svg>
746
+ `;
747
+ default:
748
+ return "";
749
+ }
750
+ }
751
+ }, selectedShipStyle = (e, t) => {
752
+ const o = t === "ship" ? 109 : 49, n = `<svg xmlns="http://www.w3.org/2000/svg" width="${o}" height="${o}" viewBox="0 0 49 49" fill="none">
753
+ <path d="M1.99982 46.9998L1.99982 1.99982L46.9998 1.99982L46.9998 46.9998L1.99982 46.9998Z" fill="#FF2424" fill-opacity="0.2"/>
754
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M19.9998 0.5V3.5L3.49976 3.5V20H0.499756V0.500002L19.9998 0.5ZM45.4998 3.5H28.9998V0.5H48.4998V20H45.4998V3.5ZM48.4998 29L48.4998 48.5H28.9998V45.5H45.4998L45.4998 29H48.4998ZM3.49976 45.5L3.49976 29H0.499756L0.499758 48.5L19.9998 48.5V45.5L3.49976 45.5Z" fill="#FF2424"/>
755
+ </svg>`;
756
+ return new Style({
757
+ image: new Icon({
758
+ src: `data:image/svg+xml;utf8,${encodeURIComponent(n)}`,
759
+ scale: e || MAP_ZOOM.scaleNum
760
+ }),
761
+ zIndex: 100
762
+ });
763
+ }, createLabelStyle = (e) => new Style({
764
+ renderer: (t, o) => {
765
+ createLabelRenderer(o.context, t, e);
766
+ },
767
+ zIndex: 99
768
+ }), shipsSource = new VectorSource(), shipsLayer = new VectorLayer({
769
+ source: shipsSource,
770
+ className: "zh-map--ship-layer",
771
+ updateWhileInteracting: !1,
772
+ updateWhileAnimating: !1,
773
+ renderBuffer: 300,
774
+ zIndex: 101
775
+ });
776
+ let hoveredShipId = "", attentionShips = {}, attentionShipsColor = {};
777
+ const renderShipList = (e) => {
778
+ const t = getInstall();
779
+ if (!t) return;
780
+ t.getLayers().getArray().includes(shipsLayer) || t.addLayer(shipsLayer), shipsSource && shipsSource.clear();
781
+ const o = [];
782
+ e.forEach((n) => {
783
+ const r = fromLonLat([n.lon, n.lat]), a = new Feature({
784
+ geometry: new Point(r),
785
+ // 船舶数据
786
+ shipData: n,
787
+ id: n.id,
788
+ name: n.cnname || "未命名船舶",
789
+ selected: n.id === (selectedShipFeature == null ? void 0 : selectedShipFeature.get("id")),
790
+ // 图标
791
+ rightIcons: getRightIcons(n),
792
+ // 是否闪烁
793
+ blinking: attentionShips[n.id] || !1,
794
+ // 闪烁颜色
795
+ blinkingColor: attentionShipsColor[n.id] || "",
796
+ // 船舶颜色
797
+ color: n.fill || "#04C900",
798
+ // 船艏向的方向
799
+ direct: getShipDirectPath(n),
800
+ // 高亮
801
+ isHighlight: !1
802
+ });
803
+ a.setStyle(createShipStyle(a)), o.push(a);
804
+ }), shipsSource.addFeatures(o);
805
+ };
806
+ let selectedShipFeature = null;
807
+ const clearShipList = () => {
808
+ getInstall() && shipsSource && shipsSource.getFeatures().forEach((t) => {
809
+ (!selectedShipFeature || t.get("shipData").shipId !== selectedShipFeature.get("id")) && shipsSource.removeFeature(t);
810
+ });
811
+ }, renderShipBlink = (e, t) => {
812
+ attentionShips = e, attentionShipsColor = t;
813
+ }, filterShipShow = (e) => {
814
+ if (!getInstall()) return;
815
+ const o = shipsSource.getFeatures(), n = selectedShipFeature ? selectedShipFeature.get("id") : "", r = o.filter((i) => i.getId() !== n), a = /* @__PURE__ */ new Map();
816
+ e.forEach((i) => {
817
+ a.set(i.id, !0);
818
+ }), r.forEach((i) => {
819
+ const s = i.get("id");
820
+ if (!a.has(s))
821
+ i.setStyle([]);
822
+ else {
823
+ const d = i.getStyle();
824
+ (d == null ? void 0 : d.length) == 0 && i.setStyle(createShipStyle(i));
825
+ }
826
+ });
827
+ }, renderShipSelected = (e) => {
828
+ if (e) {
829
+ console.log("选中");
830
+ const t = shipsSource.getFeatures().find((o) => o.get("id") === e.id);
831
+ if (t)
832
+ if (!selectedShipFeature)
833
+ selectedShipFeature = t, selectedShipFeature.set("selected", !0), selectedShipFeature.setStyle(createShipStyle(selectedShipFeature));
834
+ else {
835
+ const o = selectedShipFeature.get("id"), n = shipsSource.getFeatures().find((r) => r.get("id") === o);
836
+ n == null || n.set("selected", !1), n == null || n.setStyle(createShipStyle(n)), selectedShipFeature = null;
837
+ }
838
+ else {
839
+ console.log("选中,不存在");
840
+ const o = fromLonLat([e.lon, e.lat]);
841
+ selectedShipFeature = new Feature({
842
+ geometry: new Point(o),
843
+ // 船舶数据
844
+ shipData: e,
845
+ id: e.id,
846
+ name: e.cnname || "未命名船舶",
847
+ selected: e.id === (selectedShipFeature == null ? void 0 : selectedShipFeature.get("id")),
848
+ // 图标
849
+ rightIcons: getRightIcons(e),
850
+ // 是否闪烁
851
+ blinking: attentionShips[e.id] || !1,
852
+ // 闪烁颜色
853
+ blinkingColor: attentionShipsColor[e.id] || "",
854
+ // 船舶颜色
855
+ color: e.fill || "#04C900",
856
+ // 船艏向的方向
857
+ direct: getShipDirectPath(e),
858
+ // 高亮
859
+ isHighlight: !1
860
+ });
861
+ }
862
+ } else if (console.log("取消选中"), selectedShipFeature) {
863
+ selectedShipFeature.set("selected", !1);
864
+ const t = shipsSource.getFeatures().find((o) => o.get("id") === (selectedShipFeature == null ? void 0 : selectedShipFeature.get("id")));
865
+ t && (selectedShipFeature = t), selectedShipFeature.set("selected", !1), selectedShipFeature.setStyle(createShipStyle(selectedShipFeature)), selectedShipFeature = null;
866
+ }
867
+ }, handleShipMapEvent = debounce((e, t, o) => {
868
+ const n = getInstall();
869
+ if (e) {
870
+ const r = e.get("shipData"), a = e.get("id");
871
+ if (n.getTargetElement().style.cursor = a ? "pointer" : "", t === "click" && (selectedShipFeature && renderShipSelected(r), o && o(a)), t === "hover") {
872
+ hoveredShipId && hoveredShipId == a && clearHoverHight(), hoveredShipId = a;
873
+ const i = hoveredShipId ? shipsSource.getFeatureById(hoveredShipId) : null;
874
+ i == null || i.set("hightlight", !0), i == null || i.setStyle(createShipStyle(i));
875
+ }
876
+ } else
877
+ n.getTargetElement().style.cursor = "", clearHoverHight();
878
+ }, 10), clearHoverHight = () => {
879
+ const e = hoveredShipId ? shipsSource.getFeatureById(hoveredShipId) : null;
880
+ hoveredShipId = null, e == null || e.set("hightlight", !1), e == null || e.setStyle(createShipStyle(e));
881
+ }, convertSixHundredThousandToLatLng = function(e, t) {
882
+ const o = Number(t) / 6e5;
883
+ return [Number(e) / 6e5, o];
884
+ }, stopIcon = "&#xe6e2;", stopColor = "#E31818", slowIcon = "&#xe703;", slowColor = "#1890FF", dropletsIcon = "&#xe6d2", DEFAULT_VALUE = "--";
885
+ let moveFeatureHandler = null;
886
+ const stopIconStyle = getIconStyle(stopIcon), slowIconStyle = getIconStyle(slowIcon), popupEle = document.createElement("div"), popupOverlay = new Overlay({
887
+ element: popupEle,
888
+ positioning: "top-left",
889
+ stopEvent: !1
890
+ });
891
+ let polyline, linePath, startMarker, position, geoMarker, trackAnimating = !1, lastTime = Date.now(), vectorLayer$3, distance = 0, thresholdNum = 20;
892
+ const labelConfig = {
893
+ textOffset: [30, -30],
894
+ padding: [2, 5, 2, 5],
895
+ bgColor: "rgba(255,255,255,0.8)",
896
+ textColor: "#333",
897
+ fontSize: 12,
898
+ fontFamily: "Arial",
899
+ fontWeight: "500"
900
+ }, routesSource = new VectorSource(), routeLayer = new VectorLayer({
901
+ source: routesSource,
902
+ className: "zh-map--track-layer",
903
+ zIndex: 102
904
+ });
905
+ let routeFeatures = [], showTracks = [], allTracks = {}, trackId = "", trackColor = "", trackList = [], mapInstance = null;
906
+ const reRenderTrackLine = () => {
907
+ mapInstance = getInstall(), handlerRenderLine();
908
+ }, renderTrackLine = async (e, t, o, n = LENGTH_UNIT.NM, r = "ship", a = 200) => {
909
+ if (mapInstance = getInstall(), !mapInstance) return;
910
+ if (routeLayer == null || routeLayer.setVisible(!0), t = t == null ? void 0 : t.reverse(), popupOverlay && r === "ship" && (mapInstance != null && mapInstance.getOverlays().getArray().includes(popupOverlay) || mapInstance.addOverlay(popupOverlay)), clearShipList$1(), (t == null ? void 0 : t.length) < 2) {
911
+ (showTracks == null ? void 0 : showTracks.findIndex((c) => c.id === e)) < 0 && showTracks.push({ id: e, length: "" });
912
+ return;
913
+ }
914
+ const i = {};
915
+ t.forEach((c) => {
916
+ c.state ? c.state = Number(c.state) : delete c.state;
917
+ }), trackId = e, i[e] = t, trackList = t;
918
+ const s = i[e].map(
919
+ (c) => transform([c.lon, c.lat], projection.data, projection.mercator)
920
+ ), d = new LineString(s), u = formatLength(d, n) || "--", l = showTracks == null ? void 0 : showTracks.findIndex((c) => c.id === e);
921
+ l < 0 ? showTracks.push({ id: e, length: u }) : showTracks[l].length = u, allTracks[e] = t, trackList = [], trackColor = o, thresholdNum = a, await handlerRenderLine(), await setTrackViewCenter(trackId);
922
+ }, handlerRenderLine = async () => {
923
+ const e = trackColor || "", t = trackId, o = allTracks[trackId] || [], n = thresholdNum || 200, r = Math.max(1, Math.floor(o.length / n));
924
+ trackList = o.filter((s, d) => d % r === 0).map((s, d) => {
925
+ if (Number(s.lon) > 180 || Number(s.lat) > 180) {
926
+ const [u, l] = convertSixHundredThousandToLatLng(s.lon, s.lat);
927
+ s.lon = u, s.lat = l;
928
+ }
929
+ return s.center = [s.lon, s.lat], s.centerPoint = lonLatToMercator(s.center), s.id = t, s.index = d, s.time = hooks(s.createdAt).format("YYYY-MM-DD HH:mm:ss"), s;
930
+ });
931
+ const i = trackList.map((s) => s.centerPoint);
932
+ i.length >= 2 && (mapInstance == null || mapInstance.addLayer(routeLayer), await createTrackLineFeature(t, i, e));
933
+ }, createTrackLineFeature = (e, t, o) => {
934
+ var i;
935
+ const n = new LineString(t), r = new Feature({ geometry: n });
936
+ r.setStyle(createTrackLineStyle(o)), r.setId(e), r.set("type", "line"), (i = routeLayer == null ? void 0 : routeLayer.getSource()) == null || i.clear(), routeFeatures = [];
937
+ const a = routeFeatures.findIndex((s) => s.getId() === e);
938
+ a >= 0 ? routeFeatures[a] = r : routeFeatures.push(r), routesSource.addFeatures([...routeFeatures]), createPointFeature(o);
939
+ }, createTrackLineStyle = (e) => new Style({
940
+ stroke: new Stroke({
941
+ color: e,
942
+ width: 2
943
+ })
944
+ }), handleTrackMapEvent = (e, t, o) => {
945
+ const n = e == null ? void 0 : e.get("trackId");
946
+ if (e && n && t === "hover") {
947
+ mapInstance.getTargetElement().style.cursor = n ? "pointer" : "";
948
+ const r = e.get("data"), a = renderTrackPointHtml(r), i = o == null ? void 0 : o.coordinate;
949
+ i && (popupEle.querySelector(".popup-content"), popupEle.innerHTML = a, popupOverlay == null || popupOverlay.setPosition(i));
950
+ } else
951
+ popupOverlay && popupOverlay.setPosition(void 0);
952
+ }, formatMinutesToDDHHMM = (e) => {
953
+ const t = hooks.duration(e, "minutes"), o = Math.floor(t.asDays()), n = t.hours(), r = t.minutes();
954
+ let a = `${String(r).padStart(2, "0")}分`;
955
+ return n !== 0 && (a = `${String(n).padStart(2, "0")}时${a}`), o !== 0 && (a = `${String(o).padStart(2, "0")}天${a}`), a;
956
+ }, renderTrackPointHtml = (e) => {
957
+ if (!(e != null && e.time)) return;
958
+ let t = "";
959
+ return e != null && e.stayTime && (t = `
960
+ <div class="item w-100">
961
+ <div class="item-label">停泊时间约</div>
962
+ <div class="item-item">${formatMinutesToDDHHMM(Number(e.stayTime))}</div>
963
+ </div>
964
+ `), `
965
+ <div class="track-point-popup">
966
+ <div class="item">
967
+ <div class="item-label">状态</div>
968
+ <div class="item-item">${e != null && e.sailStatus ? SHIP_SAIL_STATUS[e.sailStatus] : DEFAULT_VALUE}</div>
969
+ </div>
970
+ <div class="item">
971
+ <div class="item-label">航速</div>
972
+ <div class="item-item">${e.speed || DEFAULT_VALUE}</div>
973
+ </div>
974
+ <div class="item">
975
+ <div class="item-label">艏向</div>
976
+ <div class="item-item">${e.hdg || DEFAULT_VALUE}</div>
977
+ </div>
978
+ <div class="item">
979
+ <div class="item-label">航向</div>
980
+ <div class="item-item">${e.cog || DEFAULT_VALUE}</div>
981
+ </div>
982
+ <div class="item">
983
+ <div class="item-label">经度</div>
984
+ <div class="item-item">${e.lon || DEFAULT_VALUE}</div>
985
+ </div>
986
+ <div class="item">
987
+ <div class="item-label">纬度</div>
988
+ <div class="item-item">${e.lat || DEFAULT_VALUE}</div>
989
+ </div>
990
+ <div class="item w-100">
991
+ <div class="item-label">时间</div>
992
+ <div class="item-item">${e.time}</div>
993
+ </div>
994
+ ${t ?? t}
995
+ </div>`;
996
+ }, createPointFeature = (e) => {
997
+ const t = trackList || [];
998
+ if (!(t && t.length > 1)) return [];
999
+ const o = { 16: 24, 17: 15, default: 4 }, n = [], r = t.length;
1000
+ for (let a = 0; a < r; a++) {
1001
+ t[a].index = a;
1002
+ const i = mapInstance == null ? void 0 : mapInstance.getPixelFromCoordinate(t[a].centerPoint);
1003
+ if (i) {
1004
+ let s = i.concat(i);
1005
+ s = adjustBounds(s, [20, 20]);
1006
+ const d = mapInstance == null ? void 0 : mapInstance.getView().getZoom();
1007
+ if (!d) return;
1008
+ if (d > 15) {
1009
+ const l = o[d] || o.default;
1010
+ s = adjustBounds(s, [l, l]);
1011
+ }
1012
+ let u = !0;
1013
+ if (t[a].state !== "0") {
1014
+ for (let l = 0; l < n.length; l++)
1015
+ if (isOverlapping(s, n[l].bounds)) {
1016
+ u = !1;
1017
+ break;
1018
+ }
1019
+ }
1020
+ u && (t[a].bounds = s, n.push(t[a]));
1021
+ }
1022
+ }
1023
+ n.forEach((a) => {
1024
+ const i = new Feature({
1025
+ geometry: new Point(a.centerPoint),
1026
+ time: a.time
1027
+ });
1028
+ i.set("type", "track_point"), i.set("trackId", a.id), i.set("data", a), i.setStyle(createPointStyle(e, i, a)), routesSource.addFeature(i), typeof a == "object" && Object.prototype.hasOwnProperty.call(a, "state") && createIconFeature(a);
1029
+ }), createArrowFetaure(n, e), createIconPointFeature();
1030
+ }, createPointStyle = (e, t, o) => {
1031
+ var g;
1032
+ const n = (g = t == null ? void 0 : t.getGeometry()) == null ? void 0 : g.getCoordinates(), a = document.createElement("canvas").getContext("2d", { willReadFrequently: !0 });
1033
+ a.font = `${labelConfig.fontWeight} ${labelConfig.fontSize}px ${labelConfig.fontFamily}`;
1034
+ const i = a == null ? void 0 : a.measureText(o.time), s = (i == null ? void 0 : i.width) + labelConfig.padding[1] + labelConfig.padding[3], d = labelConfig.fontSize + labelConfig.padding[0] + labelConfig.padding[2], [u, l] = labelConfig.textOffset, c = [
1035
+ n[0] + u,
1036
+ n[1] + l - d
1037
+ ], p = new LineString([n, c]);
1038
+ console.log("lineGeom", p), new Polygon([[
1039
+ c,
1040
+ [c[0] + s, c[1]],
1041
+ [c[0] + s, c[1] + d],
1042
+ [c[0], c[1] + d],
1043
+ c
1044
+ ]]);
1045
+ const m = c[0] + labelConfig.padding[3], h = c[1] + labelConfig.padding[0] + labelConfig.fontSize / 2;
1046
+ return console.log("textY", m, h, s, d), [
1047
+ new Style({
1048
+ // 扩大交互热区
1049
+ image: new CircleStyle({
1050
+ stroke: new Stroke({ color: "rgba(0, 0, 0, 0.01)", width: 20 }),
1051
+ radius: 3
1052
+ })
1053
+ }),
1054
+ // 轨迹点样式
1055
+ new Style({
1056
+ image: new CircleStyle({
1057
+ fill: new Fill({ color: e }),
1058
+ stroke: new Stroke({ color: "#fff", width: 2 }),
1059
+ radius: 3
1060
+ })
1061
+ }),
1062
+ // // 信息框背景
1063
+ // new Style({
1064
+ // geometry: boxGeom,
1065
+ // fill: new Fill({ color: labelConfig.bgColor }),
1066
+ // stroke: new Stroke({
1067
+ // color: trackColor,
1068
+ // width: 1
1069
+ // })
1070
+ // }),
1071
+ // 连接线
1072
+ new Style({
1073
+ geometry: p,
1074
+ stroke: new Stroke({
1075
+ color: e,
1076
+ width: 1
1077
+ })
1078
+ }),
1079
+ new Style({
1080
+ text: new Text({
1081
+ text: o.time,
1082
+ font: `500 ${labelConfig.fontSize}px ${labelConfig.fontFamily}`,
1083
+ textAlign: "left",
1084
+ textBaseline: "middle",
1085
+ fill: new Fill({ color: labelConfig.textColor }),
1086
+ backgroundFill: new Fill({
1087
+ color: labelConfig.bgColor
1088
+ }),
1089
+ backgroundStroke: new Stroke({
1090
+ color: e,
1091
+ width: 0.5
1092
+ }),
1093
+ padding: labelConfig.padding,
1094
+ offsetX: m - c[0],
1095
+ // 转换为相对偏移
1096
+ offsetY: h - c[1]
1097
+ }),
1098
+ zIndex: 99
1099
+ })
1100
+ ];
1101
+ }, createIconFeature = (e) => {
1102
+ const t = new Feature({
1103
+ //point.centerPoint
1104
+ geometry: new Point([e.lon, e.lat]),
1105
+ time: e.time
1106
+ });
1107
+ t.set("type", "track_icon");
1108
+ const o = new Style({
1109
+ text: new Text({
1110
+ font: "Normal 22px map-iconfont",
1111
+ text: getIconFont$1(dropletsIcon),
1112
+ offsetY: -10,
1113
+ fill: new Fill({
1114
+ color: Number(e.state) === 0 ? stopColor : Number(e.state) === 1 ? slowColor : ""
1115
+ })
1116
+ }),
1117
+ zIndex: 99
1118
+ }), n = [];
1119
+ Number(e.state) === 0 ? n.push(stopIconStyle) : Number(e.state) === 1 && n.push(slowIconStyle), n.push(o), t.setStyle(n), routesSource.addFeature(t);
1120
+ }, createArrowFetaure = (e, t) => {
1121
+ const o = e || [], n = e.length;
1122
+ n || (o.push(trackList[0]), o.push(trackList[trackList.length - 1]));
1123
+ for (let r = 0; r < n - 1; r++) {
1124
+ let a;
1125
+ const i = e[r], s = (e[r + 1].index + i.index) / 2;
1126
+ if (s % 2 === 0)
1127
+ a = trackList[s].centerPoint;
1128
+ else {
1129
+ const d = trackList[Math.floor(s)], u = trackList[Math.ceil(s)];
1130
+ if (d && u) {
1131
+ const [l, c] = d.centerPoint, [p, m] = u.centerPoint;
1132
+ a = [(l + p) / 2, (c + m) / 2];
1133
+ }
1134
+ }
1135
+ if (a) {
1136
+ const d = new Feature({
1137
+ geometry: new Point(a)
1138
+ });
1139
+ d.set("type", "track_arrow"), d.setStyle(
1140
+ new Style({
1141
+ text: new Text({
1142
+ font: "700 14px map-iconfont",
1143
+ text: getIconFont$1("&#xe6bc;"),
1144
+ fill: new Fill({ color: t }),
1145
+ // 设置箭头旋转 角度转为弧度
1146
+ rotation: getRotation(
1147
+ e[r].center,
1148
+ e[r + 1].center
1149
+ ) * (Math.PI / 180)
1150
+ })
1151
+ })
1152
+ ), routesSource == null || routesSource.addFeature(d);
1153
+ }
1154
+ }
1155
+ }, setTrackViewCenter = (e) => {
1156
+ var r;
1157
+ const t = mapInstance.getView(), o = e ? routeFeatures.find((a) => a.getId() === e) : routeFeatures[0];
1158
+ if (!o) return;
1159
+ const n = (r = o == null ? void 0 : o.getGeometry()) == null ? void 0 : r.getExtent();
1160
+ if (n != null && n.length)
1161
+ try {
1162
+ const a = buffer(n, Math.max(n[2] - n[0], n[3] - n[1]) * 0.02);
1163
+ t.fit(a);
1164
+ } catch (a) {
1165
+ console.log(a);
1166
+ }
1167
+ }, createIconPointFeature = () => {
1168
+ const e = "&#xe69b;", t = "#fcdc3f", o = "#ff0000";
1169
+ (trackList.length < 2 ? [trackList[0]] : [trackList[0], trackList[trackList.length - 1]]).forEach((r) => {
1170
+ const a = new Feature({
1171
+ geometry: new Point(r.centerPoint)
1172
+ });
1173
+ a.set("type", "track_begin"), a.set("data", r);
1174
+ const i = r.index === 0 && trackList.length >= 2 ? t : o;
1175
+ a.setStyle(
1176
+ new Style({
1177
+ text: new Text({
1178
+ font: "Normal 14px map-iconfont",
1179
+ text: getIconFont$1(e),
1180
+ fill: new Fill({ color: i })
1181
+ }),
1182
+ zIndex: 101
1183
+ })
1184
+ ), routesSource.addFeature(a);
1185
+ });
1186
+ }, geoMarkerStyle = new Style({
1187
+ text: new Text({
1188
+ font: "700 20px map-iconfont",
1189
+ text: getIconFont$1("&#xe657;"),
1190
+ fill: new Fill({ color: "#ff0000" }),
1191
+ rotation: 0
1192
+ // 初始旋转角度
1193
+ })
1194
+ }), playShipTrack = (e, t) => {
1195
+ handlePlay(String(e), t);
1196
+ }, removeAllTrackLayer = () => {
1197
+ showTracks = [], allTracks = {}, routesSource == null || routesSource.clear();
1198
+ }, closeTrack = (e = !1) => {
1199
+ routeLayer == null || routeLayer.setVisible(!1), e && removeAllTrackLayer(), stopAnimation();
1200
+ }, handlePlay = (e, t) => {
1201
+ const o = allTracks[String(e)];
1202
+ playAnimation(o == null ? void 0 : o.map((n) => [n.lon, n.lat]), t);
1203
+ }, moveFeature = (e, t) => {
1204
+ var c, p;
1205
+ const o = Number(50 * t), n = ((c = e.frameState) == null ? void 0 : c.time) ?? Date.now(), r = n - lastTime;
1206
+ if (distance = (distance + o * r / 1e6) % 2, lastTime = n, distance >= 1) {
1207
+ stopAnimation();
1208
+ return;
1209
+ }
1210
+ const a = linePath.getCoordinateAt(
1211
+ distance > 1 ? 2 - distance : distance
1212
+ ), i = linePath.getCoordinateAt(
1213
+ distance > 1 ? distance - 0.01 : distance
1214
+ ), s = linePath.getCoordinateAt(
1215
+ distance > 1 ? 2 - distance : distance + 0.01
1216
+ ), u = getRotation(
1217
+ mercatorToLonLat(i, "array"),
1218
+ mercatorToLonLat(s, "array")
1219
+ ) * Math.PI / 180;
1220
+ (p = geoMarkerStyle.getText()) == null || p.setRotation(u), position.setCoordinates(a);
1221
+ const l = getVectorContext(e);
1222
+ l.setStyle(geoMarkerStyle), l.drawGeometry(position), mapInstance == null || mapInstance.render();
1223
+ }, startAnimation = () => {
1224
+ var e;
1225
+ trackAnimating = !0, lastTime = Date.now(), distance = 0, position = ((e = startMarker.getGeometry()) == null ? void 0 : e.clone()) || new Point([0, 0]), moveFeatureHandler && (vectorLayer$3 == null || vectorLayer$3.on("postrender", moveFeatureHandler)), geoMarker == null || geoMarker.setGeometry(void 0);
1226
+ }, stopAnimation = () => {
1227
+ trackAnimating && (trackAnimating = !1, geoMarker == null || geoMarker.setGeometry(void 0), moveFeatureHandler && vectorLayer$3 && vectorLayer$3.un("postrender", moveFeatureHandler), vectorLayer$3 && (mapInstance == null || mapInstance.removeLayer(vectorLayer$3)), vectorLayer$3 = null, geoMarker = null);
1228
+ }, playAnimation = (e, t) => {
1229
+ trackAnimating && stopAnimation(), polyline = new Polyline({
1230
+ factor: 1e6
1231
+ }).writeGeometry(new LineString(e)), linePath = new Polyline({
1232
+ factor: 1e6
1233
+ }).readGeometry(polyline, {
1234
+ dataProjection: projection.data,
1235
+ featureProjection: projection.mercator
1236
+ }), startMarker = new Feature({
1237
+ type: "icon",
1238
+ geometry: new Point(linePath.getFirstCoordinate())
1239
+ });
1240
+ const o = startMarker.getGeometry();
1241
+ position = o ? o.clone() : new Point([0, 0]), geoMarker = new Feature({
1242
+ type: "geoMarker",
1243
+ style: geoMarkerStyle,
1244
+ geometry: position
1245
+ }), vectorLayer$3 = new VectorLayer({
1246
+ source: new VectorSource({
1247
+ features: [geoMarker]
1248
+ })
1249
+ }), mapInstance == null || mapInstance.addLayer(vectorLayer$3), moveFeatureHandler = (n) => moveFeature(n, t), startAnimation();
1250
+ }, getRotation = (e, t, o) => {
1251
+ function n(c) {
1252
+ return 180 * (c % (2 * Math.PI)) / Math.PI;
1253
+ }
1254
+ function r(c) {
1255
+ return c % 360 * Math.PI / 180;
1256
+ }
1257
+ function a(c) {
1258
+ var p;
1259
+ if (!c) throw new Error("Coordinate is required");
1260
+ if (!Array.isArray(c)) {
1261
+ if ((c == null ? void 0 : c.type) === "Feature" && (c == null ? void 0 : c.geometry) !== null && ((p = c == null ? void 0 : c.geometry) == null ? void 0 : p.type) === "Point")
1262
+ return c == null ? void 0 : c.geometry.coordinates;
1263
+ if (c.type === "Point") return (c == null ? void 0 : c.coordinates) || [];
1264
+ }
1265
+ if (Array.isArray(c) && c.length >= 2 && !Array.isArray(c[0]) && !Array.isArray(c[1]))
1266
+ return c;
1267
+ throw new Error(
1268
+ "Coordinate must be GeoJSON Point or an Array of numbers"
1269
+ );
1270
+ }
1271
+ function i(c, p, m = {}) {
1272
+ if (m.final)
1273
+ return function(L, I) {
1274
+ return (i(I, L) + 180) % 360;
1275
+ }(c, p);
1276
+ const h = a(c), g = a(p), f = r(h[0]), w = r(g[0]), v = r(h[1]), S = r(g[1]), T = Math.sin(w - f) * Math.cos(S), $ = Math.cos(v) * Math.sin(S) - Math.sin(v) * Math.cos(S) * Math.cos(w - f);
1277
+ return n(Math.atan2(T, $));
1278
+ }
1279
+ function s(c) {
1280
+ return !isNaN(c) && c !== null && !Array.isArray(c);
1281
+ }
1282
+ function d(c, p = {}, m = {}) {
1283
+ return c || console.log("Coordinates are required"), Array.isArray(c) || console.log("Coordinates must be an Array"), c.length < 2 && console.log("Coordinates must be at least 2 numbers long"), (!s(c[0]) || !s(c[1])) && console.log("Coordinates must contain numbers"), u({ type: "Point", coordinates: c }, p, m);
1284
+ }
1285
+ function u(c, p = {}, m = {}) {
1286
+ const h = {
1287
+ type: "Feature",
1288
+ id: "",
1289
+ properties: {},
1290
+ bbox: {},
1291
+ geometry: {}
1292
+ };
1293
+ return m.id !== void 0 && (h.id = m.id), m.bbox && (h.bbox = m.bbox), h.properties = p, h.geometry = c, h;
1294
+ }
1295
+ const l = i(d(e), d(t), o);
1296
+ return l < 0 ? 360 + l : l;
1297
+ }, disableDoubleClickZoom = () => {
1298
+ getInstall().getInteractions().forEach((t) => {
1299
+ t instanceof DoubleClickZoom && t.setActive(!1);
1300
+ });
1301
+ }, enableDoubleClickZoom = () => {
1302
+ getInstall().getInteractions().forEach((t) => {
1303
+ t instanceof DoubleClickZoom && t.setActive(!0);
1304
+ });
1305
+ }, measureHistory = ref([]), config$1 = {
1306
+ // 绘制线条的回调
1307
+ lineDrawEndFn: (e) => {
1308
+ console.log("lineDrawEndFn", e);
1309
+ },
1310
+ //
1311
+ unit: "km"
1312
+ }, setConfig$1 = (e) => {
1313
+ console.log("setConfig", e), merge(config$1, e), console.log("setConfig", config$1);
1314
+ };
1315
+ let helpTooltipElement$1;
1316
+ const state = ref(!1), open$1 = () => {
1317
+ initMapLayer(), disableDoubleClickZoom(), changeCursor("pointer");
1318
+ const e = getInstall();
1319
+ e.on("pointermove", pointerMoveHandler$1), console.log("openMeasure", e.getViewport()), e.getViewport().addEventListener("mouseout", () => {
1320
+ helpTooltipElement$1 && helpTooltipElement$1.classList.add("hidden");
1321
+ }), addInteraction(), state.value = !0;
1322
+ };
1323
+ let vectorSource$3, vectorLayer$2;
1324
+ const initMapLayer = () => {
1325
+ vectorSource$3 = new VectorSource(), vectorLayer$2 = new VectorLayer({
1326
+ source: vectorSource$3,
1327
+ zIndex: 1e3,
1328
+ style: {
1329
+ "fill-color": "rgba(255, 255, 255, 0.2)",
1330
+ "stroke-color": "#ffcc33",
1331
+ "stroke-width": 2,
1332
+ "circle-radius": 7,
1333
+ "circle-fill-color": "#ffcc33"
1334
+ }
1335
+ }), getInstall().addLayer(vectorLayer$2);
1336
+ };
1337
+ let sketch$1, helpTooltip;
1338
+ const pointerMoveHandler$1 = (e) => {
1339
+ if (e.dragging)
1340
+ return;
1341
+ let t = "点击选择起点";
1342
+ sketch$1 && (t = "单击继续,双击结束"), helpTooltipElement$1 && (helpTooltipElement$1.innerHTML = t, helpTooltip.setPosition(e.coordinate), helpTooltipElement$1.classList.remove("hidden"));
1343
+ }, changeCursor = (e) => {
1344
+ getInstall().getTargetElement().style.cursor = e;
1345
+ };
1346
+ let draw$1;
1347
+ const addInteraction = () => {
1348
+ draw$1 = new Draw({
1349
+ source: vectorSource$3,
1350
+ type: "LineString",
1351
+ style: new Style({
1352
+ fill: new Fill({
1353
+ color: "rgba(255, 255, 255, 0.2)"
1354
+ }),
1355
+ stroke: new Stroke({
1356
+ color: "rgba(255,204,51)",
1357
+ lineDash: [10, 10],
1358
+ width: 2
1359
+ }),
1360
+ image: new CircleStyle({
1361
+ radius: 5,
1362
+ stroke: new Stroke({
1363
+ color: "rgba(0, 0, 0, 0.7)"
1364
+ }),
1365
+ fill: new Fill({
1366
+ color: "rgba(255, 255, 255, 0.2)"
1367
+ })
1368
+ })
1369
+ }),
1370
+ // 添加条件函数,判断是否应该出发点绘制
1371
+ condition: (t) => t.originalEvent.target.tagName !== "DIV"
1372
+ }), getInstall().addInteraction(draw$1), createMeasureTooltip$1(), createHelpTooltip$1();
1373
+ let e;
1374
+ draw$1.on("drawstart", function(t) {
1375
+ var n;
1376
+ sketch$1 = t.feature, sketch$1.set("randomId", generateRandomId());
1377
+ let o;
1378
+ e = (n = sketch$1.getGeometry()) == null ? void 0 : n.on("change", function(r) {
1379
+ const a = r.target, i = computedDistance(a, config$1.unit);
1380
+ o = a.getLastCoordinate(), measureTooltipElement$1 && i && (measureTooltipElement$1.innerHTML = i), measureTooltip$1.setPosition(o);
1381
+ });
1382
+ }), draw$1.on("drawend", function() {
1383
+ var t;
1384
+ if (measureTooltipElement$1 && (measureTooltipElement$1.className = "ol-tooltip ol-tooltip-static ol-tooltip-measure"), measureTooltipElement$1 != null && measureTooltipElement$1.innerHTML) {
1385
+ const o = (sketch$1 == null ? void 0 : sketch$1.get("randomId")) || generateRandomId();
1386
+ measureHistory.value.push({ id: o, value: measureTooltipElement$1 == null ? void 0 : measureTooltipElement$1.innerHTML }), measureTooltipElement$1.innerHTML = `${measureTooltipElement$1.innerHTML}<div class="ol-tooltip-delete-button" data-id="${o}"><i class="map-iconfont icon-delete"></i></div>`;
1387
+ }
1388
+ (t = document.querySelector(".ol-selectable:has(.ol-tooltip-delete-button):last-child .ol-tooltip-delete-button")) == null || t.addEventListener("click", (o) => {
1389
+ var r;
1390
+ o.preventDefault(), o.stopPropagation();
1391
+ const n = (r = o.target) == null ? void 0 : r.getAttribute("data-id");
1392
+ n && deleteLine(n);
1393
+ }), measureTooltip$1.setOffset([0, -7]), sketch$1 = null, measureTooltipElement$1 = null, createMeasureTooltip$1(), e && unByKey(e), config$1.lineDrawEndFn(measureHistory.value);
1394
+ });
1395
+ }, generateRandomId = () => Math.random().toString(36).substring(2, 9);
1396
+ let measureTooltipElement$1, measureTooltip$1;
1397
+ const createMeasureTooltip$1 = () => {
1398
+ measureTooltipElement$1 != null && measureTooltipElement$1.parentNode && measureTooltipElement$1.parentNode.removeChild(measureTooltipElement$1), measureTooltipElement$1 = document.createElement("div"), measureTooltipElement$1.className = "ol-tooltip ol-tooltip-measure", measureTooltip$1 = new Overlay({
1399
+ element: measureTooltipElement$1,
1400
+ offset: [0, -15],
1401
+ positioning: "bottom-center",
1402
+ stopEvent: !1,
1403
+ insertFirst: !1
1404
+ }), getInstall().addOverlay(measureTooltip$1);
1405
+ }, createHelpTooltip$1 = () => {
1406
+ helpTooltipElement$1 != null && helpTooltipElement$1.parentNode && helpTooltipElement$1.parentNode.removeChild(helpTooltipElement$1), helpTooltipElement$1 = document.createElement("div"), helpTooltipElement$1.className = "ol-tooltip hidden", helpTooltip = new Overlay({
1407
+ element: helpTooltipElement$1,
1408
+ offset: [15, 0],
1409
+ positioning: "center-left"
1410
+ }), getInstall().addOverlay(helpTooltip);
1411
+ }, close$1 = () => {
1412
+ measureHistory.value.forEach((e, t) => {
1413
+ var r, a;
1414
+ const o = document.querySelectorAll(".ol-tooltip.ol-tooltip-static.ol-tooltip-measure");
1415
+ o[t] && ((a = (r = o[t]) == null ? void 0 : r.parentNode) == null || a.removeChild(o[t]));
1416
+ const n = vectorSource$3.getFeatures();
1417
+ n[t] && vectorSource$3.removeFeature(n[t]);
1418
+ }), removeInteraction(), enableDoubleClickZoom(), state.value = !1;
1419
+ }, deleteLine = (e) => {
1420
+ var o, n;
1421
+ const t = measureHistory.value.findIndex((r) => r.id === e);
1422
+ if (t !== -1) {
1423
+ measureHistory.value.splice(t, 1);
1424
+ const r = document.querySelectorAll(".ol-tooltip.ol-tooltip-static.ol-tooltip-measure");
1425
+ r[t] && ((n = (o = r[t]) == null ? void 0 : o.parentNode) == null || n.removeChild(r[t]));
1426
+ const a = vectorSource$3.getFeatures();
1427
+ a[t] && vectorSource$3.removeFeature(a[t]);
1428
+ }
1429
+ config$1.lineDrawEndFn(measureHistory.value);
1430
+ }, computedDistance = (e, t) => {
1431
+ const n = getLength(e);
1432
+ let r = "";
1433
+ switch (t) {
1434
+ case "m":
1435
+ r = `${Math.round(n * 100) / 100} m`;
1436
+ break;
1437
+ case "km":
1438
+ r = `${Math.round(n / 1e3 * 100) / 100} km`;
1439
+ break;
1440
+ case "nm":
1441
+ r = `${Math.round(n / 1.852 * 100) / 100} nm`;
1442
+ break;
1443
+ }
1444
+ return r;
1445
+ }, removeInteraction = () => {
1446
+ measureHistory.value = [], document.querySelectorAll(".ol-tooltip.ol-tooltip-static").forEach((t) => {
1447
+ var o;
1448
+ (o = t == null ? void 0 : t.parentNode) == null || o.removeChild(t);
1449
+ }), vectorSource$3.clear();
1450
+ const e = getInstall();
1451
+ if (draw$1) {
1452
+ const t = e.getInteractions().getArray().find((o) => getUid(o) === getUid(draw$1));
1453
+ t && e.removeInteraction(t);
1454
+ }
1455
+ e.removeLayer(vectorLayer$2), helpTooltipElement$1 != null && helpTooltipElement$1.parentNode && helpTooltipElement$1.parentNode.removeChild(helpTooltipElement$1), measureTooltipElement$1 != null && measureTooltipElement$1.parentNode && measureTooltipElement$1.parentNode.removeChild(measureTooltipElement$1);
1456
+ }, getState = () => state.value, drawLine = {
1457
+ open: open$1,
1458
+ close: close$1,
1459
+ deleteLine,
1460
+ setConfig: setConfig$1,
1461
+ getState
1462
+ }, config = {
1463
+ // 回调函数
1464
+ endCallback: void 0
1465
+ }, setConfig = (e) => {
1466
+ merge(config, e);
1467
+ }, open = () => {
1468
+ console.log("绘制多边形"), initLayer(), initDraw(), createMeasureTooltip(), createHelpTooltip();
1469
+ };
1470
+ let vectorLayer$1 = null, vectorSource$2 = null;
1471
+ const initLayer = () => {
1472
+ if (vectorLayer$1 || vectorSource$2) return;
1473
+ const e = new VectorSource(), t = new VectorLayer({
1474
+ source: e,
1475
+ style: new Style({
1476
+ stroke: new Stroke({
1477
+ color: "#fbcc33",
1478
+ width: 2
1479
+ })
1480
+ })
1481
+ });
1482
+ vectorLayer$1 = t, vectorSource$2 = e;
1483
+ const o = getInstall();
1484
+ o.on("pointermove", pointerMoveHandler), o.addLayer(t), o.on(["dblclick"], function(n) {
1485
+ draw && (n.stopPropagation(), n.preventDefault());
1486
+ });
1487
+ };
1488
+ let sketch;
1489
+ const pointerMoveHandler = (e) => {
1490
+ if (e.dragging) return;
1491
+ const t = sketch ? "单击继续,双击结束" : "点击选择起点";
1492
+ helpTooltipElement && (helpTooltipElement.innerHTML = t, tipOverlay.setPosition(e.coordinate));
1493
+ };
1494
+ let draw;
1495
+ const initDraw = () => {
1496
+ let e = !1;
1497
+ draw = new Draw({
1498
+ type: "Polygon",
1499
+ source: vectorSource$2,
1500
+ trace: !0,
1501
+ style: [new Style({
1502
+ stroke: new Stroke({
1503
+ color: "rgba(255, 255, 255, 1)",
1504
+ width: 1.5,
1505
+ lineDash: [10, 10]
1506
+ }),
1507
+ fill: new Fill({
1508
+ color: "rgba(255, 255, 255, 0.25)"
1509
+ })
1510
+ }), new Style({
1511
+ image: new CircleStyle({
1512
+ radius: 5,
1513
+ fill: new Fill({
1514
+ color: "rgb(51,112,255, 1)"
1515
+ })
1516
+ }),
1517
+ geometry: function(o) {
1518
+ const n = o.getGeometry().getCoordinates();
1519
+ return new MultiPoint(n);
1520
+ }
1521
+ })]
1522
+ }), getInstall().addInteraction(draw);
1523
+ let t;
1524
+ draw.on("drawstart", function(o) {
1525
+ var n;
1526
+ sketch = o.feature, t = (n = sketch.getGeometry()) == null ? void 0 : n.on("change", (r) => {
1527
+ const a = r.target, i = computedArea(a, "nm"), d = a.getCoordinates()[0], u = new LineString([d[d.length - 2], d[d.length - 1]]), l = computedDistance(u, "nm");
1528
+ if (e = Number(getLength(u) / 1e3) > 150, !i) return;
1529
+ const c = '<span class="error pl-4">超出可以绘画的距离</span>';
1530
+ measureTooltipElement && (measureTooltipElement.innerHTML = `
1531
+ <div class="text">
1532
+ 面积:${i}
1533
+ ${e ? c : ""}
1534
+ </div>
1535
+ `), helpTooltipElement && (helpTooltipElement.innerHTML = `
1536
+ <div class="text">
1537
+ 面积:${i}
1538
+ </div>
1539
+ <div class="text ${e ? "error" : ""}">
1540
+ 线段 ${d.length - 2}: ${l}
1541
+ ${e ? c : ""}
1542
+
1543
+ </div>
1544
+ <div>
1545
+ <span class="text">单击继续,双击结束</span>
1546
+ </div>
1547
+ `);
1548
+ });
1549
+ }), draw.on("drawend", function(o) {
1550
+ var i;
1551
+ if (!o.feature.getGeometry()) return;
1552
+ measureTooltipElement && (measureTooltipElement.innerHTML += '<span class="delete-icon"><i class="map-iconfont icon-delete" /></div>'), measureTooltip.setOffset([10, 0]);
1553
+ const r = o.feature.getGeometry().getCoordinates(), a = r[0][r[0].length - 2];
1554
+ measureTooltip.setPosition(a), draw && draw.setActive(!1), helpTooltipElement != null && helpTooltipElement.parentNode && helpTooltipElement.parentNode.removeChild(helpTooltipElement), t && unByKey(t), console.log("coordinates", r), config.endCallback(r), (i = document.querySelector(".delete-icon")) == null || i.addEventListener("click", () => {
1555
+ reset();
1556
+ });
1557
+ });
1558
+ }, computedArea = (e, t) => {
1559
+ const o = getArea(e);
1560
+ switch (t) {
1561
+ case "km":
1562
+ return o > 1e4 ? Math.round(o / 1e6 * 100) / 100 + " km<sup>2</sup>" : Math.round(o * 100) / 100 + " m<sup>2</sup>";
1563
+ case "nm":
1564
+ return o > 1e4 ? Math.round(o / 1e6 / Math.pow(1.852, 2) * 100) / 100 + " nm<sup>2</sup>" : Math.round(o * 100) / 100 + " m<sup>2</sup>";
1565
+ }
1566
+ };
1567
+ let measureTooltipElement, measureTooltip;
1568
+ const createMeasureTooltip = () => {
1569
+ measureTooltipElement != null && measureTooltipElement.parentNode && measureTooltipElement.parentNode.removeChild(measureTooltipElement), measureTooltipElement = document.createElement("div"), measureTooltipElement.style.display = "flex", measureTooltipElement.className = "ol-tooltip ol-tooltip-draw-polygon", measureTooltip = new Overlay({
1570
+ element: measureTooltipElement,
1571
+ offset: [0, -15],
1572
+ positioning: "bottom-center"
1573
+ // stopEvent: false,
1574
+ // insertFirst: false
1575
+ }), getInstall().addOverlay(measureTooltip);
1576
+ };
1577
+ let helpTooltipElement, tipOverlay;
1578
+ const createHelpTooltip = () => {
1579
+ helpTooltipElement != null && helpTooltipElement.parentNode && helpTooltipElement.parentNode.removeChild(helpTooltipElement), helpTooltipElement = document.createElement("div"), helpTooltipElement.className = "ol-tooltip ol-help-tooltip hidden", tipOverlay = new Overlay({
1580
+ element: helpTooltipElement,
1581
+ offset: [15, 0],
1582
+ positioning: "center-left"
1583
+ }), getInstall().addOverlay(tipOverlay);
1584
+ }, reset = () => {
1585
+ var e;
1586
+ vectorSource$2.clear(), draw == null || draw.setActive(!0), (e = measureTooltipElement == null ? void 0 : measureTooltipElement.parentNode) == null || e.removeChild(measureTooltipElement), measureTooltip.setPosition(void 0), createMeasureTooltip(), createHelpTooltip(), getInstall().removeOverlay(tipOverlay), getInstall().removeOverlay(measureTooltip);
1587
+ }, close = () => {
1588
+ vectorSource$2 == null || vectorSource$2.clear(), vectorSource$2 = null;
1589
+ const e = getInstall();
1590
+ vectorLayer$1 && (e.removeLayer(vectorLayer$1), vectorLayer$1 = null), sketch = null, draw && (e.removeInteraction(draw), draw = null);
1591
+ }, drawPolygon = {
1592
+ open,
1593
+ reset,
1594
+ close,
1595
+ setConfig
1596
+ }, vectorSource$1 = new VectorSource();
1597
+ new VectorLayer({
1598
+ source: vectorSource$1
1599
+ });
1600
+ let currentTruckOverlay = null;
1601
+ const locationTruck = async (e) => {
1602
+ const t = getInstall();
1603
+ if (!t || (console.log("vehicleInfo", e), !(e != null && e.lon && (e != null && e.lat)))) return;
1604
+ const o = Math.abs(Number(e.lon)) > 180 ? convertSixHundredThousandToLatLng(e.lon, e.lat) : [e.lon, e.lat];
1605
+ drawTruckIcon(e, fromLonLat(o));
1606
+ const n = t.getView(), r = new Point(o);
1607
+ n.setCenter(transform(r.getCoordinates(), projection.data, projection.mercator));
1608
+ }, drawTruckIcon = (e, t) => {
1609
+ const o = getInstall(), n = `${CDN_URL}map/car-icon.gif`;
1610
+ currentTruckOverlay || (currentTruckOverlay = new Overlay({
1611
+ element: document.createElement("div"),
1612
+ positioning: "center-center",
1613
+ stopEvent: !1
1614
+ // 允许交互事件穿透
1615
+ }), o.addOverlay(currentTruckOverlay));
1616
+ const r = currentTruckOverlay.getElement();
1617
+ r.style.backgroundImage = `url(${n})`, r.style.width = "80px", r.style.height = "80px";
1618
+ const a = (e == null ? void 0 : e.drc) || "";
1619
+ r.style.transform = `rotate(${a}deg)`, r.style.backgroundSize = "cover", currentTruckOverlay == null || currentTruckOverlay.setPosition(t);
1620
+ }, renderTruckTrack = (e, t, o, n = 1e3) => {
1621
+ renderTrackLine(e, t, o, LENGTH_UNIT.KM, "truck", n);
1622
+ }, closeTruckTrack = () => {
1623
+ closeTrack();
1624
+ }, removeTruckIcon = () => {
1625
+ const e = currentTruckOverlay == null ? void 0 : currentTruckOverlay.getElement();
1626
+ e && (e.innerHTML = "");
1627
+ }, resetTrackView = (e) => {
1628
+ setTrackViewCenter(e);
1629
+ }, playTrack = (e, t) => {
1630
+ playShipTrack(e, t);
1631
+ }, carTrack = {
1632
+ locationTruck,
1633
+ renderTruckTrack,
1634
+ removeTruckIcon,
1635
+ closeTruckTrack,
1636
+ resetTrackView,
1637
+ playTrack
1638
+ }, PORT_LAYER_CLASS_NAME = "zh-map-port-layer";
1639
+ let vectorLayer, vectorSource;
1640
+ const renderPortList = (e) => {
1641
+ var o;
1642
+ if (!e || e.length === 0) return;
1643
+ const t = getZoom();
1644
+ vectorSource || (vectorSource = new VectorSource()), e.forEach((n) => {
1645
+ if ((selectedPortFeature == null ? void 0 : selectedPortFeature.get("portData").id) === n.id) return;
1646
+ const [r, a] = n.latLon.split(","), i = new Feature({
1647
+ geometry: new Point(fromLonLat([Number(r), Number(a)]))
1648
+ });
1649
+ i.setStyle(setPortStyle(n, t, !1)), i.set("portData", n), vectorSource.addFeature(i);
1650
+ }), vectorLayer || (vectorLayer = new VectorLayer({
1651
+ className: PORT_LAYER_CLASS_NAME,
1652
+ source: vectorSource,
1653
+ zIndex: 100
1654
+ }), (o = getInstall()) == null || o.addLayer(vectorLayer));
1655
+ }, setPortStyle = (e, t, o) => {
1656
+ const n = (a) => `<svg width="46" height="46" viewBox="0 0 46 46" fill="none" xmlns="http://www.w3.org/2000/svg">
1657
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M22.6563 44.9304C22.5453 44.8844 22.4445 44.817 22.3595 44.7321C22.3595 44.7321 9.36986 31.7424 9.32952 31.6913C7.09059 29.0791 5.64794 25.8802 5.17255 22.4736C4.69716 19.0671 5.20896 15.5957 6.64728 12.471C8.08561 9.34625 10.3902 6.69909 13.2878 4.84325C16.1855 2.98741 19.5548 2.00068 22.9965 2C26.4381 1.99932 29.8078 2.98473 32.7062 4.83943C35.6046 6.69414 37.9102 9.34039 39.3498 12.4646C40.7893 15.5888 41.3025 19.0599 40.8284 22.4666C40.3544 25.8734 38.913 29.0729 36.6751 31.686C36.6401 31.737 23.6531 44.7321 23.6531 44.7321C23.5682 44.817 23.4674 44.8844 23.3564 44.9304C23.2454 44.9763 23.1265 45 23.0063 45C22.8862 45 22.7673 44.9763 22.6563 44.9304Z" fill="${a}"/>
1658
+ <g clip-path="url(#clip0_10059_122082)">
1659
+ <path d="M34.8624 22.8687L32.5874 25.6313L33.4812 25.7125C33.4812 25.7125 30.5562 28.0687 27.9562 28.2312C25.3562 28.3937 24.1374 24.9 24.1374 24.9V19.1312H27.6312V17.425H24.2999V15.15C25.7624 14.6625 26.7374 13.2812 26.7374 11.6562C26.7374 9.625 25.1124 8 23.0812 8H22.9999C20.9687 8 19.3437 9.625 19.3437 11.6562C19.3437 13.2812 20.3999 14.6625 21.7812 15.15V17.425H18.4499V19.1312H21.9437V24.9C21.9437 24.9 20.6437 28.3125 18.0437 28.2312C15.4437 28.0687 12.5187 25.7125 12.5187 25.7125L13.4124 25.6313L11.0562 22.8687L10.2437 26.2812L11.2187 26.0375C11.2187 26.0375 13.1687 29.5313 16.1749 30.8313C19.1812 32.2125 22.1874 33.9187 22.8374 34C23.4874 33.9187 26.4937 32.2125 29.4187 30.8313C32.3437 29.45 34.3749 26.0375 34.3749 26.0375L35.3499 26.2812L34.8624 22.8687ZM23.0812 13.6875C21.9437 13.6875 21.0499 12.7937 21.0499 11.6562C21.0499 10.6 21.9437 9.70625 22.9999 9.70625H23.0812C24.1374 9.70625 25.0312 10.6 25.0312 11.6562C25.1124 12.7937 24.1374 13.6875 23.0812 13.6875Z" fill="white"/>
1660
+ </g>
1661
+ <defs>
1662
+ <clipPath id="clip0_10059_122082">
1663
+ <rect width="26" height="26" fill="white" transform="translate(10 8)"/>
1664
+ </clipPath>
1665
+ </defs>
1666
+ </svg>
1667
+ `, r = () => `data:image/svg+xml;utf8,${encodeURIComponent(n(o ? "#FF5733" : "#3370FF"))}`;
1668
+ return new Style({
1669
+ text: new Text({
1670
+ text: e.shortName,
1671
+ font: "12px sans-serif",
1672
+ fill: new Fill({
1673
+ color: o ? "#ffffff" : "#000000"
1674
+ }),
1675
+ backgroundFill: new Fill({
1676
+ color: o ? "#FF5733" : "#FFFFFF"
1677
+ }),
1678
+ offsetY: 30
1679
+ }),
1680
+ image: new Icon({
1681
+ src: r(),
1682
+ scale: 0.5 * t / 10
1683
+ })
1684
+ });
1685
+ }, clearPortList = () => {
1686
+ if (selectedPortFeature) {
1687
+ console.log("清除非选中的港口");
1688
+ const e = selectedPortFeature.get("portData").id;
1689
+ vectorSource.getFeatures().forEach((t) => {
1690
+ t.get("portData").id !== e && vectorSource.removeFeature(t);
1691
+ });
1692
+ } else
1693
+ console.log("清除所有港口"), vectorSource.clear();
1694
+ };
1695
+ let selectedPortFeature = null;
1696
+ const selectedPort = (e) => {
1697
+ clearPrevSelectedPort(), addSelectedPortStyle(e);
1698
+ }, clearPrevSelectedPort = () => {
1699
+ if (selectedPortFeature) {
1700
+ const e = selectedPortFeature.get("portData"), t = getZoom();
1701
+ selectedPortFeature.setStyle(setPortStyle(e, t, !1));
1702
+ }
1703
+ }, addSelectedPortStyle = (e) => {
1704
+ const t = e.get("portData"), o = getZoom();
1705
+ selectedPortFeature = e, e.setStyle(setPortStyle(t, o, !0));
1706
+ }, handlePortHover = (e) => {
1707
+ const t = getInstall(), o = t.forEachFeatureAtPixel(e, (n) => n);
1708
+ o && o.get("portData") && (t.getTargetElement().style.cursor = "pointer");
1709
+ }, _sfc_main = /* @__PURE__ */ defineComponent({
1710
+ __name: "Map",
1711
+ props: {
1712
+ zoom: { default: MAP_ZOOM.default },
1713
+ center: { default: MAP_DEFAULT_CENTER },
1714
+ layerType: { default: "vector" },
1715
+ showGreenLayer: { type: Boolean, default: !1 },
1716
+ showScale: { type: Boolean, default: !0 },
1717
+ scaleLineUnit: { default: "metric" },
1718
+ mapMoveEnd: { type: Function, default: () => {
1719
+ } },
1720
+ lineDrawEnd: {},
1721
+ selectShip: { type: Function, default: () => {
1722
+ } },
1723
+ selectPort: { type: Function, default: () => {
1724
+ } }
1725
+ },
1726
+ setup(e, { expose: t }) {
1727
+ const o = ref(), n = ref(), r = e, a = ref();
1728
+ provide("mapInstance", a);
1729
+ const i = ref(!1), s = () => {
1730
+ var h;
1731
+ if (i.value) return;
1732
+ const u = {
1733
+ vectorTile: new TileLayer({
1734
+ source: new XYZ({ url: BASE_MAP_LINK.vectorTile }),
1735
+ visible: r.layerType === "vector",
1736
+ zIndex: 0,
1737
+ preload: 1,
1738
+ className: "vector"
1739
+ }),
1740
+ vectorTileMark: new TileLayer({
1741
+ source: new XYZ({ url: BASE_MAP_LINK.vectorTileMark }),
1742
+ visible: r.layerType === "vector",
1743
+ zIndex: 1,
1744
+ preload: 1,
1745
+ className: "vector"
1746
+ }),
1747
+ satelliteImgTile: new TileLayer({
1748
+ source: new XYZ({ url: BASE_MAP_LINK.satelliteImgTile }),
1749
+ visible: r.layerType === "satellite",
1750
+ zIndex: 0,
1751
+ preload: 1,
1752
+ className: "satellite"
1753
+ }),
1754
+ satelliteImgTileMark: new TileLayer({
1755
+ source: new XYZ({ url: BASE_MAP_LINK.satelliteImgTileMark }),
1756
+ visible: r.layerType === "satellite",
1757
+ zIndex: 1,
1758
+ preload: 1,
1759
+ className: "satellite"
1760
+ }),
1761
+ greenMark: new TileLayer({
1762
+ source: new XYZ({ url: BASE_MAP_LINK.greenTile }),
1763
+ visible: r.showGreenLayer,
1764
+ zIndex: 2,
1765
+ className: "greenTile"
1766
+ })
1767
+ }, l = {
1768
+ zoom: r.zoom,
1769
+ center: fromLonLat(r.center),
1770
+ minZoom: MAP_ZOOM.min,
1771
+ maxZoom: MAP_ZOOM.max,
1772
+ constrainResolution: !0,
1773
+ enableRotation: !1,
1774
+ multiWorld: !0
1775
+ };
1776
+ a.value = new Map$2({
1777
+ target: "map",
1778
+ layers: [
1779
+ u.vectorTile,
1780
+ u.vectorTileMark,
1781
+ u.satelliteImgTile,
1782
+ u.satelliteImgTileMark
1783
+ // BASE_MAP.greenMark
1784
+ ],
1785
+ view: new View(l)
1786
+ }), a.value.on("moveend", () => {
1787
+ var f;
1788
+ const g = getZoom();
1789
+ (f = r.mapMoveEnd) == null || f.call(r, g), reRenderTrackLine();
1790
+ }), a.value.on("pointermove", (g) => {
1791
+ const f = a.value.getEventPixel(g.originalEvent), w = a.value.getFeaturesAtPixel(f), v = w.length > 0 ? w[0] : void 0;
1792
+ handleShipMapEvent(v, "hover"), v && (handleTrackMapEvent(v, "hover", g), handlePortHover(f));
1793
+ });
1794
+ const c = (g) => {
1795
+ handleShipMapEvent(g, "click", r == null ? void 0 : r.selectShip);
1796
+ }, p = (g) => {
1797
+ const f = g.get("portData");
1798
+ selectedPort(g), r == null || r.selectPort(String(f == null ? void 0 : f.id));
1799
+ }, m = debounce((g) => {
1800
+ if (drawLine.getState()) return;
1801
+ const f = a.value.getEventPixel(g.originalEvent), w = a.value.forEachFeatureAtPixel(
1802
+ f,
1803
+ (v) => {
1804
+ if (v != null && v.get("shipData") || v != null && v.get("portData"))
1805
+ return v;
1806
+ }
1807
+ );
1808
+ w && (g.preventDefault(), g.stopPropagation(), w.get("shipData") ? c(w) : w.get("portData") && p(w));
1809
+ }, 150);
1810
+ a.value.on("click", m), a.value.getView().on("change:resolution", () => {
1811
+ handleShipChange();
1812
+ }), i.value = !0, setInstall(a.value), setShowLayerType(r.layerType), console.log("props.showGreenLayer", r.showGreenLayer), setGreenTileVisible(r.showGreenLayer), drawLine.setConfig({ lineDrawEndFn: r.lineDrawEnd }), (h = n.value) == null || h.setScaleLine(r.scaleLineUnit);
1813
+ };
1814
+ return onMounted(() => {
1815
+ s();
1816
+ }), t({
1817
+ getInstall,
1818
+ getZoom,
1819
+ setZoom,
1820
+ getView,
1821
+ setCenter,
1822
+ getCenter,
1823
+ layer: {
1824
+ getGreenTileVisible,
1825
+ setGreenTileVisible,
1826
+ getShowLayerType,
1827
+ setShowLayerType
1828
+ },
1829
+ ship: {
1830
+ render: renderShipList,
1831
+ selected: renderShipSelected,
1832
+ filter: filterShipShow,
1833
+ blinking: renderShipBlink,
1834
+ clear: clearShipList
1835
+ },
1836
+ track: {
1837
+ renderTrackLine,
1838
+ handleTrackMapEvent,
1839
+ removeAllTrackLayer,
1840
+ playShipTrack,
1841
+ setTrackViewCenter,
1842
+ closeTrack
1843
+ },
1844
+ port: {
1845
+ render: renderPortList,
1846
+ clear: clearPortList,
1847
+ selected: selectedPort
1848
+ },
1849
+ drawLine,
1850
+ // 绘制矩形
1851
+ drawPolygon,
1852
+ carTrack,
1853
+ utils: {
1854
+ getCalculateExtent: () => {
1855
+ const u = getView().calculateExtent(a.value.getSize()), l = transform([u[0], u[1]], projection.mercator, projection.data), c = transform([u[2], u[3]], projection.mercator, projection.data);
1856
+ return [l[0], l[1], c[0], c[1]];
1857
+ },
1858
+ convertSixHundredThousandToLatLng
1859
+ }
1860
+ }), (u, l) => (openBlock(), createElementBlock(Fragment, null, [
1861
+ createElementVNode("div", {
1862
+ id: "map",
1863
+ ref_key: "zhMapRef",
1864
+ ref: o,
1865
+ class: "zh-map"
1866
+ }, null, 512),
1867
+ createVNode(ScaleLine, {
1868
+ ref_key: "scaleLineRef",
1869
+ ref: n
1870
+ }, null, 512),
1871
+ createVNode(ZoomControl, { ref: "zoomControlRef" }, null, 512)
1872
+ ], 64));
1873
+ }
1874
+ }), Map$1 = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-6bb98b8e"]]), ZhMap = withInstall(Map$1);
1875
+ export {
1876
+ ZhMap as Z
1877
+ };