@fleet-frontend/mower-maps 0.2.0-beta.11 → 0.2.0-beta.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -313,7 +313,7 @@ function initObstacle() {
313
313
  const obstacle = {
314
314
  id: null,
315
315
  area: 0,
316
- name: 'off-imit island',
316
+ name: 'Noname',
317
317
  status: 1,
318
318
  end_timestamp: 0,
319
319
  start_timestamp: 0,
@@ -15092,10 +15092,10 @@ const DashPath = ({ points, stroke, strokeWidth, strokeOpacity, className, }) =>
15092
15092
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { fill: "none", d: parallelPath2Data, stroke: stroke, strokeWidth: strokeWidth, strokeOpacity: strokeOpacity, strokeLinecap: "round", strokeLinejoin: "round", strokeDasharray: `${strokeWidth}px ${strokeWidth * 2}px`, style: { pointerEvents: 'none' } }), jsxRuntime.jsx("path", { fill: "none", d: parallelPath1Data, stroke: stroke, strokeWidth: strokeWidth, strokeOpacity: strokeOpacity, strokeLinecap: "round", strokeLinejoin: "round", strokeDasharray: `${strokeWidth}px ${strokeWidth * 2}px`, style: { pointerEvents: 'none' } })] }));
15093
15093
  };
15094
15094
 
