@fleet-frontend/mower-maps 0.0.9-beta.3 → 0.0.9-beta.5

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