@fleet-frontend/mower-maps 0.0.9-beta.3 → 0.0.9-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +253 -264
- package/dist/index.js +252 -263
- package/dist/render/AntennaManager.d.ts +2 -24
- package/dist/render/AntennaManager.d.ts.map +1 -1
- package/dist/render/BoundaryLabelsManager.d.ts +1 -20
- package/dist/render/BoundaryLabelsManager.d.ts.map +1 -1
- package/dist/render/ChargingPileManager.d.ts +3 -18
- package/dist/render/ChargingPileManager.d.ts.map +1 -1
- package/dist/render/MowerMapOverlay.d.ts +4 -1
- package/dist/render/MowerMapOverlay.d.ts.map +1 -1
- package/dist/render/MowerMapRenderer.d.ts.map +1 -1
- package/dist/render/MowerPositionManager.d.ts +3 -6
- package/dist/render/MowerPositionManager.d.ts.map +1 -1
- package/dist/render/SvgMapView.d.ts +0 -25
- package/dist/render/SvgMapView.d.ts.map +1 -1
- package/dist/render/layers/BoundaryBorderLayer.d.ts +5 -0
- package/dist/render/layers/BoundaryBorderLayer.d.ts.map +1 -1
- package/dist/render/layers/index.d.ts +0 -1
- package/dist/render/layers/index.d.ts.map +1 -1
- package/dist/types/realTime.d.ts +3 -0
- package/dist/types/realTime.d.ts.map +1 -1
- package/dist/types/renderer.d.ts +1 -0
- package/dist/types/renderer.d.ts.map +1 -1
- package/dist/utils/boundaryUtils.d.ts.map +1 -1
- package/dist/utils/mapBounds.d.ts.map +1 -1
- package/dist/utils/mower.d.ts +1 -1
- package/dist/utils/mower.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import React, { forwardRef, useState, useRef, useMemo, useCallback, useEffect, useImperativeHandle } from 'react';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -14,7 +14,6 @@ class SvgMapView {
|
|
|
14
14
|
this.lineScale = 1; // 线条缩放系数
|
|
15
15
|
// 状态标志
|
|
16
16
|
this.destroyed = false;
|
|
17
|
-
this.showScale = false;
|
|
18
17
|
// 渲染系统 - 移除节流以确保用户操作的实时响应
|
|
19
18
|
// 拖动功能
|
|
20
19
|
this.isDragging = false;
|
|
@@ -97,6 +96,7 @@ class SvgMapView {
|
|
|
97
96
|
*/
|
|
98
97
|
removeLayer(layer) {
|
|
99
98
|
const index = this.layers.indexOf(layer);
|
|
99
|
+
console.log('removeLayer----->', index);
|
|
100
100
|
if (index !== -1) {
|
|
101
101
|
this.layers.splice(index, 1);
|
|
102
102
|
this.refresh();
|
|
@@ -153,43 +153,8 @@ class SvgMapView {
|
|
|
153
153
|
// 宽高比差异较大,使用meet确保内容完全可见
|
|
154
154
|
this.svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
|
|
155
155
|
}
|
|
156
|
+
console.log('fitToView');
|
|
156
157
|
this.updateViewBox();
|
|
157
|
-
this.refresh();
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* 重置变换
|
|
161
|
-
*/
|
|
162
|
-
resetTransform() {
|
|
163
|
-
this.scale = 1;
|
|
164
|
-
// 重置viewBox到默认状态
|
|
165
|
-
const containerRect = this.container.getBoundingClientRect();
|
|
166
|
-
this.viewBox = {
|
|
167
|
-
x: 0,
|
|
168
|
-
y: 0,
|
|
169
|
-
width: containerRect.width,
|
|
170
|
-
height: containerRect.height,
|
|
171
|
-
};
|
|
172
|
-
this.updateViewBox();
|
|
173
|
-
this.refresh();
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* 设置缩放级别
|
|
177
|
-
*/
|
|
178
|
-
setZoom(zoomLevel) {
|
|
179
|
-
if (zoomLevel <= 0)
|
|
180
|
-
return;
|
|
181
|
-
const oldScale = this.scale;
|
|
182
|
-
this.scale = zoomLevel;
|
|
183
|
-
// 调整viewBox以实现缩放
|
|
184
|
-
const scaleFactor = oldScale / this.scale;
|
|
185
|
-
const centerX = this.viewBox.x + this.viewBox.width / 2;
|
|
186
|
-
const centerY = this.viewBox.y + this.viewBox.height / 2;
|
|
187
|
-
this.viewBox.width *= scaleFactor;
|
|
188
|
-
this.viewBox.height *= scaleFactor;
|
|
189
|
-
this.viewBox.x = centerX - this.viewBox.width / 2;
|
|
190
|
-
this.viewBox.y = centerY - this.viewBox.height / 2;
|
|
191
|
-
this.updateViewBox();
|
|
192
|
-
this.refresh();
|
|
193
158
|
}
|
|
194
159
|
/**
|
|
195
160
|
* 获取当前缩放级别
|
|
@@ -197,15 +162,6 @@ class SvgMapView {
|
|
|
197
162
|
getZoom() {
|
|
198
163
|
return this.scale;
|
|
199
164
|
}
|
|
200
|
-
/**
|
|
201
|
-
* 设置线条缩放系数
|
|
202
|
-
*/
|
|
203
|
-
setLineScale(lineScale) {
|
|
204
|
-
if (lineScale <= 0)
|
|
205
|
-
return;
|
|
206
|
-
this.lineScale = lineScale;
|
|
207
|
-
this.refresh();
|
|
208
|
-
}
|
|
209
165
|
/**
|
|
210
166
|
* 获取当前线条缩放系数
|
|
211
167
|
*/
|
|
@@ -268,6 +224,7 @@ class SvgMapView {
|
|
|
268
224
|
* 绘制图层,不传参数则默认绘制所有图层
|
|
269
225
|
*/
|
|
270
226
|
onDrawLayers(type) {
|
|
227
|
+
console.log('onDrawLayers----->', type);
|
|
271
228
|
if (type) {
|
|
272
229
|
const layer = this.layers.find((layer) => layer.getType() === type);
|
|
273
230
|
if (layer) {
|
|
@@ -344,14 +301,9 @@ class SvgMapView {
|
|
|
344
301
|
refresh() {
|
|
345
302
|
if (this.destroyed)
|
|
346
303
|
return;
|
|
304
|
+
console.log('refresh----->');
|
|
347
305
|
this.render();
|
|
348
306
|
}
|
|
349
|
-
/**
|
|
350
|
-
* 重新初始化SVG(用于容器大小变化)
|
|
351
|
-
*/
|
|
352
|
-
reinitializeSVG() {
|
|
353
|
-
this.refresh();
|
|
354
|
-
}
|
|
355
307
|
// ==================== 拖拽功能 ====================
|
|
356
308
|
/**
|
|
357
309
|
* 设置拖拽事件处理器
|
|
@@ -476,22 +428,6 @@ class SvgMapView {
|
|
|
476
428
|
return null;
|
|
477
429
|
}
|
|
478
430
|
}
|
|
479
|
-
/**
|
|
480
|
-
* 自动适配viewBox到实际内容
|
|
481
|
-
*/
|
|
482
|
-
autoFitToContent() {
|
|
483
|
-
if (this.destroyed || this.layers.length === 0)
|
|
484
|
-
return;
|
|
485
|
-
const bounds = this.getLayersGroupBounds();
|
|
486
|
-
if (bounds) {
|
|
487
|
-
this.fitToView({
|
|
488
|
-
minX: bounds.x,
|
|
489
|
-
minY: bounds.y,
|
|
490
|
-
maxX: bounds.x + bounds.width,
|
|
491
|
-
maxY: bounds.y + bounds.height,
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
431
|
/**
|
|
496
432
|
* 获取ViewBox信息
|
|
497
433
|
*/
|
|
@@ -512,13 +448,6 @@ class SvgMapView {
|
|
|
512
448
|
* 诊断SVG尺寸信息
|
|
513
449
|
*/
|
|
514
450
|
diagnosticSizeInfo() { }
|
|
515
|
-
/**
|
|
516
|
-
* 设置是否显示比例尺
|
|
517
|
-
*/
|
|
518
|
-
setShowScale(show) {
|
|
519
|
-
this.showScale = show;
|
|
520
|
-
this.refresh();
|
|
521
|
-
}
|
|
522
451
|
/**
|
|
523
452
|
* 获取SVG元素
|
|
524
453
|
*/
|
|
@@ -1894,26 +1823,7 @@ function generateBoundaryData(mapData, pathData) {
|
|
|
1894
1823
|
}
|
|
1895
1824
|
// 第一步:收集所有TUNNEL数据的connection信息
|
|
1896
1825
|
const connectedBoundaryIds = new Set();
|
|
1897
|
-
//
|
|
1898
|
-
for (const subMap of mapData.sub_maps) {
|
|
1899
|
-
if (!subMap.elements)
|
|
1900
|
-
continue;
|
|
1901
|
-
// 找到该子地图中所有 type 为 TUNNEL 的元素
|
|
1902
|
-
const tunnelElements = subMap.elements.filter(element => element.type === 'TUNNEL');
|
|
1903
|
-
for (const tunnelElement of tunnelElements) {
|
|
1904
|
-
const connection = tunnelElement.connection;
|
|
1905
|
-
if (connection) {
|
|
1906
|
-
// connection可能是单个数字或数组
|
|
1907
|
-
if (Array.isArray(connection)) {
|
|
1908
|
-
connection.forEach(id => connectedBoundaryIds.add(id));
|
|
1909
|
-
}
|
|
1910
|
-
else if (typeof connection === 'number') {
|
|
1911
|
-
connectedBoundaryIds.add(connection);
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
}
|
|
1915
|
-
}
|
|
1916
|
-
// 1.2 遍历mapData中的tunnels字段
|
|
1826
|
+
// 遍历mapData中的tunnels字段
|
|
1917
1827
|
if (mapData.tunnels && Array.isArray(mapData.tunnels)) {
|
|
1918
1828
|
for (const tunnel of mapData.tunnels) {
|
|
1919
1829
|
const connection = tunnel.connection;
|
|
@@ -1935,6 +1845,8 @@ function generateBoundaryData(mapData, pathData) {
|
|
|
1935
1845
|
continue;
|
|
1936
1846
|
// 每个sub_map的elements是边界坐标,没有sub_map只有一个boundary数据
|
|
1937
1847
|
const boundaryElement = subMap.elements.find(element => element.type === 'BOUNDARY');
|
|
1848
|
+
// 如果当前subMap存在充电桩且充电桩存在tunnel,说明当前subMap中的boundary是初始boundary,这个boundary不为孤立区域
|
|
1849
|
+
const hasTunnelToChargingPile = subMap.elements.some(element => element.type === 'CHARGING_PILE' && element.tunnel);
|
|
1938
1850
|
// 创建基础的 boundary 数据(来自 mapData)
|
|
1939
1851
|
const boundary = {
|
|
1940
1852
|
// 从 BOUNDARY 元素复制属性
|
|
@@ -1944,7 +1856,7 @@ function generateBoundaryData(mapData, pathData) {
|
|
|
1944
1856
|
points: convertPointsFormat(boundaryElement?.points) || [],
|
|
1945
1857
|
type: boundaryElement.type,
|
|
1946
1858
|
// 判断是否为孤立子区域
|
|
1947
|
-
isIsolated: !connectedBoundaryIds.has(boundaryElement.id)
|
|
1859
|
+
isIsolated: hasTunnelToChargingPile ? false : !connectedBoundaryIds.has(boundaryElement.id)
|
|
1948
1860
|
};
|
|
1949
1861
|
// 如果有 pathData,尝试匹配对应的分区数据
|
|
1950
1862
|
if (pathData) {
|
|
@@ -2212,10 +2124,10 @@ function getNoPositionMowerImageByModal(mowerModal) {
|
|
|
2212
2124
|
}
|
|
2213
2125
|
return iNoPosition;
|
|
2214
2126
|
}
|
|
2215
|
-
function getMowerImage(positonConfig) {
|
|
2127
|
+
function getMowerImage(positonConfig, modelType) {
|
|
2216
2128
|
if (!positonConfig)
|
|
2217
2129
|
return '';
|
|
2218
|
-
const model =
|
|
2130
|
+
const model = modelType?.toLowerCase() || 'i';
|
|
2219
2131
|
const state = positonConfig.vehicleState;
|
|
2220
2132
|
const mowerImage = getMowerImageByModal(model);
|
|
2221
2133
|
const disabledImage = getDisabledMowerImageByModal(model);
|
|
@@ -4955,6 +4867,13 @@ class BoundaryBorderLayer extends BaseLayer {
|
|
|
4955
4867
|
this.level = LAYER_LEVELS.BOUNDARY_BORDER; // 中等层级
|
|
4956
4868
|
this.type = LAYER_DEFAULT_TYPE.BOUNDARY_BORDER;
|
|
4957
4869
|
this.boudaryBorderPaths = {};
|
|
4870
|
+
this.mowingBoundarys = [];
|
|
4871
|
+
}
|
|
4872
|
+
/**
|
|
4873
|
+
* 设置当前割草任务的边界
|
|
4874
|
+
*/
|
|
4875
|
+
setMowingBoundarys(mowingBoundarys) {
|
|
4876
|
+
this.mowingBoundarys = mowingBoundarys;
|
|
4958
4877
|
}
|
|
4959
4878
|
/**
|
|
4960
4879
|
* SVG渲染方法
|
|
@@ -4964,6 +4883,7 @@ class BoundaryBorderLayer extends BaseLayer {
|
|
|
4964
4883
|
return;
|
|
4965
4884
|
}
|
|
4966
4885
|
this.scale = scale;
|
|
4886
|
+
console.log('draw boundary border->', this.elements, this.mowingBoundarys);
|
|
4967
4887
|
// 只渲染边界边框类型的元素
|
|
4968
4888
|
for (const element of this.elements) {
|
|
4969
4889
|
if (element.type === 'boundary_border') {
|
|
@@ -5000,7 +4920,8 @@ class BoundaryBorderLayer extends BaseLayer {
|
|
|
5000
4920
|
* 创建直接路径(type=2)
|
|
5001
4921
|
*/
|
|
5002
4922
|
createDirectPath(svgGroup, points, style, id) {
|
|
5003
|
-
const
|
|
4923
|
+
const isMowing = this.mowingBoundarys.includes(Number(id));
|
|
4924
|
+
const strokeColor = isMowing ? style.mowingLineColor : style.lineColor;
|
|
5004
4925
|
const lineWidth = dp2px(style.lineWidth || 3);
|
|
5005
4926
|
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
5006
4927
|
// 构建路径数据
|
|
@@ -5033,7 +4954,8 @@ class BoundaryBorderLayer extends BaseLayer {
|
|
|
5033
4954
|
* 使用PathMeasure逻辑创建平行路径(type=1)
|
|
5034
4955
|
*/
|
|
5035
4956
|
createParallelPathsWithMeasure(svgGroup, points, style, id) {
|
|
5036
|
-
const
|
|
4957
|
+
const isMowing = this.mowingBoundarys.includes(Number(id));
|
|
4958
|
+
const strokeColor = isMowing ? style.mowingLineColor : style.lineColor;
|
|
5037
4959
|
const lineWidth = dp2px(style.lineWidth || 3);
|
|
5038
4960
|
// 获取当前SVG的缩放级别,计算固定屏幕像素间距
|
|
5039
4961
|
const fixedScreenDistance = lineWidth; // 固定的屏幕像素距离
|
|
@@ -6427,12 +6349,6 @@ class BoundaryLabelsManager {
|
|
|
6427
6349
|
this.container.style.display = visible ? 'block' : 'none';
|
|
6428
6350
|
}
|
|
6429
6351
|
}
|
|
6430
|
-
/**
|
|
6431
|
-
* 获取边界数据
|
|
6432
|
-
*/
|
|
6433
|
-
getBoundaryData() {
|
|
6434
|
-
return this.boundaryData;
|
|
6435
|
-
}
|
|
6436
6352
|
/**
|
|
6437
6353
|
* 根据ID获取特定边界的标签元素
|
|
6438
6354
|
*/
|
|
@@ -6482,18 +6398,6 @@ class BoundaryLabelsManager {
|
|
|
6482
6398
|
}
|
|
6483
6399
|
});
|
|
6484
6400
|
}
|
|
6485
|
-
/**
|
|
6486
|
-
* 重置标签层级(公共方法)
|
|
6487
|
-
*/
|
|
6488
|
-
resetZIndex() {
|
|
6489
|
-
this.resetLabelZIndex();
|
|
6490
|
-
}
|
|
6491
|
-
/**
|
|
6492
|
-
* 获取层级常量(静态方法)
|
|
6493
|
-
*/
|
|
6494
|
-
static getZIndexConstants() {
|
|
6495
|
-
return BoundaryLabelsManager.Z_INDEX;
|
|
6496
|
-
}
|
|
6497
6401
|
/**
|
|
6498
6402
|
* 设置标签旋转角度,使其与地图旋转相反,保持水平状态
|
|
6499
6403
|
* @param rotation 地图的旋转角度(度)
|
|
@@ -6510,19 +6414,6 @@ class BoundaryLabelsManager {
|
|
|
6510
6414
|
labelElement.style.transform = `translate(-50%, -50%) rotate(${counterRotation}deg)`;
|
|
6511
6415
|
});
|
|
6512
6416
|
}
|
|
6513
|
-
/**
|
|
6514
|
-
* 重置标签旋转角度
|
|
6515
|
-
*/
|
|
6516
|
-
resetLabelsRotation() {
|
|
6517
|
-
if (!this.container)
|
|
6518
|
-
return;
|
|
6519
|
-
const labels = this.container.querySelectorAll('.boundary-label');
|
|
6520
|
-
labels.forEach((label) => {
|
|
6521
|
-
const labelElement = label;
|
|
6522
|
-
// 重置为默认的居中变换
|
|
6523
|
-
labelElement.style.transform = 'translate(-50%, -50%)';
|
|
6524
|
-
});
|
|
6525
|
-
}
|
|
6526
6417
|
}
|
|
6527
6418
|
// 简化的层级定义
|
|
6528
6419
|
BoundaryLabelsManager.Z_INDEX = {
|
|
@@ -6698,26 +6589,6 @@ class ChargingPileManager {
|
|
|
6698
6589
|
this.container.innerHTML = '';
|
|
6699
6590
|
}
|
|
6700
6591
|
}
|
|
6701
|
-
/**
|
|
6702
|
-
* 设置可见性
|
|
6703
|
-
*/
|
|
6704
|
-
setVisible(visible) {
|
|
6705
|
-
if (this.container) {
|
|
6706
|
-
this.container.style.display = visible ? 'block' : 'none';
|
|
6707
|
-
}
|
|
6708
|
-
}
|
|
6709
|
-
/**
|
|
6710
|
-
* 获取充电桩数量
|
|
6711
|
-
*/
|
|
6712
|
-
getElementCount() {
|
|
6713
|
-
return this.chargingPileElements.length;
|
|
6714
|
-
}
|
|
6715
|
-
/**
|
|
6716
|
-
* 充电桩不需要动态层级调整(为了接口统一而保留)
|
|
6717
|
-
*/
|
|
6718
|
-
resetZIndex() {
|
|
6719
|
-
// 充电桩层级始终保持固定,无需重置
|
|
6720
|
-
}
|
|
6721
6592
|
/**
|
|
6722
6593
|
* 销毁管理器
|
|
6723
6594
|
*/
|
|
@@ -6740,17 +6611,6 @@ class ChargingPileManager {
|
|
|
6740
6611
|
pileElement.style.transform = `translate(-50%, -50%) rotate(${this.originalRotation - this.rotation}deg)`;
|
|
6741
6612
|
});
|
|
6742
6613
|
}
|
|
6743
|
-
/**
|
|
6744
|
-
* 重置充电桩旋转角度
|
|
6745
|
-
*/
|
|
6746
|
-
resetRotation() {
|
|
6747
|
-
this.rotation = 0;
|
|
6748
|
-
const allContainers = this.container.querySelectorAll('.charging-pile');
|
|
6749
|
-
allContainers.forEach((container) => {
|
|
6750
|
-
const pileElement = container;
|
|
6751
|
-
pileElement.style.transform = `translate(-50%, -50%) rotate(${this.originalRotation - this.rotation}deg)`;
|
|
6752
|
-
});
|
|
6753
|
-
}
|
|
6754
6614
|
}
|
|
6755
6615
|
// 简化的层级定义 - 充电桩只需要一个固定层级
|
|
6756
6616
|
ChargingPileManager.Z_INDEX = {
|
|
@@ -7136,32 +6996,6 @@ class AntennaManager {
|
|
|
7136
6996
|
this.container.innerHTML = '';
|
|
7137
6997
|
}
|
|
7138
6998
|
}
|
|
7139
|
-
/**
|
|
7140
|
-
* 设置可见性
|
|
7141
|
-
*/
|
|
7142
|
-
setVisible(visible) {
|
|
7143
|
-
if (this.container) {
|
|
7144
|
-
this.container.style.display = visible ? 'block' : 'none';
|
|
7145
|
-
}
|
|
7146
|
-
}
|
|
7147
|
-
/**
|
|
7148
|
-
* 获取天线数量
|
|
7149
|
-
*/
|
|
7150
|
-
getElementCount() {
|
|
7151
|
-
return this.antennaElements.length;
|
|
7152
|
-
}
|
|
7153
|
-
/**
|
|
7154
|
-
* 重置天线层级(公共方法)
|
|
7155
|
-
*/
|
|
7156
|
-
resetZIndex() {
|
|
7157
|
-
this.resetAntennaZIndex();
|
|
7158
|
-
}
|
|
7159
|
-
/**
|
|
7160
|
-
* 获取层级常量(静态方法)
|
|
7161
|
-
*/
|
|
7162
|
-
static getZIndexConstants() {
|
|
7163
|
-
return AntennaManager.Z_INDEX;
|
|
7164
|
-
}
|
|
7165
6999
|
/**
|
|
7166
7000
|
* 销毁管理器
|
|
7167
7001
|
*/
|
|
@@ -7189,17 +7023,6 @@ class AntennaManager {
|
|
|
7189
7023
|
antennaContainer.style.transform = `translate(-50%, -50%) rotate(${-this.rotation}deg)`;
|
|
7190
7024
|
});
|
|
7191
7025
|
}
|
|
7192
|
-
/**
|
|
7193
|
-
* 重置天线旋转角度
|
|
7194
|
-
*/
|
|
7195
|
-
resetRotation() {
|
|
7196
|
-
this.rotation = 0;
|
|
7197
|
-
const allContainers = this.container.querySelectorAll('.antenna-container-item');
|
|
7198
|
-
allContainers.forEach((container) => {
|
|
7199
|
-
const antennaContainer = container;
|
|
7200
|
-
antennaContainer.style.transform = `translate(-50%, -50%) rotate(${-this.rotation}deg)`;
|
|
7201
|
-
});
|
|
7202
|
-
}
|
|
7203
7026
|
}
|
|
7204
7027
|
// 简化的层级定义
|
|
7205
7028
|
AntennaManager.Z_INDEX = {
|
|
@@ -7255,7 +7078,7 @@ const EDIT_BEHAVIOR = {
|
|
|
7255
7078
|
};
|
|
7256
7079
|
|
|
7257
7080
|
class MowerPositionManager {
|
|
7258
|
-
constructor(svgView, mowerPositionConfig, overlayDiv, onAnimationComplete, onMowingPositionChange) {
|
|
7081
|
+
constructor(svgView, mowerPositionConfig, modelType, overlayDiv, onAnimationComplete, onMowingPositionChange) {
|
|
7259
7082
|
this.container = null;
|
|
7260
7083
|
this.overlayDiv = null;
|
|
7261
7084
|
this.mowerElement = null;
|
|
@@ -7273,6 +7096,7 @@ class MowerPositionManager {
|
|
|
7273
7096
|
this.onlyUpdateTheta = false;
|
|
7274
7097
|
this.svgView = svgView;
|
|
7275
7098
|
this.mowerPositionConfig = mowerPositionConfig;
|
|
7099
|
+
this.modelType = modelType;
|
|
7276
7100
|
this.overlayDiv = overlayDiv;
|
|
7277
7101
|
this.onAnimationComplete = onAnimationComplete;
|
|
7278
7102
|
this.onMowingPositionChange = onMowingPositionChange;
|
|
@@ -7327,6 +7151,7 @@ class MowerPositionManager {
|
|
|
7327
7151
|
}
|
|
7328
7152
|
this.mowerElement.appendChild(imgElement);
|
|
7329
7153
|
this.container.appendChild(this.mowerElement);
|
|
7154
|
+
this.updatePosition(this.mowerPositionConfig);
|
|
7330
7155
|
}
|
|
7331
7156
|
/**
|
|
7332
7157
|
* 设置叠加层div引用(用于坐标转换)
|
|
@@ -7348,9 +7173,9 @@ class MowerPositionManager {
|
|
|
7348
7173
|
return;
|
|
7349
7174
|
this.mowerPositionConfig = chargingPilesPositionConfig;
|
|
7350
7175
|
const lastPosition = this.lastPosition;
|
|
7351
|
-
const postureX = chargingPilesPositionConfig.postureX
|
|
7352
|
-
const postureY = chargingPilesPositionConfig.postureY
|
|
7353
|
-
const postureTheta = chargingPilesPositionConfig.postureTheta
|
|
7176
|
+
const postureX = chargingPilesPositionConfig.postureX ?? chargingPilesPositionConfig.lastPostureX ?? lastPosition?.x ?? 0;
|
|
7177
|
+
const postureY = chargingPilesPositionConfig.postureY ?? chargingPilesPositionConfig.lastPostureY ?? lastPosition?.y ?? 0;
|
|
7178
|
+
const postureTheta = chargingPilesPositionConfig.postureTheta ?? chargingPilesPositionConfig.lastPostureTheta ?? lastPosition?.rotation ?? 0;
|
|
7354
7179
|
// 检查是否需要更新图片
|
|
7355
7180
|
this.updateMowerImage(chargingPilesPositionConfig);
|
|
7356
7181
|
// 立即更新位置
|
|
@@ -7364,9 +7189,10 @@ class MowerPositionManager {
|
|
|
7364
7189
|
this.updateMowerImage(positionConfig);
|
|
7365
7190
|
// 更新配置
|
|
7366
7191
|
this.mowerPositionConfig = positionConfig;
|
|
7367
|
-
const postureX = positionConfig
|
|
7368
|
-
const postureY = positionConfig
|
|
7369
|
-
const postureTheta = positionConfig
|
|
7192
|
+
const postureX = positionConfig?.postureX ?? this.lastPosition?.x;
|
|
7193
|
+
const postureY = positionConfig?.postureY ?? this.lastPosition?.y;
|
|
7194
|
+
const postureTheta = positionConfig?.postureTheta ?? this.lastPosition?.rotation;
|
|
7195
|
+
console.log('updatePosition manager', positionConfig, this.lastPosition);
|
|
7370
7196
|
// 停止当前动画(如果有)
|
|
7371
7197
|
this.stopAnimation();
|
|
7372
7198
|
// 第一个点
|
|
@@ -7397,9 +7223,14 @@ class MowerPositionManager {
|
|
|
7397
7223
|
const imgElement = this.mowerElement.querySelector('img');
|
|
7398
7224
|
if (!imgElement)
|
|
7399
7225
|
return;
|
|
7400
|
-
const imageSrc = getMowerImage(positonConfig);
|
|
7226
|
+
const imageSrc = getMowerImage(positonConfig, this.modelType);
|
|
7401
7227
|
if (imageSrc) {
|
|
7402
7228
|
imgElement.src = imageSrc;
|
|
7229
|
+
imgElement.style.display = 'block';
|
|
7230
|
+
}
|
|
7231
|
+
else {
|
|
7232
|
+
imgElement.style.display = 'none';
|
|
7233
|
+
return;
|
|
7403
7234
|
}
|
|
7404
7235
|
}
|
|
7405
7236
|
/**
|
|
@@ -7420,6 +7251,7 @@ class MowerPositionManager {
|
|
|
7420
7251
|
if (!positonOutOfRange && !positionValid) {
|
|
7421
7252
|
this.lastPosition = { x, y, rotation: theta };
|
|
7422
7253
|
}
|
|
7254
|
+
// console.log('setElementPosition', x, y, targetRotation, positonOutOfRange, positionValid, targetPixelPosition);
|
|
7423
7255
|
if (!this.mowerElement)
|
|
7424
7256
|
return;
|
|
7425
7257
|
this.mowerElement.style.left = `${targetPixelPosition?.x}px`;
|
|
@@ -7557,12 +7389,6 @@ class MowerPositionManager {
|
|
|
7557
7389
|
this.container.style.display = visible ? 'block' : 'none';
|
|
7558
7390
|
}
|
|
7559
7391
|
}
|
|
7560
|
-
/**
|
|
7561
|
-
* 检查是否正在动画中
|
|
7562
|
-
*/
|
|
7563
|
-
getIsAnimating() {
|
|
7564
|
-
return this.isAnimating;
|
|
7565
|
-
}
|
|
7566
7392
|
/**
|
|
7567
7393
|
* 销毁管理器
|
|
7568
7394
|
*/
|
|
@@ -7627,7 +7453,7 @@ function throttleAdvanced(func, delay, options = { leading: true, trailing: true
|
|
|
7627
7453
|
|
|
7628
7454
|
// Google Maps 叠加层类 - 带编辑功能
|
|
7629
7455
|
class MowerMapOverlay {
|
|
7630
|
-
constructor(bounds, mapData, partitionBoundary, mowerPositionConfig, pathData, isEditMode = false, mapConfig = {}, antennaConfig = {}, mowPartitionData = null, defaultTransform, onMapLoad, onPathLoad, dragCallbacks) {
|
|
7456
|
+
constructor(bounds, mapData, partitionBoundary, mowerPositionConfig, modelType, pathData, isEditMode = false, mapConfig = {}, antennaConfig = {}, mowPartitionData = null, defaultTransform, onMapLoad, onPathLoad, dragCallbacks) {
|
|
7631
7457
|
this.div = null;
|
|
7632
7458
|
this.svgMapView = null;
|
|
7633
7459
|
this.offscreenContainer = null;
|
|
@@ -7682,6 +7508,7 @@ class MowerMapOverlay {
|
|
|
7682
7508
|
this.dragCallbacks = dragCallbacks;
|
|
7683
7509
|
this.mowerPositionConfig = mowerPositionConfig;
|
|
7684
7510
|
this.mowPartitionData = mowPartitionData;
|
|
7511
|
+
this.modelType = modelType;
|
|
7685
7512
|
// 设置默认的transform
|
|
7686
7513
|
if (defaultTransform) {
|
|
7687
7514
|
this.defaultTransform = {
|
|
@@ -7720,12 +7547,14 @@ class MowerMapOverlay {
|
|
|
7720
7547
|
this.isUserAnimation = animationTime > 0;
|
|
7721
7548
|
// 更新割草机位置配置
|
|
7722
7549
|
this.mowerPositionConfig = positionConfig;
|
|
7550
|
+
console.log('updatePosition overlay', positionConfig);
|
|
7723
7551
|
// 更新割草机位置管理器
|
|
7724
7552
|
if (this.mowerPositionManager) {
|
|
7725
7553
|
this.mowerPositionManager.updatePosition(positionConfig, animationTime);
|
|
7726
7554
|
}
|
|
7727
7555
|
}
|
|
7728
7556
|
updatePositionByLastPosition(chargingPilesPositionConfig) {
|
|
7557
|
+
this.mowerPositionConfig = chargingPilesPositionConfig;
|
|
7729
7558
|
// 更新配置
|
|
7730
7559
|
if (this.mowerPositionManager) {
|
|
7731
7560
|
this.mowerPositionManager.updatePositionByLastPosition(chargingPilesPositionConfig);
|
|
@@ -7746,30 +7575,24 @@ class MowerMapOverlay {
|
|
|
7746
7575
|
return this.overlayView ? this.overlayView.getPanes() : null;
|
|
7747
7576
|
}
|
|
7748
7577
|
resetBorderLayerHighlight() {
|
|
7578
|
+
this.mowPartitionData = null;
|
|
7749
7579
|
const boundaryBorderLayer = this.svgMapView?.getLayer(LAYER_DEFAULT_TYPE.BOUNDARY_BORDER);
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
path.setAttribute('stroke', BOUNDARY_STYLES.lineColor);
|
|
7755
|
-
});
|
|
7756
|
-
}
|
|
7757
|
-
});
|
|
7580
|
+
if (!boundaryBorderLayer)
|
|
7581
|
+
return;
|
|
7582
|
+
boundaryBorderLayer.setMowingBoundarys([]);
|
|
7583
|
+
this.svgMapView?.renderLayer(LAYER_DEFAULT_TYPE.BOUNDARY_BORDER);
|
|
7758
7584
|
}
|
|
7759
7585
|
setBorderLayerHighlight(mowPartitionData) {
|
|
7760
7586
|
this.mowPartitionData = mowPartitionData;
|
|
7761
7587
|
const boundaryBorderLayer = this.svgMapView?.getLayer(LAYER_DEFAULT_TYPE.BOUNDARY_BORDER);
|
|
7762
7588
|
const partitionIds = mowPartitionData?.partitionIds || [];
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
path.setAttribute('stroke', BOUNDARY_STYLES.mowingLineColor);
|
|
7768
|
-
});
|
|
7769
|
-
}
|
|
7770
|
-
}
|
|
7589
|
+
if (!boundaryBorderLayer)
|
|
7590
|
+
return;
|
|
7591
|
+
boundaryBorderLayer.setMowingBoundarys(partitionIds);
|
|
7592
|
+
this.svgMapView?.renderLayer(LAYER_DEFAULT_TYPE.BOUNDARY_BORDER);
|
|
7771
7593
|
}
|
|
7772
7594
|
onAdd() {
|
|
7595
|
+
console.log('onAdd');
|
|
7773
7596
|
// 创建包含SVG的div
|
|
7774
7597
|
this.div = document.createElement('div');
|
|
7775
7598
|
this.div.style.borderStyle = 'none';
|
|
@@ -7830,16 +7653,6 @@ class MowerMapOverlay {
|
|
|
7830
7653
|
const map = this.getMap();
|
|
7831
7654
|
if (!map || !this.svgMapView)
|
|
7832
7655
|
return;
|
|
7833
|
-
// const currentZoom = map.getZoom();
|
|
7834
|
-
// const center = map.getCenter();
|
|
7835
|
-
// 基础公式:像素/米 = 156543.03392 * cos(latitude) / (2 ^ zoom)
|
|
7836
|
-
// const metersPerPixel =
|
|
7837
|
-
// (156543.03392 * Math.cos((center.lat() * Math.PI) / 180)) / Math.pow(2, currentZoom);
|
|
7838
|
-
// 缩放比例 = 1 / 米/像素
|
|
7839
|
-
// const scale = (1 / metersPerPixel) * 50;
|
|
7840
|
-
// 应用缩放到SVG
|
|
7841
|
-
// this.svgMapView.setZoom(scale);
|
|
7842
|
-
// 当缩放变化时,重新绘制以确保位置正确
|
|
7843
7656
|
this.draw();
|
|
7844
7657
|
}
|
|
7845
7658
|
// 创建边界标签管理器
|
|
@@ -7891,7 +7704,7 @@ class MowerMapOverlay {
|
|
|
7891
7704
|
if (!this.div || !this.svgMapView)
|
|
7892
7705
|
return;
|
|
7893
7706
|
// 创建割草机位置管理器,传入动画完成回调
|
|
7894
|
-
this.mowerPositionManager = new MowerPositionManager(this.svgMapView, this.mowerPositionConfig, this.div, () => {
|
|
7707
|
+
this.mowerPositionManager = new MowerPositionManager(this.svgMapView, this.mowerPositionConfig, this.modelType, this.div, () => {
|
|
7895
7708
|
console.log('动画完成');
|
|
7896
7709
|
}, this.updatePathDataByMowingPositionThrottled.bind(this));
|
|
7897
7710
|
// 设置叠加层div引用
|
|
@@ -7924,7 +7737,7 @@ class MowerMapOverlay {
|
|
|
7924
7737
|
this.boundaryLabelsManager.updatePositionsWithPrecomputedData(width, height, viewBoxInfo);
|
|
7925
7738
|
}
|
|
7926
7739
|
// 更新管理器位置
|
|
7927
|
-
updateManagerPositions(
|
|
7740
|
+
updateManagerPositions(_width, _height) {
|
|
7928
7741
|
if (!this.div)
|
|
7929
7742
|
return;
|
|
7930
7743
|
// 更新充电桩位置
|
|
@@ -8489,13 +8302,13 @@ class MowerMapOverlay {
|
|
|
8489
8302
|
try {
|
|
8490
8303
|
// 创建SvgMapView实例
|
|
8491
8304
|
this.svgMapView = new SvgMapView(this.offscreenContainer, 800, 600);
|
|
8492
|
-
window.svgMapView = this.svgMapView;
|
|
8493
8305
|
// 加载地图数据
|
|
8494
8306
|
this.loadMapData();
|
|
8495
8307
|
// 加载路径数据
|
|
8496
8308
|
if (this.pathData && this.svgMapView) {
|
|
8497
8309
|
this.loadPathData(this.pathData, this.mowPartitionData);
|
|
8498
8310
|
}
|
|
8311
|
+
console.log('initializeSvgMapView');
|
|
8499
8312
|
// 刷新绘制图层
|
|
8500
8313
|
this.svgMapView.refresh();
|
|
8501
8314
|
// 获取生成的SVG并添加到叠加层div中
|
|
@@ -8520,9 +8333,6 @@ class MowerMapOverlay {
|
|
|
8520
8333
|
// 使用现有的MapDataProcessor处理地图数据
|
|
8521
8334
|
const elements = MapDataProcessor.processMapData(this.mapData, this.mapConfig);
|
|
8522
8335
|
// 分离充电桩和天线元素,其他元素添加到SVG图层
|
|
8523
|
-
// const svgElements = elements.filter(element =>
|
|
8524
|
-
// element.type !== 'charging_pile' && element.type !== 'antenna'
|
|
8525
|
-
// );
|
|
8526
8336
|
const svgElements = elements.filter((element) => element.type !== 'charging_pile' && element.type !== 'antenna');
|
|
8527
8337
|
const chargingPileElements = elements.filter((element) => element.type === 'charging_pile');
|
|
8528
8338
|
// 处理SVG图层元素
|
|
@@ -8537,6 +8347,10 @@ class MowerMapOverlay {
|
|
|
8537
8347
|
const layers = drawLayer.getLayers();
|
|
8538
8348
|
this.svgMapView.clear();
|
|
8539
8349
|
this.svgMapView.addLayers(layers);
|
|
8350
|
+
const boundaryBorderLayer = this.svgMapView.getLayer(LAYER_DEFAULT_TYPE.BOUNDARY_BORDER);
|
|
8351
|
+
if (boundaryBorderLayer) {
|
|
8352
|
+
boundaryBorderLayer.setMowingBoundarys(this.mowPartitionData?.partitionIds || []);
|
|
8353
|
+
}
|
|
8540
8354
|
this.createChargingPileManager();
|
|
8541
8355
|
// 使用管理器处理充电桩和天线
|
|
8542
8356
|
if (this.chargingPileManager && chargingPileElements.length > 0) {
|
|
@@ -8801,6 +8615,10 @@ class MowerMapOverlay {
|
|
|
8801
8615
|
this.mowerPositionManager.setVisible(visible);
|
|
8802
8616
|
}
|
|
8803
8617
|
}
|
|
8618
|
+
// 获取SvgMapView实例(用于debug)
|
|
8619
|
+
getSvgMapView() {
|
|
8620
|
+
return this.svgMapView;
|
|
8621
|
+
}
|
|
8804
8622
|
}
|
|
8805
8623
|
|
|
8806
8624
|
var RealTimeDataType;
|
|
@@ -8810,6 +8628,35 @@ var RealTimeDataType;
|
|
|
8810
8628
|
RealTimeDataType[RealTimeDataType["PARTITION"] = 3] = "PARTITION";
|
|
8811
8629
|
})(RealTimeDataType || (RealTimeDataType = {}));
|
|
8812
8630
|
|
|
8631
|
+
// 获取车辆状态的中文文案
|
|
8632
|
+
const getVehicleStateText = (vehicleState) => {
|
|
8633
|
+
switch (vehicleState) {
|
|
8634
|
+
case RobotStatus.PARKED:
|
|
8635
|
+
return 'PARKED';
|
|
8636
|
+
case RobotStatus.CHARGING:
|
|
8637
|
+
return 'CHARGING';
|
|
8638
|
+
case RobotStatus.STANDBY:
|
|
8639
|
+
return 'STANDBY';
|
|
8640
|
+
case RobotStatus.MOWING:
|
|
8641
|
+
return 'MOWING';
|
|
8642
|
+
case RobotStatus.WORKING:
|
|
8643
|
+
return 'WORKING';
|
|
8644
|
+
case RobotStatus.MAPPING:
|
|
8645
|
+
return 'MAPPING';
|
|
8646
|
+
case RobotStatus.ERROR:
|
|
8647
|
+
return 'ERROR';
|
|
8648
|
+
case RobotStatus.UPGRADING:
|
|
8649
|
+
return 'UPGRADING';
|
|
8650
|
+
case RobotStatus.DISCONNECTED:
|
|
8651
|
+
return 'DISCONNECTED';
|
|
8652
|
+
case RobotStatus.TASK_DELAY:
|
|
8653
|
+
return 'TASK_DELAY';
|
|
8654
|
+
case RobotStatus.UNKNOWN:
|
|
8655
|
+
return '未知';
|
|
8656
|
+
default:
|
|
8657
|
+
return `未知状态(${vehicleState})`;
|
|
8658
|
+
}
|
|
8659
|
+
};
|
|
8813
8660
|
// 验证GPS坐标是否有效
|
|
8814
8661
|
const isValidGpsCoordinate = (coordinate) => {
|
|
8815
8662
|
if (!coordinate || coordinate.length < 2)
|
|
@@ -8892,7 +8739,7 @@ const getValidGpsBounds = (mapData, rotation = 0) => {
|
|
|
8892
8739
|
// 默认配置
|
|
8893
8740
|
const defaultMapConfig = DEFAULT_STYLES;
|
|
8894
8741
|
// 地图渲染器组件
|
|
8895
|
-
const MowerMapRenderer = forwardRef(({ mapConfig, modelType, mapRef, mapJson, pathJson, realTimeData, antennaConfig, onMapLoad, onPathLoad, onError, className, style, googleMapInstance, isEditMode = false, dragCallbacks, defaultTransform, }, ref) => {
|
|
8742
|
+
const MowerMapRenderer = forwardRef(({ mapConfig, modelType, mapRef, mapJson, pathJson, realTimeData, antennaConfig, onMapLoad, onPathLoad, onError, className, style, googleMapInstance, isEditMode = false, dragCallbacks, defaultTransform, debug = false, }, ref) => {
|
|
8896
8743
|
const [elementCount, setElementCount] = useState(0);
|
|
8897
8744
|
const [pathCount, setPathCount] = useState(0);
|
|
8898
8745
|
const [currentError, setCurrentError] = useState(null);
|
|
@@ -8904,6 +8751,8 @@ const MowerMapRenderer = forwardRef(({ mapConfig, modelType, mapRef, mapJson, pa
|
|
|
8904
8751
|
const currentProcessMowingStatusRef = useRef(false);
|
|
8905
8752
|
const { updateProcessStateIsMowing, processStateIsMowing } = useProcessMowingState();
|
|
8906
8753
|
const [mowPartitionData, setMowPartitionData] = useState(null);
|
|
8754
|
+
// Debug相关状态
|
|
8755
|
+
const [debugInfo, setDebugInfo] = useState({});
|
|
8907
8756
|
// 处理地图分区边界
|
|
8908
8757
|
const partitionBoundary = useMemo(() => {
|
|
8909
8758
|
const allBoundaryElements = [];
|
|
@@ -8928,7 +8777,12 @@ const MowerMapRenderer = forwardRef(({ mapConfig, modelType, mapRef, mapJson, pa
|
|
|
8928
8777
|
const mowerPositionData = useMemo(() => {
|
|
8929
8778
|
// realTimeData 中包含三个种类的数据,之需要实时坐标的数据即可。
|
|
8930
8779
|
if (!realTimeData || realTimeData.length === 0)
|
|
8931
|
-
return
|
|
8780
|
+
return {
|
|
8781
|
+
postureX: 0,
|
|
8782
|
+
postureY: 0,
|
|
8783
|
+
postureTheta: 0,
|
|
8784
|
+
vehicleState: RobotStatus.PARKED,
|
|
8785
|
+
};
|
|
8932
8786
|
let currentPositionData;
|
|
8933
8787
|
if (realTimeData.length === 1 && realTimeData[0].type === RealTimeDataType.LOCATION) {
|
|
8934
8788
|
currentPositionData = realTimeData[0];
|
|
@@ -8950,7 +8804,6 @@ const MowerMapRenderer = forwardRef(({ mapConfig, modelType, mapRef, mapJson, pa
|
|
|
8950
8804
|
lastPostureX: currentPositionData?.lastPostureX ? Number(currentPositionData.lastPostureX) : 0,
|
|
8951
8805
|
lastPostureY: currentPositionData?.lastPostureY ? Number(currentPositionData.lastPostureY) : 0,
|
|
8952
8806
|
vehicleState: currentPositionData?.vehicleState || RobotStatus.CHARGING,
|
|
8953
|
-
vehicleModel: modelType?.toLowerCase() || '',
|
|
8954
8807
|
};
|
|
8955
8808
|
}, [realTimeData, modelType]);
|
|
8956
8809
|
console.log('mowerPositionData', mowerPositionData);
|
|
@@ -9019,8 +8872,9 @@ const MowerMapRenderer = forwardRef(({ mapConfig, modelType, mapRef, mapJson, pa
|
|
|
9019
8872
|
overlayRef.current.setMap(null);
|
|
9020
8873
|
overlayRef.current = null;
|
|
9021
8874
|
}
|
|
8875
|
+
console.log('initializeGoogleMapsOverlay', mowPartitionData);
|
|
9022
8876
|
// 创建叠加层
|
|
9023
|
-
const overlay = new MowerMapOverlay(googleBounds, mapJson, partitionBoundary, mowerPositionData, pathJson || {}, isEditMode, mergedMapConfig, mergedAntennaConfig, null, defaultTransform, (count) => {
|
|
8877
|
+
const overlay = new MowerMapOverlay(googleBounds, mapJson, partitionBoundary, mowerPositionData, modelType, pathJson || {}, isEditMode, mergedMapConfig, mergedAntennaConfig, null, defaultTransform, (count) => {
|
|
9024
8878
|
setElementCount(count);
|
|
9025
8879
|
onMapLoad?.(count);
|
|
9026
8880
|
}, (count) => {
|
|
@@ -9078,6 +8932,7 @@ const MowerMapRenderer = forwardRef(({ mapConfig, modelType, mapRef, mapJson, pa
|
|
|
9078
8932
|
const isOffLine = mowerPositionData.vehicleState === RobotStatus.DISCONNECTED;
|
|
9079
8933
|
const isInChargingPile = inChargingPiles.includes(mowerPositionData.vehicleState);
|
|
9080
8934
|
// 如果在充电桩上,则直接更新位置到充电桩的位置
|
|
8935
|
+
console.log('usefeect mowerPositionData----->', mowerPositionData);
|
|
9081
8936
|
if (isInChargingPile) {
|
|
9082
8937
|
overlayRef.current.updatePosition({
|
|
9083
8938
|
...mowerPositionData,
|
|
@@ -9115,19 +8970,137 @@ const MowerMapRenderer = forwardRef(({ mapConfig, modelType, mapRef, mapJson, pa
|
|
|
9115
8970
|
}
|
|
9116
8971
|
}
|
|
9117
8972
|
}, [mowerPositionData]);
|
|
8973
|
+
// 更新debug信息
|
|
9118
8974
|
useEffect(() => {
|
|
8975
|
+
if (!debug)
|
|
8976
|
+
return;
|
|
8977
|
+
const updateDebugInfo = () => {
|
|
8978
|
+
const newDebugInfo = {};
|
|
8979
|
+
// 获取地图GPS边界
|
|
8980
|
+
if (mapJson) {
|
|
8981
|
+
newDebugInfo.mapBounds = getValidGpsBounds(mapJson, defaultTransform?.rotation);
|
|
8982
|
+
}
|
|
8983
|
+
// 获取SVG viewBox信息
|
|
8984
|
+
if (overlayRef.current) {
|
|
8985
|
+
const overlay = overlayRef.current;
|
|
8986
|
+
const svgMapView = overlay.getSvgMapView?.();
|
|
8987
|
+
if (svgMapView) {
|
|
8988
|
+
const viewBoxInfo = svgMapView.getViewBoxInfo();
|
|
8989
|
+
// 计算实际的米单位数据(除以缩放比例)
|
|
8990
|
+
const SCALE_FACTOR = 50; // 根据项目中的缩放因子
|
|
8991
|
+
newDebugInfo.viewBox = {
|
|
8992
|
+
x: viewBoxInfo.x / SCALE_FACTOR,
|
|
8993
|
+
y: viewBoxInfo.y / SCALE_FACTOR,
|
|
8994
|
+
width: viewBoxInfo.width / SCALE_FACTOR,
|
|
8995
|
+
height: viewBoxInfo.height / SCALE_FACTOR,
|
|
8996
|
+
scale: SCALE_FACTOR,
|
|
8997
|
+
// 计算左下角和右上角坐标
|
|
8998
|
+
sw: {
|
|
8999
|
+
x: viewBoxInfo.x / SCALE_FACTOR,
|
|
9000
|
+
y: viewBoxInfo.y / SCALE_FACTOR
|
|
9001
|
+
},
|
|
9002
|
+
ne: {
|
|
9003
|
+
x: (viewBoxInfo.x + viewBoxInfo.width) / SCALE_FACTOR,
|
|
9004
|
+
y: (viewBoxInfo.y + viewBoxInfo.height) / SCALE_FACTOR
|
|
9005
|
+
}
|
|
9006
|
+
};
|
|
9007
|
+
}
|
|
9008
|
+
}
|
|
9009
|
+
// 获取当前割草机位置
|
|
9010
|
+
if (mowerPositionData) {
|
|
9011
|
+
newDebugInfo.mowerPosition = {
|
|
9012
|
+
x: mowerPositionData.postureX || 0,
|
|
9013
|
+
y: mowerPositionData.postureY || 0,
|
|
9014
|
+
theta: mowerPositionData.postureTheta || 0,
|
|
9015
|
+
lastX: mowerPositionData.lastPostureX || 0,
|
|
9016
|
+
lastY: mowerPositionData.lastPostureY || 0,
|
|
9017
|
+
lastTheta: mowerPositionData.lastPostureTheta || 0,
|
|
9018
|
+
vehicleState: mowerPositionData.vehicleState || RobotStatus.UNKNOWN,
|
|
9019
|
+
vehicleStateText: getVehicleStateText(mowerPositionData.vehicleState || RobotStatus.UNKNOWN)
|
|
9020
|
+
};
|
|
9021
|
+
}
|
|
9022
|
+
// 获取当前割草地块数据
|
|
9023
|
+
newDebugInfo.partitionData = mowPartitionData;
|
|
9024
|
+
setDebugInfo(newDebugInfo);
|
|
9025
|
+
};
|
|
9026
|
+
updateDebugInfo();
|
|
9027
|
+
// 设置定时更新(仅在没有数据变化时使用)
|
|
9028
|
+
const interval = setInterval(updateDebugInfo, 1000);
|
|
9029
|
+
return () => clearInterval(interval);
|
|
9030
|
+
}, [debug, mapJson, mowerPositionData, mowPartitionData, defaultTransform]);
|
|
9031
|
+
// 当关键数据变化时立即更新debug信息
|
|
9032
|
+
useEffect(() => {
|
|
9033
|
+
if (!debug)
|
|
9034
|
+
return;
|
|
9035
|
+
const updateDebugInfo = () => {
|
|
9036
|
+
const newDebugInfo = {};
|
|
9037
|
+
// 获取地图GPS边界
|
|
9038
|
+
if (mapJson) {
|
|
9039
|
+
newDebugInfo.mapBounds = getValidGpsBounds(mapJson, defaultTransform?.rotation);
|
|
9040
|
+
}
|
|
9041
|
+
// 获取SVG viewBox信息
|
|
9042
|
+
if (overlayRef.current) {
|
|
9043
|
+
const overlay = overlayRef.current;
|
|
9044
|
+
const svgMapView = overlay.getSvgMapView?.();
|
|
9045
|
+
if (svgMapView) {
|
|
9046
|
+
const viewBoxInfo = svgMapView.getViewBoxInfo();
|
|
9047
|
+
// 计算实际的米单位数据(除以缩放比例)
|
|
9048
|
+
const SCALE_FACTOR = 50; // 根据项目中的缩放因子
|
|
9049
|
+
newDebugInfo.viewBox = {
|
|
9050
|
+
x: viewBoxInfo.x / SCALE_FACTOR,
|
|
9051
|
+
y: viewBoxInfo.y / SCALE_FACTOR,
|
|
9052
|
+
width: viewBoxInfo.width / SCALE_FACTOR,
|
|
9053
|
+
height: viewBoxInfo.height / SCALE_FACTOR,
|
|
9054
|
+
scale: SCALE_FACTOR,
|
|
9055
|
+
// 计算左下角和右上角坐标
|
|
9056
|
+
sw: {
|
|
9057
|
+
x: viewBoxInfo.x / SCALE_FACTOR,
|
|
9058
|
+
y: viewBoxInfo.y / SCALE_FACTOR
|
|
9059
|
+
},
|
|
9060
|
+
ne: {
|
|
9061
|
+
x: (viewBoxInfo.x + viewBoxInfo.width) / SCALE_FACTOR,
|
|
9062
|
+
y: (viewBoxInfo.y + viewBoxInfo.height) / SCALE_FACTOR
|
|
9063
|
+
}
|
|
9064
|
+
};
|
|
9065
|
+
}
|
|
9066
|
+
}
|
|
9067
|
+
// 获取当前割草机位置
|
|
9068
|
+
if (mowerPositionData) {
|
|
9069
|
+
newDebugInfo.mowerPosition = {
|
|
9070
|
+
x: mowerPositionData.postureX || 0,
|
|
9071
|
+
y: mowerPositionData.postureY || 0,
|
|
9072
|
+
theta: mowerPositionData.postureTheta || 0,
|
|
9073
|
+
lastX: mowerPositionData.lastPostureX || 0,
|
|
9074
|
+
lastY: mowerPositionData.lastPostureY || 0,
|
|
9075
|
+
lastTheta: mowerPositionData.lastPostureTheta || 0,
|
|
9076
|
+
vehicleState: mowerPositionData.vehicleState || RobotStatus.UNKNOWN,
|
|
9077
|
+
vehicleStateText: getVehicleStateText(mowerPositionData.vehicleState || RobotStatus.UNKNOWN)
|
|
9078
|
+
};
|
|
9079
|
+
}
|
|
9080
|
+
// 获取当前割草地块数据
|
|
9081
|
+
newDebugInfo.partitionData = mowPartitionData;
|
|
9082
|
+
setDebugInfo(newDebugInfo);
|
|
9083
|
+
};
|
|
9084
|
+
updateDebugInfo();
|
|
9085
|
+
}, [debug, mowerPositionData, mowPartitionData]);
|
|
9086
|
+
useEffect(() => {
|
|
9087
|
+
if (!realTimeData || realTimeData.length === 0 || !Array.isArray(realTimeData)) {
|
|
9088
|
+
return;
|
|
9089
|
+
}
|
|
9090
|
+
console.log('usefeect realTimeData----->', realTimeData, mapJson, pathJson, overlayRef.current);
|
|
9091
|
+
// realtime中包含当前割草任务的数据,根据数据进行path路径和边界的高亮操作,
|
|
9092
|
+
const mowingPartition = realTimeData.find((item) => item.type === RealTimeDataType.PARTITION);
|
|
9093
|
+
if (mowingPartition) {
|
|
9094
|
+
setMowPartitionData(mowingPartition);
|
|
9095
|
+
}
|
|
9096
|
+
const curMowPartitionData = mowingPartition || mowPartitionData;
|
|
9119
9097
|
if (!mapJson ||
|
|
9120
9098
|
!pathJson ||
|
|
9121
|
-
!realTimeData ||
|
|
9122
|
-
realTimeData.length === 0 ||
|
|
9123
|
-
!Array.isArray(realTimeData) ||
|
|
9124
9099
|
!overlayRef.current)
|
|
9125
9100
|
return;
|
|
9126
9101
|
// 根据后端推送的实时数据,进行不同处理
|
|
9127
9102
|
// TODO:需要根据返回的数据,处理车辆的移动位置
|
|
9128
|
-
console.log('realTimeData----->', realTimeData);
|
|
9129
|
-
// realtime中包含当前割草任务的数据,根据数据进行path路径和边界的高亮操作
|
|
9130
|
-
const curMowPartitionData = realTimeData.find((item) => item.type === RealTimeDataType.PARTITION) || mowPartitionData;
|
|
9103
|
+
console.log('realTimeData----->', realTimeData, curMowPartitionData);
|
|
9131
9104
|
if (curMowPartitionData) {
|
|
9132
9105
|
setMowPartitionData(curMowPartitionData);
|
|
9133
9106
|
const isMowing = curMowPartitionData?.partitionIds && curMowPartitionData.partitionIds.length > 0;
|
|
@@ -9170,12 +9143,9 @@ const MowerMapRenderer = forwardRef(({ mapConfig, modelType, mapRef, mapJson, pa
|
|
|
9170
9143
|
}
|
|
9171
9144
|
}, [realTimeData, mapJson, pathJson]);
|
|
9172
9145
|
useEffect(() => {
|
|
9173
|
-
console.log('defaultTransform----->', defaultTransform, overlayRef.current);
|
|
9146
|
+
console.log('defaultTransform----->', defaultTransform, overlayRef.current, mapJson);
|
|
9174
9147
|
if (!overlayRef.current || !defaultTransform)
|
|
9175
9148
|
return;
|
|
9176
|
-
if (defaultTransform.x === 0 && defaultTransform.y === 0 && defaultTransform.rotation === 0) {
|
|
9177
|
-
return;
|
|
9178
|
-
}
|
|
9179
9149
|
overlayRef.current?.setTransform(defaultTransform);
|
|
9180
9150
|
const validBounds = getValidGpsBounds(mapJson, defaultTransform?.rotation);
|
|
9181
9151
|
// 地图数据中的坐标格式是 [longitude, latitude]
|
|
@@ -9223,12 +9193,31 @@ const MowerMapRenderer = forwardRef(({ mapConfig, modelType, mapRef, mapJson, pa
|
|
|
9223
9193
|
setTransform: (t) => overlayRef.current?.setTransform(t),
|
|
9224
9194
|
resetToDefaultTransform: () => overlayRef.current?.resetToDefaultTransform(),
|
|
9225
9195
|
}));
|
|
9196
|
+
// Debug信息组件
|
|
9197
|
+
const DebugInfo = () => {
|
|
9198
|
+
if (!debug)
|
|
9199
|
+
return null;
|
|
9200
|
+
return (jsxs("div", { style: {
|
|
9201
|
+
position: 'fixed',
|
|
9202
|
+
bottom: '10px',
|
|
9203
|
+
left: '10px',
|
|
9204
|
+
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
|
9205
|
+
color: 'white',
|
|
9206
|
+
padding: '10px',
|
|
9207
|
+
borderRadius: '5px',
|
|
9208
|
+
fontSize: '12px',
|
|
9209
|
+
fontFamily: 'monospace',
|
|
9210
|
+
zIndex: 10000,
|
|
9211
|
+
maxWidth: '300px',
|
|
9212
|
+
lineHeight: '1.4'
|
|
9213
|
+
}, children: [jsx("div", { style: { fontWeight: 'bold', marginBottom: '8px' }, children: "\uD83D\uDC1B Debug Info" }), debugInfo.mapBounds && (jsxs("div", { style: { marginBottom: '6px' }, children: [jsx("div", { style: { fontWeight: 'bold' }, children: "\uD83D\uDCCD Map GPS Bounds:" }), jsxs("div", { children: ["SW: [", debugInfo.mapBounds.sw[0].toFixed(6), ", ", debugInfo.mapBounds.sw[1].toFixed(6), "]"] }), jsxs("div", { children: ["NE: [", debugInfo.mapBounds.ne[0].toFixed(6), ", ", debugInfo.mapBounds.ne[1].toFixed(6), "]"] })] })), debugInfo.viewBox && (jsxs("div", { style: { marginBottom: '6px' }, children: [jsx("div", { style: { fontWeight: 'bold' }, children: "\uD83D\uDCD0 SVG ViewBox (meters):" }), jsxs("div", { children: ["SW: [", debugInfo.viewBox.sw.x.toFixed(2), ", ", debugInfo.viewBox.sw.y.toFixed(2), "]"] }), jsxs("div", { children: ["NE: [", debugInfo.viewBox.ne.x.toFixed(2), ", ", debugInfo.viewBox.ne.y.toFixed(2), "]"] }), jsxs("div", { children: ["Size: ", debugInfo.viewBox.width.toFixed(2), "m \u00D7 ", debugInfo.viewBox.height.toFixed(2), "m"] }), jsxs("div", { children: ["Scale: 1:", debugInfo.viewBox.scale] })] })), debugInfo.mowerPosition && (jsxs("div", { style: { marginBottom: '6px' }, children: [jsx("div", { style: { fontWeight: 'bold' }, children: "\uD83D\uDE9C Mower Position:" }), jsxs("div", { children: ["Current: X=", debugInfo.mowerPosition.x.toFixed(2), ", Y=", debugInfo.mowerPosition.y.toFixed(2)] }), jsxs("div", { children: ["Theta: ", (debugInfo.mowerPosition.theta * 180 / Math.PI).toFixed(1), "\u00B0"] }), jsxs("div", { children: ["Last: X=", debugInfo.mowerPosition.lastX.toFixed(2), ", Y=", debugInfo.mowerPosition.lastY.toFixed(2)] }), jsxs("div", { children: ["Last Theta: ", (debugInfo.mowerPosition.lastTheta * 180 / Math.PI).toFixed(1), "\u00B0"] }), jsxs("div", { children: ["Status: ", debugInfo.mowerPosition.vehicleStateText, " (", debugInfo.mowerPosition.vehicleState, ")"] })] })), debugInfo.partitionData && (jsxs("div", { style: { marginBottom: '6px' }, children: [jsx("div", { style: { fontWeight: 'bold' }, children: "\uD83D\uDD32 Mow Partition Data:" }), jsxs("div", { children: ["Type: ", debugInfo.partitionData.type || 'N/A'] }), debugInfo.partitionData.partitionIds && debugInfo.partitionData.partitionIds.length > 0 ? (jsxs("div", { children: ["Active IDs: [", debugInfo.partitionData.partitionIds.join(', '), "]"] })) : (jsx("div", { children: "No active partitions" })), debugInfo.partitionData.time && (jsxs("div", { children: ["Updated: ", new Date(debugInfo.partitionData.time).toLocaleTimeString()] }))] })), !debugInfo.partitionData && (jsxs("div", { style: { marginBottom: '6px' }, children: [jsx("div", { style: { fontWeight: 'bold' }, children: "\uD83D\uDD32 Mow Partition Data:" }), jsx("div", { style: { color: '#888' }, children: "No partition data available" })] }))] }));
|
|
9214
|
+
};
|
|
9226
9215
|
// 错误显示
|
|
9227
9216
|
if (currentError) {
|
|
9228
|
-
return (
|
|
9217
|
+
return (jsxs("div", { className: className, style: style, children: [jsxs("div", { style: { color: 'red', padding: '10px' }, children: ["\u9519\u8BEF: ", currentError] }), jsx(DebugInfo, {})] }));
|
|
9229
9218
|
}
|
|
9230
|
-
// 使用goole maps
|
|
9231
|
-
return null;
|
|
9219
|
+
// 使用goole maps自定义叠加层,返回debug信息(如果启用)
|
|
9220
|
+
return debug ? jsx(DebugInfo, {}) : null;
|
|
9232
9221
|
});
|
|
9233
9222
|
MowerMapRenderer.displayName = 'MowerMapRenderer';
|
|
9234
9223
|
|