15095
- const VertexElement = React.memo(({ r, stroke, ...props }) => {
15096
- const { overlayScale } = useCommonContext();
15095
+ const VertexElement = React.memo(({ r, stroke, fill, ...props }) => {
15096
+ const { overlayScale, platform } = useCommonContext();
15097
15097
  const radius = typeof r === 'number' ? r : 12;
15098
- return (jsxRuntime.jsx("circle", { r: radius * overlayScale, stroke: stroke || '#fff', fill: '#fff', strokeWidth: 2 * overlayScale, ...props }));
15098
+ return (jsxRuntime.jsx("circle", { r: platform === exports.PlatformType.H5 ? (radius * overlayScale) / 2 : radius * overlayScale, stroke: stroke || '#fff', fill: fill || '#fff', strokeWidth: 2 * overlayScale, ...props }));
15099
15099
  });
15100
15100
 
15101
15101
  var _path$2;
@@ -15179,6 +15179,7 @@ const normalizePadding = (padding) => {
15179
15179
  return { x: padding?.x ?? 4, y: padding?.y ?? 2 };
15180
15180
  };
15181
15181
  const TextElement = ({ x, y, fontSize = 30, fill = '#fff', text, background = 'rgba(0, 0, 0, 0.34)', padding = 2, rx = 4, ry = 4, backgroundStroke, backgroundStrokeWidth = 0, textAnchor = 'middle', alignmentBaseline = 'middle', className, style, rotate, pointerEvents = 'auto', onClick, onMouseEnter, onMouseLeave, children, }) => {
15182
+ const { platform } = useCommonContext();
15182
15183
  const textRef = React.useRef(null);
15183
15184
  const [bbox, setBbox] = React.useState(null);
15184
15185
  const pad = React.useMemo(() => normalizePadding(padding), [padding]);
@@ -15205,7 +15206,7 @@ const TextElement = ({ x, y, fontSize = 30, fill = '#fff', text, background = 'r
15205
15206
  height: bbox.height + pad.y * 2,
15206
15207
  };
15207
15208
  }, [bbox, pad.x, pad.y]);
15208
- return (jsxRuntime.jsxs("g", { className: className, style: style, pointerEvents: pointerEvents, onClick: onClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: [background && rectProps && (jsxRuntime.jsx("rect", { x: rectProps.x, y: rectProps.y, width: rectProps.width, height: rectProps.height, rx: rx, ry: ry, fill: background, stroke: backgroundStroke, strokeWidth: backgroundStrokeWidth })), jsxRuntime.jsx("text", { ref: textRef, x: x, y: y, letterSpacing: -5, fontSize: fontSize, fill: fill, textAnchor: textAnchor, alignmentBaseline: alignmentBaseline,
15209
+ return (jsxRuntime.jsxs("g", { className: className, style: style, pointerEvents: pointerEvents, onClick: onClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: [background && rectProps && (jsxRuntime.jsx("rect", { x: rectProps.x, y: rectProps.y, width: rectProps.width, height: rectProps.height, rx: rx, ry: ry, fill: background, stroke: backgroundStroke, strokeWidth: backgroundStrokeWidth })), jsxRuntime.jsx("text", { ref: textRef, x: x, y: y, letterSpacing: platform === exports.PlatformType.H5 ? 1 : -5, fontSize: fontSize, fill: fill, textAnchor: textAnchor, alignmentBaseline: alignmentBaseline,
15209
15210
  // keep text crisp at various zoom levels
15210
15211
  vectorEffect: "non-scaling-stroke", style: { pointerEvents: 'none' }, children: children || text })] }));
15211
15212
  };
@@ -15235,7 +15236,7 @@ const calculateMidpoint$1 = (point1, point2) => {
15235
15236
  const DistanceLabels = ({ coordinates, createMode = false, editMode = false, completed = false, showPoints = false, mousePos: _mousePos = null, ghostLastDistance = null, ghostLastMidpoint = null, ghostFirstDistance = null, ghostFirstMidpoint = null, fontSize = 30, }) => {
15236
15237
  // 只在显示可操作顶点时显示距离
15237
15238
  if (!((createMode && showPoints) || editMode || (createMode && completed)) ||
15238
- coordinates.length < 1) {
15239
+ coordinates.length < 2) {
15239
15240
  return null;
15240
15241
  }
15241
15242
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [coordinates.map((coord, idx) => {
@@ -15250,8 +15251,22 @@ const DistanceLabels = ({ coordinates, createMode = false, editMode = false, com
15250
15251
  return (jsxRuntime.jsx(TextElement, { x: midpoint[0], y: midpoint[1], textAnchor: "middle", alignmentBaseline: "middle", fontSize: fontSize, fill: "#fff", style: {
15251
15252
  pointerEvents: 'none',
15252
15253
  fontWeight: 'bold',
15254
+ userSelect: 'none',
15255
+ WebkitUserSelect: 'none',
15256
+ WebkitTouchCallout: 'none',
15257
+ touchAction: 'none',
15253
15258
  }, text: distance }, `distance-${idx}`));
15254
- }), ghostLastDistance && ghostLastMidpoint && (jsxRuntime.jsx(TextElement, { fontSize: fontSize, x: ghostLastMidpoint[0], y: ghostLastMidpoint[1], text: ghostLastDistance })), ghostFirstDistance && ghostFirstMidpoint && (jsxRuntime.jsx(TextElement, { fontSize: fontSize, x: ghostFirstMidpoint[0], y: ghostFirstMidpoint[1], text: ghostFirstDistance }))] }));
15259
+ }), ghostLastDistance && ghostLastMidpoint && (jsxRuntime.jsx(TextElement, { fontSize: fontSize, x: ghostLastMidpoint[0], y: ghostLastMidpoint[1], text: ghostLastDistance, style: {
15260
+ userSelect: 'none',
15261
+ WebkitUserSelect: 'none',
15262
+ WebkitTouchCallout: 'none',
15263
+ touchAction: 'none',
15264
+ } })), ghostFirstDistance && ghostFirstMidpoint && (jsxRuntime.jsx(TextElement, { fontSize: fontSize, x: ghostFirstMidpoint[0], y: ghostFirstMidpoint[1], text: ghostFirstDistance, style: {
15265
+ userSelect: 'none',
15266
+ WebkitUserSelect: 'none',
15267
+ WebkitTouchCallout: 'none',
15268
+ touchAction: 'none',
15269
+ } }))] }));
15255
15270
  };
15256
15271
 
15257
15272
  var css_248z$2 = ".index-module_polygonPathG__S-Bpl {\n pointer-events: stroke;\n cursor: pointer;\n}\n\n.index-module_vertex__-Qb1u {\n cursor: pointer;\n}\n\n.index-module_dragging__xSFdO {\n cursor: grabbing;\n}\n\n.index-module_createVertex__ldz2E {\n cursor: crosshair;\n}\n\n.index-module_addVertex__hrF71 {\n cursor: pointer;\n}\n\n.index-module_polygonPath__PynOn {\n pointer-events: stroke;\n cursor: pointer;\n}\n\n.index-module_notCreate__bFnkV {\n cursor: no-drop;\n}";
@@ -15547,6 +15562,7 @@ function coordinatesToPoints$1(coordinates) {
15547
15562
 
15548
15563
  const useCheckElement = () => {
15549
15564
  const { editMapInfo, minDistance } = useMapEditContext();
15565
+ const { platform } = useCommonContext();
15550
15566
  const { svgElementDatas } = useSvgEditContext();
15551
15567
  const checkDoodle = React.useCallback(() => {
15552
15568
  console.log('checkdoodle', editMapInfo, svgElementDatas);
@@ -15647,7 +15663,7 @@ const useCheckElement = () => {
15647
15663
  return { isValid: true };
15648
15664
  }, [editMapInfo, svgElementDatas, minDistance]);
15649
15665
  const checkCanNotCreateAtPosition = React.useCallback((checkPoint, checkPoints) => {
15650
- console.log('editMapInfo.elementType--->', editMapInfo);
15666
+ // console.log('editMapInfo.elementType--->', editMapInfo);
15651
15667
  if (!editMapInfo.elementType)
15652
15668
  return false;
15653
15669
  const currentPoints = editMapInfo?.selectElement?.points;
@@ -15674,8 +15690,10 @@ const useCheckElement = () => {
15674
15690
  return false;
15675
15691
  // 获取当前正在创建的 obstacle 的点
15676
15692
  const currentObstaclePoints = coordinatesToPoints$1(points) || [];
15677
- if (currentObstaclePoints.length === 0)
15678
- return false; // 还没有开始绘制
15693
+ if (platform !== exports.PlatformType.H5) {
15694
+ if (currentObstaclePoints.length === 0)
15695
+ return false; // 还没有开始绘制
15696
+ }
15679
15697
  // 构建当前 obstacle 的多边形(包括检查点位置)
15680
15698
  const currentObstaclePolygon = [...currentObstaclePoints, checkPoint];
15681
15699
  // 获取当前边界内的所有元素
@@ -15831,6 +15849,8 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
15831
15849
  });
15832
15850
  // 虚拟顶点hover状态
15833
15851
  const [hoverVertex, setHoverVertex] = React.useState(null);
15852
+ // H5平台选中的顶点索引(长按后选中)
15853
+ const [selectedVertexIndex, setSelectedVertexIndex] = React.useState(-1);
15834
15854
  const { checkCanNotCreateAtPosition } = useCheckElement();
15835
15855
  const { editMapInfo } = useMapEditContext();
15836
15856
  const { platform } = useCommonContext();
@@ -15898,11 +15918,33 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
15898
15918
  if (tooltipIndex !== null)
15899
15919
  setTooltipIndex(null);
15900
15920
  }, [editMode, createMode, completed]);
15921
+ // H5平台:点击空白处取消选中状态
15922
+ React.useEffect(() => {
15923
+ if (platform !== exports.PlatformType.H5 || selectedVertexIndex === -1)
15924
+ return;
15925
+ const handleDocumentClick = (e) => {
15926
+ // 检查点击的目标是否是顶点
15927
+ const target = e.target;
15928
+ const isClickingVertex = target.closest('circle') !== null;
15929
+ // 如果点击的不是顶点,则取消选中状态
15930
+ if (!isClickingVertex) {
15931
+ setSelectedVertexIndex(-1);
15932
+ }
15933
+ };
15934
+ document.addEventListener('click', handleDocumentClick);
15935
+ return () => {
15936
+ document.removeEventListener('click', handleDocumentClick);
15937
+ };
15938
+ }, [platform, selectedVertexIndex]);
15901
15939
  // 处理顶点拖拽
15902
15940
  const handleVertexMouseDown = React.useCallback((e, index) => {
15903
15941
  // 只有在编辑模式或者创建模式已完成时才能拖拽
15904
15942
  if (!editMode && !(createMode && completed))
15905
15943
  return;
15944
+ // H5模式下,只有选中的顶点才能拖拽
15945
+ if (platform === exports.PlatformType.H5 && selectedVertexIndex !== index) {
15946
+ return;
15947
+ }
15906
15948
  e.preventDefault();
15907
15949
  e.stopPropagation();
15908
15950
  // 如果正在双击,忽略mouseDown事件
@@ -15929,7 +15971,7 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
15929
15971
  });
15930
15972
  mouseDownTimerRef.current = null;
15931
15973
  }, 250);
15932
- }, [editMode, createMode, completed, coordinates, tooltipIndex]);
15974
+ }, [editMode, createMode, completed, coordinates, tooltipIndex, platform, selectedVertexIndex]);
15933
15975
  // 点击边线创建新顶点
