@fleet-frontend/mower-maps 0.0.6 → 0.0.8

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 (50) hide show
  1. package/dist/config/constants.d.ts +4 -3
  2. package/dist/config/constants.d.ts.map +1 -1
  3. package/dist/config/index.d.ts +0 -18
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/styles.d.ts +17 -15
  6. package/dist/config/styles.d.ts.map +1 -1
  7. package/dist/index.esm.js +2717 -522
  8. package/dist/index.js +2719 -524
  9. package/dist/processor/MapDataProcessor.d.ts +3 -2
  10. package/dist/processor/MapDataProcessor.d.ts.map +1 -1
  11. package/dist/processor/PathDataProcessor.d.ts +3 -2
  12. package/dist/processor/PathDataProcessor.d.ts.map +1 -1
  13. package/dist/processor/builder/AntennaDataBuilder.d.ts +2 -2
  14. package/dist/processor/builder/AntennaDataBuilder.d.ts.map +1 -1
  15. package/dist/processor/builder/BoundaryDataBuilder.d.ts +4 -3
  16. package/dist/processor/builder/BoundaryDataBuilder.d.ts.map +1 -1
  17. package/dist/processor/builder/ChannelDataBuilder.d.ts +5 -33
  18. package/dist/processor/builder/ChannelDataBuilder.d.ts.map +1 -1
  19. package/dist/processor/builder/ChargingPileDataBuilder.d.ts +4 -4
  20. package/dist/processor/builder/ChargingPileDataBuilder.d.ts.map +1 -1
  21. package/dist/processor/builder/ObstacleDataBuilder.d.ts +2 -2
  22. package/dist/processor/builder/ObstacleDataBuilder.d.ts.map +1 -1
  23. package/dist/processor/builder/PathDataBuilder.d.ts.map +1 -1
  24. package/dist/processor/builder/SvgElementDataBuilder.d.ts +2 -2
  25. package/dist/processor/builder/SvgElementDataBuilder.d.ts.map +1 -1
  26. package/dist/processor/builder/VisionOffDataBuilder.d.ts +2 -2
  27. package/dist/processor/builder/VisionOffDataBuilder.d.ts.map +1 -1
  28. package/dist/render/BoundaryLabelsManager.d.ts +2 -5
  29. package/dist/render/BoundaryLabelsManager.d.ts.map +1 -1
  30. package/dist/render/ChargingPileManager.d.ts.map +1 -1
  31. package/dist/render/MowerMapOverlay.d.ts +1 -3
  32. package/dist/render/MowerMapOverlay.d.ts.map +1 -1
  33. package/dist/render/MowerMapRenderer.d.ts.map +1 -1
  34. package/dist/render/layers/BoundaryLayer.d.ts.map +1 -1
  35. package/dist/render/layers/ChannelLayer.d.ts +6 -0
  36. package/dist/render/layers/ChannelLayer.d.ts.map +1 -1
  37. package/dist/render/layers/DrawLayer.d.ts +1 -1
  38. package/dist/render/layers/DrawLayer.d.ts.map +1 -1
  39. package/dist/render/layers/SvgElementLayer.d.ts.map +1 -1
  40. package/dist/render/layers/VisionOffLayer.d.ts.map +1 -1
  41. package/dist/render/layers/types.d.ts +3 -45
  42. package/dist/render/layers/types.d.ts.map +1 -1
  43. package/dist/types/renderer.d.ts +44 -15
  44. package/dist/types/renderer.d.ts.map +1 -1
  45. package/dist/utils/handleRealTime.d.ts.map +1 -1
  46. package/dist/utils/index.d.ts +2 -0
  47. package/dist/utils/index.d.ts.map +1 -1
  48. package/dist/utils/sleep.d.ts +2 -0
  49. package/dist/utils/sleep.d.ts.map +1 -0
  50. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var React = require('react');
5
- var lodashEs = require('lodash-es');
6
5
 
7
6
  /**
8
7
  * SVG基础MapView
@@ -604,8 +603,8 @@ const createStoreImpl = (createState) => {
604
603
  };
605
604
  const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
606
605
 
607
- const identity = (arg) => arg;
608
- function useStore(api, selector = identity) {
606
+ const identity$1 = (arg) => arg;
607
+ function useStore(api, selector = identity$1) {
609
608
  const slice = React.useSyncExternalStore(
610
609
  api.subscribe,
611
610
  () => selector(api.getState()),
@@ -656,19 +655,20 @@ const SCALE_FACTOR = 50; // 50像素/米
656
655
  * 默认线宽设置
657
656
  */
658
657
  const DEFAULT_LINE_WIDTHS = {
659
- BOUNDARY: 2,
660
658
  OBSTACLE: 2,
661
659
  CHARGING_PILE: 2,
662
- PATH: 6,
660
+ CHANNEL: 2,
661
+ PATH: 20,
663
662
  VISION_OFF_AREA: 2,
664
- TIME_LIMIT_OBSTACLE: 2,
663
+ TIME_LIMIT_OBSTACLE: 1,
665
664
  };
666
665
  /**
667
666
  * 默认透明度设置
668
667
  */
669
668
  const DEFAULT_OPACITIES = {
670
669
  FULL: 1.0,
671
- HIGH: 0.8};
670
+ HIGH: 0.7,
671
+ LOW: 0.4};
672
672
  /**
673
673
  * 默认半径设置
674
674
  */
@@ -771,6 +771,12 @@ class ChannelLayer extends BaseLayer {
771
771
  this.scale = 1;
772
772
  this.type = LAYER_DEFAULT_TYPE.CHANNEL;
773
773
  }
774
+ /**
775
+ * 获取元素
776
+ */
777
+ getElements() {
778
+ return this.elements;
779
+ }
774
780
  /**
775
781
  * SVG渲染方法
776
782
  */
@@ -863,9 +869,9 @@ class ChannelLayer extends BaseLayer {
863
869
  for (let i = 1; i < coordinates.length; i++) {
864
870
  pathData += ` L ${coordinates[i][0]} ${coordinates[i][1]}`;
865
871
  }
866
- const topLineWidth = dp2px(2).toString();
867
- const bottomLineWidth = dp2px(20).toString();
868
- const dashLength = dp2px(2);
872
+ const topLineWidth = dp2px(style.lineWidth).toString();
873
+ const bottomLineWidth = dp2px(style.bottomLineWidth).toString();
874
+ const dashLength = dp2px(style.lineWidth);
869
875
  // 1. 创建底层path(宽度20,boundaryBorder颜色)
870
876
  const bottomPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
871
877
  bottomPath.setAttribute('d', pathData);
@@ -895,16 +901,8 @@ class ChannelLayer extends BaseLayer {
895
901
  topPath.style.clipPath = `url(#${clipPathIdsMap[element.originalData?.id.toString()]})`;
896
902
  }
897
903
  // 支持两种虚线格式:lineDash数组和strokeDasharray字符串
898
- if (style.lineDash && style.lineDash.length > 0) {
899
- topPath.setAttribute('stroke-dasharray', style.lineDash.join(','));
900
- }
901
- else if (style.strokeDasharray) {
902
- topPath.setAttribute('stroke-dasharray', style.strokeDasharray);
903
- }
904
- else {
905
- // 默认虚线样式
906
- topPath.setAttribute('stroke-dasharray', `${dashLength * 2}, ${dashLength}`);
907
- }
904
+ // 默认虚线样式
905
+ topPath.setAttribute('stroke-dasharray', `${dashLength * 2}, ${dashLength}`);
908
906
  topPath.classList.add('vector-path-top');
909
907
  svgGroup.appendChild(topPath);
910
908
  }
