This commit is contained in:
yyy 2025-07-19 08:52:29 +08:00
parent 6e13f318e5
commit 9fe9d3eeb0
10 changed files with 387 additions and 462 deletions

View File

@ -960,6 +960,7 @@ input::input-placeholder {
transition: background 0.2s;
}
.popover-menu-item:hover {
background: #f5f5f5;
background-color: #f5f7fa;
color: #1677ff;
}
</style>

View File

@ -175,7 +175,7 @@ const checkPointList = ref([])
//
const getTakePointList = async () => {
try {
takePointList.value = await DeviceApi.getWareHouseTakePointList({ pointType: 1 })
takePointList.value = await DeviceApi.getWareHouseTakePointList({ pointType: 0 })
} catch (error) {
console.error('获取取放货点位失败:', error)
takePointList.value = []
@ -185,7 +185,7 @@ const getTakePointList = async () => {
//
const getCheckPointList = async () => {
try {
checkPointList.value = await DeviceApi.getWareHouseTakePointList({ pointType: 0 })
checkPointList.value = await DeviceApi.getWareHouseTakePointList({ pointType: 1 })
} catch (error) {
console.error('获取检测区点位失败:', error)
checkPointList.value = []

View File

@ -278,6 +278,9 @@ const clockDevice = (item) => {
})
})
.catch(() => {})
.finally(() => {
loading.value = false // loading
})
}
//
const openForm = (type, id) => {
@ -298,6 +301,9 @@ const deleteCar = (id) => {
})
})
.catch(() => {})
.finally(() => {
loading.value = false // loading
})
}
//

View File