15934
15976
  const handleEdgeClick = React.useCallback((e, edgeStartIndex) => {
15935
15977
  // 只有在编辑模式或者创建模式已完成时才能点击边线创建新顶点
@@ -15964,6 +16006,8 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
15964
16006
  edgeInfo: edgeInfo,
15965
16007
  dragType: 'new',
15966
16008
  });
16009
+ // 将新创建的点设为选中态,便于后续直接拖拽
16010
+ setSelectedVertexIndex(insertIndex);
15967
16011
  }, [
15968
16012
  editMode,
15969
16013
  createMode,
@@ -15973,6 +16017,69 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
15973
16017
  getSVGCoordinates,
15974
16018
  calculatePerpendicularFoot$1,
15975
16019
  ]);
16020
+ // H5平台长按边线创建新顶点
16021
+ const handleEdgeLongPressStart = React.useCallback((e, edgeStartIndex) => {
16022
+ if ((!editMode && !(createMode && completed)) || dragState.isDragging)
16023
+ return;
16024
+ e.preventDefault();
16025
+ e.stopPropagation();
16026
+ const clickCoords = getSVGCoordinates(e.clientX, e.clientY);
16027
+ longPressStartPosRef.current = clickCoords;
16028
+ longPressEdgeIndexRef.current = edgeStartIndex;
16029
+ // 开始长按计时器(500ms)
16030
+ longPressTimerRef.current = window.setTimeout(() => {
16031
+ isLongPressedRef.current = true;
16032
+ // 长按触发,创建新顶点
16033
+ if (longPressEdgeIndexRef.current !== -1 && longPressStartPosRef.current) {
16034
+ handleEdgeClick(e, longPressEdgeIndexRef.current);
16035
+ }
16036
+ }, 500);
16037
+ }, [editMode, createMode, completed, dragState.isDragging, getSVGCoordinates, handleEdgeClick]);
16038
+ // 长按结束或取消
16039
+ const handleEdgeLongPressEnd = React.useCallback(() => {
16040
+ if (longPressTimerRef.current !== null) {
16041
+ window.clearTimeout(longPressTimerRef.current);
16042
+ longPressTimerRef.current = null;
16043
+ }
16044
+ isLongPressedRef.current = false;
16045
+ longPressStartPosRef.current = null;
16046
+ longPressEdgeIndexRef.current = -1;
16047
+ }, []);
16048
+ // H5平台长按顶点选中
16049
+ const vertexLongPressTimerRef = React.useRef(null);
16050
+ const isVertexLongPressedRef = React.useRef(false);
16051
+ const longPressVertexIndexRef = React.useRef(-1);
16052
+ // 长按拖拽判定相关
16053
+ const touchStartPosRef = React.useRef(null);
16054
+ const hasStartedDragViaLongPressRef = React.useRef(false);
16055
+ const DRAG_START_THRESHOLD = 8; // 像素阈值,超过则认为进入拖拽
16056
+ // H5平台双击检测
16057
+ const lastTapRef = React.useRef(0);
16058
+ const lastTapIndexRef = React.useRef(-1);
16059
+ const DOUBLE_TAP_DELAY = 300; // 双击检测间隔时间(ms)
16060
+ const handleVertexLongPressStart = React.useCallback((e, index) => {
16061
+ if ((!editMode && !(createMode && completed)) || dragState.isDragging)
16062
+ return;
16063
+ e.preventDefault();
16064
+ e.stopPropagation();
16065
+ longPressVertexIndexRef.current = index;
16066
+ hasStartedDragViaLongPressRef.current = false;
16067
+ touchStartPosRef.current = { x: e.clientX, y: e.clientY };
16068
+ // 开始长按计时器(1000ms)
16069
+ vertexLongPressTimerRef.current = window.setTimeout(() => {
16070
+ isVertexLongPressedRef.current = true;
16071
+ setSelectedVertexIndex(index);
16072
+ }, 1000);
16073
+ }, [editMode, createMode, completed, dragState.isDragging]);
16074
+ const handleVertexLongPressEnd = React.useCallback(() => {
16075
+ if (vertexLongPressTimerRef.current !== null) {
16076
+ window.clearTimeout(vertexLongPressTimerRef.current);
16077
+ vertexLongPressTimerRef.current = null;
16078
+ }
16079
+ isVertexLongPressedRef.current = false;
16080
+ longPressVertexIndexRef.current = -1;
16081
+ touchStartPosRef.current = null;
16082
+ }, []);
15976
16083
  const showNotCreateCursor = React.useMemo(() => {
15977
16084
  if (!dragState?.isDragging || !dragState?.currentPosition)
15978
16085
  return false;
@@ -16002,6 +16109,11 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
16002
16109
  const clickTimerRef = React.useRef(null);
16003
16110
  const mouseDownTimerRef = React.useRef(null);
16004
16111
  const isDoubleClickingRef = React.useRef(false);
16112
+ // 长按事件相关
16113
+ const longPressTimerRef = React.useRef(null);
16114
+ const isLongPressedRef = React.useRef(false);
16115
+ const longPressStartPosRef = React.useRef(null);
16116
+ const longPressEdgeIndexRef = React.useRef(-1);
16005
16117
  // 清理 requestAnimationFrame 和事件定时器
16006
16118
  React.useEffect(() => {
16007
16119
  return () => {
@@ -16017,6 +16129,14 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
16017
16129
  window.clearTimeout(mouseDownTimerRef.current);
16018
16130
  mouseDownTimerRef.current = null;
16019
16131
  }
16132
+ if (longPressTimerRef.current !== null) {
16133
+ window.clearTimeout(longPressTimerRef.current);
16134
+ longPressTimerRef.current = null;
16135
+ }
16136
+ if (vertexLongPressTimerRef.current !== null) {
16137
+ window.clearTimeout(vertexLongPressTimerRef.current);
16138
+ vertexLongPressTimerRef.current = null;
16139
+ }
16020
16140
  };
16021
16141
  }, []);
16022
16142
  // 拖拽过程中更新坐标 - 使用节流优化性能
@@ -16044,6 +16164,40 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
16044
16164
  });