@@ -944,9 +942,9 @@ class PathLayer extends BaseLayer {
944
942
  Object.values(subBoundaryBorder).forEach((item) => {
945
943
  const bCoords = item.coordinates;
946
944
  if (bCoords.length >= 3) {
947
- d += `M ${Math.round(bCoords[0][0])} ${Math.round(bCoords[0][1])}`;
945
+ d += `M ${bCoords[0][0]} ${bCoords[0][1]}`;
948
946
  for (let i = 1; i < bCoords.length; i++) {
949
- d += ` L ${Math.round(bCoords[i][0])} ${Math.round(bCoords[i][1])}`;
947
+ d += ` L ${bCoords[i][0]} ${bCoords[i][1]}`;
950
948
  }
951
949
  d += ' Z ';
952
950
  }
@@ -991,9 +989,9 @@ class PathLayer extends BaseLayer {
991
989
  return;
992
990
  const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
993
991
  // 构建路径数据
994
- let pathData = `M ${Math.round(coordinates[0][0])} ${Math.round(coordinates[0][1])}`;
992
+ let pathData = `M ${coordinates[0][0]} ${coordinates[0][1]}`;
995
993
  for (let i = 1; i < coordinates.length; i++) {
996
- pathData += ` L ${Math.round(coordinates[i][0])} ${Math.round(coordinates[i][1])}`;
994
+ pathData += ` L ${coordinates[i][0]} ${coordinates[i][1]}`;
997
995
  }
998
996
  path.style.mixBlendMode = 'normal';
999
997
  // 设置路径属性
@@ -1061,7 +1059,7 @@ class BoundaryLayer extends BaseLayer {
1061
1059
  const polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
1062
1060
  // 构建点集合,使用整数坐标(只取x,y坐标)
1063
1061
  const points = coordinates
1064
- .map((coord) => `${Math.round(coord[0])},${Math.round(coord[1])}`)
1062
+ .map((coord) => `${coord[0]},${coord[1]}`)
1065
1063
  .join(' ');
1066
1064
  const fillColor = style.fillColor;
1067
1065
  polygon.setAttribute('points', points);
@@ -1107,11 +1105,11 @@ class ObstacleLayer extends BaseLayer {
1107
1105
  const polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
1108
1106
  // 构建点集合,使用整数坐标
1109
1107
  const points = coordinates
1110
- .map((coord) => `${Math.round(coord[0])},${Math.round(coord[1])}`)
1108
+ .map((coord) => `${coord[0]},${coord[1]}`)
1111
1109
  .join(' ');
1112
1110
  polygon.setAttribute('points', points);
1113
1111
  polygon.setAttribute('fill', style.fillColor || 'rgba(220, 53, 69, 0.2)');
1114
- polygon.setAttribute('stroke', style.strokeColor || '#dc3545');
1112
+ polygon.setAttribute('stroke', style.lineColor || '#dc3545');
1115
1113
  // 确保最小线条宽度
1116
1114
  const lineWidth = Math.max(style.lineWidth || 2, 0.5);
1117
1115
  polygon.setAttribute('stroke-width', lineWidth.toString());
@@ -1165,8 +1163,8 @@ class ChargingPileLayer extends BaseLayer {
1165
1163
  const rotationDegree = 270 - angle; // 坐标系转换
1166
1164
  const image = document.createElementNS('http://www.w3.org/2000/svg', 'image');
1167
1165
  // 图片居中定位
1168
- const x = Math.round(center[0]);
1169
- const y = Math.round(center[1]);
1166
+ const x = center[0];
1167
+ const y = center[1];
1170
1168
  image.setAttribute('x', x.toString());
1171
1169
  image.setAttribute('y', y.toString());
1172
1170
  image.setAttribute('width', `${size}px`);
@@ -1236,8 +1234,8 @@ class PointLayer extends BaseLayer {
1236
1234
  const coordinate = coordinates[0];
1237
1235
  const radius = style.radius || 4;
1238
1236
  const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
1239
- circle.setAttribute('cx', Math.round(coordinate[0]).toString());
1240
- circle.setAttribute('cy', Math.round(coordinate[1]).toString());
1237
+ circle.setAttribute('cx', coordinate[0].toString());
1238
+ circle.setAttribute('cy', coordinate[1].toString());
1241
1239
  circle.setAttribute('r', radius.toString());
1242
1240
  circle.setAttribute('fill', style.fillColor || style.strokeColor || '#000000');
1243
1241
  circle.setAttribute('stroke', style.strokeColor || '#000000');
@@ -1301,31 +1299,31 @@ class SvgElementLayer extends BaseLayer {
1301
1299
  const svgElement = svgDoc.documentElement;
1302
1300
  if (svgElement.tagName === 'svg') {
1303
1301
  // 获取原始SVG尺寸
1304
- const svgWidth = parseFloat(svgElement.getAttribute('width') || '139');
1305
- const svgHeight = parseFloat(svgElement.getAttribute('height') || '138');
1302
+ const originalWidth = parseFloat(svgElement.getAttribute('width') || '139');
1303
+ const originalHeight = parseFloat(svgElement.getAttribute('height') || '138');
1306
1304
  // 计算变换参数
1307
1305
  const userScale = metadata.scale || 1;
1308
1306
  const direction = metadata.direction || 0;
1307
+ // 设置原始SVG的实际尺寸(限制大小)
1308
+ svgElement.setAttribute('width', originalWidth.toString());
1309
+ svgElement.setAttribute('height', originalHeight.toString());
1309
1310
  // 创建变换组
1310
1311
  const transformGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
1311
- // 应用变换:平移到中心,旋转,缩放
1312
+ // 在transformGroup上应用变换:平移到中心,旋转,缩放,然后居中SVG
1312
1313
  const transform = [
1313
1314
  `translate(${center[0]}, ${center[1]})`,
1314
1315
  `rotate(${(direction * 180) / Math.PI})`,
1315
1316
  `scale(${userScale})`,
1316
- `translate(${-svgWidth / 2}, ${-svgHeight / 2})`,
1317
+ `translate(${-originalWidth / 2}, ${-originalHeight / 2})`,
1317
1318
  ].join(' ');
1318
1319
  transformGroup.setAttribute('transform', transform);
1319
- // 复制SVG内容
1320
- while (svgElement.firstChild) {
1321
- const child = svgElement.firstChild;
1322
- svgElement.removeChild(child);
1323
- transformGroup.appendChild(child);
1324
- }
1325
1320
  // 设置样式
1326
1321
  if (style.opacity !== undefined) {
1327
1322
  transformGroup.setAttribute('opacity', style.opacity.toString());
1328
1323
  }
1324
+ // 将限制好尺寸的原始SVG添加到transformGroup中
1325
+ transformGroup.appendChild(svgElement);
1326
+ // 将transformGroup添加到svgGroup中
1329
1327
  svgGroup.appendChild(transformGroup);
1330
1328
  }
1331
1329
  else {
@@ -1343,14 +1341,15 @@ class SvgElementLayer extends BaseLayer {
1343
1341
  renderSvgPlaceholder(svgGroup, center, metadata, style) {
1344
1342
  const size = (metadata?.scale || 1) * 20;
1345
1343
  const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
1346
- rect.setAttribute('x', (center[0] - size / 2).toString());
1347
- rect.setAttribute('y', (center[1] - size / 2).toString());
1344
+ console.log('style==', style);
1345
+ rect.setAttribute('x', ((center[0] - size / 2) / 50).toString());
1346
+ rect.setAttribute('y', ((center[1] - size / 2) / 50).toString());
1348
1347
  rect.setAttribute('width', size.toString());
1349
1348
  rect.setAttribute('height', size.toString());
1350
- rect.setAttribute('fill', style.fillColor || '#ff9800');
1351
- rect.setAttribute('stroke', style.strokeColor || '#ff5722');
1352
- rect.setAttribute('stroke-width', (style.lineWidth || 1).toString());
1353
- rect.setAttribute('opacity', (style.opacity || 0.7).toString());
1349
+ rect.setAttribute('fill', style.fillColor);
1350
+ rect.setAttribute('stroke', style.lineColor);
1351
+ rect.setAttribute('stroke-width', style.lineWidth.toString());
1352
+ rect.setAttribute('opacity', style.opacity.toString());
1354
1353
  svgGroup.appendChild(rect);
1355
1354
  }
1356
1355
  }
@@ -1389,12 +1388,12 @@ class VisionOffLayer extends BaseLayer {
1389
1388
  const polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
1390
1389
  // 构建点集合,使用整数坐标
1391
1390
  const points = coordinates
1392
- .map((coord) => `${Math.round(coord[0])},${Math.round(coord[1])}`)
1391
+ .map((coord) => `${coord[0]},${coord[1]}`)
1393
1392
  .join(' ');
1394
1393
  const fillColor = style.fillColor || 'rgba(0, 255, 0, 0.4)';
1395
1394
  polygon.setAttribute('points', points);
1396
1395
  polygon.setAttribute('fill', fillColor);
1397
- polygon.setAttribute('stroke', style.strokeColor || '#000000');
1396
+ polygon.setAttribute('stroke', style.lineColor);
1398
1397
  // 确保最小线条宽度
1399
1398
  const lineWidth = Math.max(style.lineWidth || 2, 0.5);
1400
1399
  polygon.setAttribute('stroke-width', lineWidth.toString());
@@ -1411,66 +1410,65 @@ class VisionOffLayer extends BaseLayer {
1411
1410
  * 边界相关样式配置
1412
1411
  */
1413
1412
  const BOUNDARY_STYLES = {
1414
- strokeColor: '#ffffff',
1413
+ lineColor: '#ffffff',
1415
1414
  fillColor: 'rgba(239, 255, 237, 0.15)', // 更鲜艳的绿色半透明填充,增强可见性
1416
1415
  lineWidth: 2,
1417
- opacity: DEFAULT_OPACITIES.FULL
1418
- };
1419
- const BOUNDARY_BORDER_STYLES = {
1420
- strokeColor: '#ffffff',
1421
- fillColor: 'rgba(239, 255, 237, 0.15)', // 更鲜艳的绿色半透明填充,增强可见性
1422
- lineWidth: DEFAULT_LINE_WIDTHS.BOUNDARY,
1423
- opacity: DEFAULT_OPACITIES.FULL
1416
+ opacity: DEFAULT_OPACITIES.FULL,
1424
1417
  };
1425
1418
  const VISION_OFF_AREA_STYLES = {
1426
- strokeColor: 'rgba(108, 167, 255, 1)',
1419
+ lineColor: 'rgba(108, 167, 255, 1)',
1427
1420
  fillColor: 'rgba(43, 128, 255, 0.45)', // 浅蓝色半透明填充
1428
1421
  lineWidth: DEFAULT_LINE_WIDTHS.VISION_OFF_AREA,
1429
- opacity: DEFAULT_OPACITIES.HIGH
1422
+ opacity: DEFAULT_OPACITIES.HIGH,
1430
1423
  };
1431
1424
  const OBSTACLE_STYLES = {
1432
- strokeColor: 'rgba(255, 122, 51, 1)',
1425
+ lineColor: 'rgba(255, 122, 51, 1)',
1433
1426
  fillColor: 'rgba(255, 113, 51, 0.2)', // 红色半透明填充
1434
1427
  lineWidth: DEFAULT_LINE_WIDTHS.OBSTACLE,
1435
- opacity: DEFAULT_OPACITIES.FULL
1428
+ opacity: DEFAULT_OPACITIES.FULL,
1436
1429
  };
1437
1430
  const CHARGING_PILE_STYLES = {
1438
- strokeColor: 'blue',
1431
+ lineColor: 'blue',
1439
1432
  fillColor: 'blue',
1440
1433
  lineWidth: DEFAULT_LINE_WIDTHS.CHARGING_PILE,
1441
1434
  radius: DEFAULT_RADII.CHARGING_PILE,
1442
- opacity: DEFAULT_OPACITIES.FULL
1435
+ opacity: DEFAULT_OPACITIES.FULL,
1443
1436
  };
1444
1437
  const DOODLE_STYLES = {
1445
- strokeColor: 'pink',
1446
- fillColor: 'rgba(255, 192, 203, 0.3)', // 粉色半透明填充
1438
+ lineColor: '#ff5722',
1439
+ fillColor: '#ff9800', // 粉色半透明填充
1447
1440
  lineWidth: DEFAULT_LINE_WIDTHS.TIME_LIMIT_OBSTACLE,
1448
- opacity: DEFAULT_OPACITIES.HIGH
1441
+ opacity: DEFAULT_OPACITIES.HIGH,
1449
1442
  };
1450
1443
  const PATH_EDGE_STYLES = {
1451
- strokeColor: 'red',
1452
- lineWidth: DEFAULT_LINE_WIDTHS.PATH};
1453
- const CHANNEL_STYLES = {
1454
- strokeColor: 'purple',
1455
1444
  lineWidth: DEFAULT_LINE_WIDTHS.PATH,
1456
- opacity: DEFAULT_OPACITIES.FULL
1445
+ opacity: DEFAULT_OPACITIES.LOW,
1446
+ edgeLineColor: 'rgba(194, 203, 212)',
1447
+ transLineColor: 'transparent',
1448
+ mowingLineColor: 'rgba(194, 203, 212)',
1449
+ };
1450
+ const CHANNEL_STYLES = {
1451
+ lineColor: 'purple',
1452
+ lineWidth: DEFAULT_LINE_WIDTHS.CHANNEL,
1453
+ bottomLineWidth: 20,
1454
+ bottomLineColor: '#8498A9',
1455
+ opacity: DEFAULT_OPACITIES.FULL,
1457
1456
  };
1458
1457
  const ANTENNA_STYLES = {
1459
- strokeColor: 'transparent',
1458
+ lineColor: 'transparent',
1460
1459
  fillColor: 'transparent',
1461
1460
  radius: 12, // 默认24px大小
1462
- opacity: DEFAULT_OPACITIES.FULL
1461
+ opacity: DEFAULT_OPACITIES.FULL,
1463
1462
  };
1464
1463
  const DEFAULT_STYLES = {
1465
- BOUNDARY: BOUNDARY_STYLES,
1466
- BOUNDARY_BORDER: BOUNDARY_BORDER_STYLES,
1467
- VISION_OFF_AREA: VISION_OFF_AREA_STYLES,
1468
- OBSTACLE: OBSTACLE_STYLES,
1469
- CHARGING_PILE: CHARGING_PILE_STYLES,
1470
- DOODLE: DOODLE_STYLES,
1471
- PATH_EDGE: PATH_EDGE_STYLES,
1472
- CHANNEL: CHANNEL_STYLES,
1473
- ANTENNA: ANTENNA_STYLES
1464
+ boundary: BOUNDARY_STYLES,
1465
+ visionOffArea: VISION_OFF_AREA_STYLES,
1466
+ obstacle: OBSTACLE_STYLES,
1467
+ chargingPile: CHARGING_PILE_STYLES,
1468
+ doodle: DOODLE_STYLES,
1469
+ path: PATH_EDGE_STYLES,
1470
+ channel: CHANNEL_STYLES,
1471
+ antenna: ANTENNA_STYLES,
1474
1472
  };
1475
1473
 
1476
1474
  /**
@@ -2218,18 +2216,20 @@ const handleRealTimeData = ({ realTimeData, isMowing, pathData, partitionBoundar
2218
2216
  else if (item.type === REAL_TIME_DATA_TYPE.PROCESS) {
2219
2217
  // 割草进度
2220
2218
  const { mapWorkPosition } = item;
2221
- // 解析mapWorkPosition数据,获取到当前的割草状态,割草进度,割草边界id
2222
- const { isMowing, currentMowBoundaryId, currentMowProgress } = parseMapWorkPosition(mapWorkPosition);
2223
- // const { isMowing, currentMowBoundaryId, currentMowProgress } = parseMapWorkPosition(
2224
- // '000000060000000000000001000000030000001BA5A5A5A5A5A5A5A5240000A024010D50FFFFFFED000000000000000000000000000000010000000000000000'
2225
- // );
2226
- console.log('isMowing===', isMowing, currentMowBoundaryId, currentMowProgress);
2227
- mowingStatus = isMowing;
2228
- const currentPartitionId = currentMowBoundaryId ? currentMowBoundaryId.toString() : null;
2229
- if (currentMowProgress && currentPartitionId && newPathData?.[currentPartitionId]) {
2230
- newPathData[currentPartitionId].partitionPercentage = currentMowProgress;
2231
- newPathData[currentPartitionId].finishedArea =
2232
- (newPathData[currentPartitionId].area * currentMowProgress) / 100;
2219
+ if (mapWorkPosition) {
2220
+ // 解析mapWorkPosition数据,获取到当前的割草状态,割草进度,割草边界id
2221
+ const { isMowing, currentMowBoundaryId, currentMowProgress } = parseMapWorkPosition(mapWorkPosition);
2222
+ // const { isMowing, currentMowBoundaryId, currentMowProgress } = parseMapWorkPosition(
2223
+ // '000000060000000000000001000000030000001BA5A5A5A5A5A5A5A5240000A024010D50FFFFFFED000000000000000000000000000000010000000000000000'
2224
+ // );
2225
+ console.log('isMowing===', isMowing, currentMowBoundaryId, currentMowProgress);
2226
+ mowingStatus = isMowing;
2227
+ const currentPartitionId = currentMowBoundaryId ? currentMowBoundaryId.toString() : null;
2228
+ if (currentMowProgress && currentPartitionId && newPathData?.[currentPartitionId]) {
2229
+ newPathData[currentPartitionId].partitionPercentage = currentMowProgress / 100;
2230
+ newPathData[currentPartitionId].finishedArea =
2231
+ (newPathData[currentPartitionId].area * currentMowProgress) / 10000;
2232
+ }
2233
2233
  }
2234
2234
  }
2235
2235
  });
@@ -2281,61 +2281,2486 @@ function getDisabledMowerImageByModal(mowerModal) {
2281
2281
  }
2282
2282
  return iDisabled;
2283
2283
  }
2284
- function getNoPositionMowerImageByModal(mowerModal) {
2285
- if (mowerModal.includes('i')) {
2286
- return iNoPosition;
2287
- }
2288
- else if (mowerModal.includes('h')) {
2289
- return hNoPosition;
2290
- }
2291
- else if (mowerModal.includes('x3')) {
2292
- return x3NoPosition;
2293
- }
2294
- return iNoPosition;
2284
+ function getNoPositionMowerImageByModal(mowerModal) {
2285
+ if (mowerModal.includes('i')) {
2286
+ return iNoPosition;
2287
+ }
2288
+ else if (mowerModal.includes('h')) {
2289
+ return hNoPosition;
2290
+ }
2291
+ else if (mowerModal.includes('x3')) {
2292
+ return x3NoPosition;
2293
+ }
2294
+ return iNoPosition;
2295
+ }
2296
+ function getMowerImage(positonConfig) {
2297
+ const model = positonConfig.vehicleModel || '';
2298
+ const state = positonConfig.vehicleState;
2299
+ const mowerImage = getMowerImageByModal(model);
2300
+ const disabledImage = getDisabledMowerImageByModal(model);
2301
+ const noPositionImage = getNoPositionMowerImageByModal(model);
2302
+ const positonOutOfRange = isOutOfRange(positonConfig);
2303
+ const positionValid = isInvalidPosition(positonConfig);
2304
+ const isOffLine = state === RobotStatus.DISCONNECTED;
2305
+ if (isOffLine) {
2306
+ return disabledImage;
2307
+ }
2308
+ else if (positionValid || positonOutOfRange) {
2309
+ return noPositionImage;
2310
+ }
2311
+ else {
2312
+ return mowerImage;
2313
+ }
2314
+ }
2315
+ function isNoPosture(posture) {
2316
+ if (posture == null || posture == undefined) {
2317
+ return true;
2318
+ }
2319
+ if (posture == 0) {
2320
+ return true;
2321
+ }
2322
+ else if (posture == -99999) {
2323
+ return true;
2324
+ }
2325
+ return false;
2326
+ }
2327
+ function isInvalidPosition(positonConfig) {
2328
+ return (isNoPosture(positonConfig.postureX) &&
2329
+ isNoPosture(positonConfig.postureY) &&
2330
+ isNoPosture(positonConfig.postureTheta));
2331
+ }
2332
+ function isOutOfRange(positonConfig) {
2333
+ return (positonConfig.postureX != null &&
2334
+ Math.abs(positonConfig.postureX) > 1000 * SCALE_FACTOR &&
2335
+ positonConfig.postureY != null &&
2336
+ Math.abs(positonConfig.postureY) > 1000 * SCALE_FACTOR);
2337
+ }
2338
+
2339
+ /** Detect free variable `global` from Node.js. */
2340
+ var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
2341
+
2342
+ /** Detect free variable `self`. */
2343
+ var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
2344
+
2345
+ /** Used as a reference to the global object. */
2346
+ var root = freeGlobal || freeSelf || Function('return this')();
2347
+
2348
+ /** Built-in value references. */
2349
+ var Symbol = root.Symbol;
2350
+
2351
+ /** Used for built-in method references. */
2352
+ var objectProto$9 = Object.prototype;
2353
+
2354
+ /** Used to check objects for own properties. */
2355
+ var hasOwnProperty$7 = objectProto$9.hasOwnProperty;
2356
+
2357
+ /**
2358
+ * Used to resolve the
2359
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
2360
+ * of values.
2361
+ */
2362
+ var nativeObjectToString$1 = objectProto$9.toString;
2363
+
2364
+ /** Built-in value references. */
2365
+ var symToStringTag$1 = Symbol ? Symbol.toStringTag : undefined;
2366
+
2367
+ /**
2368
+ * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
2369
+ *
2370
+ * @private
2371
+ * @param {*} value The value to query.
2372
+ * @returns {string} Returns the raw `toStringTag`.
2373
+ */
2374
+ function getRawTag(value) {
2375
+ var isOwn = hasOwnProperty$7.call(value, symToStringTag$1),
2376
+ tag = value[symToStringTag$1];
2377
+
2378
+ try {
2379
+ value[symToStringTag$1] = undefined;
2380
+ var unmasked = true;
2381
+ } catch (e) {}
2382
+
2383
+ var result = nativeObjectToString$1.call(value);
2384
+ if (unmasked) {
2385
+ if (isOwn) {
2386
+ value[symToStringTag$1] = tag;
2387
+ } else {
2388
+ delete value[symToStringTag$1];
2389
+ }
2390
+ }
2391
+ return result;
2392
+ }
2393
+
2394
+ /** Used for built-in method references. */
2395
+ var objectProto$8 = Object.prototype;
2396
+
2397
+ /**
2398
+ * Used to resolve the
2399
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
2400
+ * of values.
2401
+ */
2402
+ var nativeObjectToString = objectProto$8.toString;
2403
+
2404
+ /**
2405
+ * Converts `value` to a string using `Object.prototype.toString`.
2406
+ *
2407
+ * @private
2408
+ * @param {*} value The value to convert.
2409
+ * @returns {string} Returns the converted string.
2410
+ */
2411
+ function objectToString(value) {
2412
+ return nativeObjectToString.call(value);
2413
+ }
2414
+
2415
+ /** `Object#toString` result references. */
2416
+ var nullTag = '[object Null]',
2417
+ undefinedTag = '[object Undefined]';
2418
+
2419
+ /** Built-in value references. */
2420
+ var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
2421
+
2422
+ /**
2423
+ * The base implementation of `getTag` without fallbacks for buggy environments.
2424
+ *
2425
+ * @private
2426
+ * @param {*} value The value to query.
2427
+ * @returns {string} Returns the `toStringTag`.
2428
+ */
2429
+ function baseGetTag(value) {
2430
+ if (value == null) {
2431
+ return value === undefined ? undefinedTag : nullTag;
2432
+ }
2433
+ return (symToStringTag && symToStringTag in Object(value))
2434
+ ? getRawTag(value)
2435
+ : objectToString(value);
2436
+ }
2437
+
2438
+ /**
2439
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
2440
+ * and has a `typeof` result of "object".
2441
+ *
2442
+ * @static
2443
+ * @memberOf _
2444
+ * @since 4.0.0
2445
+ * @category Lang
2446
+ * @param {*} value The value to check.
2447
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
2448
+ * @example
2449
+ *
2450
+ * _.isObjectLike({});
2451
+ * // => true
2452
+ *
2453
+ * _.isObjectLike([1, 2, 3]);
2454
+ * // => true
2455
+ *
2456
+ * _.isObjectLike(_.noop);
2457
+ * // => false
2458
+ *
2459
+ * _.isObjectLike(null);
2460
+ * // => false
2461
+ */
2462
+ function isObjectLike(value) {
2463
+ return value != null && typeof value == 'object';
2464
+ }
2465
+
2466
+ /** `Object#toString` result references. */
2467
+ var symbolTag = '[object Symbol]';
2468
+
2469
+ /**
2470
+ * Checks if `value` is classified as a `Symbol` primitive or object.
2471
+ *
2472
+ * @static
2473
+ * @memberOf _
2474
+ * @since 4.0.0
2475
+ * @category Lang
2476
+ * @param {*} value The value to check.
2477
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
2478
+ * @example
2479
+ *
2480
+ * _.isSymbol(Symbol.iterator);
2481
+ * // => true
2482
+ *
2483
+ * _.isSymbol('abc');
2484
+ * // => false
2485
+ */
2486
+ function isSymbol(value) {
2487
+ return typeof value == 'symbol' ||
2488
+ (isObjectLike(value) && baseGetTag(value) == symbolTag);
2489
+ }
2490
+
2491
+ /**
2492
+ * A specialized version of `_.map` for arrays without support for iteratee
2493
+ * shorthands.
2494
+ *
2495
+ * @private
2496
+ * @param {Array} [array] The array to iterate over.
2497
+ * @param {Function} iteratee The function invoked per iteration.
2498
+ * @returns {Array} Returns the new mapped array.
2499
+ */
2500
+ function arrayMap(array, iteratee) {
2501
+ var index = -1,
2502
+ length = array == null ? 0 : array.length,
2503
+ result = Array(length);
2504
+
2505
+ while (++index < length) {
2506
+ result[index] = iteratee(array[index], index, array);
2507
+ }
2508
+ return result;
2509
+ }
2510
+
2511
+ /**
2512
+ * Checks if `value` is classified as an `Array` object.
2513
+ *
2514
+ * @static
2515
+ * @memberOf _
2516
+ * @since 0.1.0
2517
+ * @category Lang
2518
+ * @param {*} value The value to check.
2519
+ * @returns {boolean} Returns `true` if `value` is an array, else `false`.
2520
+ * @example
2521
+ *
2522
+ * _.isArray([1, 2, 3]);
2523
+ * // => true
2524
+ *
2525
+ * _.isArray(document.body.children);
2526
+ * // => false
2527
+ *
2528
+ * _.isArray('abc');
2529
+ * // => false
2530
+ *
2531
+ * _.isArray(_.noop);
2532
+ * // => false
2533
+ */
2534
+ var isArray = Array.isArray;
2535
+
2536
+ /** Used to convert symbols to primitives and strings. */
2537
+ var symbolProto = Symbol ? Symbol.prototype : undefined,
2538
+ symbolToString = symbolProto ? symbolProto.toString : undefined;
2539
+
2540
+ /**
2541
+ * The base implementation of `_.toString` which doesn't convert nullish
2542
+ * values to empty strings.
2543
+ *
2544
+ * @private
2545
+ * @param {*} value The value to process.
2546
+ * @returns {string} Returns the string.
2547
+ */
2548
+ function baseToString(value) {
2549
+ // Exit early for strings to avoid a performance hit in some environments.
2550
+ if (typeof value == 'string') {
2551
+ return value;
2552
+ }
2553
+ if (isArray(value)) {
2554
+ // Recursively convert values (susceptible to call stack limits).
2555
+ return arrayMap(value, baseToString) + '';
2556
+ }
2557
+ if (isSymbol(value)) {
2558
+ return symbolToString ? symbolToString.call(value) : '';
2559
+ }
2560
+ var result = (value + '');
2561
+ return (result == '0' && (1 / value) == -Infinity) ? '-0' : result;
2562
+ }
2563
+
2564
+ /** Used to match a single whitespace character. */
2565
+ var reWhitespace = /\s/;
2566
+
2567
+ /**
2568
+ * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
2569
+ * character of `string`.
2570
+ *
2571
+ * @private
2572
+ * @param {string} string The string to inspect.
2573
+ * @returns {number} Returns the index of the last non-whitespace character.
2574
+ */
2575
+ function trimmedEndIndex(string) {
2576
+ var index = string.length;
2577
+
2578
+ while (index-- && reWhitespace.test(string.charAt(index))) {}
2579
+ return index;
2580
+ }
2581
+
2582
+ /** Used to match leading whitespace. */
2583
+ var reTrimStart = /^\s+/;
2584
+
2585
+ /**
2586
+ * The base implementation of `_.trim`.
2587
+ *
2588
+ * @private
2589
+ * @param {string} string The string to trim.
2590
+ * @returns {string} Returns the trimmed string.
2591
+ */
2592
+ function baseTrim(string) {
2593
+ return string
2594
+ ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
2595
+ : string;
2596
+ }
2597
+
2598
+ /**
2599
+ * Checks if `value` is the
2600
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
2601
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
2602
+ *
2603
+ * @static
2604
+ * @memberOf _
2605
+ * @since 0.1.0
2606
+ * @category Lang
2607
+ * @param {*} value The value to check.
2608
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
2609
+ * @example
2610
+ *
2611
+ * _.isObject({});
2612
+ * // => true
2613
+ *
2614
+ * _.isObject([1, 2, 3]);
2615
+ * // => true
2616
+ *
2617
+ * _.isObject(_.noop);
2618
+ * // => true
2619
+ *
2620
+ * _.isObject(null);
2621
+ * // => false
2622
+ */
2623
+ function isObject(value) {
2624
+ var type = typeof value;
2625
+ return value != null && (type == 'object' || type == 'function');
2626
+ }
2627
+
2628
+ /** Used as references for various `Number` constants. */
2629
+ var NAN = 0 / 0;
2630
+
2631
+ /** Used to detect bad signed hexadecimal string values. */
2632
+ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
2633
+
2634
+ /** Used to detect binary string values. */
2635
+ var reIsBinary = /^0b[01]+$/i;
2636
+
2637
+ /** Used to detect octal string values. */
2638
+ var reIsOctal = /^0o[0-7]+$/i;
2639
+
2640
+ /** Built-in method references without a dependency on `root`. */
2641
+ var freeParseInt = parseInt;
2642
+
2643
+ /**
2644
+ * Converts `value` to a number.
2645
+ *
2646
+ * @static
2647
+ * @memberOf _
2648
+ * @since 4.0.0
2649
+ * @category Lang
2650
+ * @param {*} value The value to process.
2651
+ * @returns {number} Returns the number.
2652
+ * @example
2653
+ *
2654
+ * _.toNumber(3.2);
2655
+ * // => 3.2
2656
+ *
2657
+ * _.toNumber(Number.MIN_VALUE);
2658
+ * // => 5e-324
2659
+ *
2660
+ * _.toNumber(Infinity);
2661
+ * // => Infinity
2662
+ *
2663
+ * _.toNumber('3.2');
2664
+ * // => 3.2
2665
+ */
2666
+ function toNumber(value) {
2667
+ if (typeof value == 'number') {
2668
+ return value;
2669
+ }
2670
+ if (isSymbol(value)) {
2671
+ return NAN;
2672
+ }
2673
+ if (isObject(value)) {
2674
+ var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
2675
+ value = isObject(other) ? (other + '') : other;
2676
+ }
2677
+ if (typeof value != 'string') {
2678
+ return value === 0 ? value : +value;
2679
+ }
2680
+ value = baseTrim(value);
2681
+ var isBinary = reIsBinary.test(value);
2682
+ return (isBinary || reIsOctal.test(value))
2683
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
2684
+ : (reIsBadHex.test(value) ? NAN : +value);
2685
+ }
2686
+
2687
+ /** Used as references for various `Number` constants. */
2688
+ var INFINITY = 1 / 0,
2689
+ MAX_INTEGER = 1.7976931348623157e+308;
2690
+
2691
+ /**
2692
+ * Converts `value` to a finite number.
2693
+ *
2694
+ * @static
2695
+ * @memberOf _
2696
+ * @since 4.12.0
2697
+ * @category Lang
2698
+ * @param {*} value The value to convert.
2699
+ * @returns {number} Returns the converted number.
2700
+ * @example
2701
+ *
2702
+ * _.toFinite(3.2);
2703
+ * // => 3.2
2704
+ *
2705
+ * _.toFinite(Number.MIN_VALUE);
2706
+ * // => 5e-324
2707
+ *
2708
+ * _.toFinite(Infinity);
2709
+ * // => 1.7976931348623157e+308
2710
+ *
2711
+ * _.toFinite('3.2');
2712
+ * // => 3.2
2713
+ */
2714
+ function toFinite(value) {
2715
+ if (!value) {
2716
+ return value === 0 ? value : 0;
2717
+ }
2718
+ value = toNumber(value);
2719
+ if (value === INFINITY || value === -INFINITY) {
2720
+ var sign = (value < 0 ? -1 : 1);
2721
+ return sign * MAX_INTEGER;
2722
+ }
2723
+ return value === value ? value : 0;
2724
+ }
2725
+
2726
+ /**
2727
+ * Converts `value` to an integer.
2728
+ *
2729
+ * **Note:** This method is loosely based on
2730
+ * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
2731
+ *
2732
+ * @static
2733
+ * @memberOf _
2734
+ * @since 4.0.0
2735
+ * @category Lang
2736
+ * @param {*} value The value to convert.
2737
+ * @returns {number} Returns the converted integer.
2738
+ * @example
2739
+ *
2740
+ * _.toInteger(3.2);
2741
+ * // => 3
2742
+ *
2743
+ * _.toInteger(Number.MIN_VALUE);
2744
+ * // => 0
2745
+ *
2746
+ * _.toInteger(Infinity);
2747
+ * // => 1.7976931348623157e+308
2748
+ *
2749
+ * _.toInteger('3.2');
2750
+ * // => 3
2751
+ */
2752
+ function toInteger(value) {
2753
+ var result = toFinite(value),
2754
+ remainder = result % 1;
2755
+
2756
+ return result === result ? (remainder ? result - remainder : result) : 0;
2757
+ }
2758
+
2759
+ /**
2760
+ * This method returns the first argument it receives.
2761
+ *
2762
+ * @static
2763
+ * @since 0.1.0
2764
+ * @memberOf _
2765
+ * @category Util
2766
+ * @param {*} value Any value.
2767
+ * @returns {*} Returns `value`.
2768
+ * @example
2769
+ *
2770
+ * var object = { 'a': 1 };
2771
+ *
2772
+ * console.log(_.identity(object) === object);
2773
+ * // => true
2774
+ */
2775
+ function identity(value) {
2776
+ return value;
2777
+ }
2778
+
2779
+ /** `Object#toString` result references. */
2780
+ var asyncTag = '[object AsyncFunction]',
2781
+ funcTag$1 = '[object Function]',
2782
+ genTag = '[object GeneratorFunction]',
2783
+ proxyTag = '[object Proxy]';
2784
+
2785
+ /**
2786
+ * Checks if `value` is classified as a `Function` object.
2787
+ *
2788
+ * @static
2789
+ * @memberOf _
2790
+ * @since 0.1.0
2791
+ * @category Lang
2792
+ * @param {*} value The value to check.
2793
+ * @returns {boolean} Returns `true` if `value` is a function, else `false`.
2794
+ * @example
2795
+ *
2796
+ * _.isFunction(_);
2797
+ * // => true
2798
+ *
2799
+ * _.isFunction(/abc/);
2800
+ * // => false
2801
+ */
2802
+ function isFunction(value) {
2803
+ if (!isObject(value)) {
2804
+ return false;
2805
+ }
2806
+ // The use of `Object#toString` avoids issues with the `typeof` operator
2807
+ // in Safari 9 which returns 'object' for typed arrays and other constructors.
2808
+ var tag = baseGetTag(value);
2809
+ return tag == funcTag$1 || tag == genTag || tag == asyncTag || tag == proxyTag;
2810
+ }
2811
+
2812
+ /** Used to detect overreaching core-js shims. */
2813
+ var coreJsData = root['__core-js_shared__'];
2814
+
2815
+ /** Used to detect methods masquerading as native. */
2816
+ var maskSrcKey = (function() {
2817
+ var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
2818
+ return uid ? ('Symbol(src)_1.' + uid) : '';
2819
+ }());
2820
+
2821
+ /**
2822
+ * Checks if `func` has its source masked.
2823
+ *
2824
+ * @private
2825
+ * @param {Function} func The function to check.
2826
+ * @returns {boolean} Returns `true` if `func` is masked, else `false`.
2827
+ */
2828
+ function isMasked(func) {
2829
+ return !!maskSrcKey && (maskSrcKey in func);
2830
+ }
2831
+
2832
+ /** Used for built-in method references. */
2833
+ var funcProto$2 = Function.prototype;
2834
+
2835
+ /** Used to resolve the decompiled source of functions. */
2836
+ var funcToString$2 = funcProto$2.toString;
2837
+
2838
+ /**
2839
+ * Converts `func` to its source code.
2840
+ *
2841
+ * @private
2842
+ * @param {Function} func The function to convert.
2843
+ * @returns {string} Returns the source code.
2844
+ */
2845
+ function toSource(func) {
2846
+ if (func != null) {
2847
+ try {
2848
+ return funcToString$2.call(func);
2849
+ } catch (e) {}
2850
+ try {
2851
+ return (func + '');
2852
+ } catch (e) {}
2853
+ }
2854
+ return '';
2855
+ }
2856
+
2857
+ /**
2858
+ * Used to match `RegExp`
2859
+ * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
2860
+ */
2861
+ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
2862
+
2863
+ /** Used to detect host constructors (Safari). */
2864
+ var reIsHostCtor = /^\[object .+?Constructor\]$/;
2865
+
2866
+ /** Used for built-in method references. */
2867
+ var funcProto$1 = Function.prototype,
2868
+ objectProto$7 = Object.prototype;
2869
+
2870
+ /** Used to resolve the decompiled source of functions. */
2871
+ var funcToString$1 = funcProto$1.toString;
2872
+
2873
+ /** Used to check objects for own properties. */
2874
+ var hasOwnProperty$6 = objectProto$7.hasOwnProperty;
2875
+
2876
+ /** Used to detect if a method is native. */
2877
+ var reIsNative = RegExp('^' +
2878
+ funcToString$1.call(hasOwnProperty$6).replace(reRegExpChar, '\\$&')
2879
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
2880
+ );
2881
+
2882
+ /**
2883
+ * The base implementation of `_.isNative` without bad shim checks.
2884
+ *
2885
+ * @private
2886
+ * @param {*} value The value to check.
2887
+ * @returns {boolean} Returns `true` if `value` is a native function,
2888
+ * else `false`.
2889
+ */
2890
+ function baseIsNative(value) {
2891
+ if (!isObject(value) || isMasked(value)) {
2892
+ return false;
2893
+ }
2894
+ var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
2895
+ return pattern.test(toSource(value));
2896
+ }
2897
+
2898
+ /**
2899
+ * Gets the value at `key` of `object`.
2900
+ *
2901
+ * @private
2902
+ * @param {Object} [object] The object to query.
2903
+ * @param {string} key The key of the property to get.
2904
+ * @returns {*} Returns the property value.
2905
+ */
2906
+ function getValue(object, key) {
2907
+ return object == null ? undefined : object[key];
2908
+ }
2909
+
2910
+ /**
2911
+ * Gets the native function at `key` of `object`.
2912
+ *
2913
+ * @private
2914
+ * @param {Object} object The object to query.
2915
+ * @param {string} key The key of the method to get.
2916
+ * @returns {*} Returns the function if it's native, else `undefined`.
2917
+ */
2918
+ function getNative(object, key) {
2919
+ var value = getValue(object, key);
2920
+ return baseIsNative(value) ? value : undefined;
2921
+ }
2922
+
2923
+ /** Built-in value references. */
2924
+ var objectCreate = Object.create;
2925
+
2926
+ /**
2927
+ * The base implementation of `_.create` without support for assigning
2928
+ * properties to the created object.
2929
+ *
2930
+ * @private
2931
+ * @param {Object} proto The object to inherit from.
2932
+ * @returns {Object} Returns the new object.
2933
+ */
2934
+ var baseCreate = (function() {
2935
+ function object() {}
2936
+ return function(proto) {
2937
+ if (!isObject(proto)) {
2938
+ return {};
2939
+ }
2940
+ if (objectCreate) {
2941
+ return objectCreate(proto);
2942
+ }
2943
+ object.prototype = proto;
2944
+ var result = new object;
2945
+ object.prototype = undefined;
2946
+ return result;
2947
+ };
2948
+ }());
2949
+
2950
+ /**
2951
+ * A faster alternative to `Function#apply`, this function invokes `func`
2952
+ * with the `this` binding of `thisArg` and the arguments of `args`.
2953
+ *
2954
+ * @private
2955
+ * @param {Function} func The function to invoke.
2956
+ * @param {*} thisArg The `this` binding of `func`.
2957
+ * @param {Array} args The arguments to invoke `func` with.
2958
+ * @returns {*} Returns the result of `func`.
2959
+ */
2960
+ function apply(func, thisArg, args) {
2961
+ switch (args.length) {
2962
+ case 0: return func.call(thisArg);
2963
+ case 1: return func.call(thisArg, args[0]);
2964
+ case 2: return func.call(thisArg, args[0], args[1]);
2965
+ case 3: return func.call(thisArg, args[0], args[1], args[2]);
2966
+ }
2967
+ return func.apply(thisArg, args);
2968
+ }
2969
+
2970
+ /**
2971
+ * Copies the values of `source` to `array`.
2972
+ *
2973
+ * @private
2974
+ * @param {Array} source The array to copy values from.
2975
+ * @param {Array} [array=[]] The array to copy values to.
2976
+ * @returns {Array} Returns `array`.
2977
+ */
2978
+ function copyArray(source, array) {
2979
+ var index = -1,
2980
+ length = source.length;
2981
+
2982
+ array || (array = Array(length));
2983
+ while (++index < length) {
2984
+ array[index] = source[index];
2985
+ }
2986
+ return array;
2987
+ }
2988
+
2989
+ /** Used to detect hot functions by number of calls within a span of milliseconds. */
2990
+ var HOT_COUNT = 800,
2991
+ HOT_SPAN = 16;
2992
+
2993
+ /* Built-in method references for those with the same name as other `lodash` methods. */
2994
+ var nativeNow = Date.now;
2995
+
2996
+ /**
2997
+ * Creates a function that'll short out and invoke `identity` instead
2998
+ * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
2999
+ * milliseconds.
3000
+ *
3001
+ * @private
3002
+ * @param {Function} func The function to restrict.
3003
+ * @returns {Function} Returns the new shortable function.
3004
+ */
3005
+ function shortOut(func) {
3006
+ var count = 0,
3007
+ lastCalled = 0;
3008
+
3009
+ return function() {
3010
+ var stamp = nativeNow(),
3011
+ remaining = HOT_SPAN - (stamp - lastCalled);
3012
+
3013
+ lastCalled = stamp;
3014
+ if (remaining > 0) {
3015
+ if (++count >= HOT_COUNT) {
3016
+ return arguments[0];
3017
+ }
3018
+ } else {
3019
+ count = 0;
3020
+ }
3021
+ return func.apply(undefined, arguments);
3022
+ };
3023
+ }
3024
+
3025
+ /**
3026
+ * Creates a function that returns `value`.
3027
+ *
3028
+ * @static
3029
+ * @memberOf _
3030
+ * @since 2.4.0
3031
+ * @category Util
3032
+ * @param {*} value The value to return from the new function.
3033
+ * @returns {Function} Returns the new constant function.
3034
+ * @example
3035
+ *
3036
+ * var objects = _.times(2, _.constant({ 'a': 1 }));
3037
+ *
3038
+ * console.log(objects);
3039
+ * // => [{ 'a': 1 }, { 'a': 1 }]
3040
+ *
3041
+ * console.log(objects[0] === objects[1]);
3042
+ * // => true
3043
+ */
3044
+ function constant(value) {
3045
+ return function() {
3046
+ return value;
3047
+ };
3048
+ }
3049
+
3050
+ var defineProperty = (function() {
3051
+ try {
3052
+ var func = getNative(Object, 'defineProperty');
3053
+ func({}, '', {});
3054
+ return func;
3055
+ } catch (e) {}
3056
+ }());
3057
+
3058
+ /**
3059
+ * The base implementation of `setToString` without support for hot loop shorting.
3060
+ *
3061
+ * @private
3062
+ * @param {Function} func The function to modify.
3063
+ * @param {Function} string The `toString` result.
3064
+ * @returns {Function} Returns `func`.
3065
+ */
3066
+ var baseSetToString = !defineProperty ? identity : function(func, string) {
3067
+ return defineProperty(func, 'toString', {
3068
+ 'configurable': true,
3069
+ 'enumerable': false,
3070
+ 'value': constant(string),
3071
+ 'writable': true
3072
+ });
3073
+ };
3074
+
3075
+ /**
3076
+ * Sets the `toString` method of `func` to return `string`.
3077
+ *
3078
+ * @private
3079
+ * @param {Function} func The function to modify.
3080
+ * @param {Function} string The `toString` result.
3081
+ * @returns {Function} Returns `func`.
3082
+ */
3083
+ var setToString = shortOut(baseSetToString);
3084
+
3085
+ /** Used as references for various `Number` constants. */
3086
+ var MAX_SAFE_INTEGER$1 = 9007199254740991;
3087
+
3088
+ /** Used to detect unsigned integer values. */
3089
+ var reIsUint = /^(?:0|[1-9]\d*)$/;
3090
+
3091
+ /**
3092
+ * Checks if `value` is a valid array-like index.
3093
+ *
3094
+ * @private
3095
+ * @param {*} value The value to check.
3096
+ * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
3097
+ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
3098
+ */
3099
+ function isIndex(value, length) {
3100
+ var type = typeof value;
3101
+ length = length == null ? MAX_SAFE_INTEGER$1 : length;
3102
+
3103
+ return !!length &&
3104
+ (type == 'number' ||
3105
+ (type != 'symbol' && reIsUint.test(value))) &&
3106
+ (value > -1 && value % 1 == 0 && value < length);
3107
+ }
3108
+
3109
+ /**
3110
+ * The base implementation of `assignValue` and `assignMergeValue` without
3111
+ * value checks.
3112
+ *
3113
+ * @private
3114
+ * @param {Object} object The object to modify.
3115
+ * @param {string} key The key of the property to assign.
3116
+ * @param {*} value The value to assign.
3117
+ */
3118
+ function baseAssignValue(object, key, value) {
3119
+ if (key == '__proto__' && defineProperty) {
3120
+ defineProperty(object, key, {
3121
+ 'configurable': true,
3122
+ 'enumerable': true,
3123
+ 'value': value,
3124
+ 'writable': true
3125
+ });
3126
+ } else {
3127
+ object[key] = value;
3128
+ }
3129
+ }
3130
+
3131
+ /**
3132
+ * Performs a
3133
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
3134
+ * comparison between two values to determine if they are equivalent.
3135
+ *
3136
+ * @static
3137
+ * @memberOf _
3138
+ * @since 4.0.0
3139
+ * @category Lang
3140
+ * @param {*} value The value to compare.
3141
+ * @param {*} other The other value to compare.
3142
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
3143
+ * @example
3144
+ *
3145
+ * var object = { 'a': 1 };
3146
+ * var other = { 'a': 1 };
3147
+ *
3148
+ * _.eq(object, object);
3149
+ * // => true
3150
+ *
3151
+ * _.eq(object, other);
3152
+ * // => false
3153
+ *
3154
+ * _.eq('a', 'a');
3155
+ * // => true
3156
+ *
3157
+ * _.eq('a', Object('a'));
3158
+ * // => false
3159
+ *
3160
+ * _.eq(NaN, NaN);
3161
+ * // => true
3162
+ */
3163
+ function eq(value, other) {
3164
+ return value === other || (value !== value && other !== other);
3165
+ }
3166
+
3167
+ /** Used for built-in method references. */
3168
+ var objectProto$6 = Object.prototype;
3169
+
3170
+ /** Used to check objects for own properties. */
3171
+ var hasOwnProperty$5 = objectProto$6.hasOwnProperty;
3172
+
3173
+ /**
3174
+ * Assigns `value` to `key` of `object` if the existing value is not equivalent
3175
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
3176
+ * for equality comparisons.
3177
+ *
3178
+ * @private
3179
+ * @param {Object} object The object to modify.
3180
+ * @param {string} key The key of the property to assign.
3181
+ * @param {*} value The value to assign.
3182
+ */
3183
+ function assignValue(object, key, value) {
3184
+ var objValue = object[key];
3185
+ if (!(hasOwnProperty$5.call(object, key) && eq(objValue, value)) ||
3186
+ (value === undefined && !(key in object))) {
3187
+ baseAssignValue(object, key, value);
3188
+ }
3189
+ }
3190
+
3191
+ /**
3192
+ * Copies properties of `source` to `object`.
3193
+ *
3194
+ * @private
3195
+ * @param {Object} source The object to copy properties from.
3196
+ * @param {Array} props The property identifiers to copy.
3197
+ * @param {Object} [object={}] The object to copy properties to.
3198
+ * @param {Function} [customizer] The function to customize copied values.
3199
+ * @returns {Object} Returns `object`.
3200
+ */
3201
+ function copyObject(source, props, object, customizer) {
3202
+ var isNew = !object;
3203
+ object || (object = {});
3204
+
3205
+ var index = -1,
3206
+ length = props.length;
3207
+
3208
+ while (++index < length) {
3209
+ var key = props[index];
3210
+
3211
+ var newValue = undefined;
3212
+
3213
+ if (newValue === undefined) {
3214
+ newValue = source[key];
3215
+ }
3216
+ if (isNew) {
3217
+ baseAssignValue(object, key, newValue);
3218
+ } else {
3219
+ assignValue(object, key, newValue);
3220
+ }
3221
+ }
3222
+ return object;
3223
+ }
3224
+
3225
+ /* Built-in method references for those with the same name as other `lodash` methods. */
3226
+ var nativeMax = Math.max;
3227
+
3228
+ /**
3229
+ * A specialized version of `baseRest` which transforms the rest array.
3230
+ *
3231
+ * @private
3232
+ * @param {Function} func The function to apply a rest parameter to.
3233
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
3234
+ * @param {Function} transform The rest array transform.
3235
+ * @returns {Function} Returns the new function.
3236
+ */
3237
+ function overRest(func, start, transform) {
3238
+ start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
3239
+ return function() {
3240
+ var args = arguments,
3241
+ index = -1,
3242
+ length = nativeMax(args.length - start, 0),
3243
+ array = Array(length);
3244
+
3245
+ while (++index < length) {
3246
+ array[index] = args[start + index];
3247
+ }
3248
+ index = -1;
3249
+ var otherArgs = Array(start + 1);
3250
+ while (++index < start) {
3251
+ otherArgs[index] = args[index];
3252
+ }
3253
+ otherArgs[start] = transform(array);
3254
+ return apply(func, this, otherArgs);
3255
+ };
3256
+ }
3257
+
3258
+ /**
3259
+ * The base implementation of `_.rest` which doesn't validate or coerce arguments.
3260
+ *
3261
+ * @private
3262
+ * @param {Function} func The function to apply a rest parameter to.
3263
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
3264
+ * @returns {Function} Returns the new function.
3265
+ */
3266
+ function baseRest(func, start) {
3267
+ return setToString(overRest(func, start, identity), func + '');
3268
+ }
3269
+
3270
+ /** Used as references for various `Number` constants. */
3271
+ var MAX_SAFE_INTEGER = 9007199254740991;
3272
+
3273
+ /**
3274
+ * Checks if `value` is a valid array-like length.
3275
+ *
3276
+ * **Note:** This method is loosely based on
3277
+ * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
3278
+ *
3279
+ * @static
3280
+ * @memberOf _
3281
+ * @since 4.0.0
3282
+ * @category Lang
3283
+ * @param {*} value The value to check.
3284
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
3285
+ * @example
3286
+ *
3287
+ * _.isLength(3);
3288
+ * // => true
3289
+ *
3290
+ * _.isLength(Number.MIN_VALUE);
3291
+ * // => false
3292
+ *
3293
+ * _.isLength(Infinity);
3294
+ * // => false
3295
+ *
3296
+ * _.isLength('3');
3297
+ * // => false
3298
+ */
3299
+ function isLength(value) {
3300
+ return typeof value == 'number' &&
3301
+ value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
3302
+ }
3303
+
3304
+ /**
3305
+ * Checks if `value` is array-like. A value is considered array-like if it's
3306
+ * not a function and has a `value.length` that's an integer greater than or
3307
+ * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
3308
+ *
3309
+ * @static
3310
+ * @memberOf _
3311
+ * @since 4.0.0
3312
+ * @category Lang
3313
+ * @param {*} value The value to check.
3314
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
3315
+ * @example
3316
+ *
3317
+ * _.isArrayLike([1, 2, 3]);
3318
+ * // => true
3319
+ *
3320
+ * _.isArrayLike(document.body.children);
3321
+ * // => true
3322
+ *
3323
+ * _.isArrayLike('abc');
3324
+ * // => true
3325
+ *
3326
+ * _.isArrayLike(_.noop);
3327
+ * // => false
3328
+ */
3329
+ function isArrayLike(value) {
3330
+ return value != null && isLength(value.length) && !isFunction(value);
3331
+ }
3332
+
3333
+ /**
3334
+ * Checks if the given arguments are from an iteratee call.
3335
+ *
3336
+ * @private
3337
+ * @param {*} value The potential iteratee value argument.
3338
+ * @param {*} index The potential iteratee index or key argument.
3339
+ * @param {*} object The potential iteratee object argument.
3340
+ * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
3341
+ * else `false`.
3342
+ */
3343
+ function isIterateeCall(value, index, object) {
3344
+ if (!isObject(object)) {
3345
+ return false;
3346
+ }
3347
+ var type = typeof index;
3348
+ if (type == 'number'
3349
+ ? (isArrayLike(object) && isIndex(index, object.length))
3350
+ : (type == 'string' && index in object)
3351
+ ) {
3352
+ return eq(object[index], value);
3353
+ }
3354
+ return false;
3355
+ }
3356
+
3357
+ /**
3358
+ * Creates a function like `_.assign`.
3359
+ *
3360
+ * @private
3361
+ * @param {Function} assigner The function to assign values.
3362
+ * @returns {Function} Returns the new assigner function.
3363
+ */
3364
+ function createAssigner(assigner) {
3365
+ return baseRest(function(object, sources) {
3366
+ var index = -1,
3367
+ length = sources.length,
3368
+ customizer = length > 1 ? sources[length - 1] : undefined,
3369
+ guard = length > 2 ? sources[2] : undefined;
3370
+
3371
+ customizer = (assigner.length > 3 && typeof customizer == 'function')
3372
+ ? (length--, customizer)
3373
+ : undefined;
3374
+
3375
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
3376
+ customizer = length < 3 ? undefined : customizer;
3377
+ length = 1;
3378
+ }
3379
+ object = Object(object);
3380
+ while (++index < length) {
3381
+ var source = sources[index];
3382
+ if (source) {
3383
+ assigner(object, source, index, customizer);
3384
+ }
3385
+ }
3386
+ return object;
3387
+ });
3388
+ }
3389
+
3390
+ /** Used for built-in method references. */
3391
+ var objectProto$5 = Object.prototype;
3392
+
3393
+ /**
3394
+ * Checks if `value` is likely a prototype object.
3395
+ *
3396
+ * @private
3397
+ * @param {*} value The value to check.
3398
+ * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
3399
+ */
3400
+ function isPrototype(value) {
3401
+ var Ctor = value && value.constructor,
3402
+ proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$5;
3403
+
3404
+ return value === proto;
3405
+ }
3406
+
3407
+ /**
3408
+ * The base implementation of `_.times` without support for iteratee shorthands
3409
+ * or max array length checks.
3410
+ *
3411
+ * @private
3412
+ * @param {number} n The number of times to invoke `iteratee`.
3413
+ * @param {Function} iteratee The function invoked per iteration.
3414
+ * @returns {Array} Returns the array of results.
3415
+ */
3416
+ function baseTimes(n, iteratee) {
3417
+ var index = -1,
3418
+ result = Array(n);
3419
+
3420
+ while (++index < n) {
3421
+ result[index] = iteratee(index);
3422
+ }
3423
+ return result;
3424
+ }
3425
+
3426
+ /** `Object#toString` result references. */
3427
+ var argsTag$1 = '[object Arguments]';
3428
+
3429
+ /**
3430
+ * The base implementation of `_.isArguments`.
3431
+ *
3432
+ * @private
3433
+ * @param {*} value The value to check.
3434
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
3435
+ */
3436
+ function baseIsArguments(value) {
3437
+ return isObjectLike(value) && baseGetTag(value) == argsTag$1;
3438
+ }
3439
+
3440
+ /** Used for built-in method references. */
3441
+ var objectProto$4 = Object.prototype;
3442
+
3443
+ /** Used to check objects for own properties. */
3444
+ var hasOwnProperty$4 = objectProto$4.hasOwnProperty;
3445
+
3446
+ /** Built-in value references. */
3447
+ var propertyIsEnumerable = objectProto$4.propertyIsEnumerable;
3448
+
3449
+ /**
3450
+ * Checks if `value` is likely an `arguments` object.
3451
+ *
3452
+ * @static
3453
+ * @memberOf _
3454
+ * @since 0.1.0
3455
+ * @category Lang
3456
+ * @param {*} value The value to check.
3457
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
3458
+ * else `false`.
3459
+ * @example
3460
+ *
3461
+ * _.isArguments(function() { return arguments; }());
3462
+ * // => true
3463
+ *
3464
+ * _.isArguments([1, 2, 3]);
3465
+ * // => false
3466
+ */
3467
+ var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
3468
+ return isObjectLike(value) && hasOwnProperty$4.call(value, 'callee') &&
3469
+ !propertyIsEnumerable.call(value, 'callee');
3470
+ };
3471
+
3472
+ /**
3473
+ * This method returns `false`.
3474
+ *
3475
+ * @static
3476
+ * @memberOf _
3477
+ * @since 4.13.0
3478
+ * @category Util
3479
+ * @returns {boolean} Returns `false`.
3480
+ * @example
3481
+ *
3482
+ * _.times(2, _.stubFalse);
3483
+ * // => [false, false]
3484
+ */
3485
+ function stubFalse() {
3486
+ return false;
3487
+ }
3488
+
3489
+ /** Detect free variable `exports`. */
3490
+ var freeExports$2 = typeof exports == 'object' && exports && !exports.nodeType && exports;
3491
+
3492
+ /** Detect free variable `module`. */
3493
+ var freeModule$2 = freeExports$2 && typeof module == 'object' && module && !module.nodeType && module;
3494
+
3495
+ /** Detect the popular CommonJS extension `module.exports`. */
3496
+ var moduleExports$2 = freeModule$2 && freeModule$2.exports === freeExports$2;
3497
+
3498
+ /** Built-in value references. */
3499
+ var Buffer$1 = moduleExports$2 ? root.Buffer : undefined;
3500
+
3501
+ /* Built-in method references for those with the same name as other `lodash` methods. */
3502
+ var nativeIsBuffer = Buffer$1 ? Buffer$1.isBuffer : undefined;
3503
+
3504
+ /**
3505
+ * Checks if `value` is a buffer.
3506
+ *
3507
+ * @static
3508
+ * @memberOf _
3509
+ * @since 4.3.0
3510
+ * @category Lang
3511
+ * @param {*} value The value to check.
3512
+ * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
3513
+ * @example
3514
+ *
3515
+ * _.isBuffer(new Buffer(2));
3516
+ * // => true
3517
+ *
3518
+ * _.isBuffer(new Uint8Array(2));
3519
+ * // => false
3520
+ */
3521
+ var isBuffer = nativeIsBuffer || stubFalse;
3522
+
3523
+ /** `Object#toString` result references. */
3524
+ var argsTag = '[object Arguments]',
3525
+ arrayTag = '[object Array]',
3526
+ boolTag = '[object Boolean]',
3527
+ dateTag = '[object Date]',
3528
+ errorTag = '[object Error]',
3529
+ funcTag = '[object Function]',
3530
+ mapTag = '[object Map]',
3531
+ numberTag = '[object Number]',
3532
+ objectTag$1 = '[object Object]',
3533
+ regexpTag = '[object RegExp]',
3534
+ setTag = '[object Set]',
3535
+ stringTag = '[object String]',
3536
+ weakMapTag = '[object WeakMap]';
3537
+
3538
+ var arrayBufferTag = '[object ArrayBuffer]',
3539
+ dataViewTag = '[object DataView]',
3540
+ float32Tag = '[object Float32Array]',
3541
+ float64Tag = '[object Float64Array]',
3542
+ int8Tag = '[object Int8Array]',
3543
+ int16Tag = '[object Int16Array]',
3544
+ int32Tag = '[object Int32Array]',
3545
+ uint8Tag = '[object Uint8Array]',
3546
+ uint8ClampedTag = '[object Uint8ClampedArray]',
3547
+ uint16Tag = '[object Uint16Array]',
3548
+ uint32Tag = '[object Uint32Array]';
3549
+
3550
+ /** Used to identify `toStringTag` values of typed arrays. */
3551
+ var typedArrayTags = {};
3552
+ typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
3553
+ typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
3554
+ typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
3555
+ typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
3556
+ typedArrayTags[uint32Tag] = true;
3557
+ typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
3558
+ typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
3559
+ typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
3560
+ typedArrayTags[errorTag] = typedArrayTags[funcTag] =
3561
+ typedArrayTags[mapTag] = typedArrayTags[numberTag] =
3562
+ typedArrayTags[objectTag$1] = typedArrayTags[regexpTag] =
3563
+ typedArrayTags[setTag] = typedArrayTags[stringTag] =
3564
+ typedArrayTags[weakMapTag] = false;
3565
+
3566
+ /**
3567
+ * The base implementation of `_.isTypedArray` without Node.js optimizations.
3568
+ *
3569
+ * @private
3570
+ * @param {*} value The value to check.
3571
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
3572
+ */
3573
+ function baseIsTypedArray(value) {
3574
+ return isObjectLike(value) &&
3575
+ isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
3576
+ }
3577
+
3578
+ /**
3579
+ * The base implementation of `_.unary` without support for storing metadata.
3580
+ *
3581
+ * @private
3582
+ * @param {Function} func The function to cap arguments for.
3583
+ * @returns {Function} Returns the new capped function.
3584
+ */
3585
+ function baseUnary(func) {
3586
+ return function(value) {
3587
+ return func(value);
3588
+ };
3589
+ }
3590
+
3591
+ /** Detect free variable `exports`. */
3592
+ var freeExports$1 = typeof exports == 'object' && exports && !exports.nodeType && exports;
3593
+
3594
+ /** Detect free variable `module`. */
3595
+ var freeModule$1 = freeExports$1 && typeof module == 'object' && module && !module.nodeType && module;
3596
+
3597
+ /** Detect the popular CommonJS extension `module.exports`. */
3598
+ var moduleExports$1 = freeModule$1 && freeModule$1.exports === freeExports$1;
3599
+
3600
+ /** Detect free variable `process` from Node.js. */
3601
+ var freeProcess = moduleExports$1 && freeGlobal.process;
3602
+
3603
+ /** Used to access faster Node.js helpers. */
3604
+ var nodeUtil = (function() {
3605
+ try {
3606
+ // Use `util.types` for Node.js 10+.
3607
+ var types = freeModule$1 && freeModule$1.require && freeModule$1.require('util').types;
3608
+
3609
+ if (types) {
3610
+ return types;
3611
+ }
3612
+
3613
+ // Legacy `process.binding('util')` for Node.js < 10.
3614
+ return freeProcess && freeProcess.binding && freeProcess.binding('util');
3615
+ } catch (e) {}
3616
+ }());
3617
+
3618
+ /* Node.js helper references. */
3619
+ var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
3620
+
3621
+ /**
3622
+ * Checks if `value` is classified as a typed array.
3623
+ *
3624
+ * @static
3625
+ * @memberOf _
3626
+ * @since 3.0.0
3627
+ * @category Lang
3628
+ * @param {*} value The value to check.
3629
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
3630
+ * @example
3631
+ *
3632
+ * _.isTypedArray(new Uint8Array);
3633
+ * // => true
3634
+ *
3635
+ * _.isTypedArray([]);
3636
+ * // => false
3637
+ */
3638
+ var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
3639
+
3640
+ /**
3641
+ * Creates an array of the enumerable property names of the array-like `value`.
3642
+ *
3643
+ * @private
3644
+ * @param {*} value The value to query.
3645
+ * @param {boolean} inherited Specify returning inherited property names.
3646
+ * @returns {Array} Returns the array of property names.
3647
+ */
3648
+ function arrayLikeKeys(value, inherited) {
3649
+ var isArr = isArray(value),
3650
+ isArg = !isArr && isArguments(value),
3651
+ isBuff = !isArr && !isArg && isBuffer(value),
3652
+ isType = !isArr && !isArg && !isBuff && isTypedArray(value),
3653
+ skipIndexes = isArr || isArg || isBuff || isType,
3654
+ result = skipIndexes ? baseTimes(value.length, String) : [],
3655
+ length = result.length;
3656
+
3657
+ for (var key in value) {
3658
+ if (!(skipIndexes && (
3659
+ // Safari 9 has enumerable `arguments.length` in strict mode.
3660
+ key == 'length' ||
3661
+ // Node.js 0.10 has enumerable non-index properties on buffers.
3662
+ (isBuff && (key == 'offset' || key == 'parent')) ||
3663
+ // PhantomJS 2 has enumerable non-index properties on typed arrays.
3664
+ (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
3665
+ // Skip index properties.
3666
+ isIndex(key, length)
3667
+ ))) {
3668
+ result.push(key);
3669
+ }
3670
+ }
3671
+ return result;
3672
+ }
3673
+
3674
+ /**
3675
+ * Creates a unary function that invokes `func` with its argument transformed.
3676
+ *
3677
+ * @private
3678
+ * @param {Function} func The function to wrap.
3679
+ * @param {Function} transform The argument transform.
3680
+ * @returns {Function} Returns the new function.
3681
+ */
3682
+ function overArg(func, transform) {
3683
+ return function(arg) {
3684
+ return func(transform(arg));
3685
+ };
3686
+ }
3687
+
3688
+ /**
3689
+ * This function is like
3690
+ * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
3691
+ * except that it includes inherited enumerable properties.
3692
+ *
3693
+ * @private
3694
+ * @param {Object} object The object to query.
3695
+ * @returns {Array} Returns the array of property names.
3696
+ */
3697
+ function nativeKeysIn(object) {
3698
+ var result = [];
3699
+ if (object != null) {
3700
+ for (var key in Object(object)) {
3701
+ result.push(key);
3702
+ }
3703
+ }
3704
+ return result;
3705
+ }
3706
+
3707
+ /** Used for built-in method references. */
3708
+ var objectProto$3 = Object.prototype;
3709
+
3710
+ /** Used to check objects for own properties. */
3711
+ var hasOwnProperty$3 = objectProto$3.hasOwnProperty;
3712
+
3713
+ /**
3714
+ * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
3715
+ *
3716
+ * @private
3717
+ * @param {Object} object The object to query.
3718
+ * @returns {Array} Returns the array of property names.
3719
+ */
3720
+ function baseKeysIn(object) {
3721
+ if (!isObject(object)) {
3722
+ return nativeKeysIn(object);
3723
+ }
3724
+ var isProto = isPrototype(object),
3725
+ result = [];
3726
+
3727
+ for (var key in object) {
3728
+ if (!(key == 'constructor' && (isProto || !hasOwnProperty$3.call(object, key)))) {
3729
+ result.push(key);
3730
+ }
3731
+ }
3732
+ return result;
3733
+ }
3734
+
3735
+ /**
3736
+ * Creates an array of the own and inherited enumerable property names of `object`.
3737
+ *
3738
+ * **Note:** Non-object values are coerced to objects.
3739
+ *
3740
+ * @static
3741
+ * @memberOf _
3742
+ * @since 3.0.0
3743
+ * @category Object
3744
+ * @param {Object} object The object to query.
3745
+ * @returns {Array} Returns the array of property names.
3746
+ * @example
3747
+ *
3748
+ * function Foo() {
3749
+ * this.a = 1;
3750
+ * this.b = 2;
3751
+ * }
3752
+ *
3753
+ * Foo.prototype.c = 3;
3754
+ *
3755
+ * _.keysIn(new Foo);
3756
+ * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
3757
+ */
3758
+ function keysIn(object) {
3759
+ return isArrayLike(object) ? arrayLikeKeys(object) : baseKeysIn(object);
3760
+ }
3761
+
3762
+ /* Built-in method references that are verified to be native. */
3763
+ var nativeCreate = getNative(Object, 'create');
3764
+
3765
+ /**
3766
+ * Removes all key-value entries from the hash.
3767
+ *
3768
+ * @private
3769
+ * @name clear
3770
+ * @memberOf Hash
3771
+ */
3772
+ function hashClear() {
3773
+ this.__data__ = nativeCreate ? nativeCreate(null) : {};
3774
+ this.size = 0;
3775
+ }
3776
+
3777
+ /**
3778
+ * Removes `key` and its value from the hash.
3779
+ *
3780
+ * @private
3781
+ * @name delete
3782
+ * @memberOf Hash
3783
+ * @param {Object} hash The hash to modify.
3784
+ * @param {string} key The key of the value to remove.
3785
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
3786
+ */
3787
+ function hashDelete(key) {
3788
+ var result = this.has(key) && delete this.__data__[key];
3789
+ this.size -= result ? 1 : 0;
3790
+ return result;
3791
+ }
3792
+
3793
+ /** Used to stand-in for `undefined` hash values. */
3794
+ var HASH_UNDEFINED$1 = '__lodash_hash_undefined__';
3795
+
3796
+ /** Used for built-in method references. */
3797
+ var objectProto$2 = Object.prototype;
3798
+
3799
+ /** Used to check objects for own properties. */
3800
+ var hasOwnProperty$2 = objectProto$2.hasOwnProperty;
3801
+
3802
+ /**
3803
+ * Gets the hash value for `key`.
3804
+ *
3805
+ * @private
3806
+ * @name get
3807
+ * @memberOf Hash
3808
+ * @param {string} key The key of the value to get.
3809
+ * @returns {*} Returns the entry value.
3810
+ */
3811
+ function hashGet(key) {
3812
+ var data = this.__data__;
3813
+ if (nativeCreate) {
3814
+ var result = data[key];
3815
+ return result === HASH_UNDEFINED$1 ? undefined : result;
3816
+ }
3817
+ return hasOwnProperty$2.call(data, key) ? data[key] : undefined;
3818
+ }
3819
+
3820
+ /** Used for built-in method references. */
3821
+ var objectProto$1 = Object.prototype;
3822
+
3823
+ /** Used to check objects for own properties. */
3824
+ var hasOwnProperty$1 = objectProto$1.hasOwnProperty;
3825
+
3826
+ /**
3827
+ * Checks if a hash value for `key` exists.
3828
+ *
3829
+ * @private
3830
+ * @name has
3831
+ * @memberOf Hash
3832
+ * @param {string} key The key of the entry to check.
3833
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
3834
+ */
3835
+ function hashHas(key) {
3836
+ var data = this.__data__;
3837
+ return nativeCreate ? (data[key] !== undefined) : hasOwnProperty$1.call(data, key);
3838
+ }
3839
+
3840
+ /** Used to stand-in for `undefined` hash values. */
3841
+ var HASH_UNDEFINED = '__lodash_hash_undefined__';
3842
+
3843
+ /**
3844
+ * Sets the hash `key` to `value`.
3845
+ *
3846
+ * @private
3847
+ * @name set
3848
+ * @memberOf Hash
3849
+ * @param {string} key The key of the value to set.
3850
+ * @param {*} value The value to set.
3851
+ * @returns {Object} Returns the hash instance.
3852
+ */
3853
+ function hashSet(key, value) {
3854
+ var data = this.__data__;
3855
+ this.size += this.has(key) ? 0 : 1;
3856
+ data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
3857
+ return this;
3858
+ }
3859
+
3860
+ /**
3861
+ * Creates a hash object.
3862
+ *
3863
+ * @private
3864
+ * @constructor
3865
+ * @param {Array} [entries] The key-value pairs to cache.
3866
+ */
3867
+ function Hash(entries) {
3868
+ var index = -1,
3869
+ length = entries == null ? 0 : entries.length;
3870
+
3871
+ this.clear();
3872
+ while (++index < length) {
3873
+ var entry = entries[index];
3874
+ this.set(entry[0], entry[1]);
3875
+ }
3876
+ }
3877
+
3878
+ // Add methods to `Hash`.
3879
+ Hash.prototype.clear = hashClear;
3880
+ Hash.prototype['delete'] = hashDelete;
3881
+ Hash.prototype.get = hashGet;
3882
+ Hash.prototype.has = hashHas;
3883
+ Hash.prototype.set = hashSet;
3884
+
3885
+ /**
3886
+ * Removes all key-value entries from the list cache.
3887
+ *
3888
+ * @private
3889
+ * @name clear
3890
+ * @memberOf ListCache
3891
+ */
3892
+ function listCacheClear() {
3893
+ this.__data__ = [];
3894
+ this.size = 0;
3895
+ }
3896
+
3897
+ /**
3898
+ * Gets the index at which the `key` is found in `array` of key-value pairs.
3899
+ *
3900
+ * @private
3901
+ * @param {Array} array The array to inspect.
3902
+ * @param {*} key The key to search for.
3903
+ * @returns {number} Returns the index of the matched value, else `-1`.
3904
+ */
3905
+ function assocIndexOf(array, key) {
3906
+ var length = array.length;
3907
+ while (length--) {
3908
+ if (eq(array[length][0], key)) {
3909
+ return length;
3910
+ }
3911
+ }
3912
+ return -1;
3913
+ }
3914
+
3915
+ /** Used for built-in method references. */
3916
+ var arrayProto = Array.prototype;
3917
+
3918
+ /** Built-in value references. */
3919
+ var splice = arrayProto.splice;
3920
+
3921
+ /**
3922
+ * Removes `key` and its value from the list cache.
3923
+ *
3924
+ * @private
3925
+ * @name delete
3926
+ * @memberOf ListCache
3927
+ * @param {string} key The key of the value to remove.
3928
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
3929
+ */
3930
+ function listCacheDelete(key) {
3931
+ var data = this.__data__,
3932
+ index = assocIndexOf(data, key);
3933
+
3934
+ if (index < 0) {
3935
+ return false;
3936
+ }
3937
+ var lastIndex = data.length - 1;
3938
+ if (index == lastIndex) {
3939
+ data.pop();
3940
+ } else {
3941
+ splice.call(data, index, 1);
3942
+ }
3943
+ --this.size;
3944
+ return true;
3945
+ }
3946
+
3947
+ /**
3948
+ * Gets the list cache value for `key`.
3949
+ *
3950
+ * @private
3951
+ * @name get
3952
+ * @memberOf ListCache
3953
+ * @param {string} key The key of the value to get.
3954
+ * @returns {*} Returns the entry value.
3955
+ */
3956
+ function listCacheGet(key) {
3957
+ var data = this.__data__,
3958
+ index = assocIndexOf(data, key);
3959
+
3960
+ return index < 0 ? undefined : data[index][1];
3961
+ }
3962
+
3963
+ /**
3964
+ * Checks if a list cache value for `key` exists.
3965
+ *
3966
+ * @private
3967
+ * @name has
3968
+ * @memberOf ListCache
3969
+ * @param {string} key The key of the entry to check.
3970
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
3971
+ */
3972
+ function listCacheHas(key) {
3973
+ return assocIndexOf(this.__data__, key) > -1;
3974
+ }
3975
+
3976
+ /**
3977
+ * Sets the list cache `key` to `value`.
3978
+ *
3979
+ * @private
3980
+ * @name set
3981
+ * @memberOf ListCache
3982
+ * @param {string} key The key of the value to set.
3983
+ * @param {*} value The value to set.
3984
+ * @returns {Object} Returns the list cache instance.
3985
+ */
3986
+ function listCacheSet(key, value) {
3987
+ var data = this.__data__,
3988
+ index = assocIndexOf(data, key);
3989
+
3990
+ if (index < 0) {
3991
+ ++this.size;
3992
+ data.push([key, value]);
3993
+ } else {
3994
+ data[index][1] = value;
3995
+ }
3996
+ return this;
3997
+ }
3998
+
3999
+ /**
4000
+ * Creates an list cache object.
4001
+ *
4002
+ * @private
4003
+ * @constructor
4004
+ * @param {Array} [entries] The key-value pairs to cache.
4005
+ */
4006
+ function ListCache(entries) {
4007
+ var index = -1,
4008
+ length = entries == null ? 0 : entries.length;
4009
+
4010
+ this.clear();
4011
+ while (++index < length) {
4012
+ var entry = entries[index];
4013
+ this.set(entry[0], entry[1]);
4014
+ }
4015
+ }
4016
+
4017
+ // Add methods to `ListCache`.
4018
+ ListCache.prototype.clear = listCacheClear;
4019
+ ListCache.prototype['delete'] = listCacheDelete;
4020
+ ListCache.prototype.get = listCacheGet;
4021
+ ListCache.prototype.has = listCacheHas;
4022
+ ListCache.prototype.set = listCacheSet;
4023
+
4024
+ /* Built-in method references that are verified to be native. */
4025
+ var Map$1 = getNative(root, 'Map');
4026
+
4027
+ /**
4028
+ * Removes all key-value entries from the map.
4029
+ *
4030
+ * @private
4031
+ * @name clear
4032
+ * @memberOf MapCache
4033
+ */
4034
+ function mapCacheClear() {
4035
+ this.size = 0;
4036
+ this.__data__ = {
4037
+ 'hash': new Hash,
4038
+ 'map': new (Map$1 || ListCache),
4039
+ 'string': new Hash
4040
+ };
4041
+ }
4042
+
4043
+ /**
4044
+ * Checks if `value` is suitable for use as unique object key.
4045
+ *
4046
+ * @private
4047
+ * @param {*} value The value to check.
4048
+ * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
4049
+ */
4050
+ function isKeyable(value) {
4051
+ var type = typeof value;
4052
+ return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
4053
+ ? (value !== '__proto__')
4054
+ : (value === null);
4055
+ }
4056
+
4057
+ /**
4058
+ * Gets the data for `map`.
4059
+ *
4060
+ * @private
4061
+ * @param {Object} map The map to query.
4062
+ * @param {string} key The reference key.
4063
+ * @returns {*} Returns the map data.
4064
+ */
4065
+ function getMapData(map, key) {
4066
+ var data = map.__data__;
4067
+ return isKeyable(key)
4068
+ ? data[typeof key == 'string' ? 'string' : 'hash']
4069
+ : data.map;
4070
+ }
4071
+
4072
+ /**
4073
+ * Removes `key` and its value from the map.
4074
+ *
4075
+ * @private
4076
+ * @name delete
4077
+ * @memberOf MapCache
4078
+ * @param {string} key The key of the value to remove.
4079
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
4080
+ */
4081
+ function mapCacheDelete(key) {
4082
+ var result = getMapData(this, key)['delete'](key);
4083
+ this.size -= result ? 1 : 0;
4084
+ return result;
4085
+ }
4086
+
4087
+ /**
4088
+ * Gets the map value for `key`.
4089
+ *
4090
+ * @private
4091
+ * @name get
4092
+ * @memberOf MapCache
4093
+ * @param {string} key The key of the value to get.
4094
+ * @returns {*} Returns the entry value.
4095
+ */
4096
+ function mapCacheGet(key) {
4097
+ return getMapData(this, key).get(key);
4098
+ }
4099
+
4100
+ /**
4101
+ * Checks if a map value for `key` exists.
4102
+ *
4103
+ * @private
4104
+ * @name has
4105
+ * @memberOf MapCache
4106
+ * @param {string} key The key of the entry to check.
4107
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
4108
+ */
4109
+ function mapCacheHas(key) {
4110
+ return getMapData(this, key).has(key);
4111
+ }
4112
+
4113
+ /**
4114
+ * Sets the map `key` to `value`.
4115
+ *
4116
+ * @private
4117
+ * @name set
4118
+ * @memberOf MapCache
4119
+ * @param {string} key The key of the value to set.
4120
+ * @param {*} value The value to set.
4121
+ * @returns {Object} Returns the map cache instance.
4122
+ */
4123
+ function mapCacheSet(key, value) {
4124
+ var data = getMapData(this, key),
4125
+ size = data.size;
4126
+
4127
+ data.set(key, value);
4128
+ this.size += data.size == size ? 0 : 1;
4129
+ return this;
4130
+ }
4131
+
4132
+ /**
4133
+ * Creates a map cache object to store key-value pairs.
4134
+ *
4135
+ * @private
4136
+ * @constructor
4137
+ * @param {Array} [entries] The key-value pairs to cache.
4138
+ */
4139
+ function MapCache(entries) {
4140
+ var index = -1,
4141
+ length = entries == null ? 0 : entries.length;
4142
+
4143
+ this.clear();
4144
+ while (++index < length) {
4145
+ var entry = entries[index];
4146
+ this.set(entry[0], entry[1]);
4147
+ }
4148
+ }
4149
+
4150
+ // Add methods to `MapCache`.
4151
+ MapCache.prototype.clear = mapCacheClear;
4152
+ MapCache.prototype['delete'] = mapCacheDelete;
4153
+ MapCache.prototype.get = mapCacheGet;
4154
+ MapCache.prototype.has = mapCacheHas;
4155
+ MapCache.prototype.set = mapCacheSet;
4156
+
4157
+ /**
4158
+ * Converts `value` to a string. An empty string is returned for `null`
4159
+ * and `undefined` values. The sign of `-0` is preserved.
4160
+ *
4161
+ * @static
4162
+ * @memberOf _
4163
+ * @since 4.0.0
4164
+ * @category Lang
4165
+ * @param {*} value The value to convert.
4166
+ * @returns {string} Returns the converted string.
4167
+ * @example
4168
+ *
4169
+ * _.toString(null);
4170
+ * // => ''
4171
+ *
4172
+ * _.toString(-0);
4173
+ * // => '-0'
4174
+ *
4175
+ * _.toString([1, 2, 3]);
4176
+ * // => '1,2,3'
4177
+ */
4178
+ function toString(value) {
4179
+ return value == null ? '' : baseToString(value);
4180
+ }
4181
+
4182
+ /** Built-in value references. */
4183
+ var getPrototype = overArg(Object.getPrototypeOf, Object);
4184
+
4185
+ /** `Object#toString` result references. */
4186
+ var objectTag = '[object Object]';
4187
+
4188
+ /** Used for built-in method references. */
4189
+ var funcProto = Function.prototype,
4190
+ objectProto = Object.prototype;
4191
+
4192
+ /** Used to resolve the decompiled source of functions. */
4193
+ var funcToString = funcProto.toString;
4194
+
4195
+ /** Used to check objects for own properties. */
4196
+ var hasOwnProperty = objectProto.hasOwnProperty;
4197
+
4198
+ /** Used to infer the `Object` constructor. */
4199
+ var objectCtorString = funcToString.call(Object);
4200
+
4201
+ /**
4202
+ * Checks if `value` is a plain object, that is, an object created by the
4203
+ * `Object` constructor or one with a `[[Prototype]]` of `null`.
4204
+ *
4205
+ * @static
4206
+ * @memberOf _
4207
+ * @since 0.8.0
4208
+ * @category Lang
4209
+ * @param {*} value The value to check.
4210
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
4211
+ * @example
4212
+ *
4213
+ * function Foo() {
4214
+ * this.a = 1;
4215
+ * }
4216
+ *
4217
+ * _.isPlainObject(new Foo);
4218
+ * // => false
4219
+ *
4220
+ * _.isPlainObject([1, 2, 3]);
4221
+ * // => false
4222
+ *
4223
+ * _.isPlainObject({ 'x': 0, 'y': 0 });
4224
+ * // => true
4225
+ *
4226
+ * _.isPlainObject(Object.create(null));
4227
+ * // => true
4228
+ */
4229
+ function isPlainObject(value) {
4230
+ if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
4231
+ return false;
4232
+ }
4233
+ var proto = getPrototype(value);
4234
+ if (proto === null) {
4235
+ return true;
4236
+ }
4237
+ var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
4238
+ return typeof Ctor == 'function' && Ctor instanceof Ctor &&
4239
+ funcToString.call(Ctor) == objectCtorString;
4240
+ }
4241
+
4242
+ /* Built-in method references for those with the same name as other `lodash` methods. */
4243
+ var nativeIsFinite = root.isFinite,
4244
+ nativeMin = Math.min;
4245
+
4246
+ /**
4247
+ * Creates a function like `_.round`.
4248
+ *
4249
+ * @private
4250
+ * @param {string} methodName The name of the `Math` method to use when rounding.
4251
+ * @returns {Function} Returns the new round function.
4252
+ */
4253
+ function createRound(methodName) {
4254
+ var func = Math[methodName];
4255
+ return function(number, precision) {
4256
+ number = toNumber(number);
4257
+ precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
4258
+ if (precision && nativeIsFinite(number)) {
4259
+ // Shift with exponential notation to avoid floating-point issues.
4260
+ // See [MDN](https://mdn.io/round#Examples) for more details.
4261
+ var pair = (toString(number) + 'e').split('e'),
4262
+ value = func(pair[0] + 'e' + (+pair[1] + precision));
4263
+
4264
+ pair = (toString(value) + 'e').split('e');
4265
+ return +(pair[0] + 'e' + (+pair[1] - precision));
4266
+ }
4267
+ return func(number);
4268
+ };
4269
+ }
4270
+
4271
+ /**
4272
+ * Removes all key-value entries from the stack.
4273
+ *
4274
+ * @private
4275
+ * @name clear
4276
+ * @memberOf Stack
4277
+ */
4278
+ function stackClear() {
4279
+ this.__data__ = new ListCache;
4280
+ this.size = 0;
4281
+ }
4282
+
4283
+ /**
4284
+ * Removes `key` and its value from the stack.
4285
+ *
4286
+ * @private
4287
+ * @name delete
4288
+ * @memberOf Stack
4289
+ * @param {string} key The key of the value to remove.
4290
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
4291
+ */
4292
+ function stackDelete(key) {
4293
+ var data = this.__data__,
4294
+ result = data['delete'](key);
4295
+
4296
+ this.size = data.size;
4297
+ return result;
4298
+ }
4299
+
4300
+ /**
4301
+ * Gets the stack value for `key`.
4302
+ *
4303
+ * @private
4304
+ * @name get
4305
+ * @memberOf Stack
4306
+ * @param {string} key The key of the value to get.
4307
+ * @returns {*} Returns the entry value.
4308
+ */
4309
+ function stackGet(key) {
4310
+ return this.__data__.get(key);
4311
+ }
4312
+
4313
+ /**
4314
+ * Checks if a stack value for `key` exists.
4315
+ *
4316
+ * @private
4317
+ * @name has
4318
+ * @memberOf Stack
4319
+ * @param {string} key The key of the entry to check.
4320
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
4321
+ */
4322
+ function stackHas(key) {
4323
+ return this.__data__.has(key);
4324
+ }
4325
+
4326
+ /** Used as the size to enable large array optimizations. */
4327
+ var LARGE_ARRAY_SIZE = 200;
4328
+
4329
+ /**
4330
+ * Sets the stack `key` to `value`.
4331
+ *
4332
+ * @private
4333
+ * @name set
4334
+ * @memberOf Stack
4335
+ * @param {string} key The key of the value to set.
4336
+ * @param {*} value The value to set.
4337
+ * @returns {Object} Returns the stack cache instance.
4338
+ */
4339
+ function stackSet(key, value) {
4340
+ var data = this.__data__;
4341
+ if (data instanceof ListCache) {
4342
+ var pairs = data.__data__;
4343
+ if (!Map$1 || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
4344
+ pairs.push([key, value]);
4345
+ this.size = ++data.size;
4346
+ return this;
4347
+ }
4348
+ data = this.__data__ = new MapCache(pairs);
4349
+ }
4350
+ data.set(key, value);
4351
+ this.size = data.size;
4352
+ return this;
4353
+ }
4354
+
4355
+ /**
4356
+ * Creates a stack cache object to store key-value pairs.
4357
+ *
4358
+ * @private
4359
+ * @constructor
4360
+ * @param {Array} [entries] The key-value pairs to cache.
4361
+ */
4362
+ function Stack(entries) {
4363
+ var data = this.__data__ = new ListCache(entries);
4364
+ this.size = data.size;
4365
+ }
4366
+
4367
+ // Add methods to `Stack`.
4368
+ Stack.prototype.clear = stackClear;
4369
+ Stack.prototype['delete'] = stackDelete;
4370
+ Stack.prototype.get = stackGet;
4371
+ Stack.prototype.has = stackHas;
4372
+ Stack.prototype.set = stackSet;
4373
+
4374
+ /** Detect free variable `exports`. */
4375
+ var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
4376
+
4377
+ /** Detect free variable `module`. */
4378
+ var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
4379
+
4380
+ /** Detect the popular CommonJS extension `module.exports`. */
4381
+ var moduleExports = freeModule && freeModule.exports === freeExports;
4382
+
4383
+ /** Built-in value references. */
4384
+ var Buffer = moduleExports ? root.Buffer : undefined;
4385
+ Buffer ? Buffer.allocUnsafe : undefined;
4386
+
4387
+ /**
4388
+ * Creates a clone of `buffer`.
4389
+ *
4390
+ * @private
4391
+ * @param {Buffer} buffer The buffer to clone.
4392
+ * @param {boolean} [isDeep] Specify a deep clone.
4393
+ * @returns {Buffer} Returns the cloned buffer.
4394
+ */
4395
+ function cloneBuffer(buffer, isDeep) {
4396
+ {
4397
+ return buffer.slice();
4398
+ }
4399
+ }
4400
+
4401
+ /** Built-in value references. */
4402
+ var Uint8Array$1 = root.Uint8Array;
4403
+
4404
+ /**
4405
+ * Creates a clone of `arrayBuffer`.
4406
+ *
4407
+ * @private
4408
+ * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
4409
+ * @returns {ArrayBuffer} Returns the cloned array buffer.
4410
+ */
4411
+ function cloneArrayBuffer(arrayBuffer) {
4412
+ var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
4413
+ new Uint8Array$1(result).set(new Uint8Array$1(arrayBuffer));
4414
+ return result;
4415
+ }
4416
+
4417
+ /**
4418
+ * Creates a clone of `typedArray`.
4419
+ *
4420
+ * @private
4421
+ * @param {Object} typedArray The typed array to clone.
4422
+ * @param {boolean} [isDeep] Specify a deep clone.
4423
+ * @returns {Object} Returns the cloned typed array.
4424
+ */
4425
+ function cloneTypedArray(typedArray, isDeep) {
4426
+ var buffer = cloneArrayBuffer(typedArray.buffer) ;
4427
+ return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
4428
+ }
4429
+
4430
+ /**
4431
+ * Initializes an object clone.
4432
+ *
4433
+ * @private
4434
+ * @param {Object} object The object to clone.
4435
+ * @returns {Object} Returns the initialized clone.
4436
+ */
4437
+ function initCloneObject(object) {
4438
+ return (typeof object.constructor == 'function' && !isPrototype(object))
4439
+ ? baseCreate(getPrototype(object))
4440
+ : {};
4441
+ }
4442
+
4443
+ /**
4444
+ * Creates a base function for methods like `_.forIn` and `_.forOwn`.
4445
+ *
4446
+ * @private
4447
+ * @param {boolean} [fromRight] Specify iterating from right to left.
4448
+ * @returns {Function} Returns the new base function.
4449
+ */
4450
+ function createBaseFor(fromRight) {
4451
+ return function(object, iteratee, keysFunc) {
4452
+ var index = -1,
4453
+ iterable = Object(object),
4454
+ props = keysFunc(object),
4455
+ length = props.length;
4456
+
4457
+ while (length--) {
4458
+ var key = props[++index];
4459
+ if (iteratee(iterable[key], key, iterable) === false) {
4460
+ break;
4461
+ }
4462
+ }
4463
+ return object;
4464
+ };
4465
+ }
4466
+
4467
+ /**
4468
+ * The base implementation of `baseForOwn` which iterates over `object`
4469
+ * properties returned by `keysFunc` and invokes `iteratee` for each property.
4470
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
4471
+ *
4472
+ * @private
4473
+ * @param {Object} object The object to iterate over.
4474
+ * @param {Function} iteratee The function invoked per iteration.
4475
+ * @param {Function} keysFunc The function to get the keys of `object`.
4476
+ * @returns {Object} Returns `object`.
4477
+ */
4478
+ var baseFor = createBaseFor();
4479
+
4480
+ /**
4481
+ * This function is like `assignValue` except that it doesn't assign
4482
+ * `undefined` values.
4483
+ *
4484
+ * @private
4485
+ * @param {Object} object The object to modify.
4486
+ * @param {string} key The key of the property to assign.
4487
+ * @param {*} value The value to assign.
4488
+ */
4489
+ function assignMergeValue(object, key, value) {
4490
+ if ((value !== undefined && !eq(object[key], value)) ||
4491
+ (value === undefined && !(key in object))) {
4492
+ baseAssignValue(object, key, value);
4493
+ }
4494
+ }
4495
+
4496
+ /**
4497
+ * This method is like `_.isArrayLike` except that it also checks if `value`
4498
+ * is an object.
4499
+ *
4500
+ * @static
4501
+ * @memberOf _
4502
+ * @since 4.0.0
4503
+ * @category Lang
4504
+ * @param {*} value The value to check.
4505
+ * @returns {boolean} Returns `true` if `value` is an array-like object,
4506
+ * else `false`.
4507
+ * @example
4508
+ *
4509
+ * _.isArrayLikeObject([1, 2, 3]);
4510
+ * // => true
4511
+ *
4512
+ * _.isArrayLikeObject(document.body.children);
4513
+ * // => true
4514
+ *
4515
+ * _.isArrayLikeObject('abc');
4516
+ * // => false
4517
+ *
4518
+ * _.isArrayLikeObject(_.noop);
4519
+ * // => false
4520
+ */
4521
+ function isArrayLikeObject(value) {
4522
+ return isObjectLike(value) && isArrayLike(value);
4523
+ }
4524
+
4525
+ /**
4526
+ * Gets the value at `key`, unless `key` is "__proto__" or "constructor".
4527
+ *
4528
+ * @private
4529
+ * @param {Object} object The object to query.
4530
+ * @param {string} key The key of the property to get.
4531
+ * @returns {*} Returns the property value.
4532
+ */
4533
+ function safeGet(object, key) {
4534
+ if (key === 'constructor' && typeof object[key] === 'function') {
4535
+ return;
4536
+ }
4537
+
4538
+ if (key == '__proto__') {
4539
+ return;
4540
+ }
4541
+
4542
+ return object[key];
2295
4543
  }
2296
- function getMowerImage(positonConfig) {
2297
- const model = positonConfig.vehicleModel || '';
2298
- const state = positonConfig.vehicleState;
2299
- const mowerImage = getMowerImageByModal(model);
2300
- const disabledImage = getDisabledMowerImageByModal(model);
2301
- const noPositionImage = getNoPositionMowerImageByModal(model);
2302
- const positonOutOfRange = isOutOfRange(positonConfig);
2303
- const positionValid = isInvalidPosition(positonConfig);
2304
- const isOffLine = state === RobotStatus.DISCONNECTED;
2305
- if (isOffLine) {
2306
- return disabledImage;
2307
- }
2308
- else if (positionValid || positonOutOfRange) {
2309
- return noPositionImage;
4544
+
4545
+ /**
4546
+ * Converts `value` to a plain object flattening inherited enumerable string
4547
+ * keyed properties of `value` to own properties of the plain object.
4548
+ *
4549
+ * @static
4550
+ * @memberOf _
4551
+ * @since 3.0.0
4552
+ * @category Lang
4553
+ * @param {*} value The value to convert.
4554
+ * @returns {Object} Returns the converted plain object.
4555
+ * @example
4556
+ *
4557
+ * function Foo() {
4558
+ * this.b = 2;
4559
+ * }
4560
+ *
4561
+ * Foo.prototype.c = 3;
4562
+ *
4563
+ * _.assign({ 'a': 1 }, new Foo);
4564
+ * // => { 'a': 1, 'b': 2 }
4565
+ *
4566
+ * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
4567
+ * // => { 'a': 1, 'b': 2, 'c': 3 }
4568
+ */
4569
+ function toPlainObject(value) {
4570
+ return copyObject(value, keysIn(value));
4571
+ }
4572
+
4573
+ /**
4574
+ * A specialized version of `baseMerge` for arrays and objects which performs
4575
+ * deep merges and tracks traversed objects enabling objects with circular
4576
+ * references to be merged.
4577
+ *
4578
+ * @private
4579
+ * @param {Object} object The destination object.
4580
+ * @param {Object} source The source object.
4581
+ * @param {string} key The key of the value to merge.
4582
+ * @param {number} srcIndex The index of `source`.
4583
+ * @param {Function} mergeFunc The function to merge values.
4584
+ * @param {Function} [customizer] The function to customize assigned values.
4585
+ * @param {Object} [stack] Tracks traversed source values and their merged
4586
+ * counterparts.
4587
+ */
4588
+ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
4589
+ var objValue = safeGet(object, key),
4590
+ srcValue = safeGet(source, key),
4591
+ stacked = stack.get(srcValue);
4592
+
4593
+ if (stacked) {
4594
+ assignMergeValue(object, key, stacked);
4595
+ return;
4596
+ }
4597
+ var newValue = customizer
4598
+ ? customizer(objValue, srcValue, (key + ''), object, source, stack)
4599
+ : undefined;
4600
+
4601
+ var isCommon = newValue === undefined;
4602
+
4603
+ if (isCommon) {
4604
+ var isArr = isArray(srcValue),
4605
+ isBuff = !isArr && isBuffer(srcValue),
4606
+ isTyped = !isArr && !isBuff && isTypedArray(srcValue);
4607
+
4608
+ newValue = srcValue;
4609
+ if (isArr || isBuff || isTyped) {
4610
+ if (isArray(objValue)) {
4611
+ newValue = objValue;
4612
+ }
4613
+ else if (isArrayLikeObject(objValue)) {
4614
+ newValue = copyArray(objValue);
4615
+ }
4616
+ else if (isBuff) {
4617
+ isCommon = false;
4618
+ newValue = cloneBuffer(srcValue);
4619
+ }
4620
+ else if (isTyped) {
4621
+ isCommon = false;
4622
+ newValue = cloneTypedArray(srcValue);
4623
+ }
4624
+ else {
4625
+ newValue = [];
4626
+ }
4627
+ }
4628
+ else if (isPlainObject(srcValue) || isArguments(srcValue)) {
4629
+ newValue = objValue;
4630
+ if (isArguments(objValue)) {
4631
+ newValue = toPlainObject(objValue);
4632
+ }
4633
+ else if (!isObject(objValue) || isFunction(objValue)) {
4634
+ newValue = initCloneObject(srcValue);
4635
+ }
2310
4636
  }
2311
4637
  else {
2312
- return mowerImage;
2313
- }
4638
+ isCommon = false;
4639
+ }
4640
+ }
4641
+ if (isCommon) {
4642
+ // Recursively merge objects and arrays (susceptible to call stack limits).
4643
+ stack.set(srcValue, newValue);
4644
+ mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
4645
+ stack['delete'](srcValue);
4646
+ }
4647
+ assignMergeValue(object, key, newValue);
2314
4648
  }
2315
- function isNoPosture(posture) {
2316
- if (posture == null || posture == undefined) {
2317
- return true;
2318
- }
2319
- if (posture == 0) {
2320
- return true;
4649
+
4650
+ /**
4651
+ * The base implementation of `_.merge` without support for multiple sources.
4652
+ *
4653
+ * @private
4654
+ * @param {Object} object The destination object.
4655
+ * @param {Object} source The source object.
4656
+ * @param {number} srcIndex The index of `source`.
4657
+ * @param {Function} [customizer] The function to customize merged values.
4658
+ * @param {Object} [stack] Tracks traversed source values and their merged
4659
+ * counterparts.
4660
+ */
4661
+ function baseMerge(object, source, srcIndex, customizer, stack) {
4662
+ if (object === source) {
4663
+ return;
4664
+ }
4665
+ baseFor(source, function(srcValue, key) {
4666
+ stack || (stack = new Stack);
4667
+ if (isObject(srcValue)) {
4668
+ baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
2321
4669
  }
2322
- else if (posture == -99999) {
2323
- return true;
4670
+ else {
4671
+ var newValue = customizer
4672
+ ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)
4673
+ : undefined;
4674
+
4675
+ if (newValue === undefined) {
4676
+ newValue = srcValue;
4677
+ }
4678
+ assignMergeValue(object, key, newValue);
2324
4679
  }
2325
- return false;
2326
- }
2327
- function isInvalidPosition(positonConfig) {
2328
- return (isNoPosture(positonConfig.postureX) &&
2329
- isNoPosture(positonConfig.postureY) &&
2330
- isNoPosture(positonConfig.postureTheta));
2331
- }
2332
- function isOutOfRange(positonConfig) {
2333
- return (positonConfig.postureX != null &&
2334
- Math.abs(positonConfig.postureX) > 1000 * SCALE_FACTOR &&
2335
- positonConfig.postureY != null &&
2336
- Math.abs(positonConfig.postureY) > 1000 * SCALE_FACTOR);
4680
+ }, keysIn);
2337
4681
  }
2338
4682
 
4683
+ /**
4684
+ * Computes `number` rounded down to `precision`.
4685
+ *
4686
+ * @static
4687
+ * @memberOf _
4688
+ * @since 3.10.0
4689
+ * @category Math
4690
+ * @param {number} number The number to round down.
4691
+ * @param {number} [precision=0] The precision to round down to.
4692
+ * @returns {number} Returns the rounded down number.
4693
+ * @example
4694
+ *
4695
+ * _.floor(4.006);
4696
+ * // => 4
4697
+ *
4698
+ * _.floor(0.046, 2);
4699
+ * // => 0.04
4700
+ *
4701
+ * _.floor(4060, -2);
4702
+ * // => 4000
4703
+ */
4704
+ var floor = createRound('floor');
4705
+
4706
+ /**
4707
+ * This method is like `_.assign` except that it recursively merges own and
4708
+ * inherited enumerable string keyed properties of source objects into the
4709
+ * destination object. Source properties that resolve to `undefined` are
4710
+ * skipped if a destination value exists. Array and plain object properties
4711
+ * are merged recursively. Other objects and value types are overridden by
4712
+ * assignment. Source objects are applied from left to right. Subsequent
4713
+ * sources overwrite property assignments of previous sources.
4714
+ *
4715
+ * **Note:** This method mutates `object`.
4716
+ *
4717
+ * @static
4718
+ * @memberOf _
4719
+ * @since 0.5.0
4720
+ * @category Object
4721
+ * @param {Object} object The destination object.
4722
+ * @param {...Object} [sources] The source objects.
4723
+ * @returns {Object} Returns `object`.
4724
+ * @example
4725
+ *
4726
+ * var object = {
4727
+ * 'a': [{ 'b': 2 }, { 'd': 4 }]
4728
+ * };
4729
+ *
4730
+ * var other = {
4731
+ * 'a': [{ 'c': 3 }, { 'e': 5 }]
4732
+ * };
4733
+ *
4734
+ * _.merge(object, other);
4735
+ * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
4736
+ */
4737
+ var merge = createAssigner(function(object, source, srcIndex) {
4738
+ baseMerge(object, source, srcIndex);
4739
+ });
4740
+
4741
+ /**
4742
+ * Computes `number` rounded to `precision`.
4743
+ *
4744
+ * @static
4745
+ * @memberOf _
4746
+ * @since 3.10.0
4747
+ * @category Math
4748
+ * @param {number} number The number to round.
4749
+ * @param {number} [precision=0] The precision to round to.
4750
+ * @returns {number} Returns the rounded number.
4751
+ * @example
4752
+ *
4753
+ * _.round(4.006);
4754
+ * // => 4
4755
+ *
4756
+ * _.round(4.006, 2);
4757
+ * // => 4.01
4758
+ *
4759
+ * _.round(4060, -2);
4760
+ * // => 4100
4761
+ */
4762
+ var round = createRound('round');
4763
+
2339
4764
  /**
2340
4765
  * 默认航向相对于canvas的偏移角度: 航向默认是东
2341
4766
  */
@@ -2368,10 +4793,10 @@ function calAngle(x1, y1, x2, y2) {
2368
4793
  return Math.atan2((y2 - y1), (x2 - x1));
2369
4794
  }
2370
4795
  const mathRound = (value, decimals = 2) => {
2371
- return Number.isInteger(value) ? value : lodashEs.round(value, decimals);
4796
+ return Number.isInteger(value) ? value : round(value, decimals);
2372
4797
  };
2373
4798
  const mathFloor = (value, decimals = 2) => {
2374
- return Number.isInteger(value) ? value : lodashEs.floor(value, decimals);
4799
+ return Number.isInteger(value) ? value : floor(value, decimals);
2375
4800
  };
2376
4801
  // 公制平方米-》英制平方英尺
2377
4802
  function areaToft2(area) {
@@ -2656,7 +5081,7 @@ class BoundaryBorderLayer extends BaseLayer {
2656
5081
  * 创建直接路径(type=2)
2657
5082
  */
2658
5083
  createDirectPath(svgGroup, points, style) {
2659
- const strokeColor = style.strokeColor;
5084
+ const strokeColor = style.lineColor;
2660
5085
  const lineWidth = dp2px(style.lineWidth || 3);
2661
5086
  const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
2662
5087
  // 构建路径数据
@@ -2685,7 +5110,7 @@ class BoundaryBorderLayer extends BaseLayer {
2685
5110
  * 使用PathMeasure逻辑创建平行路径(type=1)
2686
5111
  */
2687
5112
  createParallelPathsWithMeasure(svgGroup, points, style) {
2688
- const strokeColor = style.strokeColor;
5113
+ const strokeColor = style.lineColor;
2689
5114
  const lineWidth = dp2px(style.lineWidth || 3);
2690
5115
  // 获取当前SVG的缩放级别,计算固定屏幕像素间距
2691
5116
  const fixedScreenDistance = lineWidth; // 固定的屏幕像素距离
@@ -2851,8 +5276,8 @@ class AntennaLayer extends BaseLayer {
2851
5276
  }
2852
5277
  const image = document.createElementNS('http://www.w3.org/2000/svg', 'image');
2853
5278
  // 图片居中定位
2854
- const x = Math.round(center[0] - size / 2);
2855
- const y = Math.round(center[1] - size / 2);
5279
+ const x = center[0] - size / 2;
5280
+ const y = center[1] - size / 2;
2856
5281
  image.setAttribute('x', x.toString());
2857
5282
  image.setAttribute('y', y.toString());
2858
5283
  image.setAttribute('width', `${size}px`);
@@ -3033,19 +5458,19 @@ class BoundaryDataBuilder {
3033
5458
  /**
3034
5459
  * 从地图元素创建边界数据
3035
5460
  */
3036
- static fromMapElement(element) {
5461
+ static fromMapElement(element, style) {
3037
5462
  const convertedPoints = convertPointsFormat(element.points);
3038
5463
  if (!convertedPoints || convertedPoints.length < 3)
3039
5464
  return null;
3040
- const drawElement = this.create('boundary', convertedPoints, DEFAULT_STYLES.BOUNDARY);
5465
+ const drawElement = this.create('boundary', convertedPoints, style);
3041
5466
  drawElement.originalData = element; // 保存完整的原始数据
3042
5467
  return drawElement;
3043
5468
  }
3044
- static createBoundaryBorder(element) {
5469
+ static createBoundaryBorder(element, style) {
3045
5470
  const convertedPoints = convertPointsFormat(element.points);
3046
5471
  if (!convertedPoints || convertedPoints.length < 3)
3047
5472
  return null;
3048
- const drawElement = this.create('boundary_border', convertedPoints, DEFAULT_STYLES.BOUNDARY_BORDER);
5473
+ const drawElement = this.create('boundary_border', convertedPoints, style);
3049
5474
  drawElement.originalData = element; // 保存完整的原始数据
3050
5475
  return drawElement;
3051
5476
  }
@@ -3068,27 +5493,22 @@ class ObstacleDataBuilder {
3068
5493
  /**
3069
5494
  * 从地图元素创建障碍物数据
3070
5495
  */
3071
- static fromMapElement(element) {
5496
+ static fromMapElement(element, style) {
3072
5497
  const convertedPoints = convertPointsFormat(element.points);
3073
5498
  if (!convertedPoints || convertedPoints.length < 3)
3074
5499
  return null;
3075
- const drawElement = this.create(convertedPoints, DEFAULT_STYLES.OBSTACLE);
5500
+ const drawElement = this.create(convertedPoints, style);
3076
5501
  drawElement.originalData = element; // 保存完整的原始数据
3077
5502
  return drawElement;
3078
5503
  }
3079
5504
  /**
3080
5505
  * 创建时间限制障碍物多边形数据
3081
5506
  */
3082
- static createTimeLimitObstacle(element) {
5507
+ static createTimeLimitObstacle(element, style) {
3083
5508
  const convertedPoints = convertPointsFormat(element.points);
3084
5509
  if (!convertedPoints || convertedPoints.length < 3)
3085
5510
  return null;
3086
- const drawElement = this.create(convertedPoints, {
3087
- strokeColor: DEFAULT_STYLES.OBSTACLE.strokeColor,
3088
- fillColor: 'rgba(255, 192, 203, 0.3)', // 粉色半透明填充
3089
- lineWidth: 2,
3090
- opacity: 0.8,
3091
- });
5511
+ const drawElement = this.create(convertedPoints, style);
3092
5512
  drawElement.originalData = element; // 保存完整的原始数据
3093
5513
  return drawElement;
3094
5514
  }
@@ -3111,12 +5531,12 @@ class ChargingPileDataBuilder {
3111
5531
  /**
3112
5532
  * 从地图元素创建充电桩数据
3113
5533
  */
3114
- static fromMapElement(element) {
5534
+ static fromMapElement(element, style) {
3115
5535
  const elements = [];
3116
5536
  // 创建充电桩本体
3117
5537
  const point = convertPositionFormat(element.position);
3118
5538
  if (point) {
3119
- const mainPileElement = this.create([point.x, point.y], DEFAULT_STYLES.CHARGING_PILE);
5539
+ const mainPileElement = this.create([point.x, point.y], style);
3120
5540
  mainPileElement.originalData = element; // 保存完整的原始数据
3121
5541
  elements.push(mainPileElement);
3122
5542
  }
@@ -3144,7 +5564,7 @@ class AntennaDataBuilder {
3144
5564
  * 1. 如果副天线位置数据的相对坐标都是0,则需要展示在主天线旁边
3145
5565
  * 2. 否则,副天线有自己的独立位置
3146
5566
  */
3147
- static fromAntennaData(antennas) {
5567
+ static fromAntennaData(antennas, style) {
3148
5568
  const elements = [];
3149
5569
  const size = 30;
3150
5570
  // 查找主天线(ID=1)和副天线(ID=2)
@@ -3159,7 +5579,7 @@ class AntennaDataBuilder {
3159
5579
  online: antenna1.status === 1,
3160
5580
  size
3161
5581
  };
3162
- const element1 = this.create([point1.x, point1.y], DEFAULT_STYLES.ANTENNA || {}, metadata1);
5582
+ const element1 = this.create([point1.x, point1.y], style, metadata1);
3163
5583
  element1.originalData = antenna1;
3164
5584
  elements.push(element1);
3165
5585
  }
@@ -3174,7 +5594,7 @@ class AntennaDataBuilder {
3174
5594
  online: antenna2.status === 2,
3175
5595
  size
3176
5596
  };
3177
- const element2 = this.create([point2.x, point2.y], DEFAULT_STYLES.ANTENNA || {}, metadata2);
5597
+ const element2 = this.create([point2.x, point2.y], style, metadata2);
3178
5598
  element2.originalData = antenna2;
3179
5599
  elements.push(element2);
3180
5600
  }
@@ -3201,7 +5621,7 @@ class SvgElementDataBuilder {
3201
5621
  /**
3202
5622
  * 从地图元素创建SVG数据(用于时间限制障碍物)
3203
5623
  */
3204
- static fromMapElement(element) {
5624
+ static fromMapElement(element, style) {
3205
5625
  if (!element.svg ||
3206
5626
  !element.center ||
3207
5627
  element.scale === undefined ||
@@ -3215,7 +5635,7 @@ class SvgElementDataBuilder {
3215
5635
  svg: element.svg,
3216
5636
  scale: element.scale,
3217
5637
  direction: element.direction,
3218
- }, DEFAULT_STYLES.DOODLE);
5638
+ }, style);
3219
5639
  drawElement.originalData = element; // 保存完整的原始数据
3220
5640
  return drawElement;
3221
5641
  }
@@ -3249,11 +5669,11 @@ class VisionOffDataBuilder {
3249
5669
  /**
3250
5670
  * 创建视觉盲区元素数据(使用边界样式)
3251
5671
  */
3252
- static createVisionOffArea(element) {
5672
+ static createVisionOffArea(element, style) {
3253
5673
  const convertedPoints = convertPointsFormat(element.points);
3254
5674
  if (!convertedPoints || convertedPoints.length < 3)
3255
5675
  return null;
3256
- const drawElement = this.create(convertedPoints, DEFAULT_STYLES.VISION_OFF_AREA);
5676
+ const drawElement = this.create(convertedPoints, style);
3257
5677
  drawElement.originalData = element; // 保存完整的原始数据
3258
5678
  return drawElement;
3259
5679
  }
@@ -3276,33 +5696,18 @@ class ChannelDataBuilder {
3276
5696
  /**
3277
5697
  * 创建隧道元素数据
3278
5698
  */
3279
- static createTunnel(element) {
5699
+ static createTunnel(element, style) {
3280
5700
  const convertedPoints = convertPointsFormat(element.tunnel?.points || element.points);
3281
5701
  if (!convertedPoints || convertedPoints.length < 2)
3282
5702
  return null;
3283
- const drawElement = this.create(convertedPoints, DEFAULT_STYLES.CHANNEL);
3284
- drawElement.originalData = element; // 保存完整的原始数据
3285
- return drawElement;
3286
- }
3287
- /**
3288
- * 创建充电桩隧道元素数据
3289
- */
3290
- static createTunnelToChargingPile(element) {
3291
- const convertedPoints = convertPointsFormat(element.points);
3292
- if (!convertedPoints || convertedPoints.length < 2)
3293
- return null;
3294
- const drawElement = this.create(convertedPoints, {
3295
- strokeColor: DEFAULT_STYLES.CHANNEL.strokeColor,
3296
- lineWidth: 2,
3297
- opacity: 1.0,
3298
- });
5703
+ const drawElement = this.create(convertedPoints, style);
3299
5704
  drawElement.originalData = element; // 保存完整的原始数据
3300
5705
  return drawElement;
3301
5706
  }
3302
5707
  /**
3303
5708
  * 创建充电桩内部隧道路径(用于CHARGING_PILE元素中的tunnel.points)
3304
5709
  */
3305
- static createChargingPileTunnelPath(element) {
5710
+ static createChargingPileTunnelPath(element, style) {
3306
5711
  if (!element.tunnel || !element.tunnel.points)
3307
5712
  return null;
3308
5713
  // 对应android代码逻辑modules/deviceModule/src/main/java/com/segway/mower/device/map/data/MapDataManager.java
@@ -3316,45 +5721,10 @@ class ChannelDataBuilder {
3316
5721
  ]);
3317
5722
  if (!convertedTunnelPoints || convertedTunnelPoints.length < 2)
3318
5723
  return null;
3319
- const drawElement = this.create(convertedTunnelPoints, {
3320
- strokeColor: DEFAULT_STYLES.CHANNEL.strokeColor,
3321
- lineWidth: 2,
3322
- opacity: 1.0,
3323
- });
5724
+ const drawElement = this.create(convertedTunnelPoints, style);
3324
5725
  drawElement.originalData = element; // 保存完整的原始数据
3325
5726
  return drawElement;
3326
5727
  }
3327
- /**
3328
- * 创建边缘路径
3329
- */
3330
- static createEdgePath(points, config) {
3331
- return this.create(points, {
3332
- strokeColor: config?.color || DEFAULT_STYLES.PATH_EDGE.strokeColor,
3333
- lineWidth: config?.lineWidth || 2,
3334
- opacity: config?.opacity || 1.0,
3335
- });
3336
- }
3337
- /**
3338
- * 创建割草路径
3339
- */
3340
- static createMowingPath(points, config) {
3341
- return this.create(points, {
3342
- strokeColor: config?.color || DEFAULT_STYLES.PATH_EDGE.strokeColor,
3343
- lineWidth: config?.lineWidth || 2,
3344
- opacity: config?.opacity || 1.0,
3345
- });
3346
- }
3347
- /**
3348
- * 创建传输路径
3349
- */
3350
- static createTransPath(points, config) {
3351
- return this.create(points, {
3352
- strokeColor: config?.color || DEFAULT_STYLES.PATH_EDGE.strokeColor,
3353
- lineWidth: config?.lineWidth || 1,
3354
- lineDash: [5, 5], // 虚线样式
3355
- opacity: config?.opacity || 1.0,
3356
- });
3357
- }
3358
5728
  }
3359
5729
 
3360
5730
  /**
@@ -3365,7 +5735,8 @@ class MapDataProcessor {
3365
5735
  /**
3366
5736
  * 处理地图数据,返回绘制图层
3367
5737
  */
3368
- static processMapData(mapData) {
5738
+ static processMapData(mapData, mapConfig) {
5739
+ this.mapConfig = mapConfig;
3369
5740
  // 收集所有地图元素
3370
5741
  const allElements = [];
3371
5742
  // 处理子地图中的元素
@@ -3456,10 +5827,10 @@ class MapDataProcessor {
3456
5827
  switch (element.type) {
3457
5828
  case 'BOUNDARY': {
3458
5829
  try {
3459
- const boundaryElement = BoundaryDataBuilder.fromMapElement(element);
5830
+ const boundaryElement = BoundaryDataBuilder.fromMapElement(element, this.mapConfig.boundary);
3460
5831
  if (boundaryElement)
3461
5832
  result.push(boundaryElement);
3462
- const boundaryBorderElement = BoundaryDataBuilder.createBoundaryBorder(element);
5833
+ const boundaryBorderElement = BoundaryDataBuilder.createBoundaryBorder(element, this.mapConfig.boundary);
3463
5834
  if (boundaryBorderElement) {
3464
5835
  result.push(boundaryBorderElement);
3465
5836
  // 将边界边框存储到 store 中,以分区ID为key
@@ -3480,7 +5851,7 @@ class MapDataProcessor {
3480
5851
  try {
3481
5852
  // 为ObstacleData创建兼容的MapElement接口
3482
5853
  const mapElement = element;
3483
- const obstacleElement = ObstacleDataBuilder.fromMapElement(mapElement);
5854
+ const obstacleElement = ObstacleDataBuilder.fromMapElement(mapElement, this.mapConfig.obstacle);
3484
5855
  if (obstacleElement)
3485
5856
  result.push(obstacleElement);
3486
5857
  }
@@ -3491,10 +5862,10 @@ class MapDataProcessor {
3491
5862
  }
3492
5863
  case 'CHARGING_PILE': {
3493
5864
  try {
3494
- const chargingPileElements = ChargingPileDataBuilder.fromMapElement(element);
5865
+ const chargingPileElements = ChargingPileDataBuilder.fromMapElement(element, this.mapConfig.chargingPile);
3495
5866
  result.push(...chargingPileElements);
3496
5867
  // 有充电桩通道时再连接到充电桩
3497
- const tunnelPath = ChannelDataBuilder.createChargingPileTunnelPath(element);
5868
+ const tunnelPath = ChannelDataBuilder.createChargingPileTunnelPath(element, this.mapConfig.channel);
3498
5869
  if (tunnelPath)
3499
5870
  result.push(tunnelPath);
3500
5871
  // 创建导航位置(如果存在)
@@ -3507,7 +5878,7 @@ class MapDataProcessor {
3507
5878
  case 'VISION_OFF_AREA': {
3508
5879
  try {
3509
5880
  const mapElement = element;
3510
- const visionOffElement = VisionOffDataBuilder.createVisionOffArea(mapElement);
5881
+ const visionOffElement = VisionOffDataBuilder.createVisionOffArea(mapElement, this.mapConfig.visionOffArea);
3511
5882
  if (visionOffElement)
3512
5883
  result.push(visionOffElement);
3513
5884
  }
@@ -3519,7 +5890,7 @@ class MapDataProcessor {
3519
5890
  case 'TUNNEL': {
3520
5891
  try {
3521
5892
  const mapElement = element;
3522
- const tunnelElement = ChannelDataBuilder.createTunnel(mapElement);
5893
+ const tunnelElement = ChannelDataBuilder.createTunnel(mapElement, this.mapConfig.channel);
3523
5894
  if (tunnelElement)
3524
5895
  result.push({
3525
5896
  ...tunnelElement,
@@ -3542,7 +5913,8 @@ class MapDataProcessor {
3542
5913
  'direction' in element &&
3543
5914
  element.direction !== undefined) {
3544
5915
  const mapElement = element;
3545
- const svgElement = SvgElementDataBuilder.fromMapElement(mapElement);
5916
+ const svgElement = SvgElementDataBuilder.fromMapElement(mapElement, this.mapConfig.doodle);
5917
+ console.log('svgElement==', svgElement);
3546
5918
  if (svgElement)
3547
5919
  result.push(svgElement);
3548
5920
  }
@@ -3552,7 +5924,7 @@ class MapDataProcessor {
3552
5924
  Array.isArray(element.points) &&
3553
5925
  element.points.length >= 3) {
3554
5926
  const mapElement = element;
3555
- const polygonElement = ObstacleDataBuilder.createTimeLimitObstacle(mapElement);
5927
+ const polygonElement = ObstacleDataBuilder.createTimeLimitObstacle(mapElement, this.mapConfig.obstacle);
3556
5928
  if (polygonElement)
3557
5929
  result.push(polygonElement);
3558
5930
  }
@@ -3562,21 +5934,6 @@ class MapDataProcessor {
3562
5934
  }
3563
5935
  break;
3564
5936
  }
3565
- // case 'TUNNEL_TO_CHARGING_PILE': {
3566
- // try {
3567
- // // const chargingPileElement = elements.find(e => e.type === 'CHARGING_PILE');
3568
- // // if (chargingPileElement) {
3569
- // // const tunnelToChargingPileElement = ChannelDataBuilder.createTunnelToChargingPile(chargingPileElement);
3570
- // // if (tunnelToChargingPileElement) result.push(tunnelToChargingPileElement);
3571
- // // }
3572
- // const tunnelToChargingPileElement =
3573
- // ChannelDataBuilder.createTunnelToChargingPile(element);
3574
- // if (tunnelToChargingPileElement) result.push(tunnelToChargingPileElement);
3575
- // } catch (error) {
3576
- // console.warn(`Error processing TUNNEL_TO_CHARGING_PILE element:`, element, error);
3577
- // }
3578
- // break;
3579
- // }
3580
5937
  default: {
3581
5938
  console.warn(`Unknown element type: ${element.type}`, element);
3582
5939
  break;
@@ -3623,18 +5980,6 @@ class PathDataBuilder {
3623
5980
  // return this.create(convertedPoints, DEFAULT_STYLES.PATH_EDGE);
3624
5981
  // }
3625
5982
  // /**
3626
- // * 创建充电桩隧道元素数据
3627
- // */
3628
- // static createTunnelToChargingPile(element: MapElement): DrawElement | null {
3629
- // const convertedPoints = convertPointsFormat(element.points);
3630
- // if (!convertedPoints || convertedPoints.length < 2) return null;
3631
- // return this.create(convertedPoints, {
3632
- // strokeColor: DEFAULT_STYLES.CHANNEL.strokeColor,
3633
- // lineWidth: 2,
3634
- // opacity: 1.0
3635
- // });
3636
- // }
3637
- // /**
3638
5983
  // * 创建充电桩内部隧道路径(用于CHARGING_PILE元素中的tunnel.points)
3639
5984
  // */
3640
5985
  // static createChargingPileTunnelPath(element: MapElement): DrawElement | null {
@@ -3694,7 +6039,7 @@ class PathDataProcessor {
3694
6039
  /**
3695
6040
  * 处理路径数据,创建路径绘制图层
3696
6041
  */
3697
- static processPathData(pathData, pathConfig) {
6042
+ static processPathData(pathData, mapConfig) {
3698
6043
  if (!pathData || typeof pathData !== 'object') {
3699
6044
  return [];
3700
6045
  }
@@ -3706,62 +6051,45 @@ class PathDataProcessor {
3706
6051
  return acc;
3707
6052
  }, []);
3708
6053
  // 合并配置
3709
- const config = {
3710
- lineWidth: pathConfig?.lineWidth ?? 6,
3711
- showEdgePaths: pathConfig?.showEdgePaths ?? false,
3712
- showTransPaths: pathConfig?.showTransPaths ?? false,
3713
- showMowingPaths: pathConfig?.showMowingPaths ?? true,
3714
- edgePathColor: pathConfig?.edgePathColor,
3715
- transPathColor: pathConfig?.transPathColor,
3716
- mowingPathColor: pathConfig?.mowingPathColor,
3717
- edgePathOpacity: pathConfig?.edgePathOpacity ?? 1.0,
3718
- transPathOpacity: pathConfig?.transPathOpacity ?? 1.0,
3719
- mowingPathOpacity: pathConfig?.mowingPathOpacity ?? 1.0,
3720
- };
6054
+ const config = mapConfig.path;
3721
6055
  // 使用Python相同的逻辑:按线段分组而不是按点分组
3722
6056
  const pathSegments = createPathSegmentsByType(allPathItems);
3723
6057
  const elements = [];
3724
- // 处理边缘路径段(只有在showEdgePaths为true时才添加)
3725
- if (config.showEdgePaths) {
3726
- for (const segment of pathSegments.edge) {
3727
- // 转换 Point[] number[][]
3728
- const points = segment.points.map((point) => [point.x, point.y]);
3729
- const element = PathDataBuilder.createEdgePath(points, {
3730
- lineWidth: config.lineWidth,
3731
- color: config.edgePathColor,
3732
- opacity: config.edgePathOpacity,
3733
- });
3734
- element.originalData = points;
3735
- elements.push(element);
3736
- }
3737
- }
3738
- // 处理割草路径段(只有在showMowingPathstrue时才添加)
3739
- if (config.showMowingPaths) {
3740
- for (const segment of pathSegments.mowing) {
3741
- // 转换 Point[] 为 number[][]
3742
- const points = segment.points.map((point) => [point.x, point.y]);
3743
- const element = PathDataBuilder.createMowingPath(points, {
3744
- lineWidth: config.lineWidth,
3745
- color: config.mowingPathColor,
3746
- opacity: config.mowingPathOpacity,
3747
- });
3748
- element.originalData = points;
3749
- elements.push(element);
3750
- }
6058
+ // 处理边缘路径段
6059
+ for (const segment of pathSegments.edge) {
6060
+ // 转换 Point[] number[][]
6061
+ const points = segment.points.map((point) => [point.x, point.y]);
6062
+ const element = PathDataBuilder.createEdgePath(points, {
6063
+ lineWidth: config.lineWidth,
6064
+ color: config.edgeLineColor,
6065
+ opacity: config.opacity,
6066
+ });
6067
+ element.originalData = points;
6068
+ elements.push(element);
6069
+ }
6070
+ // 处理割草路径段
6071
+ for (const segment of pathSegments.mowing) {
6072
+ // 转换 Point[] number[][]
6073
+ const points = segment.points.map((point) => [point.x, point.y]);
6074
+ const element = PathDataBuilder.createMowingPath(points, {
6075
+ lineWidth: config.lineWidth,
6076
+ color: config.mowingLineColor,
6077
+ opacity: config.opacity,
6078
+ });
6079
+ element.originalData = points;
6080
+ elements.push(element);
3751
6081
  }
3752
6082
  // 处理传输路径段(只有在showTransPaths为true时才添加)
3753
- if (config.showTransPaths) {
3754
- for (const segment of pathSegments.trans) {
3755
- // 转换 Point[] number[][]
3756
- const points = segment.points.map((point) => [point.x, point.y]);
3757
- const element = PathDataBuilder.createTransPath(points, {
3758
- lineWidth: config.lineWidth,
3759
- color: config.transPathColor,
3760
- opacity: config.transPathOpacity,
3761
- });
3762
- element.originalData = points;
3763
- elements.push(element);
3764
- }
6083
+ for (const segment of pathSegments.trans) {
6084
+ // 转换 Point[] number[][]
6085
+ const points = segment.points.map((point) => [point.x, point.y]);
6086
+ const element = PathDataBuilder.createTransPath(points, {
6087
+ lineWidth: config.lineWidth,
6088
+ color: config.transLineColor,
6089
+ opacity: config.opacity,
6090
+ });
6091
+ element.originalData = points;
6092
+ elements.push(element);
3765
6093
  }
3766
6094
  return elements;
3767
6095
  }
@@ -3776,6 +6104,8 @@ class BoundaryLabelsManager {
3776
6104
  this.container = null;
3777
6105
  this.overlayDiv = null;
3778
6106
  this.globalClickHandler = null;
6107
+ // 当前展开的边界id
6108
+ this.currentExpandedBoundaryId = null;
3779
6109
  this.svgView = svgView;
3780
6110
  this.boundaryData = boundaryData;
3781
6111
  this.initializeContainer();
@@ -3874,7 +6204,7 @@ class BoundaryLabelsManager {
3874
6204
  extendedContent.style.marginTop = '6px';
3875
6205
  extendedContent.style.fontSize = '11px';
3876
6206
  extendedContent.style.opacity = '0.9';
3877
- extendedContent.style.display = 'none';
6207
+ extendedContent.style.display = this.currentExpandedBoundaryId === boundary.id ? 'block' : 'none';
3878
6208
  extendedContent.style.borderTop = '1px solid rgba(255,255,255,0.2)';
3879
6209
  extendedContent.style.paddingTop = '6px';
3880
6210
  // 面积信息
@@ -3899,17 +6229,17 @@ class BoundaryLabelsManager {
3899
6229
  labelDiv.addEventListener('click', (e) => {
3900
6230
  e.stopPropagation();
3901
6231
  this.elevateLabelZIndex();
3902
- this.expandLabel(labelDiv);
3903
- });
3904
- // 添加悬停效果
3905
- labelDiv.addEventListener('mouseenter', () => {
3906
- labelDiv.style.backgroundColor = 'rgba(30, 30, 31, 0.6)';
3907
- labelDiv.style.transform = 'translate(-50%, -50%) scale(1.05)';
3908
- });
3909
- labelDiv.addEventListener('mouseleave', () => {
3910
- labelDiv.style.backgroundColor = 'rgba(30, 30, 31, 0.3)';
3911
- labelDiv.style.transform = 'translate(-50%, -50%) scale(1)';
6232
+ this.expandLabel(boundary.id);
3912
6233
  });
6234
+ // // 添加悬停效果
6235
+ // labelDiv.addEventListener('mouseenter', () => {
6236
+ // labelDiv.style.backgroundColor = 'rgba(30, 30, 31, 0.6)';
6237
+ // labelDiv.style.transform = 'translate(-50%, -50%) scale(1.05)';
6238
+ // });
6239
+ // labelDiv.addEventListener('mouseleave', () => {
6240
+ // labelDiv.style.backgroundColor = 'rgba(30, 30, 31, 0.3)';
6241
+ // labelDiv.style.transform = 'translate(-50%, -50%) scale(1)';
6242
+ // });
3913
6243
  this.container.appendChild(labelDiv);
3914
6244
  return labelDiv;
3915
6245
  }
@@ -3934,25 +6264,30 @@ class BoundaryLabelsManager {
3934
6264
  /**
3935
6265
  * 展开标签
3936
6266
  */
3937
- expandLabel(labelDiv) {
6267
+ expandLabel(boundaryId) {
6268
+ const labelDiv = this.getLabelElement(boundaryId);
6269
+ if (!labelDiv)
6270
+ return;
3938
6271
  const extendedContent = labelDiv.querySelector('.boundary-label-extended');
3939
6272
  if (!extendedContent)
3940
6273
  return;
3941
6274
  // 关闭其他展开的标签
3942
- this.collapseOtherLabels(labelDiv);
6275
+ this.collapseOtherLabels(boundaryId);
3943
6276
  // 展开当前标签
3944
6277
  extendedContent.style.display = 'block';
3945
6278
  labelDiv.style.whiteSpace = 'normal';
6279
+ this.currentExpandedBoundaryId = boundaryId;
3946
6280
  }
3947
6281
  /**
3948
6282
  * 关闭其他展开的标签
3949
6283
  */
3950
- collapseOtherLabels(currentLabel) {
6284
+ collapseOtherLabels(boundaryId) {
3951
6285
  if (!this.container)
3952
6286
  return;
3953
6287
  const allLabels = this.container.querySelectorAll('.boundary-label');
3954
6288
  allLabels.forEach(label => {
3955
- if (label !== currentLabel) {
6289
+ const labelBoundaryId = label.getAttribute('data-boundary-id');
6290
+ if (labelBoundaryId && labelBoundaryId !== boundaryId.toString()) {
3956
6291
  const extendedContent = label.querySelector('.boundary-label-extended');
3957
6292
  if (extendedContent) {
3958
6293
  extendedContent.style.display = 'none';
@@ -3968,6 +6303,7 @@ class BoundaryLabelsManager {
3968
6303
  this.boundaryData.forEach((boundary) => {
3969
6304
  this.addElement(boundary);
3970
6305
  });
6306
+ this.updatePositionsWithPrecomputedData();
3971
6307
  }
3972
6308
  /**
3973
6309
  * 获取容器元素
@@ -3975,28 +6311,6 @@ class BoundaryLabelsManager {
3975
6311
  getElement() {
3976
6312
  return this.container;
3977
6313
  }
3978
- /**
3979
- * 更新所有边界标签位置
3980
- */
3981
- updatePositions() {
3982
- if (!this.container || !this.overlayDiv)
3983
- return;
3984
- const labels = this.container.querySelectorAll('.boundary-label');
3985
- labels.forEach((label, index) => {
3986
- const boundary = this.boundaryData[index];
3987
- if (!boundary)
3988
- return;
3989
- // 计算边界中心点
3990
- const center = this.calculateBoundaryCenter(boundary);
3991
- if (!center) {
3992
- console.warn(`BoundaryLabelsManager: 无法计算边界 ${boundary.name} (ID: ${boundary.id}) 的中心点`);
3993
- return;
3994
- }
3995
- // 设置标签位置
3996
- label.style.left = `${center.x}px`;
3997
- label.style.top = `${center.y}px`;
3998
- });
3999
- }
4000
6314
  /**
4001
6315
  * 使用预计算的数据更新边界标签位置(优化版本)
4002
6316
  * @param divWidth 叠加层div的宽度
@@ -4004,8 +6318,11 @@ class BoundaryLabelsManager {
4004
6318
  * @param viewBox SVG的viewBox信息
4005
6319
  */
4006
6320
  updatePositionsWithPrecomputedData(divWidth, divHeight, viewBox) {
4007
- if (!this.container)
6321
+ if (!this.container || !this.svgView)
4008
6322
  return;
6323
+ const dw = parseFloat(this.svgView.getSVG().getAttribute('width')) || divWidth;
6324
+ const dh = parseFloat(this.svgView.getSVG().getAttribute('height')) || divHeight;
6325
+ const vb = this.svgView.getSVG().viewBox.baseVal || viewBox;
4009
6326
  const labels = this.container.querySelectorAll('.boundary-label');
4010
6327
  labels.forEach((label, index) => {
4011
6328
  const boundary = this.boundaryData[index];
@@ -4018,7 +6335,7 @@ class BoundaryLabelsManager {
4018
6335
  return;
4019
6336
  }
4020
6337
  // 直接使用预计算的数据进行坐标转换
4021
- const center = this.convertMapCoordinateToPixelWithPrecomputedData(mapCenter.x, mapCenter.y, divWidth, divHeight, viewBox);
6338
+ const center = this.convertMapCoordinateToPixelWithPrecomputedData(mapCenter.x, mapCenter.y, dw, dh, vb);
4022
6339
  if (!center)
4023
6340
  return;
4024
6341
  // 设置标签位置
@@ -4215,6 +6532,7 @@ class BoundaryLabelsManager {
4215
6532
  if (!this.container)
4216
6533
  return;
4217
6534
  const allLabels = this.container.querySelectorAll('.boundary-label');
6535
+ this.currentExpandedBoundaryId = null;
4218
6536
  allLabels.forEach(label => {
4219
6537
  const extendedContent = label.querySelector('.boundary-label-extended');
4220
6538
  if (extendedContent) {
@@ -4269,8 +6587,7 @@ class BoundaryLabelsManager {
4269
6587
  const allLabels = this.container.querySelectorAll('.boundary-label');
4270
6588
  allLabels.forEach((label, index) => {
4271
6589
  const labelElement = label;
4272
- const currentZIndex = labelElement.style.zIndex;
4273
- console.log(`Label ${index} z-index: ${currentZIndex}`);
6590
+ labelElement.style.zIndex;
4274
6591
  });
4275
6592
  }
4276
6593
  }
@@ -4331,7 +6648,6 @@ class ChargingPileManager {
4331
6648
  pileDiv.style.position = 'absolute';
4332
6649
  pileDiv.style.width = `${size}px`;
4333
6650
  pileDiv.style.height = `${size}px`;
4334
- pileDiv.style.transform = 'translate(-50%, -50%)';
4335
6651
  pileDiv.style.pointerEvents = 'auto';
4336
6652
  pileDiv.style.zIndex = ChargingPileManager.Z_INDEX.CHARGING_PILE.toString();
4337
6653
  // 创建图片元素
@@ -4340,13 +6656,14 @@ class ChargingPileManager {
4340
6656
  imgElement.style.width = '100%';
4341
6657
  imgElement.style.height = '100%';
4342
6658
  imgElement.style.objectFit = 'contain';
4343
- imgElement.style.opacity = '0'; // 初始透明
6659
+ imgElement.style.opacity = '1'; // 初始透明
4344
6660
  pileDiv.appendChild(imgElement);
4345
6661
  // 将弧度转换为角度
4346
6662
  const angle = (direction * 180) / Math.PI;
4347
6663
  const rotationDegree = 270 - angle; // 坐标系转换
6664
+ pileDiv.style.transform = `translate(-50%, -50%) rotate(${rotationDegree}deg)`;
4348
6665
  // 添加动画
4349
- this.addChargingPileAnimation(pileDiv, imgElement, rotationDegree);
6666
+ // this.addChargingPileAnimation(pileDiv, imgElement, rotationDegree);
4350
6667
  // 生成唯一ID
4351
6668
  const pileId = `pile_${center[0]}_${center[1]}`;
4352
6669
  this.pileElements.set(pileId, pileDiv);
@@ -4967,31 +7284,6 @@ const EDIT_STYLES = {
4967
7284
  const EDIT_BEHAVIOR = {
4968
7285
  SUCCESS_MESSAGE_DURATION_MS: 3000,
4969
7286
  };
4970
- // 默认配置
4971
- const DEFAULT_MAP_CONFIG = {
4972
- showScale: true,
4973
- fitToView: true,
4974
- initialZoom: 1,
4975
- enableDrag: true,
4976
- width: 800,
4977
- height: 600,
4978
- backgroundColor: '#f5f5f5',
4979
- borderRadius: '8px',
4980
- border: '1px solid #ddd',
4981
- useGoogleMaps: true,
4982
- };
4983
- const DEFAULT_PATH_CONFIG = {
4984
- lineWidth: 20,
4985
- showEdgePaths: true,
4986
- showTransPaths: true,
4987
- showMowingPaths: true,
4988
- edgePathColor: 'rgba(194, 203, 212)',
4989
- transPathColor: 'transparent',
4990
- mowingPathColor: 'rgba(194, 203, 212)',
4991
- edgePathOpacity: 1,
4992
- transPathOpacity: 0.6,
4993
- mowingPathOpacity: 1,
4994
- };
4995
7287
 
4996
7288
  class MowerPostionManager {
4997
7289
  constructor(svgView, mowerPositonConfig, overlayDiv, onAnimationComplete) {
@@ -5048,8 +7340,8 @@ class MowerPostionManager {
5048
7340
  this.mowerElement = document.createElement('div');
5049
7341
  this.mowerElement.className = 'mower-position';
5050
7342
  this.mowerElement.style.position = 'absolute';
5051
- this.mowerElement.style.width = '24px';
5052
- this.mowerElement.style.height = '24px';
7343
+ this.mowerElement.style.width = '30px';
7344
+ this.mowerElement.style.height = '30px';
5053
7345
  this.mowerElement.style.transform = 'translate(-50%, -50%)';
5054
7346
  this.mowerElement.style.pointerEvents = 'none';
5055
7347
  this.mowerElement.style.zIndex = '1';
@@ -5299,7 +7591,7 @@ class MowerPostionManager {
5299
7591
 
5300
7592
  // Google Maps 叠加层类 - 带编辑功能
5301
7593
  class MowerMapOverlay {
5302
- constructor(bounds, mapData, mowerPositonConfig, pathData, isEditMode = false, mapConfig = {}, pathConfig = {}, antennaConfig = {}, onMapLoad, onPathLoad, dragCallbacks) {
7594
+ constructor(bounds, mapData, mowerPositonConfig, pathData, isEditMode = false, mapConfig = {}, antennaConfig = {}, onMapLoad, onPathLoad, dragCallbacks) {
5303
7595
  this.div = null;
5304
7596
  this.svgMapView = null;
5305
7597
  this.offscreenContainer = null;
@@ -5341,7 +7633,6 @@ class MowerMapOverlay {
5341
7633
  this.pathData = pathData;
5342
7634
  this.isEditMode = isEditMode;
5343
7635
  this.mapConfig = mapConfig;
5344
- this.pathConfig = pathConfig;
5345
7636
  this.antennaConfig = antennaConfig;
5346
7637
  this.onMapLoad = onMapLoad;
5347
7638
  this.onPathLoad = onPathLoad;
@@ -5365,6 +7656,7 @@ class MowerMapOverlay {
5365
7656
  this.boundaryData = generateBoundaryData(mapData, pathData);
5366
7657
  }
5367
7658
  updatePosition(positonConfig, animationTime = 2200) {
7659
+ console.log('updatePosition==', positonConfig, animationTime);
5368
7660
  // 保存当前动画时长
5369
7661
  this.currentAnimationTime = animationTime;
5370
7662
  // 标记是否为用户动画(大于0表示用户主动触发的动画)
@@ -5525,12 +7817,6 @@ class MowerMapOverlay {
5525
7817
  this.div.appendChild(container);
5526
7818
  }
5527
7819
  }
5528
- // 更新边界标签位置
5529
- updateBoundaryLabelsPosition() {
5530
- if (this.boundaryLabelsManager) {
5531
- this.boundaryLabelsManager.updatePositions();
5532
- }
5533
- }
5534
7820
  // 使用优化版本更新边界标签位置
5535
7821
  updateBoundaryLabelsPositionOptimized(width, height) {
5536
7822
  if (!this.boundaryLabelsManager || !this.div)
@@ -6076,7 +8362,6 @@ class MowerMapOverlay {
6076
8362
  try {
6077
8363
  // 创建SvgMapView实例
6078
8364
  this.svgMapView = new SvgMapView(this.offscreenContainer, 800, 600);
6079
- this.svgMapView.setShowScale(this.mapConfig.showScale !== false);
6080
8365
  // 加载地图数据
6081
8366
  this.loadMapData();
6082
8367
  // 加载路径数据
@@ -6103,7 +8388,7 @@ class MowerMapOverlay {
6103
8388
  return;
6104
8389
  try {
6105
8390
  // 使用现有的MapDataProcessor处理地图数据
6106
- const elements = MapDataProcessor.processMapData(this.mapData);
8391
+ const elements = MapDataProcessor.processMapData(this.mapData, this.mapConfig);
6107
8392
  // 分离充电桩和天线元素,其他元素添加到SVG图层
6108
8393
  // const svgElements = elements.filter(element =>
6109
8394
  // element.type !== 'charging_pile' && element.type !== 'antenna'
@@ -6152,7 +8437,7 @@ class MowerMapOverlay {
6152
8437
  loadPathData(pathData) {
6153
8438
  try {
6154
8439
  // 使用现有的PathDataProcessor处理路径数据
6155
- const pathElements = PathDataProcessor.processPathData(pathData, this.pathConfig);
8440
+ const pathElements = PathDataProcessor.processPathData(pathData, this.mapConfig);
6156
8441
  const pathLayer = new PathLayer();
6157
8442
  pathLayer.addElements(pathElements);
6158
8443
  // 添加图层到SvgMapView
@@ -6178,6 +8463,7 @@ class MowerMapOverlay {
6178
8463
  if (!pathJson)
6179
8464
  return;
6180
8465
  const boundaryData = generateBoundaryData(this.mapData, pathJson);
8466
+ console.log('boundaryData==', boundaryData);
6181
8467
  this.boundaryLabelsManager?.updateBoundaryData(boundaryData);
6182
8468
  }
6183
8469
  draw() {
@@ -6370,11 +8656,9 @@ const getValidGpsBounds = (mapData) => {
6370
8656
  };
6371
8657
  };
6372
8658
  // 默认配置
6373
- const defaultMapConfig = DEFAULT_MAP_CONFIG;
6374
- const defaultPathConfig = DEFAULT_PATH_CONFIG;
8659
+ const defaultMapConfig = DEFAULT_STYLES;
6375
8660
  // 地图渲染器组件
6376
- const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTimeData, mowerPositionConfig, mapConfig, pathConfig, antennaConfig, onMapLoad, onPathLoad, onZoomChange, onError, className, style, googleMapInstance, isEditMode = false, dragCallbacks, }, ref) => {
6377
- const containerRef = React.useRef(null);
8661
+ const MowerMapRenderer = React.forwardRef(({ mapConfig, modelType, mapRef, mapJson, pathJson, realTimeData, currentPositionData, antennaConfig, onMapLoad, onPathLoad, onZoomChange, onError, className, style, googleMapInstance, isEditMode = false, dragCallbacks, }, ref) => {
6378
8662
  const svgMapViewRef = React.useRef(null);
6379
8663
  const [elementCount, setElementCount] = React.useState(0);
6380
8664
  const [pathCount, setPathCount] = React.useState(0);
@@ -6404,25 +8688,21 @@ const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTime
6404
8688
  }, [mapJson]);
6405
8689
  // 合并配置
6406
8690
  const mergedMapConfig = React.useMemo(() => {
6407
- // if (!mapConfig) {
6408
- // return defaultMapConfig;
6409
- // }
6410
- return { ...defaultMapConfig, ...(mapConfig || {}) };
8691
+ return merge(defaultMapConfig, mapConfig);
6411
8692
  }, [mapConfig]);
6412
- const mergedPathConfig = React.useMemo(() => {
6413
- return { ...defaultPathConfig, ...(pathConfig || {}) };
6414
- }, [pathConfig]);
6415
8693
  const mergedAntennaConfig = React.useMemo(() => antennaConfig, [antennaConfig]);
6416
8694
  const mowerPositionData = React.useMemo(() => {
6417
8695
  return {
6418
- postureTheta: mowerPositionConfig?.postureTheta ? Number(mowerPositionConfig.postureTheta) : 0,
6419
- postureX: mowerPositionConfig?.postureX ? Number(mowerPositionConfig.postureX) : 0,
6420
- postureY: mowerPositionConfig?.postureY ? Number(mowerPositionConfig.postureY) : 0,
6421
- vehicleState: mowerPositionConfig?.vehicleState || RobotStatus.STANDBY,
6422
- vehicleModel: mowerPositionConfig?.vehicleModel || 'i',
8696
+ postureTheta: currentPositionData?.postureTheta
8697
+ ? Number(currentPositionData.postureTheta)
8698
+ : 0,
8699
+ postureX: currentPositionData?.postureX ? Number(currentPositionData.postureX) : 0,
8700
+ postureY: currentPositionData?.postureY ? Number(currentPositionData.postureY) : 0,
8701
+ vehicleState: currentPositionData?.vehicleState || RobotStatus.STANDBY,
8702
+ vehicleModel: modelType,
6423
8703
  };
6424
- }, [mowerPositionConfig]);
6425
- console.log('mowerPositionData==', mowerPositionData);
8704
+ }, [currentPositionData, modelType]);
8705
+ console.log('mowerPositionData==', currentPositionData, mowerPositionData);
6426
8706
  // 处理错误
6427
8707
  const handleError = (error) => {
6428
8708
  setCurrentError(error);
@@ -6430,7 +8710,7 @@ const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTime
6430
8710
  };
6431
8711
  // 初始化Google Maps叠加层
6432
8712
  const initializeGoogleMapsOverlay = async () => {
6433
- if (!mapJson || !mergedMapConfig.useGoogleMaps)
8713
+ if (!mapJson)
6434
8714
  return;
6435
8715
  try {
6436
8716
  // 等待Google Maps API加载
@@ -6470,7 +8750,7 @@ const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTime
6470
8750
  overlayRef.current = null;
6471
8751
  }
6472
8752
  // 创建叠加层
6473
- const overlay = new MowerMapOverlay(googleBounds, mapJson, mowerPositionData, pathJson || {}, isEditMode, mergedMapConfig, mergedPathConfig, mergedAntennaConfig, (count) => {
8753
+ const overlay = new MowerMapOverlay(googleBounds, mapJson, mowerPositionData, pathJson || {}, isEditMode, mergedMapConfig, mergedAntennaConfig, (count) => {
6474
8754
  setElementCount(count);
6475
8755
  onMapLoad?.(count);
6476
8756
  }, (count) => {
@@ -6481,7 +8761,7 @@ const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTime
6481
8761
  overlay.setMap(mapInstance);
6482
8762
  overlayRef.current = overlay;
6483
8763
  // 只在首次初始化时自适应视图
6484
- if (mergedMapConfig.fitToView && !hasInitializedBounds) {
8764
+ if (!hasInitializedBounds) {
6485
8765
  mapInstance.fitBounds(googleBounds);
6486
8766
  setHasInitializedBounds(true);
6487
8767
  }
@@ -6491,87 +8771,27 @@ const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTime
6491
8771
  handleError(`初始化Google Maps叠加层失败: ${error instanceof Error ? error.message : String(error)}`);
6492
8772
  }
6493
8773
  };
6494
- // 初始化普通SVG视图
6495
- const initializeSvgView = () => {
6496
- if (!containerRef.current || !mapJson || mergedMapConfig.useGoogleMaps)
6497
- return;
6498
- try {
6499
- const container = containerRef.current;
6500
- const svgView = new SvgMapView(container, mergedMapConfig.width || 800, mergedMapConfig.height || 600);
6501
- svgView.setShowScale(mergedMapConfig.showScale !== false);
6502
- svgMapViewRef.current = svgView;
6503
- // 加载地图数据
6504
- loadMapData(svgView);
6505
- // 加载路径数据
6506
- if (pathJson) {
6507
- loadPathData(svgView);
6508
- }
6509
- // 初始缩放
6510
- setZoom(mergedMapConfig.initialZoom || 1);
6511
- svgView.setZoom(mergedMapConfig.initialZoom || 1);
6512
- // 自适应视图
6513
- if (mergedMapConfig.fitToView) {
6514
- const bounds = calculateMapBounds(mapJson);
6515
- if (bounds) {
6516
- svgView.fitToView(bounds);
6517
- }
6518
- }
6519
- }
6520
- catch (error) {
6521
- handleError(`初始化SVG视图失败: ${error instanceof Error ? error.message : String(error)}`);
6522
- }
6523
- };
6524
- // 加载地图数据
6525
- const loadMapData = (svgView) => {
6526
- if (!mapJson)
6527
- return;
6528
- try {
6529
- const elements = MapDataProcessor.processMapData(mapJson);
6530
- const drawLayer = new DrawLayer();
6531
- drawLayer.addElements(elements);
6532
- // 处理天线数据
6533
- if (mapJson.antennas && mapJson.antennas.length > 0) {
6534
- const antennaElements = AntennaDataBuilder.fromAntennaData(mapJson.antennas);
6535
- drawLayer.addElements(antennaElements);
6536
- }
6537
- const layers = drawLayer.getLayers();
6538
- svgView.clear();
6539
- layers.forEach((layer) => {
6540
- svgView.addLayer(layer);
6541
- });
6542
- const count = elements.length;
6543
- setElementCount(count);
6544
- onMapLoad?.(count);
6545
- }
6546
- catch (error) {
6547
- handleError(`加载地图数据失败: ${error instanceof Error ? error.message : String(error)}`);
6548
- }
6549
- };
6550
- // 加载路径数据
6551
- const loadPathData = (svgView) => {
6552
- if (!pathJson)
6553
- return;
6554
- try {
6555
- const pathElements = PathDataProcessor.processPathData(pathJson, mergedPathConfig);
6556
- const pathLayer = new DrawLayer();
6557
- pathLayer.addElements(pathElements);
6558
- svgView.addLayer(pathLayer);
6559
- const count = pathElements.length;
6560
- setPathCount(count);
6561
- onPathLoad?.(count);
6562
- }
6563
- catch (error) {
6564
- handleError(`加载路径数据失败: ${error instanceof Error ? error.message : String(error)}`);
8774
+ const formatRealTimeData = async (realTimeData) => {
8775
+ // await sleep(1000);
8776
+ const newRealTimeData = handleRealTimeData({
8777
+ realTimeData,
8778
+ isMowing: currentProcessMowingStatusRef.current,
8779
+ pathData: pathJson,
8780
+ partitionBoundary,
8781
+ });
8782
+ console.log('newRealTimeData==', newRealTimeData);
8783
+ // currentProcessMowingStatusRef.current = newRealTimeData.isMowing;
8784
+ currentProcessMowingStatusRef.current = true;
8785
+ // 调用overlay的updatePathData方法,更新历史路径数据
8786
+ if (overlayRef.current) {
8787
+ overlayRef.current.updatePathData(newRealTimeData.pathData);
6565
8788
  }
8789
+ overlayRef.current.updateBoundaryLabelInfo(newRealTimeData.pathData);
6566
8790
  };
6567
8791
  // 初始化效果
6568
8792
  React.useEffect(() => {
6569
- if (mergedMapConfig.useGoogleMaps) {
6570
- initializeGoogleMapsOverlay();
6571
- }
6572
- else {
6573
- initializeSvgView();
6574
- }
8793
+ initializeGoogleMapsOverlay();
8794
+ console.log('init mow map');
6575
8795
  // 清理函数
6576
8796
  return () => {
6577
8797
  clearSubBoundaryBorder();
@@ -6585,7 +8805,7 @@ const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTime
6585
8805
  svgMapViewRef.current = null;
6586
8806
  }
6587
8807
  };
6588
- }, [mapJson, pathJson, mergedMapConfig, mergedPathConfig, mergedAntennaConfig]);
8808
+ }, [mapJson, pathJson, mergedMapConfig, mergedAntennaConfig]);
6589
8809
  // 监听编辑模式变化
6590
8810
  React.useEffect(() => {
6591
8811
  if (overlayRef.current) {
@@ -6601,9 +8821,9 @@ const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTime
6601
8821
  React.useEffect(() => {
6602
8822
  if (!mapJson)
6603
8823
  return;
6604
- const elements = MapDataProcessor.processMapData(mapJson);
8824
+ const elements = MapDataProcessor.processMapData(mapJson, mergedMapConfig);
6605
8825
  const chargingPiles = elements.find((element) => element.type === 'charging_pile');
6606
- console.log('chargingPiles==', chargingPiles, mowerPositionConfig);
8826
+ console.log('chargingPiles==', chargingPiles, currentPositionData);
6607
8827
  if (!mowerPositionData || !overlayRef.current)
6608
8828
  return;
6609
8829
  const inChargingPiles = [RobotStatus.CHARGING, RobotStatus.PARKED];
@@ -6634,7 +8854,7 @@ const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTime
6634
8854
  overlayRef.current.updatePosition(mowerPositionData, isStandyBy ? 0 : 2200);
6635
8855
  }
6636
8856
  }
6637
- }, [mowerPositionConfig]);
8857
+ }, [currentPositionData]);
6638
8858
  React.useEffect(() => {
6639
8859
  if (!mapJson ||
6640
8860
  !pathJson ||
@@ -6645,19 +8865,7 @@ const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTime
6645
8865
  // 根据后端推送的实时数据,进行不同处理
6646
8866
  // TODO:需要根据返回的数据,处理车辆的移动位置
6647
8867
  // 这里是根据返回的数据,处理实时轨迹
6648
- const newRealTimeData = handleRealTimeData({
6649
- realTimeData,
6650
- isMowing: currentProcessMowingStatusRef.current,
6651
- pathData: pathJson,
6652
- partitionBoundary,
6653
- });
6654
- console.log('newRealTimeData==', newRealTimeData);
6655
- // currentProcessMowingStatusRef.current = newRealTimeData.isMowing;
6656
- currentProcessMowingStatusRef.current = true;
6657
- // 调用overlay的updatePathData方法,更新历史路径数据
6658
- if (overlayRef.current) {
6659
- overlayRef.current.updatePathData(newRealTimeData.pathData);
6660
- }
8868
+ formatRealTimeData(realTimeData);
6661
8869
  }, [realTimeData, mapJson, pathJson]);
6662
8870
  // 提供ref方法
6663
8871
  React.useImperativeHandle(ref, () => ({
@@ -6726,21 +8934,8 @@ const MowerMapRenderer = React.forwardRef(({ mapRef, mapJson, pathJson, realTime
6726
8934
  if (currentError) {
6727
8935
  return (jsxRuntime.jsx("div", { className: className, style: style, children: jsxRuntime.jsxs("div", { style: { color: 'red', padding: '10px' }, children: ["\u9519\u8BEF: ", currentError] }) }));
6728
8936
  }
6729
- // Google Maps模式 - 返回空的占位符,实际渲染由叠加层处理
6730
- if (mergedMapConfig.useGoogleMaps) {
6731
- return null;
6732
- }
6733
- // 渲染普通SVG容器
6734
- return (jsxRuntime.jsx("div", { ref: containerRef, className: className, style: {
6735
- width: mergedMapConfig.width || 800,
6736
- height: mergedMapConfig.height || 600,
6737
- backgroundColor: mergedMapConfig.backgroundColor || '#f5f5f5',
6738
- borderRadius: mergedMapConfig.borderRadius || '8px',
6739
- border: mergedMapConfig.border || '1px solid #ddd',
6740
- position: 'relative',
6741
- overflow: 'hidden',
6742
- ...style,
6743
- } }));
8937
+ // 使用goole maps自定义叠加层,不需要实际返回组件内容
8938
+ return null;
6744
8939
  });
6745
8940
  MowerMapRenderer.displayName = 'MowerMapRenderer';
6746
8941