地图编辑
This commit is contained in:
parent
6db5611af3
commit
d74f617af9
@ -1,6 +1,12 @@
|
||||
<template>
|
||||
<!-- 新增设备 -->
|
||||
<Dialog v-model="dialogFormVisible" title="编辑路线" width="780" class="map-edit-route-dialog">
|
||||
<Dialog
|
||||
v-model="dialogFormVisible"
|
||||
title="编辑路线"
|
||||
width="780"
|
||||
class="map-edit-route-dialog"
|
||||
@close="dialogClose"
|
||||
>
|
||||
<el-form :model="form" label-width="120" ref="ruleFormRef">
|
||||
<el-row :gutter="30">
|
||||
<el-col :span="12">
|
||||
@ -215,7 +221,11 @@ const open = (item) => {
|
||||
form.value = item
|
||||
}
|
||||
|
||||
const emit = defineEmits(['editMapRouteDialogSubmit'])
|
||||
const dialogClose = () => {
|
||||
emit('addEventListener')
|
||||
}
|
||||
|
||||
const emit = defineEmits(['editMapRouteDialogSubmit', 'addEventListener'])
|
||||
const submitForm = async (formEl) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate(async (valid, fields) => {
|
||||
|
@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogFormVisible" title="节点属性" width="540" class="node-form-dialog">
|
||||
<Dialog
|
||||
v-model="dialogFormVisible"
|
||||
title="节点属性"
|
||||
width="540"
|
||||
class="node-form-dialog"
|
||||
@close="dialogClose"
|
||||
>
|
||||
<el-form :model="form" label-width="auto" ref="ruleFormRef">
|
||||
<el-form-item
|
||||
label="X"
|
||||
@ -169,7 +175,7 @@ const rules = reactive({
|
||||
layersNumber: [{ required: true, message: '请输入层数', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const emit = defineEmits(['submitNodeSuccess'])
|
||||
const emit = defineEmits(['submitNodeSuccess', 'addEventListener'])
|
||||
const submit = async (formEl) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid, fields) => {
|
||||
@ -236,6 +242,10 @@ const submit = async (formEl) => {
|
||||
})
|
||||
}
|
||||
|
||||
const dialogClose = () => {
|
||||
emit('addEventListener')
|
||||
}
|
||||
|
||||
const equipmentList = ref([]) //用过的设备列表
|
||||
const open = (item, list) => {
|
||||
form.value = item
|
||||
|
@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogFormVisible" title="设备" width="586" class="equipment-form-dialog">
|
||||
<Dialog
|
||||
v-model="dialogFormVisible"
|
||||
title="设备"
|
||||
width="586"
|
||||
class="equipment-form-dialog"
|
||||
@close="dialogClose"
|
||||
>
|
||||
<div class="device-list">
|
||||
<div class="device-item" v-for="(item, index) in deviceList" :key="index">
|
||||
<img class="img" :src="item.url" />
|
||||
@ -145,6 +151,11 @@ const open = (list) => {
|
||||
getDeviceList()
|
||||
}
|
||||
|
||||
const emit = defineEmits(['addEventListener'])
|
||||
const dialogClose = () => {
|
||||
emit('addEventListener')
|
||||
}
|
||||
|
||||
const initAddForm = () => {
|
||||
deviceInfo.value.deviceInfoId = ''
|
||||
deviceInfo.value.deviceType = ''
|
||||
|
@ -4,6 +4,7 @@
|
||||
title="区域管理"
|
||||
width="600"
|
||||
class="item-area-management-dialog"
|
||||
@close="dialogClose"
|
||||
>
|
||||
<el-table
|
||||
:data="list"
|
||||
@ -55,6 +56,11 @@ const open = () => {
|
||||
getWareHouseList()
|
||||
}
|
||||
|
||||
const emit = defineEmits(['addEventListener'])
|
||||
const dialogClose = () => {
|
||||
emit('addEventListener')
|
||||
}
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref()
|
||||
|
@ -5,6 +5,7 @@
|
||||
title="物料区域设置"
|
||||
width="600"
|
||||
class="equipment-form-dialog"
|
||||
@close="dialogClose"
|
||||
>
|
||||
<el-form :model="form" label-width="110" ref="ruleFormRef">
|
||||
<el-form-item label="物料区域名称" prop="skuInfo" required>
|
||||
@ -64,6 +65,11 @@ const open = (list) => {
|
||||
form.value.skuInfo = ''
|
||||
}
|
||||
|
||||
const emit = defineEmits(['addEventListener'])
|
||||
const dialogClose = () => {
|
||||
emit('addEventListener')
|
||||
}
|
||||
|
||||
const submitForm = async (formEl) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate(async (valid, fields) => {
|
||||
|
@ -4,6 +4,7 @@
|
||||
title="线库管理"
|
||||
width="600"
|
||||
class="line-library-management-dialog"
|
||||
@close="dialogClose"
|
||||
>
|
||||
<el-table
|
||||
:data="list"
|
||||
@ -54,6 +55,11 @@ const open = () => {
|
||||
getLineLibraryList()
|
||||
}
|
||||
|
||||
const emit = defineEmits(['addEventListener'])
|
||||
const dialogClose = () => {
|
||||
emit('addEventListener')
|
||||
}
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref()
|
||||
|
@ -1,6 +1,12 @@
|
||||
<template>
|
||||
<!-- 新增设备 -->
|
||||
<Dialog v-model="dialogFormVisible" title="线库设置" width="600" class="equipment-form-dialog">
|
||||
<Dialog
|
||||
v-model="dialogFormVisible"
|
||||
title="线库设置"
|
||||
width="600"
|
||||
class="equipment-form-dialog"
|
||||
@close="dialogClose"
|
||||
>
|
||||
<el-form :model="form" label-width="110" ref="lineFormRef" :rules="rules">
|
||||
<el-form-item label="线库名称" prop="laneName" required>
|
||||
<el-input v-model="form.laneName" placeholder="请输入线库名称" />
|
||||
@ -53,6 +59,11 @@ const open = (list) => {
|
||||
form.value.laneName = ''
|
||||
}
|
||||
|
||||
const emit = defineEmits(['addEventListener'])
|
||||
const dialogClose = () => {
|
||||
emit('addEventListener')
|
||||
}
|
||||
|
||||
const submitLineLibraryForm = async () => {
|
||||
await lineFormRef.value.validate(async (valid, fields) => {
|
||||
if (valid) {
|
||||
|
@ -527,6 +527,7 @@
|
||||
ref="editNodePropertiesRef"
|
||||
:positionMapId="imgBgObj.positionMapId"
|
||||
@submitNodeSuccess="submitNodeSuccess"
|
||||
@addEventListener="addEventListener"
|
||||
/>
|
||||
<!-- 文字输入弹窗 -->
|
||||
<textFormToolDialog
|
||||
@ -542,29 +543,41 @@
|
||||
@layerSelectionSuccess="layerSelectionSuccess"
|
||||
/>
|
||||
<!-- 设备弹窗选择 -->
|
||||
<equipmentToolDialog ref="equipmentToolDialogRef" :positionMapId="imgBgObj.positionMapId" />
|
||||
<equipmentToolDialog
|
||||
ref="equipmentToolDialogRef"
|
||||
:positionMapId="imgBgObj.positionMapId"
|
||||
@addEventListener="addEventListener"
|
||||
/>
|
||||
<!-- 区域选择 -->
|
||||
<itemAreaSettingDialog ref="itemAreaSettingDialogRef" :positionMapId="imgBgObj.positionMapId" />
|
||||
<itemAreaSettingDialog
|
||||
ref="itemAreaSettingDialogRef"
|
||||
:positionMapId="imgBgObj.positionMapId"
|
||||
@addEventListener="addEventListener"
|
||||
/>
|
||||
<!-- 线库设置 -->
|
||||
<lineLibrarySettingDialog
|
||||
ref="lineLibrarySettingDialogRef"
|
||||
:positionMapId="imgBgObj.positionMapId"
|
||||
@addEventListener="addEventListener"
|
||||
/>
|
||||
<!-- 编辑地图路线 -->
|
||||
<editMapRouteDialog
|
||||
ref="editMapRouteDialogRef"
|
||||
@editMapRouteDialogSubmit="editMapRouteDialogSubmit"
|
||||
@addEventListener="addEventListener"
|
||||
:imgBgObj="imgBgObj"
|
||||
/>
|
||||
<!-- 线库管理 -->
|
||||
<lineLibraryManagementDialog
|
||||
ref="lineLibraryManagementDialogRef"
|
||||
:positionMapId="imgBgObj.positionMapId"
|
||||
@addEventListener="addEventListener"
|
||||
/>
|
||||
<!-- 区域管理 -->
|
||||
<itemAreaManagementDialog
|
||||
ref="itemAreaManagementDialogRef"
|
||||
:positionMapId="imgBgObj.positionMapId"
|
||||
@addEventListener="addEventListener"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -693,6 +706,7 @@ const activatedHandle = (item, index) => {
|
||||
//节点编辑
|
||||
if (toolbarSwitchType.value === 'editNode' && item.type !== 7) {
|
||||
let list = state.allMapPointInfo.filter((item) => item.type === 3)
|
||||
removeEventListener() //移除监听
|
||||
editNodePropertiesRef.value.open(JSON.parse(JSON.stringify(item)), list)
|
||||
}
|
||||
}
|
||||
@ -1222,9 +1236,11 @@ const toolbarClick = async (item) => {
|
||||
break
|
||||
case 'lineLibraryManage':
|
||||
// 线库管理
|
||||
removeEventListener() //移除监听
|
||||
lineLibraryManagementDialogRef.value.open()
|
||||
break
|
||||
case 'regionManage':
|
||||
removeEventListener() //移除监听
|
||||
itemAreaManagementDialogRef.value.open()
|
||||
// 区域管理
|
||||
break
|
||||
@ -1307,6 +1323,7 @@ const toolbarClick = async (item) => {
|
||||
let equipmentList = state.allMapPointInfo.filter((item) => {
|
||||
return item.type === 3
|
||||
})
|
||||
removeEventListener() //移除监听
|
||||
equipmentToolDialogRef.value.open(equipmentList)
|
||||
break
|
||||
}
|
||||
@ -1628,6 +1645,7 @@ const clickDrawSelectionArea = () => {
|
||||
message.warning('您选择的库位存在未保存的')
|
||||
return
|
||||
}
|
||||
removeEventListener() //移除监听
|
||||
lineLibrarySettingDialogRef.value.open(binLocation)
|
||||
}
|
||||
//区域
|
||||
@ -1643,6 +1661,7 @@ const clickDrawSelectionArea = () => {
|
||||
message.warning('您选择的库位存在未保存的')
|
||||
return
|
||||
}
|
||||
removeEventListener() //移除监听
|
||||
itemAreaSettingDialogRef.value.open(binLocation)
|
||||
}
|
||||
|
||||
@ -1797,6 +1816,7 @@ const handleEditRoute = (item, index) => {
|
||||
})
|
||||
state.currentDragTarget.index = index
|
||||
state.selectedCurve = item
|
||||
removeEventListener() //移除监听
|
||||
editMapRouteDialogRef.value.open(JSON.parse(JSON.stringify(item)))
|
||||
}
|
||||
//单击 选中
|
||||
@ -1965,7 +1985,7 @@ const getAllNodeList = async () => {
|
||||
item.dataList = []
|
||||
item.locationDeep = 50
|
||||
item.locationWide = 50
|
||||
item.draggable = false
|
||||
item.draggable = true
|
||||
item.resizable = false
|
||||
item.rotatable = false
|
||||
item.lockAspectRatio = true
|
||||
@ -2137,6 +2157,22 @@ const cmConversionPx = (cWidth, cHeight) => {
|
||||
pHeight
|
||||
}
|
||||
}
|
||||
//计算箭头坐标的值
|
||||
const getSingleArrowStart = (item) => {
|
||||
let distance =
|
||||
Math.sqrt((item.endPointX - item.startPointX) ** 2 + (item.endPointY - item.startPointY) ** 2) /
|
||||
2 +
|
||||
10
|
||||
|
||||
return distance
|
||||
}
|
||||
const getDoubleArrowStart = (item) => {
|
||||
let distance =
|
||||
Math.sqrt((item.endPointX - item.startPointX) ** 2 + (item.endPointY - item.startPointY) ** 2) /
|
||||
2 -
|
||||
10
|
||||
return distance
|
||||
}
|
||||
|
||||
document.onmousedown = function (e) {
|
||||
//左击
|
||||
@ -2153,7 +2189,6 @@ document.onmousedown = function (e) {
|
||||
window.document.oncontextmenu = function () {
|
||||
return false
|
||||
}
|
||||
|
||||
//监听键盘事件
|
||||
const handleKeyDown = (event) => {
|
||||
if (event.ctrlKey) {
|
||||
@ -2181,6 +2216,13 @@ const handleKeyDown = (event) => {
|
||||
}
|
||||
}
|
||||
|
||||
const addEventListener = () => {
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
}
|
||||
const removeEventListener = () => {
|
||||
window.removeEventListener('keydown', handleKeyDown)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getMapList()
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
|
@ -1,32 +1,56 @@
|
||||
<template>
|
||||
<div class="box">
|
||||
<svg :width="boxWidth" :height="boxHeight">
|
||||
<div>
|
||||
<!-- 控制箭头朝向的选择框 -->
|
||||
<select v-model="arrowDirection">
|
||||
<option value="right">向右</option>
|
||||
<option value="left">向左</option>
|
||||
<option value="up">向上</option>
|
||||
<option value="down">向下</option>
|
||||
</select>
|
||||
<!-- 控制单向或双向箭头的选择框 -->
|
||||
<select v-model="isDoubleArrow">
|
||||
<option value="false">单向箭头</option>
|
||||
<option value="true">双向箭头</option>
|
||||
</select>
|
||||
<!-- 控制箭头大小的输入框 -->
|
||||
<input type="number" v-model="arrowSize" min="1" max="50" placeholder="箭头大小" />
|
||||
<!-- SVG容器 -->
|
||||
<svg width="200" height="200">
|
||||
<!-- 定义箭头样式 -->
|
||||
<defs>
|
||||
<!-- 单向箭头 -->
|
||||
<marker
|
||||
id="single-arrow"
|
||||
viewBox="0 0 10 10"
|
||||
refX="10"
|
||||
refY="5"
|
||||
markerWidth=":arrowSize"
|
||||
markerHeight=":arrowSize"
|
||||
orient="auto-start-reverse"
|
||||
>
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="black" />
|
||||
</marker>
|
||||
<!-- 双向箭头 -->
|
||||
<marker
|
||||
id="double-arrow-start"
|
||||
viewBox="0 0 10 10"
|
||||
refX="0"
|
||||
refY="5"
|
||||
markerWidth=":arrowSize"
|
||||
markerHeight=":arrowSize"
|
||||
orient="auto-start-reverse"
|
||||
>
|
||||
<path d="M 10 0 L 0 5 L 10 10 z" fill="black" />
|
||||
</marker>
|
||||
</defs>
|
||||
<!-- 根据变量绘制线条 -->
|
||||
<path
|
||||
v-for="(curve, index) in curves"
|
||||
:key="index"
|
||||
:d="getCurvePath(curve)"
|
||||
:stroke="curve.isSelected ? 'red' : 'blue'"
|
||||
:d="getPath()"
|
||||
stroke="black"
|
||||
stroke-width="2"
|
||||
fill="none"
|
||||
@mousedown="selectCurve(index)"
|
||||
/>
|
||||
<circle
|
||||
v-for="(curve, index) in curves"
|
||||
:key="'start-' + index"
|
||||
:cx="curve.startControlX"
|
||||
:cy="curve.startControlY"
|
||||
r="5"
|
||||
fill="green"
|
||||
@mousedown="startDrag(index, 'start')"
|
||||
/>
|
||||
<circle
|
||||
v-for="(curve, index) in curves"
|
||||
:key="'end-' + index"
|
||||
:cx="curve.endControlX"
|
||||
:cy="curve.endControlY"
|
||||
r="5"
|
||||
fill="green"
|
||||
@mousedown="startDrag(index, 'end')"
|
||||
:marker-start="isDoubleArrow === 'true' ? 'url(#double-arrow-start)' : ''"
|
||||
:marker-end="isDoubleArrow === 'true' ? 'url(#single-arrow)' : 'url(#single-arrow)'"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
@ -35,93 +59,32 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
// 盒子的宽度和高度
|
||||
const boxWidth = ref(800)
|
||||
const boxHeight = ref(600)
|
||||
// 定义响应式变量
|
||||
const arrowDirection = ref('right')
|
||||
const isDoubleArrow = ref('false')
|
||||
const arrowSize = ref(10)
|
||||
|
||||
// 初始点位数据
|
||||
const curves = ref([
|
||||
{
|
||||
startX: 100,
|
||||
startY: 100,
|
||||
endX: 300,
|
||||
endY: 100,
|
||||
startControlX: 100,
|
||||
startControlY: 100,
|
||||
endControlX: 300,
|
||||
endControlY: 100,
|
||||
isSelected: false
|
||||
},
|
||||
{
|
||||
startX: 200,
|
||||
startY: 200,
|
||||
endX: 400,
|
||||
endY: 200,
|
||||
startControlX: 200,
|
||||
startControlY: 200,
|
||||
endControlX: 400,
|
||||
endControlY: 400,
|
||||
isSelected: false
|
||||
// 根据箭头朝向生成路径
|
||||
const getPath = () => {
|
||||
let startX = 20
|
||||
let startY = 100
|
||||
let endX = 180
|
||||
let endY = 100
|
||||
|
||||
switch (arrowDirection.value) {
|
||||
case 'left':
|
||||
;[startX, endX] = [endX, startX]
|
||||
break
|
||||
case 'up':
|
||||
startY = 180
|
||||
endY = 20
|
||||
break
|
||||
case 'down':
|
||||
startY = 20
|
||||
endY = 180
|
||||
break
|
||||
}
|
||||
])
|
||||
|
||||
// 当前拖动的曲线索引和控制点类型
|
||||
const dragging = ref({
|
||||
index: null,
|
||||
type: null
|
||||
})
|
||||
|
||||
// 获取曲线的路径字符串
|
||||
const getCurvePath = (curve) => {
|
||||
return `M${curve.startX},${curve.startY} C${curve.startControlX},${curve.startControlY} ${curve.endControlX},${curve.endControlY} ${curve.endX},${curve.endY}`
|
||||
}
|
||||
|
||||
// 选中曲线
|
||||
const selectCurve = (index) => {
|
||||
curves.value.forEach((curve, i) => {
|
||||
curve.isSelected = i === index
|
||||
})
|
||||
console.log('Selected curve:', curves.value[index])
|
||||
}
|
||||
|
||||
// 开始拖动控制点
|
||||
const startDrag = (index, type) => {
|
||||
dragging.value = { index, type }
|
||||
window.addEventListener('mousemove', handleDrag)
|
||||
window.addEventListener('mouseup', endDrag)
|
||||
}
|
||||
|
||||
// 处理拖动事件
|
||||
const handleDrag = (event) => {
|
||||
if (dragging.value.index !== null) {
|
||||
const curve = curves.value[dragging.value.index]
|
||||
let newX = event.offsetX
|
||||
let newY = event.offsetY
|
||||
|
||||
// 确保控制点不超出盒子范围
|
||||
newX = Math.max(0, Math.min(newX, boxWidth.value))
|
||||
newY = Math.max(0, Math.min(newY, boxHeight.value))
|
||||
|
||||
if (dragging.value.type === 'start') {
|
||||
curve.startControlX = newX
|
||||
curve.startControlY = newY
|
||||
} else {
|
||||
curve.endControlX = newX
|
||||
curve.endControlY = newY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 结束拖动
|
||||
const endDrag = () => {
|
||||
dragging.value = { index: null, type: null }
|
||||
window.removeEventListener('mousemove', handleDrag)
|
||||
window.removeEventListener('mouseup', endDrag)
|
||||
return `M ${startX} ${startY} L ${endX} ${endY}`
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.box {
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user