16045
16165
  }
16046
16166
  }, [dragState.isDragging, dragState.dragIndex, getSVGCoordinates]);
16167
+ // 处理 H5 顶点长按后的触摸移动以进入拖拽
16168
+ const handleVertexTouchMoveMaybeStartDrag = React.useCallback((e, idx) => {
16169
+ if (platform !== exports.PlatformType.H5)
16170
+ return;
16171
+ if (dragState.isDragging)
16172
+ return; // 已在拖拽
16173
+ // 允许两种进入拖拽的途径:
16174
+ // 1) 长按该点
16175
+ // 2) 该点已处于选中态
16176
+ const canDragNow = isVertexLongPressedRef.current && longPressVertexIndexRef.current === idx;
16177
+ const canDragBecauseSelected = selectedVertexIndex === idx;
16178
+ if (!canDragNow && !canDragBecauseSelected)
16179
+ return;
16180
+ if (touchStartPosRef.current) {
16181
+ const dx = e.clientX - touchStartPosRef.current.x;
16182
+ const dy = e.clientY - touchStartPosRef.current.y;
16183
+ const dist = Math.sqrt(dx * dx + dy * dy);
16184
+ if (dist >= DRAG_START_THRESHOLD) {
16185
+ // 进入拖拽状态
16186
+ const index = idx;
16187
+ hasStartedDragViaLongPressRef.current = true;
16188
+ // 启动与 mouseDown 相同的拖拽逻辑
16189
+ setDragState({
16190
+ isDragging: true,
16191
+ dragIndex: index,
16192
+ originalPosition: [...coordinates[index]],
16193
+ currentPosition: [...coordinates[index]],
16194
+ newVertexIndex: -1,
16195
+ edgeInfo: null,
16196
+ dragType: 'existing',
16197
+ });
16198
+ }
16199
+ }
16200
+ }, [platform, dragState.isDragging, coordinates, selectedVertexIndex]);
16047
16201
  // 结束拖拽
16048
16202
  const handleMouseUp = React.useCallback(() => {
16049
16203
  console.log('handleMouseUp', JSON.stringify(dragState));
@@ -16099,9 +16253,12 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
16099
16253
  },
16100
16254
  }, platform);
16101
16255
  document.body.style.userSelect = 'none';
16256
+ // 禁止系统滚动和浏览器触摸手势,防止底层地图跟随移动
16257
+ document.body.style.touchAction = 'none';
16102
16258
  return () => {
16103
16259
  cleanup();
16104
16260
  document.body.style.userSelect = '';
16261
+ document.body.style.touchAction = '';
16105
16262
  };
16106
16263
  }
