Merge branch 'xhf' of http://git.znkjfw.com/ak/zn-admin-vue3-wcs into xhf
This commit is contained in:
commit
b909e61b0a
@ -148,3 +148,9 @@ export const getAGVPointInformation = async (macAddress) => {
|
|||||||
url: `/system/position-map-item/getAGVPointInformation?macAddress=` + macAddress
|
url: `/system/position-map-item/getAGVPointInformation?macAddress=` + macAddress
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
//根据地图id获取车辆列表
|
||||||
|
export const getListByMapId = async (mapId) => {
|
||||||
|
return await request.get({
|
||||||
|
url: `/system/robot/information/getListByMapId?mapId=` + mapId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -43,7 +43,13 @@
|
|||||||
>
|
>
|
||||||
<el-input-number v-model="form.layersNumber" :min="1" :max="3" />
|
<el-input-number v-model="form.layersNumber" :min="1" :max="3" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="排序" prop="locationNumber" v-if="form.type === 2" required>
|
<el-form-item
|
||||||
|
label="排序"
|
||||||
|
prop="locationNumber"
|
||||||
|
v-if="form.type === 2"
|
||||||
|
required
|
||||||
|
:rules="{ required: true, message: '请输入排序', trigger: 'change' }"
|
||||||
|
>
|
||||||
<el-input-number v-model="form.locationNumber" :min="1" :max="10000000" />
|
<el-input-number v-model="form.locationNumber" :min="1" :max="10000000" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
@ -173,7 +179,8 @@ const rules = reactive({
|
|||||||
locationX: [{ required: true, message: '请输入X', trigger: 'blur' }],
|
locationX: [{ required: true, message: '请输入X', trigger: 'blur' }],
|
||||||
locationY: [{ required: true, message: '请输入Y', trigger: 'blur' }],
|
locationY: [{ required: true, message: '请输入Y', trigger: 'blur' }],
|
||||||
type: [{ required: true, message: '请选择类型', trigger: 'blur' }],
|
type: [{ required: true, message: '请选择类型', trigger: 'blur' }],
|
||||||
layersNumber: [{ required: true, message: '请输入层数', trigger: 'blur' }]
|
layersNumber: [{ required: true, message: '请输入层数', trigger: 'blur' }],
|
||||||
|
locationNumber: [{ required: true, message: '请输入排序', trigger: 'blur' }]
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['submitNodeSuccess', 'addEventListener'])
|
const emit = defineEmits(['submitNodeSuccess', 'addEventListener'])
|
||||||
@ -274,22 +281,40 @@ const typeChange = (type) => {
|
|||||||
form.value.inDirection = null
|
form.value.inDirection = null
|
||||||
form.value.outDirection = null
|
form.value.outDirection = null
|
||||||
form.value.locationNumber = null
|
form.value.locationNumber = null
|
||||||
form.value.locationDeep = 50
|
form.value.locationDeep = 40
|
||||||
form.value.locationWide = 50
|
form.value.locationWide = 40
|
||||||
form.value.locationDeepPx = 10
|
form.value.locationDeepPx = 8
|
||||||
form.value.locationWidePx = 10
|
form.value.locationWidePx = 8
|
||||||
} else if (type === 2) {
|
} else if (type === 2) {
|
||||||
form.value.locationNumber = 1
|
form.value.locationNumber = null
|
||||||
|
if (!form.value.id) {
|
||||||
|
form.value.locationDeep = 150
|
||||||
|
form.value.locationWide = 150
|
||||||
|
form.value.locationDeepPx = 30
|
||||||
|
form.value.locationWidePx = 30
|
||||||
|
}
|
||||||
} else if (type === 3) {
|
} else if (type === 3) {
|
||||||
form.value.direction = null
|
form.value.direction = null
|
||||||
form.value.inDirection = null
|
form.value.inDirection = null
|
||||||
form.value.outDirection = null
|
form.value.outDirection = null
|
||||||
form.value.locationNumber = null
|
form.value.locationNumber = null
|
||||||
|
if (!form.value.id) {
|
||||||
|
form.value.locationDeep = 150
|
||||||
|
form.value.locationWide = 150
|
||||||
|
form.value.locationDeepPx = 30
|
||||||
|
form.value.locationWidePx = 30
|
||||||
|
}
|
||||||
} else if (type === 4) {
|
} else if (type === 4) {
|
||||||
form.value.direction = null
|
form.value.direction = null
|
||||||
form.value.inDirection = null
|
form.value.inDirection = null
|
||||||
form.value.outDirection = null
|
form.value.outDirection = null
|
||||||
form.value.locationNumber = null
|
form.value.locationNumber = null
|
||||||
|
if (!form.value.id) {
|
||||||
|
form.value.locationDeep = 150
|
||||||
|
form.value.locationWide = 150
|
||||||
|
form.value.locationDeepPx = 30
|
||||||
|
form.value.locationWidePx = 30
|
||||||
|
}
|
||||||
} else if (type === 5) {
|
} else if (type === 5) {
|
||||||
form.value.layersNumber = null
|
form.value.layersNumber = null
|
||||||
form.value.direction = null
|
form.value.direction = null
|
||||||
|
@ -83,9 +83,13 @@
|
|||||||
:key="index"
|
:key="index"
|
||||||
:style="{
|
:style="{
|
||||||
left: item.realX * radio + 'px',
|
left: item.realX * radio + 'px',
|
||||||
top: item.realY * radio + 'px',
|
top: item.realY * radio + 'px',
|
||||||
width: legendObj.carShow ? carWidth / nowObject.showYamlJson.resolution / 100 * radio + 'px' : '0',
|
width: legendObj.carShow
|
||||||
height: legendObj.carShow ? carHeight / nowObject.showYamlJson.resolution / 100 * radio + 'px' : '0',
|
? (carWidth / nowObject.showYamlJson.resolution / 100) * radio + 'px'
|
||||||
|
: '0',
|
||||||
|
height: legendObj.carShow
|
||||||
|
? (carHeight / nowObject.showYamlJson.resolution / 100) * radio + 'px'
|
||||||
|
: '0',
|
||||||
transform: 'rotate(' + radianToDegree(item.data.pose2d.yaw) + 'deg)',
|
transform: 'rotate(' + radianToDegree(item.data.pose2d.yaw) + 'deg)',
|
||||||
transition: 'all 0.2s linear',
|
transition: 'all 0.2s linear',
|
||||||
zIndex: 9999
|
zIndex: 9999
|
||||||
@ -438,14 +442,20 @@ const props = defineProps({
|
|||||||
isAllBoard: propTypes.bool.def(false)
|
isAllBoard: propTypes.bool.def(false)
|
||||||
})
|
})
|
||||||
const convertActualToBrowser = (pointX, pointY) => {
|
const convertActualToBrowser = (pointX, pointY) => {
|
||||||
const y1 = Number(nowObject.value.showYamlJson.origin[1]) + Number(nowObject.value.showYamlJson.height) * Number(nowObject.value.showYamlJson.resolution)
|
const y1 =
|
||||||
let x = Math.max(Number(pointX) - Number(nowObject.value.showYamlJson.origin[0]), 0)
|
Number(nowObject.value.showYamlJson.origin[1]) +
|
||||||
let y = Math.max(y1 - Number(pointY), 0)
|
Number(nowObject.value.showYamlJson.height) * Number(nowObject.value.showYamlJson.resolution)
|
||||||
|
let x = Math.max(Number(pointX) - Number(nowObject.value.showYamlJson.origin[0]), 0)
|
||||||
|
let y = Math.max(y1 - Number(pointY), 0)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x :(x / nowObject.value.showYamlJson.resolution) - (carWidth.value / nowObject.value.showYamlJson.resolution / 100/2),
|
x:
|
||||||
y: (y / nowObject.value.showYamlJson.resolution) - (carHeight.value / nowObject.value.showYamlJson.resolution / 100/2)
|
x / nowObject.value.showYamlJson.resolution -
|
||||||
}
|
carWidth.value / nowObject.value.showYamlJson.resolution / 100 / 2,
|
||||||
|
y:
|
||||||
|
y / nowObject.value.showYamlJson.resolution -
|
||||||
|
carHeight.value / nowObject.value.showYamlJson.resolution / 100 / 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//是否可以拖拽
|
//是否可以拖拽
|
||||||
const isDrag = ref(false)
|
const isDrag = ref(false)
|
||||||
@ -654,7 +664,6 @@ const getPositionMapListFun = async (positionMapId) => {
|
|||||||
} else if (item.type === 7) {
|
} else if (item.type === 7) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
const draggableElement = ref(null)
|
const draggableElement = ref(null)
|
||||||
const resetPosition = () => {
|
const resetPosition = () => {
|
||||||
@ -831,11 +840,11 @@ const getMapData = async (item) => {
|
|||||||
getMapLineList()
|
getMapLineList()
|
||||||
}
|
}
|
||||||
//偏航率斜率算旋转
|
//偏航率斜率算旋转
|
||||||
const radianToDegree = (radian) =>{
|
const radianToDegree = (radian) => {
|
||||||
// 将弧度转换为角度
|
// 将弧度转换为角度
|
||||||
const degree = radian * (180 / Math.PI);
|
const degree = radian * (180 / Math.PI)
|
||||||
// 返回带有单位 'deg' 的 CSS 角度值
|
// 返回带有单位 'deg' 的 CSS 角度值
|
||||||
return `${degree}`;
|
return `${degree}`
|
||||||
}
|
}
|
||||||
const heightVal = ref(0)
|
const heightVal = ref(0)
|
||||||
const widthVal = ref(0)
|
const widthVal = ref(0)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="edit-map-page">
|
<div class="edit-map-page" @wheel="handleWheel">
|
||||||
<div class="top-tool">
|
<div class="top-tool">
|
||||||
<div class="top-tool-list">
|
<div class="top-tool-list">
|
||||||
<div v-for="item in state.topToolList" :key="item.switchType" class="top-tool-item">
|
<div v-for="item in state.topToolList" :key="item.switchType" class="top-tool-item">
|
||||||
@ -236,7 +236,8 @@
|
|||||||
(item.switchType === 'next' &&
|
(item.switchType === 'next' &&
|
||||||
(toolbarSwitchType === 'createLineLibrary' ||
|
(toolbarSwitchType === 'createLineLibrary' ||
|
||||||
toolbarSwitchType === 'createRegion' ||
|
toolbarSwitchType === 'createRegion' ||
|
||||||
toolbarSwitchType === 'drawRoute'))
|
toolbarSwitchType === 'drawRoute' ||
|
||||||
|
toolbarSwitchType === 'generateLine'))
|
||||||
"
|
"
|
||||||
></div>
|
></div>
|
||||||
<el-button
|
<el-button
|
||||||
@ -244,7 +245,8 @@
|
|||||||
item.switchType === 'next' &&
|
item.switchType === 'next' &&
|
||||||
(toolbarSwitchType === 'createLineLibrary' ||
|
(toolbarSwitchType === 'createLineLibrary' ||
|
||||||
toolbarSwitchType === 'createRegion' ||
|
toolbarSwitchType === 'createRegion' ||
|
||||||
toolbarSwitchType === 'drawRoute')
|
toolbarSwitchType === 'drawRoute' ||
|
||||||
|
toolbarSwitchType === 'generateLine')
|
||||||
"
|
"
|
||||||
type="danger"
|
type="danger"
|
||||||
class="selection-area-btn"
|
class="selection-area-btn"
|
||||||
@ -1164,6 +1166,12 @@ const state = reactive({
|
|||||||
name: '编辑路线',
|
name: '编辑路线',
|
||||||
icon: 'ep:semi-select',
|
icon: 'ep:semi-select',
|
||||||
isActive: false
|
isActive: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
switchType: 'generateLine',
|
||||||
|
name: '生成直线',
|
||||||
|
icon: 'ep:finished',
|
||||||
|
isActive: false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
isShowToolbar: true, //工具栏展示隐藏
|
isShowToolbar: true, //工具栏展示隐藏
|
||||||
@ -1542,11 +1550,7 @@ const rotationFormSubmit = () => {
|
|||||||
|
|
||||||
//标记
|
//标记
|
||||||
const mapMark = async () => {
|
const mapMark = async () => {
|
||||||
let res = await MapApi.getRobotInformationPage({
|
state.mapMarkCarList = await MapApi.getListByMapId(imgBgObj.positionMapId)
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 20
|
|
||||||
})
|
|
||||||
state.mapMarkCarList = res.list
|
|
||||||
|
|
||||||
if (state.currentItemIndex != -1) {
|
if (state.currentItemIndex != -1) {
|
||||||
let item = state.allMapPointInfo[state.currentItemIndex]
|
let item = state.allMapPointInfo[state.currentItemIndex]
|
||||||
@ -1671,32 +1675,33 @@ const startFromPoint = (index, event) => {
|
|||||||
//开始框选绘制
|
//开始框选绘制
|
||||||
const startDrawSelection = (event) => {
|
const startDrawSelection = (event) => {
|
||||||
if (
|
if (
|
||||||
toolbarSwitchType.value === 'createLineLibrary' ||
|
toolbarSwitchType.value !== 'createLineLibrary' &&
|
||||||
toolbarSwitchType.value === 'createRegion' ||
|
toolbarSwitchType.value !== 'createRegion' &&
|
||||||
toolbarSwitchType.value === 'drawRoute'
|
toolbarSwitchType.value !== 'drawRoute' &&
|
||||||
) {
|
toolbarSwitchType.value !== 'generateLine'
|
||||||
const backgroundRect = mapBackgroundRef.value.getBoundingClientRect()
|
)
|
||||||
|
|
||||||
const x = disposeEventPoints(event).x
|
|
||||||
const y = disposeEventPoints(event).y
|
|
||||||
|
|
||||||
// 确保点击在背景区域内
|
|
||||||
if (x >= 0 && x <= backgroundRect.width && y >= 0 && y <= backgroundRect.height) {
|
|
||||||
state.drawSelectionAreaShow = true
|
|
||||||
state.drawSelectionStartPoint = { x: x, y: y }
|
|
||||||
state.drawSelectionAreaBox = { x: x, y: y, width: 0, height: 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault() // 阻止默认行为(避免选中图片或文本)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
const backgroundRect = mapBackgroundRef.value.getBoundingClientRect()
|
||||||
|
|
||||||
|
const x = disposeEventPoints(event).x
|
||||||
|
const y = disposeEventPoints(event).y
|
||||||
|
|
||||||
|
// 确保点击在背景区域内
|
||||||
|
if (x >= 0 && x <= backgroundRect.width && y >= 0 && y <= backgroundRect.height) {
|
||||||
|
state.drawSelectionAreaShow = true
|
||||||
|
state.drawSelectionStartPoint = { x: x, y: y }
|
||||||
|
state.drawSelectionAreaBox = { x: x, y: y, width: 0, height: 0 }
|
||||||
}
|
}
|
||||||
|
event.preventDefault() // 阻止默认行为(避免选中图片或文本)
|
||||||
}
|
}
|
||||||
// 更新框选区域
|
// 更新框选区域
|
||||||
const updateDrawSelection = (event) => {
|
const updateDrawSelection = (event) => {
|
||||||
if (
|
if (
|
||||||
toolbarSwitchType.value === 'createLineLibrary' ||
|
toolbarSwitchType.value === 'createLineLibrary' ||
|
||||||
toolbarSwitchType.value === 'createRegion' ||
|
toolbarSwitchType.value === 'createRegion' ||
|
||||||
toolbarSwitchType.value === 'drawRoute'
|
toolbarSwitchType.value === 'drawRoute' ||
|
||||||
|
toolbarSwitchType.value === 'generateLine'
|
||||||
) {
|
) {
|
||||||
if (state.drawSelectionAreaShow) {
|
if (state.drawSelectionAreaShow) {
|
||||||
const x = disposeEventPoints(event).x
|
const x = disposeEventPoints(event).x
|
||||||
@ -1721,16 +1726,17 @@ const updateDrawSelection = (event) => {
|
|||||||
state.currentDrawX = x
|
state.currentDrawX = x
|
||||||
state.currentDrawY = y
|
state.currentDrawY = y
|
||||||
}
|
}
|
||||||
|
event.preventDefault() // 阻止默认行为(避免选中图片或文本)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
event.preventDefault() // 阻止默认行为(避免选中图片或文本)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
//结束框选绘制
|
//结束框选绘制
|
||||||
const endDrawSelection = (event) => {
|
const endDrawSelection = (event) => {
|
||||||
if (
|
if (
|
||||||
toolbarSwitchType.value === 'createLineLibrary' ||
|
toolbarSwitchType.value === 'createLineLibrary' ||
|
||||||
toolbarSwitchType.value === 'createRegion' ||
|
toolbarSwitchType.value === 'createRegion' ||
|
||||||
toolbarSwitchType.value === 'drawRoute'
|
toolbarSwitchType.value === 'drawRoute' ||
|
||||||
|
toolbarSwitchType.value === 'generateLine'
|
||||||
) {
|
) {
|
||||||
state.drawSelectionAreaShow = false
|
state.drawSelectionAreaShow = false
|
||||||
state.allDrawSelectionAreaBox.push({ ...state.drawSelectionAreaBox })
|
state.allDrawSelectionAreaBox.push({ ...state.drawSelectionAreaBox })
|
||||||
@ -1825,7 +1831,6 @@ const endDrawSelection = (event) => {
|
|||||||
state.currentDrawX = 0
|
state.currentDrawX = 0
|
||||||
state.currentDrawY = 0
|
state.currentDrawY = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
event.preventDefault() // 阻止默认行为(避免选中图片或文本)
|
event.preventDefault() // 阻止默认行为(避免选中图片或文本)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1875,6 +1880,7 @@ const clickDrawSelectionArea = () => {
|
|||||||
item.id
|
item.id
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//线库
|
||||||
if (toolbarSwitchType.value === 'createLineLibrary') {
|
if (toolbarSwitchType.value === 'createLineLibrary') {
|
||||||
//线库
|
//线库
|
||||||
if (binLocation.length < 2) {
|
if (binLocation.length < 2) {
|
||||||
@ -1911,7 +1917,7 @@ const clickDrawSelectionArea = () => {
|
|||||||
removeEventListener() //移除监听
|
removeEventListener() //移除监听
|
||||||
itemAreaSettingDialogRef.value.open(binLocation)
|
itemAreaSettingDialogRef.value.open(binLocation)
|
||||||
}
|
}
|
||||||
|
//绘制直线
|
||||||
if (toolbarSwitchType.value === 'drawRoute') {
|
if (toolbarSwitchType.value === 'drawRoute') {
|
||||||
if (routeList.length !== 2) {
|
if (routeList.length !== 2) {
|
||||||
message.warning('只能选择两个路径点')
|
message.warning('只能选择两个路径点')
|
||||||
@ -1962,6 +1968,105 @@ const clickDrawSelectionArea = () => {
|
|||||||
state.mapRouteList.push(curve)
|
state.mapRouteList.push(curve)
|
||||||
addEditHistory()
|
addEditHistory()
|
||||||
}
|
}
|
||||||
|
//生成直线
|
||||||
|
if (toolbarSwitchType.value === 'generateLine') {
|
||||||
|
if (routeList.length < 3) {
|
||||||
|
message.warning('至少框选三个点')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let isHaveId = routeList.every((item) => {
|
||||||
|
return item.id
|
||||||
|
})
|
||||||
|
if (!isHaveId) {
|
||||||
|
message.warning('您选择的路径点存在未保存的')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const list = mapPointsToLine(routeList)
|
||||||
|
const idNameMap = {}
|
||||||
|
list.forEach((item) => {
|
||||||
|
idNameMap[item.id] = item
|
||||||
|
})
|
||||||
|
// 遍历第二个数组,更新 name
|
||||||
|
state.allMapPointInfo.forEach((item) => {
|
||||||
|
if (idNameMap[item.id]) {
|
||||||
|
let actualPoint = disposeEventPoint(
|
||||||
|
idNameMap[item.id].locationX,
|
||||||
|
idNameMap[item.id].locationY
|
||||||
|
)
|
||||||
|
item.locationX = idNameMap[item.id].locationX
|
||||||
|
item.locationY = idNameMap[item.id].locationY
|
||||||
|
item.actualLocationX = actualPoint.actualLocationX
|
||||||
|
item.actualLocationY = actualPoint.actualLocationY
|
||||||
|
}
|
||||||
|
})
|
||||||
|
state.mapRouteList.forEach((item) => {
|
||||||
|
if (idNameMap[item.startingPointId]) {
|
||||||
|
let actualPoint = disposeEventPoint(
|
||||||
|
idNameMap[item.startingPointId].locationX,
|
||||||
|
idNameMap[item.startingPointId].locationY
|
||||||
|
)
|
||||||
|
item.startPointX = idNameMap[item.startingPointId].locationX
|
||||||
|
item.startPointY = idNameMap[item.startingPointId].locationY
|
||||||
|
item.actualStartPointX = actualPoint.actualLocationX
|
||||||
|
item.actualStartPointY = actualPoint.actualLocationY
|
||||||
|
}
|
||||||
|
if (idNameMap[item.endPointId]) {
|
||||||
|
let actualPoint = disposeEventPoint(
|
||||||
|
idNameMap[item.endPointId].locationX,
|
||||||
|
idNameMap[item.endPointId].locationY
|
||||||
|
)
|
||||||
|
item.endPointX = idNameMap[item.endPointId].locationX
|
||||||
|
item.endPointY = idNameMap[item.endPointId].locationY
|
||||||
|
item.actualEndPointX = actualPoint.actualLocationX
|
||||||
|
item.actualEndPointY = actualPoint.actualLocationY
|
||||||
|
}
|
||||||
|
})
|
||||||
|
addEditHistory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//将一个数组中的点位 按照第一个和最后一个排成一条直线
|
||||||
|
const mapPointsToLine = (points) => {
|
||||||
|
if (points.length < 2) {
|
||||||
|
return points
|
||||||
|
}
|
||||||
|
// 取数组的第一项和最后一项
|
||||||
|
const firstPoint = points[0]
|
||||||
|
const lastPoint = points[points.length - 1]
|
||||||
|
|
||||||
|
// 计算直线的斜率
|
||||||
|
const dx = lastPoint.locationX - firstPoint.locationX
|
||||||
|
const dy = lastPoint.locationY - firstPoint.locationY
|
||||||
|
|
||||||
|
if (dx === 0) {
|
||||||
|
// 垂直直线的情况
|
||||||
|
return points.map((point, index) => {
|
||||||
|
if (index === 0 || index === points.length - 1) {
|
||||||
|
return point
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...point,
|
||||||
|
locationX: firstPoint.locationX,
|
||||||
|
locationY: point.locationY
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const slope = dy / dx
|
||||||
|
// 计算直线的截距
|
||||||
|
const intercept = firstPoint.locationY - slope * firstPoint.locationX
|
||||||
|
|
||||||
|
// 映射其他点到直线上
|
||||||
|
return points.map((point, index) => {
|
||||||
|
if (index === 0 || index === points.length - 1) {
|
||||||
|
return point
|
||||||
|
}
|
||||||
|
const newY = slope * point.locationX + intercept
|
||||||
|
// 考虑精度问题,这里保留三位小数
|
||||||
|
const roundedY = parseFloat(newY.toFixed(8))
|
||||||
|
return {
|
||||||
|
...point,
|
||||||
|
locationY: roundedY
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
//计算是不是在同一条直线的
|
//计算是不是在同一条直线的
|
||||||
const isStraightLine = (binLocation) => {
|
const isStraightLine = (binLocation) => {
|
||||||
@ -2489,6 +2594,33 @@ const handleKeyDown = (event) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//鼠标滚轮
|
||||||
|
const handleWheel = (event) => {
|
||||||
|
// 判断 Ctrl 键是否被按下
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
// 阻止默认的滚动行为
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
// 根据滚轮滚动方向调整缩放比例
|
||||||
|
if (event.deltaY < 0) {
|
||||||
|
// 向上滚动,放大
|
||||||
|
//放大
|
||||||
|
if (state.imageChangeMultiple < 4) {
|
||||||
|
state.imageChangeMultiple += 0.2
|
||||||
|
} else {
|
||||||
|
message.warning('不能在放大了')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//缩小
|
||||||
|
if (state.imageChangeMultiple > 0.2) {
|
||||||
|
state.imageChangeMultiple -= 0.2
|
||||||
|
} else {
|
||||||
|
message.warning('不能在缩小了')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const addEventListener = () => {
|
const addEventListener = () => {
|
||||||
window.addEventListener('keydown', handleKeyDown)
|
window.addEventListener('keydown', handleKeyDown)
|
||||||
}
|
}
|
||||||
@ -2638,8 +2770,6 @@ onUnmounted(() => {
|
|||||||
// 20px 20px,
|
// 20px 20px,
|
||||||
// 20px 20px;
|
// 20px 20px;
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-image: repeating-linear-gradient(
|
background-image: repeating-linear-gradient(
|
||||||
to right,
|
to right,
|
||||||
rgba(0, 0, 0, 0.1),
|
rgba(0, 0, 0, 0.1),
|
||||||
|
@ -1,79 +1,94 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div style="width: 600px; height: 300px; background: #dbeede; position: relative">
|
||||||
<ul>
|
<div v-for="(item, index) in points" :key="index">
|
||||||
<li v-for="(point, index) in points" :key="index">
|
<div
|
||||||
点位 {{ index + 1 }}: ({{ point.x }}, {{ point.y }})
|
:style="{
|
||||||
<button @click="movePoint(index)">移动</button>
|
position: 'absolute',
|
||||||
<button @click="deletePoint(index)">删除</button>
|
width: '10px',
|
||||||
</li>
|
height: '10px',
|
||||||
</ul>
|
backgroundColor: '#000',
|
||||||
<button @click="addPoint">新增点位</button>
|
borderRadius: '50%',
|
||||||
<button @click="undo" :disabled="historyIndex === 0">撤回</button>
|
zIndex: 999,
|
||||||
<button @click="redo" :disabled="historyIndex === history.length - 1">重做</button>
|
left: item.x + 'px',
|
||||||
|
top: item.y + 'px'
|
||||||
|
}"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="width: 600px; height: 300px; background: #b3dcff; position: relative">
|
||||||
|
<div v-for="(item, index) in mappedPoints" :key="index">
|
||||||
|
<div
|
||||||
|
:style="{
|
||||||
|
position: 'absolute',
|
||||||
|
width: '10px',
|
||||||
|
height: '10px',
|
||||||
|
backgroundColor: '#000',
|
||||||
|
borderRadius: '50%',
|
||||||
|
zIndex: 999,
|
||||||
|
left: item.x + 'px',
|
||||||
|
top: item.y + 'px'
|
||||||
|
}"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
// 初始化点位数据
|
const points = ref([
|
||||||
const points = reactive([
|
{
|
||||||
{ x: 10, y: 20 },
|
x: 123.567,
|
||||||
{ x: 30, y: 40 }
|
y: 178.123
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 255.567,
|
||||||
|
y: 79.123
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 382.567,
|
||||||
|
y: 178.123
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 481.567,
|
||||||
|
y: 238.123
|
||||||
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
// 操作历史记录
|
const mapPointsToLine = (points) => {
|
||||||
const history = reactive([[...points]])
|
if (points.length < 2) {
|
||||||
// 历史记录指针
|
return points
|
||||||
const historyIndex = ref(0)
|
|
||||||
|
|
||||||
// 新增点位方法
|
|
||||||
const addPoint = () => {
|
|
||||||
const newPoint = { x: Math.random() * 100, y: Math.random() * 100 }
|
|
||||||
points.push(newPoint)
|
|
||||||
updateHistory()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移动点位方法
|
|
||||||
const movePoint = (index) => {
|
|
||||||
points[index].x = Math.random() * 100
|
|
||||||
points[index].y = Math.random() * 100
|
|
||||||
updateHistory()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除点位方法
|
|
||||||
const deletePoint = (index) => {
|
|
||||||
points.splice(index, 1)
|
|
||||||
updateHistory()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新历史记录
|
|
||||||
const updateHistory = () => {
|
|
||||||
// 如果已经进行了撤回操作,移除撤回之后的历史记录
|
|
||||||
if (historyIndex.value < history.length - 1) {
|
|
||||||
history.splice(historyIndex.value + 1)
|
|
||||||
}
|
}
|
||||||
// 保存当前状态到历史记录
|
// 取数组的第一项和最后一项
|
||||||
history.push([...points])
|
const firstPoint = points[0]
|
||||||
// 更新历史记录指针
|
const lastPoint = points[points.length - 1]
|
||||||
historyIndex.value++
|
|
||||||
|
// 计算直线的斜率
|
||||||
|
const dx = lastPoint.x - firstPoint.x
|
||||||
|
const dy = lastPoint.y - firstPoint.y
|
||||||
|
if (dx === 0) {
|
||||||
|
// 垂直直线的情况
|
||||||
|
return points.map((point, index) => {
|
||||||
|
if (index === 0 || index === points.length - 1) {
|
||||||
|
return point
|
||||||
|
}
|
||||||
|
return { x: firstPoint.x, y: point.y }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const slope = dy / dx
|
||||||
|
// 计算直线的截距
|
||||||
|
const intercept = firstPoint.y - slope * firstPoint.x
|
||||||
|
|
||||||
|
// 映射其他点到直线上
|
||||||
|
return points.map((point, index) => {
|
||||||
|
if (index === 0 || index === points.length - 1) {
|
||||||
|
return point
|
||||||
|
}
|
||||||
|
const newY = slope * point.x + intercept
|
||||||
|
return { x: point.x, y: newY }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 撤回操作
|
const mappedPoints = mapPointsToLine(points.value)
|
||||||
const undo = () => {
|
console.log(mappedPoints)
|
||||||
if (historyIndex.value > 0) {
|
|
||||||
historyIndex.value--
|
|
||||||
// 恢复到上一个状态
|
|
||||||
points.splice(0, points.length, ...history[historyIndex.value])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重做操作
|
|
||||||
const redo = () => {
|
|
||||||
if (historyIndex.value < history.length - 1) {
|
|
||||||
historyIndex.value++
|
|
||||||
// 恢复到下一个状态
|
|
||||||
points.splice(0, points.length, ...history[historyIndex.value])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -298,7 +298,11 @@
|
|||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="指定车辆">
|
<el-form-item label="指定车辆">
|
||||||
<el-select v-model="detailItem.robotNo" placeholder="请选择车辆">
|
<el-select
|
||||||
|
v-model="detailItem.robotNo"
|
||||||
|
placeholder="请选择车辆"
|
||||||
|
@change="chooseCarErrorMsg"
|
||||||
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="car in robotList"
|
v-for="car in robotList"
|
||||||
:key="car.id"
|
:key="car.id"
|
||||||
@ -320,7 +324,11 @@
|
|||||||
:prop="`taskDetailList[${index}].robotNo`"
|
:prop="`taskDetailList[${index}].robotNo`"
|
||||||
:rules="{ required: true, message: '车辆不能为空', trigger: 'change' }"
|
:rules="{ required: true, message: '车辆不能为空', trigger: 'change' }"
|
||||||
>
|
>
|
||||||
<el-select v-model="detailItem.robotNo" placeholder="请选择车辆">
|
<el-select
|
||||||
|
v-model="detailItem.robotNo"
|
||||||
|
placeholder="请选择车辆"
|
||||||
|
@change="chooseCarErrorMsg"
|
||||||
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="car in robotList"
|
v-for="car in robotList"
|
||||||
:key="car.id"
|
:key="car.id"
|
||||||
@ -390,7 +398,11 @@
|
|||||||
:prop="`taskDetailList[${index}].robotNo`"
|
:prop="`taskDetailList[${index}].robotNo`"
|
||||||
:rules="{ required: true, message: '车辆不能为空', trigger: 'change' }"
|
:rules="{ required: true, message: '车辆不能为空', trigger: 'change' }"
|
||||||
>
|
>
|
||||||
<el-select v-model="detailItem.robotNo" placeholder="请选择车辆">
|
<el-select
|
||||||
|
v-model="detailItem.robotNo"
|
||||||
|
placeholder="请选择车辆"
|
||||||
|
@change="chooseCarErrorMsg"
|
||||||
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="car in robotList"
|
v-for="car in robotList"
|
||||||
:key="car.id"
|
:key="car.id"
|
||||||
@ -501,7 +513,11 @@
|
|||||||
:prop="`taskDetailList[${index}].robotNo`"
|
:prop="`taskDetailList[${index}].robotNo`"
|
||||||
:rules="{ required: true, message: '车辆不能为空', trigger: 'change' }"
|
:rules="{ required: true, message: '车辆不能为空', trigger: 'change' }"
|
||||||
>
|
>
|
||||||
<el-select v-model="detailItem.robotNo" placeholder="请选择车辆">
|
<el-select
|
||||||
|
v-model="detailItem.robotNo"
|
||||||
|
placeholder="请选择车辆"
|
||||||
|
@change="chooseCarErrorMsg"
|
||||||
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="car in robotList"
|
v-for="car in robotList"
|
||||||
:key="car.id"
|
:key="car.id"
|
||||||
@ -577,7 +593,11 @@
|
|||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item required label="指定车辆" prop="montageTask">
|
<el-form-item required label="指定车辆" prop="montageTask">
|
||||||
<el-select v-model="detailItem.robotNo" placeholder="请选择车辆">
|
<el-select
|
||||||
|
v-model="detailItem.robotNo"
|
||||||
|
placeholder="请选择车辆"
|
||||||
|
@change="chooseCarErrorMsg"
|
||||||
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="car in robotList"
|
v-for="car in robotList"
|
||||||
:key="car.id"
|
:key="car.id"
|
||||||
@ -828,10 +848,14 @@ const getCanUseRobotList = async () => {
|
|||||||
|
|
||||||
//车辆切换
|
//车辆切换
|
||||||
const robotNoChange = (e, detailItem) => {
|
const robotNoChange = (e, detailItem) => {
|
||||||
let car = robotList.value.filter((item) => {
|
let car = robotList.value.find((item) => {
|
||||||
return item.robotNo == e
|
return item.robotNo == e
|
||||||
})
|
})
|
||||||
detailItem.electricity = car[0].electricity
|
detailItem.electricity = car.electricity
|
||||||
|
|
||||||
|
if (car?.errorMsg) {
|
||||||
|
message.warning(car.errorMsg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//任务类型切换
|
//任务类型切换
|
||||||
@ -1073,6 +1097,15 @@ const releaseTypeChange = (item) => {
|
|||||||
item.releaseId = undefined
|
item.releaseId = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//选择车辆
|
||||||
|
const chooseCarErrorMsg = (e) => {
|
||||||
|
let carItem = robotList.value.find((item) => item.robotNo === e)
|
||||||
|
|
||||||
|
if (carItem?.errorMsg) {
|
||||||
|
message.warning(carItem.errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//提交表单
|
//提交表单
|
||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
const formLoading = ref(false)
|
const formLoading = ref(false)
|
||||||
|
Loading…
Reference in New Issue
Block a user