@fleet-frontend/mower-maps 0.0.6 → 0.0.7

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