@ -101,7 +101,7 @@
</div>
</el-popover>
</template>
<template v-else>
<template v-else-if="locationTypeNumber == 2 || locationTypeNumber == 3">
<el-popover placement="top" trigger="click" :popper-style="{ padding: '0px' }">
<template #reference>
<img
@ -135,6 +135,30 @@
</div>
</el-popover>
</template>
<template v-else-if="locationTypeNumber == 4">
<el-popover placement="top" trigger="hover" :popper-style="{ padding: '0px' }">
<template #reference>
<div
@click="choosePoint(item)"
:style="{
position: 'absolute',
left: Number(item.locationX) - Number(item.locationWidePx) / 2 + 'px',
top: Number(item.locationY) - Number(item.locationDeepPx) / 2 + 'px',
width: item.locationWidePx + 'px',
height: item.locationDeepPx + 'px',
zIndex: 999,
backgroundColor: item.id == currentItem?.id ? '#5ecc62' : '#000',
borderRadius: '50%'
}"
></div>
</template>
<div class="drop-down-menu">
<div class="drop-down-menu">
<div class="drop-down-menu-item"> 取放货点{{ item.sortNum }} </div>
</div>
</div>
</el-popover>
</template>
</div>
</div>
</div>
@ -289,10 +313,11 @@ const getAllNodeList = async () => {
item.locationDeepPx = pxObj.pHeight
}
allMapPointInfo.value.push(item)
return
}
//线 laneId
if (item.type === 2 && locationTypeNumber.value == 2 && item.laneId !== null) {
if (locationTypeNumber.value == 2 && item.type === 2 && item.laneId !== null) {
item.locationX = Number(item.locationX) * (imgBgObj.showWidth / imgBgObj.width)
item.locationY = Number(item.locationY) * (imgBgObj.showWidth / imgBgObj.width)
item.dataList = JSONBigInt({ storeAsString: true }).parse(item.dataJson)
@ -307,10 +332,11 @@ const getAllNodeList = async () => {
item.locationDeepPx = pxObj.pHeight
}
allMapPointInfo.value.push(item)
return
}
// areaId
if (item.type === 2 && locationTypeNumber.value == 3 && item?.areaId !== null) {
if (locationTypeNumber.value == 3 && item.type === 2 && item?.areaId !== null) {
item.locationX = Number(item.locationX) * (imgBgObj.showWidth / imgBgObj.width)
item.locationY = Number(item.locationY) * (imgBgObj.showWidth / imgBgObj.width)
item.dataList = JSONBigInt({ storeAsString: true }).parse(item.dataJson)
@ -325,6 +351,24 @@ const getAllNodeList = async () => {
item.locationDeepPx = pxObj.pHeight
}
allMapPointInfo.value.push(item)
return
}
if (item.type === 8 && locationTypeNumber.value == 4) {
item.locationX = Number(item.locationX) * (imgBgObj.showWidth / imgBgObj.width)
item.locationY = Number(item.locationY) * (imgBgObj.showWidth / imgBgObj.width)
item.dataList = item.dataJson ? JSONBigInt({ storeAsString: true }).parse(item.dataJson) : []
item.locationDeepPx = 8
item.locationWidePx = 8
//cmpx
if (item.locationWide && item.locationDeep) {
let pxObj = cmConversionPx(item.locationWide, item.locationDeep)
item.locationWidePx = pxObj.pWidth
item.locationDeepPx = pxObj.pHeight
}
allMapPointInfo.value.push(item)
return
}
if (item.dataList && item.dataList.length > 0) {

View File

@ -2,7 +2,7 @@
<Dialog
v-model="dialogFormVisible"
title="节点属性"
width="650"
width="700"
class="node-form-dialog"
@close="dialogClose"
>
@ -70,11 +70,13 @@
<el-option label="停车点" :value="4" />
<el-option label="区域变更点" :value="5" />
<el-option label="等待点" :value="6" />
<el-option label="取放货点" :value="8" />
</el-select>
</el-form-item>
<el-form-item label="弧度" prop="locationYaw" required>
<el-input-number
class="!w-300px"
class="!w-18.75rem"
v-model="form.locationYaw"
:min="-MathPI"
:max="MathPI"
@ -86,7 +88,7 @@
<div v-if="form.type === 2 || form.type === 3 || form.type === 4">
<el-form-item label="层数" prop="layersNumber" required v-if="form.type === 2">
<el-input-number
class="!w-300px"
class="!w-18.75rem"
v-model="form.layersNumber"
:min="1"
:max="4"
@ -97,14 +99,14 @@
<el-text class="mx-1">最大层数4</el-text>
</el-form-item>
<el-form-item label="排序" prop="locationNumber" v-if="form.type === 2" required>
<el-input-number class="!w-300px" v-model="form.locationNumber" :min="1" />
<el-input-number class="!w-18.75rem" v-model="form.locationNumber" :min="1" />
<el-text class="mx-1">最大值10000000</el-text>
</el-form-item>
<el-form-item label="编号" prop="deviceId" required v-if="form.type === 3">
<div>
<el-select
v-model="deviceInfo.deviceType"
class="!w-160px"
class="!w-10rem"
clearable
placeholder="请选择设备类型"
@change="deviceTypeChange()"
@ -118,7 +120,7 @@
</el-select>
<el-select
v-model="form.deviceId"
class="!w-160px ml-4"
class="!w-10rem ml-4"
clearable
placeholder="请选择设备编号"
@change="deviceChange"
@ -133,10 +135,9 @@
</el-select>
</div>
</el-form-item>
<el-form-item label="库位类型" required prop="locationTypeId" v-if="form.type === 2">
<el-select
class="!w-300px"
class="!w-18.75rem"
v-model="form.locationTypeId"
clearable
placeholder="请选择库位类型"
@ -150,11 +151,10 @@
/>
</el-select>
</el-form-item>
<el-form-item label="库位长度" prop="locationDeep" required>
<div style="display: flex">
<el-input-number
class="!w-300px"
class="!w-18.75rem"
placeholder="请输入"
v-model="form.locationDeep"
:min="10"
@ -166,7 +166,7 @@
<el-form-item label="库位宽度" prop="locationWide" required>
<div style="display: flex">
<el-input-number
class="!w-300px"
class="!w-18.75rem"
placeholder="请输入"
v-model="form.locationWide"
:min="10"
@ -175,35 +175,6 @@
<span class="ml-2">cm</span>
</div>
</el-form-item>
<!-- <div v-if="form.type === 2 || form.type === 4">
<el-form-item label="库位方向" prop="direction">
<el-select
v-model="form.direction"
placeholder="请选择库位方向"
@change="directionChange"
>
<el-option label="单向" :value="1" />
<el-option label="双向" :value="2" />
<el-option label="三向" :value="3" />
<el-option label="四向" :value="4" />
</el-select>
</el-form-item>
<div v-if="form.direction !== 1">
<el-form-item label="进入方向" prop="inDirection">
<el-select v-model="form.inDirection" placeholder="请选择进入方向">
<el-option label="尾入" :value="0" />
<el-option label="头入" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="离开方向" prop="outDirection">
<el-select v-model="form.outDirection" placeholder="请选择离开方向">
<el-option label="尾出" :value="0" />
<el-option label="头出" :value="1" />
</el-select>
</el-form-item>
</div>
</div> -->
</div>
<el-form-item label="区域变更点绑定" label-width="130" v-if="form.type === 5 && form.id">
@ -226,6 +197,31 @@
/>
</el-select>
</el-form-item>
<div v-if="form.type === 8">
<el-button type="primary" class="ml-9 mb-4 mt-2" @click="addPointInfo"
>添加点位信息</el-button
>
<div v-for="(item, index) in form.dataList" :key="index">
<el-row>
<el-col :span="12">
<el-form-item label="名称" :prop="`dataList.${index}.pointName`">
<el-input v-model="item.pointName" style="width: 100%" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="托盘高度" :prop="`dataList.${index}.trayHeight`">
<div class="flex-center">
<el-input v-model="item.trayHeight" style="width: 100%" placeholder="请输入" />
<el-icon size="20" class="ml-2" color="#ff4c4c" @click="deletePointInfo(index)"
><CircleCloseFilled
/></el-icon>
</div>
</el-form-item>
</el-col>
</el-row>
</div>
</div>
</el-form>
<template #footer>
<div class="dialog-footer">
@ -412,6 +408,8 @@ const submit = async (formEl) => {
form.value.dataJson = JSON.stringify(form.value.dataObj)
} else if (form.value.type === 5) {
form.value.dataJson = JSON.stringify(form.value.dataObj)
} else if (form.value.type === 8) {
form.value.dataJson = JSON.stringify(form.value.dataList)
} else {
//
form.value.dataObj.positionMapId = props.positionMapId
@ -475,63 +473,41 @@ const typeChange = (type) => {
form.value.dataObj = {}
form.value.dataList = []
form.value.locationTypeId = null
if (type === 1) {
form.value.layersNumber = null
form.value.direction = null
form.value.inDirection = null
form.value.outDirection = null
form.value.locationNumber = null
form.value.locationDeep = 40
form.value.locationWide = 40
form.value.locationDeepPx = 8
form.value.locationWidePx = 8
} else if (type === 2) {
if (type === 2) {
form.value.locationNumber = null
//
let firstItem = houseLocationTypeList.value[0]
form.value.locationTypeId = firstItem.id
form.value.locationDeep = Number(firstItem.locationDeep)
form.value.locationWide = Number(firstItem.locationWide)
} else if (type === 3) {
form.value.direction = null
form.value.inDirection = null
form.value.outDirection = null
form.value.locationNumber = null
form.value.locationDeep = 150
form.value.locationWide = 150
form.value.locationDeepPx = 30
form.value.locationWidePx = 30
} else if (type === 4) {
form.value.direction = null
form.value.inDirection = null
form.value.outDirection = null
form.value.locationNumber = null
form.value.locationDeep = 150
form.value.locationWide = 150
form.value.locationDeepPx = 30
form.value.locationWidePx = 30
} else if (type === 5) {
form.value.layersNumber = null
form.value.direction = null
form.value.inDirection = null
form.value.outDirection = null
form.value.locationNumber = null
form.value.locationDeep = 150
form.value.locationWide = 150
form.value.locationDeepPx = 30
form.value.locationWidePx = 30
} else if (type === 6) {
form.value.layersNumber = null
form.value.direction = null
form.value.inDirection = null
form.value.outDirection = null
form.value.locationNumber = null
} else {
if (type === 1 || type === 8) {
form.value.locationDeep = 40
form.value.locationWide = 40
form.value.locationDeepPx = 8
form.value.locationWidePx = 8
} else {
form.value.locationDeep = 150
form.value.locationWide = 150
form.value.locationDeepPx = 30
form.value.locationWidePx = 30
}
form.value.layersNumber = null
form.value.direction = null
form.value.inDirection = null
form.value.outDirection = null
form.value.locationNumber = null
}
}
const addPointInfo = () => {
form.value.dataList.push({ pointName: '', trayHeight: '' })
}
const deletePointInfo = (index) => {
form.value.dataList.splice(index, 1)
}
//
const deviceChange = (deviceId) => {
deviceList.value.forEach((item) => {
@ -541,13 +517,7 @@ const deviceChange = (deviceId) => {
}
})
}
//
const directionChange = (e) => {
if (e === 1) {
form.value.inDirection = undefined
form.value.outDirection = undefined
}
}
//
const deviceInfo = ref({
positionMapId: '',

View File

@ -53,6 +53,11 @@ const list = ref([
category: 'nodeImage',
name: '库位图片',
isShow: true
},
{
category: 'checkLine',
name: '校准线',
isShow: false
}
])

View File

@ -151,13 +151,33 @@
</div>
</div>
</div>
<div v-else-if="item.type === 8">
<div class="indexpage-popover-item">
<div> 节点类型 </div>
<div>取放货点</div>
<div>
{{ item.sortNum || '' }}
</div>
</div>
<div class="indexpage-popover-item">
<div>
<div
v-for="(location, locationIndex) in item.dataList"
:key="locationIndex"
>
<span style="margin-right: 10px"
>节点名称{{ location.pointName || '' }}
</span>
<span>托盘高度{{ location.trayHeight || '' }}</span>
</div>
</div>
</div>
</div>
<div v-else>
<div class="indexpage-popover-item">
<div> 节点类型 </div>
<div>{{
item.type == 1
? '路径点'
: item.type == 4
item.type == 4
? '停车点'
: item.type == 5
? '区域变更点'
@ -172,43 +192,27 @@
</div>
</template>
<div>
<!-- sortNum -->
<template v-if="legendObj.sortNumberShow && item.sortNum && sortNumberShow">
<div
v-if="
item.type === 1 &&
legendObj.sortNumberShow &&
item.sortNum &&
sortNumberShow
"
v-if="item.type === 8"
class="sort-num"
:style="getSortNumStyle(item, index)"
>
{{ item.sortNum }}
</div>
<div
v-if="
item.type !== 1 &&
legendObj.sortNumberShow &&
item.sortNum &&
sortNumberShow
"
v-else
class="sort-num-location"
:style="getSortNumLocationStyle(item, index)"
>
{{ item.sortNum }}
</div>
<div
v-if="item.type === 1"
:style="{
width: Number(item.locationWidePx) * Number(radio) + 'px',
height: Number(item.locationDeepPx) * Number(radio) + 'px',
backgroundColor: '#000',
borderRadius: '50%'
}"
>
</div>
</template>
<!-- 库位点 -->
<img
v-else-if="item.type === 2"
v-if="item.type === 2"
src="@/assets/imgs/indexPage/bin-location.png"
:style="nodeStyle(item, index)"
@dblclick="storeClick(item)"
@ -241,6 +245,16 @@
style="background: #fff"
:style="nodeStyle(item, index)"
/>
<!-- 取货点 -->
<div
v-else-if="item.type === 8"
:style="{
width: Number(item.locationWidePx) * Number(radio) + 'px',
height: Number(item.locationDeepPx) * Number(radio) + 'px',
backgroundColor: '#000',
borderRadius: '50%'
}"
></div>
</div>
</el-tooltip>
</div>
@ -331,6 +345,7 @@ import { propTypes } from '@/utils/propTypes'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import dayjs from 'dayjs'
import { throttle, debounce } from 'lodash-es'
import { ElLoading } from 'element-plus'
const message = useMessage() //
@ -435,12 +450,15 @@ const filterTypeFun = (deviceType) => {
const convertActualCarToBrowser = (pointX, pointY) => {
const resolution = Number(imgBgObj.resolution)
const [originX, originY] = imgBgObj.origin.map(Number)
const imgHeight = Number(imgBgObj.height)
// 使使radio.valueimgBgObj.height
const originalHeight = props.isFullScreen
? Number(imgBgObj.height) / Number(radio.value)
: Number(imgBgObj.height)
const carW = Number(carWidth.value)
const carH = Number(carHeight.value)
// yy
const yBottom = originY + imgHeight * resolution
const yBottom = originY + originalHeight * resolution
const xPx = Math.max(Number(pointX) - originX, 0) / resolution
const yPx = Math.max(yBottom - Number(pointY), 0) / resolution
@ -480,15 +498,6 @@ const changeIsDrag = () => {
})
}
// 线
const getCurvePath = (curve) => {
let startPointX = Number(curve.startPointX) * radio.value
let startPointY = Number(curve.startPointY) * radio.value
let endPointX = Number(curve.endPointX) * radio.value
let endPointY = Number(curve.endPointY) * radio.value
return `M ${startPointX} ${startPointY} C ${curve.beginControlX * radio.value} ${curve.beginControlY * radio.value}, ${curve.endControlX * radio.value} ${curve.endControlY * radio.value}, ${endPointX} ${endPointY}`
}
//
const isSizeRadio = ref(1)
const changeSize = (type) => {
@ -643,14 +652,12 @@ const initWebsocket = () => {
if (jsonMsg.type == 'map_push') {
requestAnimationFrame(() => {
let data = JSON.parse(jsonMsg.content)
// console.log(data)
// console.log(data, dayjs().format('HH:mm:ss SSS'))
let dataList = Object.entries(data).map(([key, value]) => ({
macAddress: key,
data: JSON.parse(value)
}))
testCarList.value = throttledUpdateCarList(testCarList.value, dataList, imgBgObj)
// console.log(data, dayjs().format('HH:mm:ss SSS'))
})
}
//
@ -719,14 +726,12 @@ const mergeArraysWithoutDelete = (arr1, arr2) => {
//
const processCarData = (car, mapInfo) => {
//
const originalResolution = mapInfo.resolution
const browserPos = convertActualCarToBrowser(car.data.pose2d.x, car.data.pose2d.y)
return {
...car,
originWidth: mapInfo.width,
originHeight: mapInfo.height,
origin: mapInfo.origin,
realX: browserPos.x,
realY: browserPos.y,
robotNo: car.data.pose2d.robotNo,
style: {
left: browserPos.x * radio.value + 'px',
@ -770,17 +775,14 @@ const computedRatio = () => {
if (props.isFullScreen) {
let width = getElementWidthByClass('index-page-container')
testCarList.value.forEach((item) => {
item.originWidth = imgBgObj.width
item.originHeight = imgBgObj.height
item.origin = imgBgObj.origin
item.realX = convertActualCarToBrowser(item.data.pose2d.x, item.data.pose2d.y).x
item.realY = convertActualCarToBrowser(item.data.pose2d.x, item.data.pose2d.y).y
})
//
const originalWidth = imgBgObj.width
const originalHeight = imgBgObj.height
radio.value = width / imgBgObj.width
imgBgObj.width = imgBgObj.width * radio.value
imgBgObj.height = imgBgObj.height * radio.value
//
imgBgObj.width = originalWidth * radio.value
imgBgObj.height = originalHeight * radio.value
}
})
}
@ -818,7 +820,7 @@ const getMapData = async (item) => {
imgBgObj.origin = yamlJson.origin
imgBgObj.resolution = yamlJson.resolution
//
getMapDownloadPng(imgBgObj)
await getMapDownloadPng(imgBgObj)
//Websocket
initWebsocket()
}
@ -830,10 +832,24 @@ const getMapDownloadPng = async (mapInfo) => {
imgBgObj.imgUrl = data
//
const loading = ElLoading.service({
lock: true,
text: '地图数据加载中',
background: 'rgba(255, 255, 255, 0.7)'
})
try {
await getAllNodeList()
await getAllMapRoute()
await computedRatio()
await getRobotByFloorAndAreaList()
//loading
loading.close()
} catch (error) {
loading.close()
} finally {
loading.close()
}
}
// 线
const getAllMapRoute = async () => {
@ -868,6 +884,11 @@ const getAllNodeList = async (positionMapId) => {
item.dataObj = JSONBigInt({ storeAsString: true }).parse(item.dataJson)
item.locationDeep = item.dataObj.locationDeep
item.locationWide = item.dataObj.locationWide
} else if (item.type === 8) {
item.dataObj = {}
item.dataList = item.dataJson ? JSONBigInt({ storeAsString: true }).parse(item.dataJson) : []
item.locationDeep = 40
item.locationWide = 40
}
//cmpx
if (item.locationWide && item.locationDeep) {

View File

@ -576,30 +576,23 @@
</div>
</template>
<div @contextmenu="handleContextMenu(item, visibleMapPointIndices[i], $event)">
<!-- sortNum -->
<template v-if="item.layerSelectionShow && state.isShowSortNum && item.sortNum">
<div
v-if="
item.type === 1 &&
item.layerSelectionShow &&
state.isShowSortNum &&
item.sortNum
"
v-if="item.type === 1 || item.type === 8"
class="sort-num"
:style="getSortNumStyle(item, visibleMapPointIndices[i])"
>
{{ item.sortNum }}
</div>
<div
v-if="
item.type !== 1 &&
item.layerSelectionShow &&
state.isShowSortNum &&
item.sortNum
"
v-else
class="sort-num-location"
:style="getSortNumLocationStyle(item, visibleMapPointIndices[i])"
>
{{ item.sortNum }}
</div>
</template>
<div
class="sort-num-location"
:style="getLocationNumberStyle(item, visibleMapPointIndices[i])"
@ -611,8 +604,9 @@
>
{{ item.locationNumber }}
</div>
<!-- 1 路径点和取放货点 -->
<div
v-if="item.type === 1 && item.layerSelectionShow"
v-if="(item.type === 1 || item.type === 8) && item.layerSelectionShow"
:style="{
width: item.locationWidePx + 'px',
height: item.locationDeepPx + 'px',
@ -682,6 +676,8 @@
{{ item.text }}
</div>
</VueDragResizeRotate>
<template v-if="state.mapCheckLineShow">
<span
class="ref-line v-line"
v-for="(item, index) in state.vLine"
@ -703,6 +699,7 @@
width: item.lineLength
}"
></span>
</template>
<div v-if="imgBgObj.width && imgBgObj.height">
<svg
@ -1320,9 +1317,6 @@ const inputBoxRef = ref() //文字输入框
const message = useMessage() //
// loading<script setup>
let loading = null
//
const nodeStyle = (item, index) => {
return {
@ -1621,11 +1615,11 @@ const mapClick = (e) => {
//
if (toolbarSwitchType.value === 'drawNodes') {
//
//
const isDuplicate = state.allMapPointInfo.some(
(item) =>
Number(item.locationX).toFixed(1) === Number(x).toFixed(1) &&
Number(item.locationY).toFixed(1) === Number(y).toFixed(1)
Number(item.locationX).toFixed(0) === Number(x).toFixed(0) &&
Number(item.locationY).toFixed(0) === Number(y).toFixed(0)
)
if (!isDuplicate) {
@ -2060,10 +2054,14 @@ const state = reactive({
currentIndex: -1
},
checkPointDistance: 0,
curveOffsetValue: 0
curveOffsetValue: 0,
mapCheckLineShow: false // 线
})
const getRefLineParams = (params) => {
if (!state.mapCheckLineShow) {
return
}
const { vLine, hLine } = params
state.vLine = vLine
state.hLine = hLine
@ -2456,8 +2454,8 @@ const equalDistanceReplicationSucceeded = (list) => {
const filteredList = list.filter((newItem) => {
const isDup = state.allMapPointInfo.some(
(item) =>
Number(item.locationX).toFixed(1) === Number(newItem.locationX).toFixed(1) &&
Number(item.locationY).toFixed(1) === Number(newItem.locationY).toFixed(1)
Number(item.locationX).toFixed(0) === Number(newItem.locationX).toFixed(0) &&
Number(item.locationY).toFixed(0) === Number(newItem.locationY).toFixed(0)
)
if (isDup) {
duplicatePoints.push(`(${newItem.locationX}, ${newItem.locationY})`)
@ -2492,11 +2490,11 @@ const generateDetectionPoint = async () => {
const newX = Number((Number(locationX) + distanceValue * Math.cos(locationYaw)).toFixed(2))
const newY = Number((Number(locationY) - distanceValue * Math.sin(locationYaw)).toFixed(2))
//,
//,
const isDuplicate = state.allMapPointInfo.some(
(item) =>
Number(item.locationX).toFixed(1) === Number(newX).toFixed(1) &&
Number(item.locationY).toFixed(1) === Number(newY).toFixed(1)
Number(item.locationX).toFixed(0) === Number(newX).toFixed(0) &&
Number(item.locationY).toFixed(0) === Number(newY).toFixed(0)
)
if (!isDuplicate) {
@ -2636,8 +2634,8 @@ const pasteNode = () => {
//
const isDuplicate = state.allMapPointInfo.some(
(item) =>
Number(item.locationX).toFixed(1) === Number(copyObj.locationX).toFixed(1) &&
Number(item.locationY).toFixed(1) === Number(copyObj.locationY).toFixed(1)
Number(item.locationX).toFixed(0) === Number(copyObj.locationX).toFixed(0) &&
Number(item.locationY).toFixed(0) === Number(copyObj.locationY).toFixed(0)
)
if (isDuplicate) {
@ -2791,8 +2789,8 @@ const markFormSubmit = async () => {
//
const isDuplicate = state.allMapPointInfo.some(
(item) =>
Number(item.locationX).toFixed(1) === Number(pointPx.x).toFixed(1) &&
Number(item.locationY).toFixed(1) === Number(pointPx.y).toFixed(1)
Number(item.locationX).toFixed(0) === Number(pointPx.x).toFixed(0) &&
Number(item.locationY).toFixed(0) === Number(pointPx.y).toFixed(0)
)
if (isDuplicate) {
@ -3445,9 +3443,10 @@ const submitBatchCopyingFormSuccess = async (form) => {
//
const calculateNewCoordinates = (x, y) => {
const newX = (Number(x) + Number(form.x)).toString()
const newY = (Number(y) + Number(form.y)).toString()
const newX = Number(x) + Number(form.x)
const newY = Number(y) + Number(form.y)
const actualPoint = disposeEventPoint(newX, newY)
return { newX, newY, actualPoint }
}
@ -3465,8 +3464,8 @@ const submitBatchCopyingFormSuccess = async (form) => {
//
const existingNode = state.allMapPointInfo.find(
(item) =>
Number(item.locationX).toFixed(1) === Number(locationX).toFixed(1) &&
Number(item.locationY).toFixed(1) === Number(locationY).toFixed(1)
Number(item.locationX).toFixed(0) === Number(locationX).toFixed(0) &&
Number(item.locationY).toFixed(0) === Number(locationY).toFixed(0)
)
if (existingNode) {
@ -3596,10 +3595,10 @@ const submitBatchCopyingFormSuccess = async (form) => {
// 线
const isDuplicate = state.mapRouteList.some(
(existingRoute) =>
Number(existingRoute.startPointX).toFixed(1) === Number(newRoute.startPointX).toFixed(1) &&
Number(existingRoute.startPointY).toFixed(1) === Number(newRoute.startPointY).toFixed(1) &&
Number(existingRoute.endPointX).toFixed(1) === Number(newRoute.endPointX).toFixed(1) &&
Number(existingRoute.endPointY).toFixed(1) === Number(newRoute.endPointY).toFixed(1)
Number(existingRoute.startPointX).toFixed(0) === Number(newRoute.startPointX).toFixed(0) &&
Number(existingRoute.startPointY).toFixed(0) === Number(newRoute.startPointY).toFixed(0) &&
Number(existingRoute.endPointX).toFixed(0) === Number(newRoute.endPointX).toFixed(0) &&
Number(existingRoute.endPointY).toFixed(0) === Number(newRoute.endPointY).toFixed(0)
)
if (isDuplicate) {
@ -3699,32 +3698,47 @@ const mapPointsToLine = (points, startPointId, endPointId) => {
if (!startPoint || !endPoint) {
message.warning('选择的点位有误')
return
return points
}
const dx = endPoint.locationX - startPoint.locationX
const dy = endPoint.locationY - startPoint.locationY
const length = Math.sqrt(dx * dx + dy * dy)
// 线线
const isVertical = startPoint.locationX === endPoint.locationX
const isHorizontal = startPoint.locationY === endPoint.locationY
// 线
if (!isVertical && !isHorizontal) {
return points
}
return points.map((point) => {
//
if (point.id === startPointId || point.id === endPointId) {
return point
}
const vx = point.locationX - startPoint.locationX
const vy = point.locationY - startPoint.locationY
const dotProduct = vx * dx + vy * dy
const projectionLength = dotProduct / length
const t = Math.max(0, Math.min(1, projectionLength / length))
const newX = startPoint.locationX + t * dx
const newY = startPoint.locationY + t * dy
// 线 - xy
if (isVertical) {
const minY = Math.min(startPoint.locationY, endPoint.locationY)
const maxY = Math.max(startPoint.locationY, endPoint.locationY)
const clampedY = Math.round(Math.max(minY, Math.min(maxY, point.locationY)))
return {
...point,
locationX: newX,
locationY: newY
locationX: startPoint.locationX,
locationY: clampedY
}
}
// 线 - yx
else {
const minX = Math.min(startPoint.locationX, endPoint.locationX)
const maxX = Math.max(startPoint.locationX, endPoint.locationX)
const clampedX = Math.round(Math.max(minX, Math.min(maxX, point.locationX)))
return {
...point,
locationX: clampedX,
locationY: startPoint.locationY
}
}
})
}
@ -4246,8 +4260,21 @@ const getMapData = async (mapInfo) => {
imgBgObj.imgUrl = data
//
const loading = ElLoading.service({
lock: true,
text: '地图数据加载中',
background: 'rgba(255, 255, 255, 0.7)'
})
try {
await getAllNodeList()
await getAllMapRoute()
//loading
loading.close()
} catch (error) {
loading.close()
} finally {
loading.close()
}
}
//
const getAllNodeList = async () => {
@ -4281,7 +4308,7 @@ const getAllNodeList = async () => {
item.lockAspectRatio = true
} else if (item.type === 2) {
//
item.dataList = JSONBigInt({ storeAsString: true }).parse(item.dataJson)
item.dataList = item.dataJson ? JSONBigInt({ storeAsString: true }).parse(item.dataJson) : []
item.locationDeep = item.dataList[0].locationDeep
item.locationWide = item.dataList[0].locationWide
item.areaName = item.dataList[0].areaName || undefined
@ -4292,7 +4319,7 @@ const getAllNodeList = async () => {
item.rotatable = false
item.lockAspectRatio = true
} else if (item.type === 3) {
item.dataObj = JSONBigInt({ storeAsString: true }).parse(item.dataJson)
item.dataObj = item.dataJson ? JSONBigInt({ storeAsString: true }).parse(item.dataJson) : {}
item.dataList = []
item.locationDeep = item.dataObj.locationDeep
item.locationWide = item.dataObj.locationWide
@ -4305,7 +4332,7 @@ const getAllNodeList = async () => {
item.rotatable = false
item.lockAspectRatio = true
} else if (item.type === 4) {
item.dataObj = JSONBigInt({ storeAsString: true }).parse(item.dataJson)
item.dataObj = item.dataJson ? JSONBigInt({ storeAsString: true }).parse(item.dataJson) : {}
item.dataList = []
item.locationDeep = item.dataObj.locationDeep
item.locationWide = item.dataObj.locationWide
@ -4323,7 +4350,7 @@ const getAllNodeList = async () => {
item.rotatable = false
item.lockAspectRatio = true
} else if (item.type === 7) {
item.dataObj = JSONBigInt({ storeAsString: true }).parse(item.dataJson)
item.dataObj = item.dataJson ? JSONBigInt({ storeAsString: true }).parse(item.dataJson) : {}
item.text = item.dataObj.text
item.fontColor = item.dataObj.fontColor
item.fontFamily = item.dataObj.fontFamily
@ -4335,6 +4362,15 @@ const getAllNodeList = async () => {
item.lockAspectRatio = true
item.locationDeep = 20
item.locationWide = 20
} else if (item.type === 8) {
item.dataObj = {}
item.dataList = item.dataJson ? JSONBigInt({ storeAsString: true }).parse(item.dataJson) : []
item.locationDeep = 40
item.locationWide = 40
item.draggable = true
item.resizable = false
item.rotatable = false
item.lockAspectRatio = true
}
//cmpx
@ -4404,6 +4440,8 @@ const saveMap = async () => {
} catch (error) {
loading.close()
message.error(error?.message || '保存失败')
} finally {
loading.close()
}
}
//
@ -4582,6 +4620,8 @@ const isCurveDisplayChange = (category, show) => {
}
})
}
} else if (category === 'checkLine') {
state.mapCheckLineShow = show
}
}
@ -4839,35 +4879,10 @@ const removeEventListener = () => {
window.removeEventListener('keydown', handleKeyDown)
}
const router = useRouter()
onBeforeRouteLeave((to, from) => {
if (to.path == '/mapPage/realTimeMap' && to.query.mapId != imgBgObj.positionMapId) {
router.replace({
name: 'MapPageRealTimeMap',
query: {
mapId: imgBgObj.positionMapId
}
})
}
})
onMounted(async () => {
// loading
loading = ElLoading.service({
lock: true,
text: '加载中,请稍候...',
background: 'rgba(255, 255, 255, 0.7)'
})
try {
await Promise.all([getMapList(), getCheckDistance()])
} catch (e) {
//
message.error(e?.message || '页面加载失败')
} finally {
setTimeout(() => {
loading.close()
}, 1000)
}
await getMapList()
await getCheckDistance()
window.addEventListener('keydown', handleKeyDown)
//

View File

@ -77,10 +77,8 @@ const getList = async () => {
} catch (error) {
console.error('解析floorArea参数失败:', error)
}
}
} else if (query.floor && query.area) {
// floorarea
if (query.floor && query.area) {
// ID
const floorItem = list.value.find((item) => item.floor === query.floor)
if (floorItem && floorItem.children) {
@ -91,20 +89,16 @@ const getList = async () => {
return
}
}
}
} else if (query.mapId) {
// mapId
if (query.mapId) {
let item = findItemById(query.mapId)
if (item) {
mapValue.value = [String(item.floor), String(item.id)]
handleChangeMap(mapValue.value)
return
}
}
} else if (list.value.length > 0 && list.value[0].children && list.value[0].children.length > 0) {
// 使
if (list.value.length > 0 && list.value[0].children && list.value[0].children.length > 0) {
mapValue.value = [list.value[0].value, list.value[0].children[0].value]
indexPageRef.value.getMapData(JSON.parse(JSON.stringify(list.value[0].children[0])))
}
@ -116,12 +110,6 @@ const handleChangeMap = async (e) => {
let item = findItemById(e[1])
if (item) {
indexPageRef.value.getMapData(item)
router.replace({
name: 'MapPageRealTimeMap',
query: {
mapId: item.id
}
})
} else {
message.warning('未找到对应地图')
}
@ -204,35 +192,6 @@ function findItemById(targetId) {
return null
}
//
watch(
() => route.query,
(newQuery) => {
if (newQuery.floorArea && list.value.length > 0) {
try {
const [floor, mapId] = JSON.parse(newQuery.floorArea)
if (floor && mapId) {
mapValue.value = [String(floor), String(mapId)]
handleChangeMap(mapValue.value)
}
} catch (error) {
console.error('解析floorArea参数失败:', error)
}
} else if (newQuery.floor && newQuery.area && list.value.length > 0) {
// floorarea
const floorItem = list.value.find((item) => item.floor === newQuery.floor)
if (floorItem && floorItem.children) {
const areaItem = floorItem.children.find((item) => item.area === newQuery.area)
if (areaItem) {
mapValue.value = [String(newQuery.floor), String(areaItem.id)]
handleChangeMap(mapValue.value)
}
}
}
},
{ deep: true }
)
onMounted(() => {
getList()
})

View File

@ -196,6 +196,7 @@
<el-option label="库位" :value="1" />
<el-option label="线库" :value="2" />
<el-option label="区域" :value="3" />
<el-option label="取放货点" :value="4" />
</el-select>
</el-form-item>
</el-col>
@ -224,7 +225,7 @@
<el-option
v-for="item in detailItem.takeList"
:key="item.id"
:label="item.locationNo"
:label="detailItem.takeType == 4 ? item.pointName : item.locationNo"
:value="item.id"
/>
</el-select>
@ -255,6 +256,7 @@
<el-option label="库位" :value="1" />
<el-option label="线库" :value="2" />
<el-option label="区域" :value="3" />
<el-option label="取放货点" :value="4" />
</el-select>
</el-form-item>
</el-col>
@ -283,7 +285,7 @@
<el-option
v-for="item in detailItem.releaseList"
:key="item.id"
:label="item.locationNo"
:label="detailItem.releaseType == 4 ? item.pointName : item.locationNo"
:value="item.id"
/>
</el-select>
@ -440,7 +442,7 @@
<el-option
v-for="item in detailItem.releaseList"
:key="item.id"
:label="item.locationNo"
:label="detailItem.releaseType == 4 ? item.pointName : item.locationNo"
:value="item.id"
/>
</el-select>
@ -466,6 +468,7 @@
<el-option label="库位" :value="1" />
<el-option label="线库" :value="2" />
<el-option label="区域" :value="3" />
<el-option label="取放货点" :value="4" />
</el-select>
</el-form-item>
</el-col>
@ -494,7 +497,7 @@
<el-option
v-for="item in detailItem.takeList"
:key="item.id"
:label="item.locationNo"
:label="detailItem.takeType == 4 ? item.pointName : item.locationNo"
:value="item.id"
/>
</el-select>
@ -551,6 +554,7 @@
<el-option label="库位" :value="1" />
<el-option label="线库" :value="2" />
<el-option label="区域" :value="3" />
<el-option label="取放货点" :value="4" />
</el-select>
</el-form-item>
</el-col>
@ -579,7 +583,7 @@
<el-option
v-for="item in detailItem.releaseList"
:key="item.id"
:label="item.locationNo"
:label="detailItem.releaseType == 4 ? item.pointName : item.locationNo"
:value="item.id"
/>
</el-select>
@ -669,117 +673,12 @@
</el-col>
</el-row>
</div>
<!-- 扫描码 -->
<!-- <div v-if="detailItem.taskType === 7">
<el-row :gutter="24">
<el-col :span="12">
<el-form-item
required
label="车辆编号"
:prop="`taskDetailList[${index}].robotNo`"
:rules="{ required: true, message: '车辆不能为空', trigger: 'change' }"
>
<el-select v-model="detailItem.robotNo" placeholder="请选择车辆">
<el-option
v-for="car in robotList"
:key="car.id"
:label="car.robotList"
:value="car.robotNo"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
required
label="放货位置"
:prop="`taskDetailList[${index}].releaseId`"
:rules="{ required: true, message: '放货位置不能为空', trigger: 'change' }"
>
<el-select
:disabled="!detailItem.releaseType"
v-model="detailItem.releaseId"
filterable
remote
reserve-keyword
placeholder="请输入放货位置"
:remote-method="
(query) => {
releaseRemoteMethod(query, detailItem)
}
"
:loading="loading"
>
<el-option
v-for="item in detailItem.releaseList"
:key="item.id"
:label="item.locationNo"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</div> -->
<!-- 检测托盘类型 -->
<!-- <div v-if="detailItem.taskType === 8">
<el-row :gutter="24">
<el-col :span="12">
<el-form-item
required
label="车辆编号"
:prop="`taskDetailList[${index}].robotNo`"
:rules="{ required: true, message: '车辆不能为空', trigger: 'change' }"
>
<el-select v-model="detailItem.robotNo" placeholder="请选择车辆">
<el-option
v-for="car in robotList"
:key="car.id"
:label="car.robotList"
:value="car.robotNo"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
required
label="检测位置"
:prop="`taskDetailList[${index}].releaseId`"
:rules="{ required: true, message: '检测位置不能为空', trigger: 'change' }"
>
<el-select
:disabled="!detailItem.releaseType"
v-model="detailItem.releaseId"
filterable
remote
reserve-keyword
placeholder="请输入检测位置"
:remote-method="
(query) => {
releaseRemoteMethod(query, detailItem)
}
"
:loading="loading"
>
<el-option
v-for="item in detailItem.releaseList"
:key="item.id"
:label="item.locationNo"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</div> -->
</div>
</div>
</el-card>
</el-form>
<locationSelectionDialog
:positionMapId="null"
ref="locationSelectionDialogRef"
@location-selection-dialog-success="locationSelectionDialogSuccess"
/>
@ -790,6 +689,7 @@
import { reactive } from 'vue'
import { RefreshRight, Position } from '@element-plus/icons-vue'
import * as MapTaskAPi from '@/api/map/mapTask'
import * as DeviceApi from '@/api/device/index'
import locationSelectionDialog from '../components/locationSelectionDialog.vue'
defineOptions({ name: 'TaskManagementCreateTask' })
@ -816,7 +716,7 @@ const formData = ref({
{
taskType: 1, //12 345678
releaseType: 1, // 12线 3
takeType: 1, //12线 3
takeType: 1, //12线 3 4.
releaseId: undefined, //id
releaseList: [], //
takeId: undefined, //id
@ -860,7 +760,7 @@ const resetFormData = () => {
{
taskType: 1, //12 345678
releaseType: 1, // 12线 3 4
takeType: 1, //12线 3
takeType: 1, //12线 3 4.
releaseId: undefined, //id
releaseList: [], //
takeId: undefined, //id
@ -905,11 +805,15 @@ const getTaskNo = async () => {
//
const getLocationList = async (type, locationNo) => {
if (type == 4) {
return await DeviceApi.getWareHouseTakePointList({ pointType: 1 })
} else {
return await MapTaskAPi.getLocationByName({
type, // 12线 3
locationNo
})
}
}
//
const loading = ref(false)
const releaseRemoteMethod = async (query, item) => {
@ -1306,7 +1210,7 @@ const chooseLocation = (type, item, index) => {
const locationSelectionDialogSuccess = (item) => {
if (chooseLocationType.value == 'take') {
//
if (locationTypeNumber.value == 1) {
if (locationTypeNumber.value == 1 || locationTypeNumber.value == 4) {
// 1
takeRemoteMethod(item.locationNo, formData.value.taskDetailList[currentItemIndex.value])
formData.value.taskDetailList[currentItemIndex.value].takeId = item.id
@ -1314,14 +1218,14 @@ const locationSelectionDialogSuccess = (item) => {
// 2线
takeRemoteMethod(item.laneName, formData.value.taskDetailList[currentItemIndex.value])
formData.value.taskDetailList[currentItemIndex.value].takeId = item.laneId
} else {
} else if (locationTypeNumber.value == 3) {
// 3
takeRemoteMethod(item.areaName, formData.value.taskDetailList[currentItemIndex.value])
formData.value.taskDetailList[currentItemIndex.value].takeId = item.areaId
}
} else if (chooseLocationType.value == 'release') {
//
if (locationTypeNumber.value == 1) {
if (locationTypeNumber.value == 1 || locationTypeNumber.value == 4) {
// 1
releaseRemoteMethod(item.locationNo, formData.value.taskDetailList[currentItemIndex.value])
formData.value.taskDetailList[currentItemIndex.value].releaseId = item.id
@ -1329,7 +1233,7 @@ const locationSelectionDialogSuccess = (item) => {
// 2线
releaseRemoteMethod(item.laneName, formData.value.taskDetailList[currentItemIndex.value])
formData.value.taskDetailList[currentItemIndex.value].releaseId = item.laneId
} else {
} else if (locationTypeNumber.value == 3) {
// 3
releaseRemoteMethod(item.areaName, formData.value.taskDetailList[currentItemIndex.value])
formData.value.taskDetailList[currentItemIndex.value].releaseId = item.areaId