1、增加路线右击自定义菜单,按照开始点和结束点自动生成左上、右下、右上、左下直角拐角
2、点击地图显示实际位置改为点击到节点则按照节点的位置展示
This commit is contained in:
parent
8efb54dd52
commit
cd17472173
@ -497,6 +497,7 @@
|
|||||||
<!-- 节点合集 -->
|
<!-- 节点合集 -->
|
||||||
<div
|
<div
|
||||||
@mousedown="startFromPoint(index, $event)"
|
@mousedown="startFromPoint(index, $event)"
|
||||||
|
@click.stop="handleNodeClick(item)"
|
||||||
:style="{ width: item.locationWidePx + 'px', height: item.locationDeepPx + 'px' }"
|
:style="{ width: item.locationWidePx + 'px', height: item.locationDeepPx + 'px' }"
|
||||||
>
|
>
|
||||||
<!-- 1 路径点 -->
|
<!-- 1 路径点 -->
|
||||||
@ -700,6 +701,7 @@
|
|||||||
:stroke="curve.isSelected ? '#f48924' : '#2d72d9'"
|
:stroke="curve.isSelected ? '#f48924' : '#2d72d9'"
|
||||||
:stroke-width="state.routeWidthForm.routeWidth"
|
:stroke-width="state.routeWidthForm.routeWidth"
|
||||||
@click="(e) => handleChooseRoute(curve, index, 'line', e)"
|
@click="(e) => handleChooseRoute(curve, index, 'line', e)"
|
||||||
|
@contextmenu="handleCurveContextMenu(curve, index, $event)"
|
||||||
/>
|
/>
|
||||||
<text
|
<text
|
||||||
style="user-select: none"
|
style="user-select: none"
|
||||||
@ -724,6 +726,7 @@
|
|||||||
:stroke-width="state.routeWidthForm.routeWidth"
|
:stroke-width="state.routeWidthForm.routeWidth"
|
||||||
fill="none"
|
fill="none"
|
||||||
@click="handleChooseRoute(curve, index)"
|
@click="handleChooseRoute(curve, index)"
|
||||||
|
@contextmenu="handleCurveContextMenu(curve, index, $event)"
|
||||||
/>
|
/>
|
||||||
<text
|
<text
|
||||||
style="user-select: none"
|
style="user-select: none"
|
||||||
@ -766,7 +769,12 @@
|
|||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<!-- 控制点circle统一渲染,保证层级最高 -->
|
<!-- 控制点circle统一渲染,保证层级最高 -->
|
||||||
<template v-if="state.currentDragTarget.index !== null">
|
<template
|
||||||
|
v-if="
|
||||||
|
state.currentDragTarget.index !== null &&
|
||||||
|
state.mapRouteList[state.currentDragTarget.index].method !== 0
|
||||||
|
"
|
||||||
|
>
|
||||||
<circle
|
<circle
|
||||||
id="startCircle"
|
id="startCircle"
|
||||||
:cx="state.mapRouteList[state.currentDragTarget.index].beginControlX"
|
:cx="state.mapRouteList[state.currentDragTarget.index].beginControlX"
|
||||||
@ -958,7 +966,7 @@
|
|||||||
:imgBgObj="imgBgObj"
|
:imgBgObj="imgBgObj"
|
||||||
@submit-batch-copying-form-success="submitBatchCopyingFormSuccess"
|
@submit-batch-copying-form-success="submitBatchCopyingFormSuccess"
|
||||||
/>
|
/>
|
||||||
|
<!-- 节点右击菜单 -->
|
||||||
<div
|
<div
|
||||||
v-if="state.contextMenu.visible"
|
v-if="state.contextMenu.visible"
|
||||||
class="context-menu"
|
class="context-menu"
|
||||||
@ -974,6 +982,24 @@
|
|||||||
>生成检测点</div
|
>生成检测点</div
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 曲线右击菜单 -->
|
||||||
|
<div
|
||||||
|
v-if="state.curveContextMenu.visible"
|
||||||
|
class="context-menu"
|
||||||
|
:style="{ left: state.curveContextMenu.x + 'px', top: state.curveContextMenu.y + 'px' }"
|
||||||
|
@click.stop
|
||||||
|
>
|
||||||
|
<div class="context-menu-item" @click="deleteCurveRoute">删除</div>
|
||||||
|
<div class="context-menu-item" @click="contextMenuEditRoute">编辑路线</div>
|
||||||
|
<template
|
||||||
|
v-for="dir in getAvailableRightAngleDirections(state.curveContextMenu.currentCurve)"
|
||||||
|
:key="dir"
|
||||||
|
>
|
||||||
|
<div class="context-menu-item" @click="() => setCurveRightAngle(dir)">
|
||||||
|
{{ rightAngleDirectionLabel(dir) }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -1742,6 +1768,13 @@ const state = reactive({
|
|||||||
y: 0, // 菜单y坐标
|
y: 0, // 菜单y坐标
|
||||||
currentItem: null, // 当前右击的库位信息
|
currentItem: null, // 当前右击的库位信息
|
||||||
currentIndex: -1 // 当前右击的库位索引
|
currentIndex: -1 // 当前右击的库位索引
|
||||||
|
},
|
||||||
|
curveContextMenu: {
|
||||||
|
visible: false,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
currentCurve: null,
|
||||||
|
currentIndex: -1
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2120,6 +2153,7 @@ const handleContextMenu = (item, index, event) => {
|
|||||||
state.contextMenu.y = event.clientY
|
state.contextMenu.y = event.clientY
|
||||||
state.contextMenu.currentItem = item
|
state.contextMenu.currentItem = item
|
||||||
state.contextMenu.currentIndex = index
|
state.contextMenu.currentIndex = index
|
||||||
|
state.currentItemIndex = index
|
||||||
}
|
}
|
||||||
|
|
||||||
// 隐藏右击菜单
|
// 隐藏右击菜单
|
||||||
@ -4347,6 +4381,129 @@ const findClosestPoint = (x, y) => {
|
|||||||
|
|
||||||
return closestIndex
|
return closestIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 曲线右击事件
|
||||||
|
const handleCurveContextMenu = (curve, index, event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
state.curveContextMenu.visible = true
|
||||||
|
state.curveContextMenu.x = event.clientX
|
||||||
|
state.curveContextMenu.y = event.clientY
|
||||||
|
state.curveContextMenu.currentCurve = curve
|
||||||
|
state.curveContextMenu.currentIndex = index
|
||||||
|
state.currentDragTarget.index = index
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏曲线右击菜单
|
||||||
|
const hideCurveContextMenu = () => {
|
||||||
|
state.curveContextMenu.visible = false
|
||||||
|
state.curveContextMenu.currentIndex = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// 曲线删除(仅UI,逻辑留空)
|
||||||
|
const deleteCurveRoute = () => {
|
||||||
|
if (state.currentDragTarget.index !== null) {
|
||||||
|
state.mapRouteList.splice(state.currentDragTarget.index, 1)
|
||||||
|
state.currentDragTarget.index = null
|
||||||
|
}
|
||||||
|
addEditHistory()
|
||||||
|
hideCurveContextMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击空白处关闭曲线菜单
|
||||||
|
window.addEventListener('click', (e) => {
|
||||||
|
if (state.curveContextMenu.visible) {
|
||||||
|
const menu = document.querySelector('.context-menu')
|
||||||
|
if (menu && !menu.contains(e.target)) {
|
||||||
|
hideCurveContextMenu()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 直角拐角控制点计算
|
||||||
|
function getRightAngleControlPoints(direction, start, end, offset = 0) {
|
||||||
|
let corner
|
||||||
|
if (direction === 'leftTop') {
|
||||||
|
corner = { x: Math.min(start.x, end.x), y: Math.min(start.y, end.y) }
|
||||||
|
} else if (direction === 'rightBottom') {
|
||||||
|
corner = { x: Math.max(start.x, end.x), y: Math.max(start.y, end.y) }
|
||||||
|
} else if (direction === 'leftBottom') {
|
||||||
|
corner = { x: Math.min(start.x, end.x), y: Math.max(start.y, end.y) }
|
||||||
|
} else if (direction === 'rightTop') {
|
||||||
|
corner = { x: Math.max(start.x, end.x), y: Math.min(start.y, end.y) }
|
||||||
|
} else {
|
||||||
|
corner = { x: end.x, y: start.y }
|
||||||
|
}
|
||||||
|
// 计算单位向量
|
||||||
|
const getUnit = (from, to) => {
|
||||||
|
const dx = from.x - to.x
|
||||||
|
const dy = from.y - to.y
|
||||||
|
const len = Math.sqrt(dx * dx + dy * dy) || 1
|
||||||
|
return { x: dx / len, y: dy / len }
|
||||||
|
}
|
||||||
|
// 控制点分别在拐点往起点/终点方向各偏移offset像素
|
||||||
|
const u1 = getUnit(corner, start)
|
||||||
|
const u2 = getUnit(corner, end)
|
||||||
|
const beginControl = { x: corner.x + u1.x * offset, y: corner.y + u1.y * offset }
|
||||||
|
const endControl = { x: corner.x + u2.x * offset, y: corner.y + u2.y * offset }
|
||||||
|
return { beginControl, endControl }
|
||||||
|
}
|
||||||
|
// 设置曲线为直角拐角
|
||||||
|
function setCurveRightAngle(direction) {
|
||||||
|
const curve = state.curveContextMenu.currentCurve
|
||||||
|
if (!curve) return
|
||||||
|
const start = { x: curve.startPointX, y: curve.startPointY }
|
||||||
|
const end = { x: curve.endPointX, y: curve.endPointY }
|
||||||
|
const { beginControl, endControl } = getRightAngleControlPoints(direction, start, end)
|
||||||
|
curve.beginControlX = beginControl.x
|
||||||
|
curve.beginControlY = beginControl.y
|
||||||
|
curve.endControlX = endControl.x
|
||||||
|
curve.endControlY = endControl.y
|
||||||
|
curve.method = 1
|
||||||
|
hideCurveContextMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态判断可用直角拐角方向
|
||||||
|
function getAvailableRightAngleDirections(curve) {
|
||||||
|
if (!curve) return []
|
||||||
|
const sx = curve.startPointX,
|
||||||
|
sy = curve.startPointY,
|
||||||
|
ex = curve.endPointX,
|
||||||
|
ey = curve.endPointY
|
||||||
|
const dx = ex - sx
|
||||||
|
const dy = ey - sy
|
||||||
|
if (dx === 0 || dy === 0) return []
|
||||||
|
if (dx * dy > 0) return ['leftBottom', 'rightTop']
|
||||||
|
if (dx * dy < 0) return ['leftTop', 'rightBottom']
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
// 方向label
|
||||||
|
function rightAngleDirectionLabel(dir) {
|
||||||
|
switch (dir) {
|
||||||
|
case 'rightTop':
|
||||||
|
return '右上直角拐角'
|
||||||
|
case 'rightBottom':
|
||||||
|
return '右下直角拐角'
|
||||||
|
case 'leftTop':
|
||||||
|
return '左上直角拐角'
|
||||||
|
case 'leftBottom':
|
||||||
|
return '左下直角拐角'
|
||||||
|
default:
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//右击编辑路线
|
||||||
|
const contextMenuEditRoute = () => {
|
||||||
|
removeEventListener() //移除监听
|
||||||
|
let item = state.mapRouteList[state.currentDragTarget.index]
|
||||||
|
editMapRouteDialogRef.value.open(JSON.parse(JSON.stringify(item)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增:处理节点点击,显示节点locationX/locationY
|
||||||
|
function handleNodeClick(item) {
|
||||||
|
state.actualLocation.x = item.actualLocationX ? Number(item.actualLocationX).toFixed(3) : ''
|
||||||
|
state.actualLocation.y = item.actualLocationY ? Number(item.actualLocationY).toFixed(3) : ''
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
Loading…
Reference in New Issue
Block a user