批量复制
This commit is contained in:
parent
dd713321b1
commit
2e148ea659
@ -5,7 +5,7 @@ VITE_DEV=true
|
|||||||
|
|
||||||
# 请求路径
|
# 请求路径
|
||||||
# VITE_BASE_URL='http://192.168.77.50:48080'
|
# VITE_BASE_URL='http://192.168.77.50:48080'
|
||||||
# VITE_BASE_URL='http://10.10.100.19:48080'
|
# VITE_BASE_URL='http://10.10.100.15:48080'
|
||||||
VITE_BASE_URL='http://10.10.5.5:48080'
|
VITE_BASE_URL='http://10.10.5.5:48080'
|
||||||
|
|
||||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
||||||
|
@ -0,0 +1,125 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 批量复制 -->
|
||||||
|
<Dialog
|
||||||
|
v-model="dialogFormVisible"
|
||||||
|
title="批量复制"
|
||||||
|
width="500"
|
||||||
|
class="batch-copying-dialog-form"
|
||||||
|
@close="dialogClose"
|
||||||
|
>
|
||||||
|
<el-form :model="batchCopyingForm" label-width="100" ref="BatchCopyingFormRef" :rules="rules">
|
||||||
|
<el-form-item label="X轴偏移量" prop="x" required>
|
||||||
|
<el-input-number
|
||||||
|
v-model="batchCopyingForm.x"
|
||||||
|
placeholder="请输入"
|
||||||
|
controls-position="right"
|
||||||
|
style="width: 100%"
|
||||||
|
precision="2"
|
||||||
|
/>
|
||||||
|
<el-text type="info" size="small">X轴往左为负值,往右为正值</el-text>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Y轴偏移量" prop="y" required>
|
||||||
|
<el-input-number
|
||||||
|
v-model="batchCopyingForm.y"
|
||||||
|
placeholder="请输入"
|
||||||
|
controls-position="right"
|
||||||
|
style="width: 100%"
|
||||||
|
precision="2"
|
||||||
|
/>
|
||||||
|
<el-text type="info" size="small">X轴往上为负值,往下为正值</el-text>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="dialogFormVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submitLineLibraryForm()"> 确定 </el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, ref } from 'vue'
|
||||||
|
import * as MapApi from '@/api/map/map'
|
||||||
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
const props = defineProps({
|
||||||
|
imgBgObj: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
//新增
|
||||||
|
const batchCopyingForm = ref({
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
})
|
||||||
|
const boundaryValue = ref()
|
||||||
|
const BatchCopyingFormRef = ref()
|
||||||
|
const dialogFormVisible = ref(false) //列表的
|
||||||
|
|
||||||
|
const validateXValue = (rule, value, callback) => {
|
||||||
|
let maxLeft = -Number(boundaryValue.value.left)
|
||||||
|
let maxRight = Number(props.imgBgObj.width) - Number(boundaryValue.value.right)
|
||||||
|
if (value < maxLeft || value > maxRight) {
|
||||||
|
callback(new Error(`不能超出地图宽度,可偏移范围为${maxLeft}至${maxRight}`))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const validateYValue = (rule, value, callback) => {
|
||||||
|
let maxTop = -Number(boundaryValue.value.top)
|
||||||
|
let maxBottom = Number(props.imgBgObj.height) - Number(boundaryValue.value.bottom)
|
||||||
|
if (value < maxTop || value > maxBottom) {
|
||||||
|
callback(new Error(`不能超出地图宽度,可偏移范围为${maxTop}至${maxBottom}`))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
x: [
|
||||||
|
{ required: true, message: '请输入X轴偏移量', trigger: 'blur' },
|
||||||
|
{ validator: validateXValue, trigger: 'blur' }
|
||||||
|
],
|
||||||
|
y: [
|
||||||
|
{ required: true, message: '请输入Y轴偏移量', trigger: 'blur' },
|
||||||
|
{ validator: validateYValue, trigger: 'blur' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const open = (boundaryObj) => {
|
||||||
|
boundaryValue.value = boundaryObj
|
||||||
|
batchCopyingForm.value.x = 0
|
||||||
|
batchCopyingForm.value.y = 0
|
||||||
|
dialogFormVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['addEventListener', 'submitBatchCopyingFormSuccess'])
|
||||||
|
const dialogClose = () => {
|
||||||
|
emit('addEventListener')
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitLineLibraryForm = async () => {
|
||||||
|
await BatchCopyingFormRef.value.validate(async (valid, fields) => {
|
||||||
|
if (valid) {
|
||||||
|
dialogFormVisible.value = false
|
||||||
|
emit('submitBatchCopyingFormSuccess', batchCopyingForm.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.batch-copying-dialog-form {
|
||||||
|
padding: 0px;
|
||||||
|
|
||||||
|
.el-dialog__footer {
|
||||||
|
padding: 0px 20px 20px 0;
|
||||||
|
border-top: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -883,7 +883,7 @@ onMounted(() => {
|
|||||||
// 监听页面可见性变化
|
// 监听页面可见性变化
|
||||||
document.addEventListener('visibilitychange', () => {
|
document.addEventListener('visibilitychange', () => {
|
||||||
if (!document.hidden && robotListTimerRef.value === null) {
|
if (!document.hidden && robotListTimerRef.value === null) {
|
||||||
robotListTimerRef.value = setInterval(getRobotByFloorAndAreaList, 5000)
|
robotListTimerRef.value = setInterval(getRobotByFloorAndAreaList, 10000)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -284,6 +284,7 @@
|
|||||||
toolbarSwitchType === 'createRegion' ||
|
toolbarSwitchType === 'createRegion' ||
|
||||||
toolbarSwitchType === 'drawRoute' ||
|
toolbarSwitchType === 'drawRoute' ||
|
||||||
toolbarSwitchType === 'generateLine' ||
|
toolbarSwitchType === 'generateLine' ||
|
||||||
|
toolbarSwitchType === 'batchCopying' ||
|
||||||
toolbarSwitchType === 'bulkDelete'))
|
toolbarSwitchType === 'bulkDelete'))
|
||||||
"
|
"
|
||||||
></div>
|
></div>
|
||||||
@ -294,6 +295,7 @@
|
|||||||
toolbarSwitchType === 'createRegion' ||
|
toolbarSwitchType === 'createRegion' ||
|
||||||
toolbarSwitchType === 'drawRoute' ||
|
toolbarSwitchType === 'drawRoute' ||
|
||||||
toolbarSwitchType === 'generateLine' ||
|
toolbarSwitchType === 'generateLine' ||
|
||||||
|
toolbarSwitchType === 'batchCopying' ||
|
||||||
toolbarSwitchType === 'bulkDelete')
|
toolbarSwitchType === 'bulkDelete')
|
||||||
"
|
"
|
||||||
type="danger"
|
type="danger"
|
||||||
@ -898,6 +900,12 @@
|
|||||||
ref="GenerateStraightLinesDialogRef"
|
ref="GenerateStraightLinesDialogRef"
|
||||||
@generate-straight-lines-submit="GenerateStraightLinesSubmit"
|
@generate-straight-lines-submit="GenerateStraightLinesSubmit"
|
||||||
/>
|
/>
|
||||||
|
<!-- 批量复制节点和路线 -->
|
||||||
|
<BatchCopyingDialogForm
|
||||||
|
ref="BatchCopyingDialogFormRef"
|
||||||
|
:imgBgObj="imgBgObj"
|
||||||
|
@submit-batch-copying-form-success="submitBatchCopyingFormSuccess"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -910,6 +918,7 @@ import editNodeProperties from './components-tool/editNodeProperties.vue'
|
|||||||
import textFormToolDialog from './components-tool/textFormToolDialog.vue'
|
import textFormToolDialog from './components-tool/textFormToolDialog.vue'
|
||||||
import equipmentToolDialog from './components-tool/equipmentToolDialog.vue'
|
import equipmentToolDialog from './components-tool/equipmentToolDialog.vue'
|
||||||
import itemAreaSettingDialog from './components-tool/itemAreaSettingDialog.vue'
|
import itemAreaSettingDialog from './components-tool/itemAreaSettingDialog.vue'
|
||||||
|
import BatchCopyingDialogForm from './components-tool/BatchCopyingDialogForm.vue'
|
||||||
import lineLibrarySettingDialog from './components-tool/lineLibrarySettingDialog.vue'
|
import lineLibrarySettingDialog from './components-tool/lineLibrarySettingDialog.vue'
|
||||||
import layerSelectionToolDialog from './components-tool/layerSelectionToolDialog.vue'
|
import layerSelectionToolDialog from './components-tool/layerSelectionToolDialog.vue'
|
||||||
import itemAreaManagementDialog from './components-tool/itemAreaManagementDialog.vue'
|
import itemAreaManagementDialog from './components-tool/itemAreaManagementDialog.vue'
|
||||||
@ -928,6 +937,7 @@ const lineLibraryManagementDialogRef = ref() //线库管理
|
|||||||
const itemAreaManagementDialogRef = ref() //区域管理
|
const itemAreaManagementDialogRef = ref() //区域管理
|
||||||
const lineLibrarySettingDialogRef = ref() //线库设置
|
const lineLibrarySettingDialogRef = ref() //线库设置
|
||||||
const itemAreaSettingDialogRef = ref() //物料区域设置
|
const itemAreaSettingDialogRef = ref() //物料区域设置
|
||||||
|
const BatchCopyingDialogFormRef = ref() //批量复制
|
||||||
const equipmentToolDialogRef = ref() //设备弹窗
|
const equipmentToolDialogRef = ref() //设备弹窗
|
||||||
const textFormToolDialogRef = ref() //文字输入弹窗
|
const textFormToolDialogRef = ref() //文字输入弹窗
|
||||||
const editMapRouteDialogRef = ref() //编辑地图路线的弹窗
|
const editMapRouteDialogRef = ref() //编辑地图路线的弹窗
|
||||||
@ -1519,6 +1529,13 @@ const state = reactive({
|
|||||||
icon: 'ep:delete',
|
icon: 'ep:delete',
|
||||||
isActive: false
|
isActive: false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
switchType: 'batchCopying',
|
||||||
|
name: '批量复制',
|
||||||
|
icon: 'ep:document-copy',
|
||||||
|
isActive: false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
switchType: 'showSortNum',
|
switchType: 'showSortNum',
|
||||||
name: '节点序号',
|
name: '节点序号',
|
||||||
@ -1566,6 +1583,7 @@ const state = reactive({
|
|||||||
drawSelectionAreaBox: { x: 0, y: 0, width: 0, height: 0 }, //绘制区域的位置,长宽
|
drawSelectionAreaBox: { x: 0, y: 0, width: 0, height: 0 }, //绘制区域的位置,长宽
|
||||||
drawSelectionStartPoint: { x: 0, y: 0 }, //开始绘制的点位
|
drawSelectionStartPoint: { x: 0, y: 0 }, //开始绘制的点位
|
||||||
drawSelectionPointList: [], //绘制选中的list
|
drawSelectionPointList: [], //绘制选中的list
|
||||||
|
drawSelectionRouteList: [], //绘制选中的路线list
|
||||||
textFormToolShow: false, //文字表单显示隐藏
|
textFormToolShow: false, //文字表单显示隐藏
|
||||||
showInputBox: false, //输入框显示隐藏
|
showInputBox: false, //输入框显示隐藏
|
||||||
inputBoxStyle: {
|
inputBoxStyle: {
|
||||||
@ -1700,7 +1718,8 @@ const toolbarClick = async (item) => {
|
|||||||
toolbarSwitchType.value === 'generateLine' ||
|
toolbarSwitchType.value === 'generateLine' ||
|
||||||
toolbarSwitchType.value === 'createLineLibrary' ||
|
toolbarSwitchType.value === 'createLineLibrary' ||
|
||||||
toolbarSwitchType.value === 'createRegion' ||
|
toolbarSwitchType.value === 'createRegion' ||
|
||||||
toolbarSwitchType.value === 'bulkDelete'
|
toolbarSwitchType.value === 'bulkDelete' ||
|
||||||
|
toolbarSwitchType.value === 'batchCopying'
|
||||||
) {
|
) {
|
||||||
state.cursorStyle = 'crosshair'
|
state.cursorStyle = 'crosshair'
|
||||||
} else if (
|
} else if (
|
||||||
@ -1734,6 +1753,7 @@ const toolbarClick = async (item) => {
|
|||||||
toolbarSwitchType.value === 'createLineLibrary' ||
|
toolbarSwitchType.value === 'createLineLibrary' ||
|
||||||
toolbarSwitchType.value === 'createRegion' ||
|
toolbarSwitchType.value === 'createRegion' ||
|
||||||
toolbarSwitchType.value === 'bulkDelete' ||
|
toolbarSwitchType.value === 'bulkDelete' ||
|
||||||
|
toolbarSwitchType.value === 'batchCopying' ||
|
||||||
toolbarSwitchType.value === 'editRoute' ||
|
toolbarSwitchType.value === 'editRoute' ||
|
||||||
toolbarSwitchType.value === 'generateLine'
|
toolbarSwitchType.value === 'generateLine'
|
||||||
) {
|
) {
|
||||||
@ -1936,6 +1956,9 @@ const toolbarClick = async (item) => {
|
|||||||
case 'bulkDelete':
|
case 'bulkDelete':
|
||||||
// 批量删除
|
// 批量删除
|
||||||
break
|
break
|
||||||
|
case 'batchCopying':
|
||||||
|
//批量复制
|
||||||
|
break
|
||||||
case 'showSortNum':
|
case 'showSortNum':
|
||||||
// 显示节点序号
|
// 显示节点序号
|
||||||
//网格
|
//网格
|
||||||
@ -2280,7 +2303,8 @@ const startDrawSelection = (event) => {
|
|||||||
toolbarSwitchType.value === 'createRegion' ||
|
toolbarSwitchType.value === 'createRegion' ||
|
||||||
toolbarSwitchType.value === 'drawRoute' ||
|
toolbarSwitchType.value === 'drawRoute' ||
|
||||||
toolbarSwitchType.value == 'generateLine' ||
|
toolbarSwitchType.value == 'generateLine' ||
|
||||||
toolbarSwitchType.value === 'bulkDelete'
|
toolbarSwitchType.value === 'bulkDelete' ||
|
||||||
|
toolbarSwitchType.value === 'batchCopying'
|
||||||
) {
|
) {
|
||||||
const { x, y } = disposeEventPoints(event)
|
const { x, y } = disposeEventPoints(event)
|
||||||
|
|
||||||
@ -2301,7 +2325,8 @@ const updateDrawSelection = throttle((event) => {
|
|||||||
toolbarSwitchType.value === 'createRegion' ||
|
toolbarSwitchType.value === 'createRegion' ||
|
||||||
toolbarSwitchType.value === 'drawRoute' ||
|
toolbarSwitchType.value === 'drawRoute' ||
|
||||||
toolbarSwitchType.value === 'generateLine' ||
|
toolbarSwitchType.value === 'generateLine' ||
|
||||||
toolbarSwitchType.value === 'bulkDelete'
|
toolbarSwitchType.value === 'bulkDelete' ||
|
||||||
|
toolbarSwitchType.value === 'batchCopying'
|
||||||
) {
|
) {
|
||||||
if (state.drawSelectionAreaShow) {
|
if (state.drawSelectionAreaShow) {
|
||||||
const { x, y } = disposeEventPoints(event)
|
const { x, y } = disposeEventPoints(event)
|
||||||
@ -2405,7 +2430,8 @@ const endDrawSelection = (event) => {
|
|||||||
toolbarSwitchType.value === 'createRegion' ||
|
toolbarSwitchType.value === 'createRegion' ||
|
||||||
toolbarSwitchType.value === 'drawRoute' ||
|
toolbarSwitchType.value === 'drawRoute' ||
|
||||||
toolbarSwitchType.value === 'generateLine' ||
|
toolbarSwitchType.value === 'generateLine' ||
|
||||||
toolbarSwitchType.value === 'bulkDelete'
|
toolbarSwitchType.value === 'bulkDelete' ||
|
||||||
|
toolbarSwitchType.value === 'batchCopying'
|
||||||
) {
|
) {
|
||||||
// 使用 requestAnimationFrame 优化渲染
|
// 使用 requestAnimationFrame 优化渲染
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
@ -2421,26 +2447,64 @@ const endDrawSelection = (event) => {
|
|||||||
|
|
||||||
//点击区域
|
//点击区域
|
||||||
const clickDrawSelectionArea = () => {
|
const clickDrawSelectionArea = () => {
|
||||||
let points = state.allMapPointInfo
|
|
||||||
|
|
||||||
state.drawSelectionPointList = []
|
state.drawSelectionPointList = []
|
||||||
|
state.drawSelectionRouteList = []
|
||||||
|
|
||||||
|
// 用于存储所有框选区域的数据
|
||||||
|
const allSelectedPoints = new Map()
|
||||||
|
const allSelectedRoutes = new Set()
|
||||||
|
|
||||||
state.allDrawSelectionAreaBox.forEach((box) => {
|
state.allDrawSelectionAreaBox.forEach((box) => {
|
||||||
points.forEach((point) => {
|
// 筛选点
|
||||||
|
state.allMapPointInfo.forEach((point) => {
|
||||||
if (
|
if (
|
||||||
point.locationX >= box.x &&
|
point.locationX >= box.x &&
|
||||||
point.locationX <= box.x + box.width &&
|
point.locationX <= box.x + box.width &&
|
||||||
point.locationY >= box.y &&
|
point.locationY >= box.y &&
|
||||||
point.locationY <= box.y + box.height
|
point.locationY <= box.y + box.height
|
||||||
) {
|
) {
|
||||||
state.drawSelectionPointList.push(point)
|
// 使用位置和类型组合作为唯一标识
|
||||||
|
const pointKey = `${point.locationX},${point.locationY},${point.type}`
|
||||||
|
if (!allSelectedPoints.has(pointKey)) {
|
||||||
|
allSelectedPoints.set(pointKey, point)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 筛选路线
|
||||||
|
if (toolbarSwitchType.value === 'batchCopying') {
|
||||||
|
state.mapRouteList.forEach((route) => {
|
||||||
|
const startPointInBox =
|
||||||
|
route.startPointX >= box.x &&
|
||||||
|
route.startPointX <= box.x + box.width &&
|
||||||
|
route.startPointY >= box.y &&
|
||||||
|
route.startPointY <= box.y + box.height
|
||||||
|
|
||||||
|
const endPointInBox =
|
||||||
|
route.endPointX >= box.x &&
|
||||||
|
route.endPointX <= box.x + box.width &&
|
||||||
|
route.endPointY >= box.y &&
|
||||||
|
route.endPointY <= box.y + box.height
|
||||||
|
|
||||||
|
if (startPointInBox && endPointInBox) {
|
||||||
|
// 使用起点ID和终点ID组合作为唯一标识
|
||||||
|
const routeKey = `${route.startingPointId}-${route.endPointId}`
|
||||||
|
if (!allSelectedRoutes.has(routeKey)) {
|
||||||
|
allSelectedRoutes.add(routeKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 将去重后的数据赋值给状态
|
||||||
|
state.drawSelectionPointList = Array.from(allSelectedPoints.values())
|
||||||
|
state.drawSelectionRouteList = state.mapRouteList.filter((route) =>
|
||||||
|
allSelectedRoutes.has(`${route.startingPointId}-${route.endPointId}`)
|
||||||
|
)
|
||||||
|
|
||||||
// 清空框选区域
|
// 清空框选区域
|
||||||
state.allDrawSelectionAreaBox = []
|
state.allDrawSelectionAreaBox = []
|
||||||
//去重
|
|
||||||
state.drawSelectionPointList = deduplicateArrayById(state.drawSelectionPointList)
|
|
||||||
//只要库位的
|
//只要库位的
|
||||||
let binLocation = state.drawSelectionPointList.filter((item) => item.type === 2)
|
let binLocation = state.drawSelectionPointList.filter((item) => item.type === 2)
|
||||||
//所以类型的
|
//所以类型的
|
||||||
@ -2578,7 +2642,120 @@ const clickDrawSelectionArea = () => {
|
|||||||
state.currentItemIndex = -1
|
state.currentItemIndex = -1
|
||||||
addEditHistory()
|
addEditHistory()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//批量复制
|
||||||
|
if (toolbarSwitchType.value === 'batchCopying') {
|
||||||
|
if (state.drawSelectionPointList.length > 0) {
|
||||||
|
let boundaryValue = {
|
||||||
|
left: Math.min(...state.drawSelectionPointList.map((point) => Number(point.locationX))),
|
||||||
|
right: Math.max(...state.drawSelectionPointList.map((point) => Number(point.locationX))),
|
||||||
|
top: Math.min(...state.drawSelectionPointList.map((point) => Number(point.locationY))),
|
||||||
|
bottom: Math.max(...state.drawSelectionPointList.map((point) => Number(point.locationY)))
|
||||||
|
}
|
||||||
|
BatchCopyingDialogFormRef.value.open(boundaryValue)
|
||||||
|
} else {
|
||||||
|
message.warning('至少选择一个点')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//批量复制
|
||||||
|
const submitBatchCopyingFormSuccess = async (form) => {
|
||||||
|
let newPoints = JSON.parse(JSON.stringify(state.drawSelectionPointList))
|
||||||
|
let newRoutes = JSON.parse(JSON.stringify(state.drawSelectionRouteList))
|
||||||
|
|
||||||
|
// 创建节点ID映射
|
||||||
|
const nodeIdMap = new Map()
|
||||||
|
|
||||||
|
// 处理节点列表
|
||||||
|
const newPointList = await Promise.all(
|
||||||
|
newPoints.map(async (node) => {
|
||||||
|
const newId = await MapApi.getNodeId()
|
||||||
|
nodeIdMap.set(node.id, newId)
|
||||||
|
|
||||||
|
const locationX = Number(node.locationX) + Number(form.x)
|
||||||
|
const locationY = Number(node.locationY) + Number(form.y)
|
||||||
|
const actualPoint = disposeEventPoint(locationX, locationY)
|
||||||
|
|
||||||
|
const { sortNum, createTime, ...restNode } = node
|
||||||
|
return {
|
||||||
|
...restNode,
|
||||||
|
id: newId,
|
||||||
|
locationX,
|
||||||
|
locationY,
|
||||||
|
actualLocationX: actualPoint.actualLocationX,
|
||||||
|
actualLocationY: actualPoint.actualLocationY
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
// 处理路线列表
|
||||||
|
const newRouteList = newRoutes.map((route) => {
|
||||||
|
const newRoute = { ...route }
|
||||||
|
|
||||||
|
// 更新起点
|
||||||
|
if (nodeIdMap.has(route.startingPointId)) {
|
||||||
|
newRoute.startingPointId = nodeIdMap.get(route.startingPointId)
|
||||||
|
newRoute.startPointX = (Number(route.startPointX) + Number(form.x)).toString()
|
||||||
|
newRoute.startPointY = (Number(route.startPointY) + Number(form.y)).toString()
|
||||||
|
|
||||||
|
const actualStartPoint = disposeEventPoint(newRoute.startPointX, newRoute.startPointY)
|
||||||
|
newRoute.actualStartPointX = actualStartPoint.actualLocationX
|
||||||
|
newRoute.actualStartPointY = actualStartPoint.actualLocationY
|
||||||
|
|
||||||
|
// 更新控制点
|
||||||
|
if (route.method == 1) {
|
||||||
|
newRoute.beginControlX = (Number(route.beginControlX) + Number(form.x)).toString()
|
||||||
|
newRoute.beginControlY = (Number(route.beginControlY) + Number(form.y)).toString()
|
||||||
|
const actualBeginControl = disposeEventPoint(newRoute.beginControlX, newRoute.beginControlY)
|
||||||
|
newRoute.actualBeginControlX = actualBeginControl.actualLocationX
|
||||||
|
newRoute.actualBeginControlY = actualBeginControl.actualLocationY
|
||||||
|
} else {
|
||||||
|
newRoute.beginControlX = 0
|
||||||
|
newRoute.beginControlY = 0
|
||||||
|
newRoute.actualBeginControlX = 0
|
||||||
|
newRoute.actualBeginControlY = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新终点
|
||||||
|
if (nodeIdMap.has(route.endPointId)) {
|
||||||
|
newRoute.endPointId = nodeIdMap.get(route.endPointId)
|
||||||
|
newRoute.endPointX = (Number(route.endPointX) + Number(form.x)).toString()
|
||||||
|
newRoute.endPointY = (Number(route.endPointY) + Number(form.y)).toString()
|
||||||
|
|
||||||
|
const actualEndPoint = disposeEventPoint(newRoute.endPointX, newRoute.endPointY)
|
||||||
|
newRoute.actualEndPointX = actualEndPoint.actualLocationX
|
||||||
|
newRoute.actualEndPointY = actualEndPoint.actualLocationY
|
||||||
|
|
||||||
|
// 更新控制点
|
||||||
|
if (route.method == 1) {
|
||||||
|
newRoute.endControlX = (Number(route.endControlX) + Number(form.x)).toString()
|
||||||
|
newRoute.endControlY = (Number(route.endControlY) + Number(form.y)).toString()
|
||||||
|
const actualEndControl = disposeEventPoint(newRoute.endControlX, newRoute.endControlY)
|
||||||
|
newRoute.actualEndControlX = actualEndControl.actualLocationX
|
||||||
|
newRoute.actualEndControlY = actualEndControl.actualLocationY
|
||||||
|
} else {
|
||||||
|
newRoute.endControlX = 0
|
||||||
|
newRoute.endControlY = 0
|
||||||
|
newRoute.actualEndControlX = 0
|
||||||
|
newRoute.actualEndControlY = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id, createTime, startingSortNum, endPointSortNum, ...restRoute } = newRoute
|
||||||
|
return restRoute
|
||||||
|
})
|
||||||
|
|
||||||
|
// 添加到地图
|
||||||
|
console.log(newPointList, newRouteList)
|
||||||
|
|
||||||
|
state.allMapPointInfo.push(...newPointList)
|
||||||
|
state.mapRouteList.push(...newRouteList)
|
||||||
|
message.success('复制成功')
|
||||||
|
addEditHistory()
|
||||||
|
}
|
||||||
|
|
||||||
//生成直线 选择完成开始点和结束点
|
//生成直线 选择完成开始点和结束点
|
||||||
const GenerateStraightLinesSubmit = (pointList, form) => {
|
const GenerateStraightLinesSubmit = (pointList, form) => {
|
||||||
// 使用 requestAnimationFrame 优化渲染
|
// 使用 requestAnimationFrame 优化渲染
|
||||||
@ -2630,24 +2807,13 @@ const GenerateStraightLinesSubmit = (pointList, form) => {
|
|||||||
}
|
}
|
||||||
return item
|
return item
|
||||||
})
|
})
|
||||||
|
|
||||||
// 批量更新状态
|
// 批量更新状态
|
||||||
state.allMapPointInfo = updatedPoints
|
state.allMapPointInfo = updatedPoints
|
||||||
state.mapRouteList = updatedRoutes
|
state.mapRouteList = updatedRoutes
|
||||||
addEditHistory()
|
addEditHistory()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
//去重
|
|
||||||
const deduplicateArrayById = (arr) => {
|
|
||||||
const idSet = new Set()
|
|
||||||
return arr.filter((item) => {
|
|
||||||
if (idSet.has(item.id)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
idSet.add(item.id)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
//返回生成线库时 排序相同项的id
|
//返回生成线库时 排序相同项的id
|
||||||
const findDuplicateLocationIds = (data) => {
|
const findDuplicateLocationIds = (data) => {
|
||||||
const locationMap = {}
|
const locationMap = {}
|
||||||
@ -3341,6 +3507,7 @@ const saveMap = async () => {
|
|||||||
message.success('保存成功')
|
message.success('保存成功')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
loading.close()
|
loading.close()
|
||||||
|
message.error(error?.message || '保存失败')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//节点的保存
|
//节点的保存
|
||||||
@ -3374,11 +3541,19 @@ const saveNodeList = async () => {
|
|||||||
item.dataJson = JSON.stringify(item.dataObj)
|
item.dataJson = JSON.stringify(item.dataObj)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
await MapApi.batchSaveOrEditOrDelMapItem(imgBgObj.positionMapId, list)
|
try {
|
||||||
|
await MapApi.batchSaveOrEditOrDelMapItem(imgBgObj.positionMapId, list)
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error('节点保存失败:' + (error?.message || '未知错误'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//路线的保存
|
//路线的保存
|
||||||
const saveMapRoute = async () => {
|
const saveMapRoute = async () => {
|
||||||
await MapApi.createOrEditOrDelPositionMapLine(imgBgObj.positionMapId, state.mapRouteList)
|
try {
|
||||||
|
await MapApi.createOrEditOrDelPositionMapLine(imgBgObj.positionMapId, state.mapRouteList)
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error('路线保存失败:' + (error?.message || '未知错误'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//线库新增 要在库位新增线库信息
|
//线库新增 要在库位新增线库信息
|
||||||
const submitLineLibraryFormSuccess = (obj) => {
|
const submitLineLibraryFormSuccess = (obj) => {
|
||||||
@ -3556,15 +3731,7 @@ const getLineMidArrowPath = (item) => {
|
|||||||
|
|
||||||
return `M ${startXArrow} ${startYArrow} L ${endXArrow} ${endYArrow}`
|
return `M ${startXArrow} ${startYArrow} L ${endXArrow} ${endYArrow}`
|
||||||
}
|
}
|
||||||
// 计算贝塞尔曲线中间箭头的路径(简单近似)
|
|
||||||
const getBezierMidArrowPath = (item) => {
|
|
||||||
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
|
|
||||||
path.setAttribute('d', item.curvePath)
|
|
||||||
const length = path.getTotalLength()
|
|
||||||
const midPoint = path.getPointAtLength(length / 2)
|
|
||||||
const prevPoint = path.getPointAtLength(length / 2 - 1)
|
|
||||||
return `M ${prevPoint.x} ${prevPoint.y} L ${midPoint.x} ${midPoint.y}`
|
|
||||||
}
|
|
||||||
// 计算贝塞尔曲线中间文字的 x 坐标
|
// 计算贝塞尔曲线中间文字的 x 坐标
|
||||||
const computedCurveTextX = (item) => {
|
const computedCurveTextX = (item) => {
|
||||||
return (
|
return (
|
||||||
@ -3851,6 +4018,8 @@ const findClosestPoint = (x, y) => {
|
|||||||
padding: 0 0.75rem;
|
padding: 0 0.75rem;
|
||||||
|
|
||||||
.top-tool-list {
|
.top-tool-list {
|
||||||
|
max-width: calc(100vw - 260px);
|
||||||
|
overflow-x: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -3896,11 +4065,13 @@ const findClosestPoint = (x, y) => {
|
|||||||
.right-tool-list {
|
.right-tool-list {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 64px;
|
top: 70px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
box-shadow: rgba(0, 0, 0, 0.05) 0rem 0rem 0rem 0.0625rem;
|
box-shadow: rgba(0, 0, 0, 0.05) 0rem 0rem 0rem 0.0625rem;
|
||||||
|
max-height: calc(100vh - 200px);
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
.tool-item {
|
.tool-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -4008,4 +4179,33 @@ const findClosestPoint = (x, y) => {
|
|||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 美化滚动条
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
width: 6px;
|
||||||
|
background: rgba(#101f1c, 0.1);
|
||||||
|
-webkit-border-radius: 2em;
|
||||||
|
-moz-border-radius: 2em;
|
||||||
|
border-radius: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgba(144, 147, 153, 0.7);
|
||||||
|
background-clip: padding-box;
|
||||||
|
min-height: 28px;
|
||||||
|
-webkit-border-radius: 2em;
|
||||||
|
-moz-border-radius: 2em;
|
||||||
|
border-radius: 2em;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: rgba(144, 147, 153, 0.3);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user