地图编辑

This commit is contained in:
yyy 2025-02-26 17:41:03 +08:00
parent 6db5611af3
commit d74f617af9
9 changed files with 185 additions and 120 deletions

View File

@ -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) => {

View File

@ -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

View File

@ -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 = ''

View File

@ -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()

View File

@ -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) => {

View File

@ -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()

View File

@ -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) {

View File

@ -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)

View File

@ -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>