16107
16264
  else {
@@ -16166,6 +16323,45 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
16166
16323
  const ghostFirstMidpoint = createMode && mousePos && !completed && renderCoordinates.length >= 1
16167
16324
  ? calculateMidpoint(renderCoordinates[0], [mousePos.x, mousePos.y])
16168
16325
  : null;
16326
+ // H5平台处理触摸双击
16327
+ const handleVertexDoubleTap = React.useCallback((index) => {
16328
+ const now = Date.now();
16329
+ const timeDelta = now - lastTapRef.current;
16330
+ // 检查是否为双击(300ms内,且是同一个点)
16331
+ if (timeDelta < DOUBLE_TAP_DELAY && lastTapIndexRef.current === index) {
16332
+ // 只有在选中点的情况下才允许删除
16333
+ if (selectedVertexIndex === index && onVertexDelete && coordinates.length > 3) {
16334
+ // 将渲染索引转换为原始points的索引
16335
+ onVertexDelete(renderCoordinates?.length - 1 - index);
16336
+ // 删除后立即取消拖拽状态,避免误触发拖动
16337
+ setDragState({
16338
+ isDragging: false,
16339
+ dragIndex: -1,
16340
+ originalPosition: null,
16341
+ currentPosition: null,
16342
+ newVertexIndex: -1,
16343
+ edgeInfo: null,
16344
+ dragType: null,
16345
+ });
16346
+ // 删除后取消选中状态
16347
+ setSelectedVertexIndex(-1);
16348
+ }
16349
+ // 重置点击时间
16350
+ lastTapRef.current = 0;
16351
+ lastTapIndexRef.current = -1;
16352
+ }
16353
+ else {
16354
+ // 记录本次点击
16355
+ lastTapRef.current = now;
16356
+ lastTapIndexRef.current = index;
16357
+ }
16358
+ }, [
16359
+ selectedVertexIndex,
16360
+ onVertexDelete,
16361
+ coordinates?.length,
16362
+ editMapInfo?.createMode,
16363
+ renderCoordinates?.length,
16364
+ ]);
16169
16365
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [(editMode || (createMode && completed)) &&
16170
16366
  dragState.isDragging &&
16171
16367
  dragState.dragType !== 'new' &&
@@ -16192,9 +16388,16 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
16192
16388
  renderCoordinates.map((coord, index) => {
16193
16389
  const nextCoord = renderCoordinates[(index + 1) % renderCoordinates.length];
16194
16390
  const isDashPath = coord[2] === 1;
16195
- return (jsxRuntime.jsx("line", { x1: coord[0], y1: coord[1], x2: nextCoord[0], y2: nextCoord[1], stroke: isDashPath ? 'transparent' : strokeColor, strokeWidth: strokeWidth, className: styles$2.addVertex, vectorEffect: "non-scaling-stroke", ...(platform === exports.PlatformType.H5
16391
+ return (jsxRuntime.jsx("line", { x1: coord[0], y1: coord[1], x2: nextCoord[0], y2: nextCoord[1], stroke: isDashPath ? 'transparent' : strokeColor, strokeWidth: platform === exports.PlatformType.H5 ? strokeWidth * 3 : strokeWidth, className: styles$2.addVertex, style: {
16392
+ userSelect: 'none',
16393
+ WebkitUserSelect: 'none',
16394
+ WebkitTouchCallout: 'none',
16395
+ touchAction: 'none',
16396
+ }, vectorEffect: "non-scaling-stroke", ...(platform === exports.PlatformType.H5
16196
16397
  ? {
16197
- onTouchStart: createReactEventHandler((e) => handleEdgeClick(e, index)),
16398
+ onTouchStart: createReactEventHandler((e) => handleEdgeLongPressStart(e, index)),
16399
+ onTouchEnd: createReactEventHandler(() => handleEdgeLongPressEnd()),
16400
+ onTouchCancel: createReactEventHandler(() => handleEdgeLongPressEnd()),
16198
16401
  }
16199
16402
  : {
16200
16403
  onMouseDown: (e) => handleEdgeClick(e, index),
@@ -16217,14 +16420,27 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
16217
16420
  setHoverVertex(null);
16218
16421
  },
16219
16422
  }) }, `edge-${index}`));
16220
- }), ghostLastPath && (jsxRuntime.jsx("path", { d: ghostLastPath, stroke: strokeColor, strokeWidth: strokeWidth, vectorEffect: "non-scaling-stroke", opacity: 0.7, onClick: onPathClick })), ghostFirstPath && renderCoordinates.length >= 2 && (jsxRuntime.jsx("path", { d: ghostFirstPath, stroke: strokeColor, strokeWidth: strokeWidth, vectorEffect: "non-scaling-stroke", opacity: 0.7, onClick: onPathClick })), jsxRuntime.jsx(DragDistanceIndicator, { dragState: dragState, strokeColor: strokeColor, editMode: editMode, createMode: createMode, completed: completed, fontSize: 30 * overlayScale }), jsxRuntime.jsx(DistanceLabels, { coordinates: renderCoordinates, createMode: createMode, editMode: editMode, completed: completed, showPoints: showPoints, mousePos: mousePos, ghostLastDistance: ghostLastDistance, ghostLastMidpoint: ghostLastMidpoint, ghostFirstDistance: ghostFirstDistance, ghostFirstMidpoint: ghostFirstMidpoint, fontSize: 30 * overlayScale }), hoverVertex && !dragState.isDragging && (jsxRuntime.jsx(VertexElement, { cx: hoverVertex.position.x, cy: hoverVertex.position.y, stroke: strokeColor, strokeOpacity: 0.6, fill: "white", fillOpacity: 0.8, pointerEvents: "none" })), ((createMode && showPoints) || editMode || (createMode && completed)) &&
16423
+ }), ghostLastPath && (jsxRuntime.jsx("path", { d: ghostLastPath, stroke: strokeColor, strokeWidth: strokeWidth, vectorEffect: "non-scaling-stroke", opacity: 0.7, onClick: onPathClick })), ghostFirstPath && renderCoordinates.length >= 2 && (jsxRuntime.jsx("path", { d: ghostFirstPath, stroke: strokeColor, strokeWidth: strokeWidth, vectorEffect: "non-scaling-stroke", opacity: 0.7, onClick: onPathClick })), jsxRuntime.jsx(DragDistanceIndicator, { dragState: dragState, strokeColor: strokeColor, editMode: editMode, createMode: createMode, completed: completed, fontSize: platform === exports.PlatformType.H5 ? 12 * overlayScale : 30 * overlayScale }), jsxRuntime.jsx(DistanceLabels, { coordinates: renderCoordinates, createMode: createMode, editMode: editMode, completed: completed, showPoints: showPoints, mousePos: mousePos, ghostLastDistance: ghostLastDistance, ghostLastMidpoint: ghostLastMidpoint, ghostFirstDistance: ghostFirstDistance, ghostFirstMidpoint: ghostFirstMidpoint, fontSize: platform === exports.PlatformType.H5 ? 12 * overlayScale : 30 * overlayScale }), hoverVertex && !dragState.isDragging && (jsxRuntime.jsx(VertexElement, { cx: hoverVertex.position.x, cy: hoverVertex.position.y, stroke: strokeColor, strokeOpacity: 0.6, fill: "white", fillOpacity: 0.8, pointerEvents: "none" })), ((createMode && showPoints) || editMode || (createMode && completed)) &&
16221
16424
  renderCoordinates.map((coord, idx) => {
16222
16425
  // 判断当前顶点的状态
16223
16426
  const isLastPoint = idx === renderCoordinates.length - 1;
16224
16427
  const canComplete = createMode && !completed && renderCoordinates.length >= 3 && isLastPoint;
16225
16428
  const isCreatedAndCanDrag = createMode && completed; // 创建完成后可拖拽
16226
16429
  const isInEditMode = editMode;
16227
- return (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx(VertexElement, { className: generateVertexClassName, stroke: strokeColor, cx: coord[0], cy: coord[1], r: canComplete ? 16 : 12, onClick: (e) => handleVertexClick(e, idx), onDoubleClick: (e) => {
16430
+ // H5模式下选中的顶点显示蓝色,并且放大1.5倍
16431
+ const isSelected = platform === exports.PlatformType.H5 && selectedVertexIndex === idx;
16432
+ const vertexRadius = isSelected ? (canComplete ? 16 : 12) * 1.2 : canComplete ? 16 : 12;
16433
+ const vertexFill = isSelected ? '#FFAB7E' : 'white';
16434
+ return (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx(VertexElement, { className: generateVertexClassName, style: {
16435
+ userSelect: 'none',
16436
+ WebkitUserSelect: 'none',
16437
+ WebkitTouchCallout: 'none',
16438
+ touchAction: 'none',
16439
+ }, stroke: strokeColor, fill: vertexFill, cx: coord[0], cy: coord[1], r: vertexRadius, onClick: (e) => handleVertexClick(e, idx), onDoubleClick: (e) => {
16440
+ console.log('双击事件', selectedVertexIndex, idx);
16441
+ if (platform === exports.PlatformType.H5) {
16442
+ return;
16443
+ }
16228
16444
  // 阻止双击事件冒泡到Google Maps
16229
16445
  e.preventDefault();
16230
16446
  e.stopPropagation();
@@ -16242,12 +16458,6 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
16242
16458
  setTimeout(() => {
16243
16459
  isDoubleClickingRef.current = false;
16244
16460
  }, 300);
16245
- if (platform === exports.PlatformType.H5) {
16246
- if (onVertexDelete && coordinates.length > 3) {
16247
- onVertexDelete(idx);
16248
- }
16249
- return;
16250
- }
16251
16461
  // 打开删除确认 Tooltip(仅在可编辑时)
16252
16462
  if (editMode || (createMode && completed)) {
16253
16463
  setTooltipIndex(idx);
@@ -16255,12 +16465,51 @@ const PolygonElement = ({ points, fillColor = 'rgba(0, 0, 0, 0.1)', fillOpacity
16255
16465
  }, ...(platform === exports.PlatformType.H5
16256
16466
  ? {
16257
16467
  onTouchStart: createReactEventHandler((e) => {
16258
- // 拖拽逻辑:编辑模式或创建完成后
16259
- if (isInEditMode || isCreatedAndCanDrag) {
16260
- if (draggable) {
16261
- handleVertexMouseDown(e, idx);
16262
- }
16468
+ e.preventDefault();
16469
+ e.stopPropagation();
16470
+ // 如果不是支持拖拽的话,则不往下走
16471
+ if (!draggable) {
16472
+ return;
16473
+ }
16474
+ // 如果未选中,则走长按选中逻辑
16475
+ if (selectedVertexIndex !== idx) {
16476
+ handleVertexLongPressStart(e, idx);
16263
16477
  }
16478
+ else {
16479
+ // 已选中:准备可能的拖拽(记录起点),不阻塞双击
16480
+ touchStartPosRef.current = {
16481
+ x: e.clientX,
16482
+ y: e.clientY,
16483
+ };
16484
+ hasStartedDragViaLongPressRef.current = false;
16485
+ isVertexLongPressedRef.current = false;
16486
+ longPressVertexIndexRef.current = idx;
16487
+ }
16488
+ }),
16489
+ onTouchMove: createReactEventHandler((e) => {
16490
+ // 如果不是支持拖拽的话,则不往下走
16491
+ if (!draggable) {
16492
+ return;
16493
+ }
16494
+ // 长按后,超过阈值再进入拖拽
16495
+ handleVertexTouchMoveMaybeStartDrag(e, idx);
16496
+ }),
16497
+ onTouchEnd: createReactEventHandler(() => {
16498
+ // 如果不是支持拖拽的话,则不往下走
16499
+ if (!draggable) {
16500
+ return;
16501
+ }
16502
+ // 如果已经通过长按进入拖拽,不触发双击检测
16503
+ const startedDrag = hasStartedDragViaLongPressRef.current;
16504
+ handleVertexLongPressEnd();
16505
+ if (!startedDrag && !isVertexLongPressedRef.current) {
16506
+ handleVertexDoubleTap(idx);
16507
+ }
16508
+ hasStartedDragViaLongPressRef.current = false;
16509
+ }),
16510
+ onTouchCancel: createReactEventHandler(() => {
16511
+ handleVertexLongPressEnd();
16512
+ hasStartedDragViaLongPressRef.current = false;
16264
16513
  }),
16265
16514
  }
16266
16515
  : {
@@ -16340,12 +16589,19 @@ const BoundaryElement = ({ data }) => {
16340
16589
  editMapInfo.mobileMode === exports.MobileEditMode.CREATE) {
16341
16590
  return;
16342
16591
  }
16343
- setEditMapInfo((prev) => ({
16344
- ...prev,
16345
- mobileMode: exports.MobileEditMode.START,
16346
- elementType: exports.DataType.BOUNDARY,
16347
- selectElement: data,
16348
- }));
16592
+ if (editMapInfo.selectElement?.id === data.id) {
16593
+ setEditMapInfo({
16594
+ ...INIT_EDIT_MAP_INFO,
16595
+ });
16596
+ }
16597
+ else {
16598
+ setEditMapInfo((prev) => ({
16599
+ ...prev,
16600
+ mobileMode: exports.MobileEditMode.START,
16601
+ elementType: exports.DataType.BOUNDARY,
16602
+ selectElement: data,
16603
+ }));
16604
+ }
16349
16605
  }
16350
16606
  else {
16351
16607
  if (editMapInfo?.selectElement)
@@ -16358,7 +16614,11 @@ const BoundaryElement = ({ data }) => {
16358
16614
  }));
16359
16615
  }
16360
16616
  }, [platform, data, editMapInfo]);
16361
- return (jsxRuntime.jsx(PolygonElement, { points: currentPoints, fillColor: style.fillColor, fillOpacity: style.fillOpacity, strokeColor: style.lineColor, strokeWidth: strokeWidth, editMode: false, onPathClick: onPathClick, onCoordinatesChange: (coordinates) => {
16617
+ return (jsxRuntime.jsx(PolygonElement, { points: currentPoints, fillColor: style.fillColor, fillOpacity: style.fillOpacity, strokeColor: style.lineColor, strokeWidth: strokeWidth, editMode: false, onPathClick: onPathClick, onPolygonClick: () => {
16618
+ if (platform === exports.PlatformType.H5) {
16619
+ onPathClick();
16620
+ }
16621
+ }, onCoordinatesChange: (coordinates) => {
16362
16622
  console.log('onCoordinatesChange', coordinates);
16363
16623
  setEditMapInfo((prev) => ({
16364
16624
  ...prev,
@@ -16480,25 +16740,26 @@ const ObstacleElement = ({ data }) => {
16480
16740
  const { addHistory } = useHistoryHandle();
16481
16741
  // 处理删除顶点
16482
16742
  const handleCreateVertexDelete = React.useCallback((vertexIndex) => {
16743
+ console.log('ObstacleElement删除顶点', vertexIndex);
16483
16744
  if (editMapInfo?.selectElement?.points && editMapInfo?.selectElement?.points?.length > 0) {
16484
16745
  const newPoints = editMapInfo?.selectElement?.points?.filter((_, index) => index !== vertexIndex);
16746
+ console.log('newPoints', newPoints);
16485
16747
  setEditMapInfo((prev) => ({
16486
16748
  ...prev,
16487
16749
  selectElement: {
16488
16750
  ...prev.selectElement,
16489
- points: newPoints,
16751
+ points: [...newPoints],
16490
16752
  },
16491
16753
  }));
16492
16754
  addHistory({
16493
16755
  selectElement: {
16494
16756
  ...editMapInfo.selectElement,
16495
- points: newPoints,
16757
+ points: [...newPoints],
16496
16758
  },
16497
16759
  });
16498
16760
  }
16499
16761
  }, [editMapInfo]);
16500
16762
  const currentPoints = React.useMemo(() => {
16501
- // 为了方便解决删除顶点的时候,delete icon被遮挡的问题,所以逆序一下
16502
16763
  if (editMapInfo?.selectElement?.id === data.id) {
16503
16764
  return editMapInfo.selectElement.points;
16504
16765
  }
@@ -16524,13 +16785,19 @@ const ObstacleElement = ({ data }) => {
16524
16785
  editMapInfo.mobileMode === exports.MobileEditMode.CREATE) {
16525
16786
  return;
16526
16787
  }
16527
- setEditMapInfo((prev) => ({
16528
- ...prev,
16529
- mobileMode: exports.MobileEditMode.START,
16530
- elementType: exports.DataType.OBSTACLE,
16531
- selectElement: data,
16532
- }));
16533
- return;
16788
+ if (editMapInfo.selectElement?.id === data.id) {
16789
+ setEditMapInfo({
16790
+ ...INIT_EDIT_MAP_INFO,
16791
+ });
16792
+ }
16793
+ else {
16794
+ setEditMapInfo((prev) => ({
16795
+ ...prev,
16796
+ mobileMode: exports.MobileEditMode.START,
16797
+ elementType: exports.DataType.OBSTACLE,
16798
+ selectElement: data,
16799
+ }));
16800
+ }
16534
16801
  }
16535
16802
  if (disabledObstacles || editMapInfo?.selectElement)
16536
16803
  return;
@@ -16561,10 +16828,12 @@ const ObstacleElement = ({ data }) => {
16561
16828
  return editMapInfo?.selectElement?.id === data.id;
16562
16829
  }, [editMapInfo, data, platform]);
16563
16830
  return (jsxRuntime.jsx(PolygonElement, { points: currentPoints, fillColor: style.fillColor, fillOpacity: style.fillOpacity, strokeColor: style.lineColor, strokeWidth: strokeWidth, editMode: editMode, showPoints: editMapInfo?.selectElement?.id === data.id, onPathClick: onPathClick, onPolygonClick: () => {
16831
+ // h5的情况下,支持点击禁区内部,也会触发选中
16564
16832
  if (platform === exports.PlatformType.H5) {
16565
16833
  onPathClick();
16566
16834
  }
16567
16835
  }, onVertexDelete: (vertexIndex) => handleCreateVertexDelete(vertexIndex), onCoordinatesChange: (coordinates) => {
16836
+ console.log('onCoordinatesChange', coordinates);
16568
16837
  if (platform === exports.PlatformType.H5 && editMapInfo.mobileMode === exports.MobileEditMode.CREATE) {
16569
16838
  return;
16570
16839
  }
@@ -17368,15 +17637,12 @@ const VisionOffElement = ({ data, onSelect }) => {
17368
17637
  if (platform === exports.PlatformType.H5) {
17369
17638
  // h5编辑模式下,
17370
17639
  // start模式可以任意选
17371
- // create或者是edit模式的话,只有选中的是visionOff的时候才能选中
17372
- if ((editMapInfo.mobileMode === exports.MobileEditMode.CREATE ||
17373
- editMapInfo.mobileMode === exports.MobileEditMode.EDIT) &&
17374
- editMapInfo.elementType !== exports.DataType.VISION_OFF) {
17375
- return;
17376
- }
17377
- if ((editMapInfo.mobileMode === exports.MobileEditMode.CREATE ||
17378
- editMapInfo.mobileMode === exports.MobileEditMode.EDIT) &&
17379
- editMapInfo.elementType === exports.DataType.VISION_OFF) {
17640
+ // create或者是edit模式的话,只有选中的是visionOff的时候才能操作
17641
+ if (editMapInfo.mobileMode === exports.MobileEditMode.CREATE ||
17642
+ editMapInfo.mobileMode === exports.MobileEditMode.EDIT) {
17643
+ if (editMapInfo.elementType !== exports.DataType.VISION_OFF) {
17644
+ return;
17645
+ }
17380
17646
  setEditMapInfo((prev) => ({
17381
17647
  ...prev,
17382
17648
  selectElement: data,
@@ -17385,12 +17651,19 @@ const VisionOffElement = ({ data, onSelect }) => {
17385
17651
  }));
17386
17652
  return;
17387
17653
  }
17388
- setEditMapInfo((prev) => ({
17389
- ...prev,
17390
- selectElement: data,
17391
- elementType: exports.DataType.VISION_OFF,
17392
- mobileMode: exports.MobileEditMode.START,
17393
- }));
17654
+ if (editMapInfo.selectElement?.id === data.id) {
17655
+ setEditMapInfo({
17656
+ ...INIT_EDIT_MAP_INFO,
17657
+ });
17658
+ }
17659
+ else {
17660
+ setEditMapInfo((prev) => ({
17661
+ ...prev,
17662
+ selectElement: data,
17663
+ elementType: exports.DataType.VISION_OFF,
17664
+ mobileMode: exports.MobileEditMode.START,
17665
+ }));
17666
+ }
17394
17667
  return;
17395
17668
  }
17396
17669
  if (editMapInfo?.selectElement)
@@ -17902,7 +18175,7 @@ const DoodleTransformWrapper = ({ data, isSelected = false, isSelectedWithoutOpe
17902
18175
  }, [data]);
17903
18176
  const remainingTime = React.useMemo(() => {
17904
18177
  const currentTime = Math.floor(Date.now() / 1000);
17905
- console.log('data.expiration_ts--', data.expiration_ts);
18178
+ // console.log('data.expiration_ts--', data.expiration_ts);
17906
18179
  if (data.expiration_ts <= currentTime) {
17907
18180
  return 0;
17908
18181
  }
@@ -18203,7 +18476,7 @@ const DoodleElement = ({ data }) => {
18203
18476
  editMapInfo.mobileMode === exports.MobileEditMode.EDIT) {
18204
18477
  return;
18205
18478
  }
18206
- // 如果是编辑的话
18479
+ // 如果start模式下
18207
18480
  setEditMapInfo((prev) => ({
18208
18481
  ...prev,
18209
18482
  selectElement: data,
@@ -19333,7 +19606,7 @@ function usePolygonDrawing(options = {}) {
19333
19606
  const { checkCanNotCreateAtPosition } = useCheckElement();
19334
19607
  const { addHistory } = useHistoryHandle();
19335
19608
  const points = React.useMemo(() => {
19336
- console.log('points->', editMapInfo?.selectElement?.points);
19609
+ // console.log('points->', editMapInfo?.selectElement?.points);
19337
19610
  return editMapInfo?.selectElement?.points?.map((item) => ({ x: item[0], y: item[1] })) || [];
19338
19611
  }, [editMapInfo?.selectElement?.points]);
19339
19612
  const completed = React.useMemo(() => {
@@ -20477,13 +20750,6 @@ modelType, mapRef, mapJson, pathJson, realTimeData, antennaConfig, onMapLoad, on
20477
20750
  const scale = Math.pow(2, -zoomDiff); // 负数实现反向缩放
20478
20751
  console.log('scale', scale, currentZoom, zoomDiff);
20479
20752
  setOverlayScale(scale < 1 ? 1 : scale);
20480
- // if (scale < 1) {
20481
- // setOverlayScale(1);
20482
- // } else if (scale > 4) {
20483
- // setOverlayScale(4);
20484
- // } else {
20485
- // setOverlayScale(scale);
20486
- // }
20487
20753
  };
20488
20754
  // 使用lodash throttle进行节流处理: 100ms内只执行一次
20489
20755
  const handleZoomChanged = throttle$2(updateScale, 50);