489 lines
16 KiB
Vue
489 lines
16 KiB
Vue
<template>
|
||
<Dialog
|
||
v-model="dialogFormVisible"
|
||
title="节点属性"
|
||
width="540"
|
||
class="node-form-dialog"
|
||
@close="dialogClose"
|
||
>
|
||
<el-form :model="form" label-width="80" ref="ruleFormRef" :rules="rules">
|
||
<el-form-item label="X" prop="locationX" required>
|
||
<el-input-number
|
||
style="width: 100%"
|
||
v-model="form.locationX"
|
||
:min="0"
|
||
placeholder="请输入"
|
||
controls-position="right"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="Y" prop="locationY" required>
|
||
<el-input-number
|
||
style="width: 100%"
|
||
v-model="form.locationY"
|
||
:min="0"
|
||
placeholder="请输入"
|
||
controls-position="right"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="类型" prop="type" required>
|
||
<el-select v-model="form.type" placeholder="请选择类型" @change="typeChange">
|
||
<el-option label="路径点位" :value="1" />
|
||
<el-option label="库位点" :value="2" />
|
||
<el-option label="设备点" :value="3" />
|
||
<el-option label="停车点" :value="4" />
|
||
<el-option label="区域变更点" :value="5" />
|
||
<el-option label="等待点" :value="6" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="弧度" prop="locationYaw" required>
|
||
<el-input-number
|
||
class="!w-200px"
|
||
v-model="form.locationYaw"
|
||
:min="0"
|
||
:max="10000"
|
||
placeholder="请输入"
|
||
:precision="2"
|
||
/>
|
||
</el-form-item>
|
||
|
||
<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-200px"
|
||
v-model="form.layersNumber"
|
||
:min="1"
|
||
:max="4"
|
||
:precision="0"
|
||
:step="1"
|
||
step-strictly
|
||
/>
|
||
<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-200px" 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"
|
||
clearable
|
||
placeholder="请选择设备类型"
|
||
@change="deviceTypeChange()"
|
||
>
|
||
<el-option
|
||
v-for="dict in getIntDictOptions(DICT_TYPE.DEVICE_TYPE)"
|
||
:key="dict.value"
|
||
:label="dict.label"
|
||
:value="dict.value"
|
||
/>
|
||
</el-select>
|
||
<el-select
|
||
v-model="form.deviceId"
|
||
class="!w-160px ml-4"
|
||
clearable
|
||
placeholder="请选择设备编号"
|
||
@change="deviceChange"
|
||
>
|
||
<el-option
|
||
:disabled="item.idDisabled"
|
||
v-for="item in deviceList"
|
||
:key="item.id"
|
||
:label="item.deviceNo"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="库位长度" prop="locationDeep" required>
|
||
<div style="display: flex">
|
||
<el-input-number
|
||
class="!w-200px"
|
||
placeholder="请输入"
|
||
v-model="form.locationDeep"
|
||
:min="10"
|
||
/>
|
||
<span class="ml-2">cm</span>
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="库位宽度" prop="locationWide" required>
|
||
<div style="display: flex">
|
||
<el-input-number
|
||
class="!w-200px"
|
||
placeholder="请输入"
|
||
v-model="form.locationWide"
|
||
:min="10"
|
||
/>
|
||
<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>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button @click="dialogFormVisible = false">取消</el-button>
|
||
<el-button type="primary" @click="submit(ruleFormRef)"> 确认 </el-button>
|
||
</div>
|
||
</template>
|
||
</Dialog>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { reactive, ref } from 'vue'
|
||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||
import * as MapApi from '@/api/map/map'
|
||
|
||
const ruleFormRef = ref()
|
||
const dialogFormVisible = ref(false)
|
||
const message = useMessage() // 消息弹窗
|
||
|
||
const props = defineProps({
|
||
positionMapId: {
|
||
type: String,
|
||
default: () => ''
|
||
},
|
||
imgBgObj: {
|
||
type: Object,
|
||
default: () => {}
|
||
}
|
||
})
|
||
|
||
const form = ref({
|
||
type: 1, //类型 1.路径点位 2.库位点 3.充电桩 4.停车点 5.区域变更点 6.等待点
|
||
layersNumber: 1, //层数
|
||
locationX: undefined, //库位坐标x轴
|
||
locationY: undefined, //库位坐标y轴
|
||
locationDeep: undefined, //长度
|
||
locationWide: undefined, //宽度
|
||
direction: undefined, //库位方向(1:单向、2:双向、3:三向、4:四向)
|
||
inDirection: undefined, //进入方向(0:尾入、1:头入)
|
||
outDirection: undefined, //离开方向(0:尾出、1:头出)
|
||
dataList: [], //存库位的
|
||
dataObj: {}, //存 设备点 停车点 文字
|
||
positionMapId: undefined,
|
||
deviceId: undefined, //设备id
|
||
locationYaw: undefined //弧度
|
||
})
|
||
|
||
const mapWidthCm = ref(0)
|
||
const mapHeightCm = ref(0)
|
||
|
||
watch(
|
||
() => props.imgBgObj,
|
||
(val) => {
|
||
mapWidthCm.value = (Number(val.width) * Number(val.resolution) * 100).toFixed(2)
|
||
mapHeightCm.value = (Number(val.height) * Number(val.resolution) * 100).toFixed(2)
|
||
},
|
||
{ immediate: true }
|
||
)
|
||
|
||
const validateNumberLength = (rule, value, callback) => {
|
||
if (value.toString().length > 25) {
|
||
callback(new Error('输入的数字长度不能超过25位'))
|
||
} else {
|
||
callback()
|
||
}
|
||
}
|
||
|
||
const rules = reactive({
|
||
locationX: [
|
||
{ required: true, message: '请输入X', trigger: 'blur' },
|
||
{
|
||
type: 'number',
|
||
min: 0,
|
||
max: Number(props.imgBgObj.width),
|
||
message: `不能超过地图宽度${props.imgBgObj.width}`,
|
||
trigger: 'blur'
|
||
},
|
||
{ validator: validateNumberLength, trigger: 'blur' }
|
||
],
|
||
locationY: [
|
||
{ required: true, message: '请输入Y', trigger: 'blur' },
|
||
{
|
||
type: 'number',
|
||
min: 0,
|
||
max: Number(props.imgBgObj.height),
|
||
message: `不能超过地图长度${props.imgBgObj.height}`,
|
||
trigger: 'blur'
|
||
},
|
||
{ validator: validateNumberLength, trigger: 'blur' }
|
||
],
|
||
locationYaw: [{ required: true, message: '请输入弧度', trigger: 'blur' }],
|
||
type: [{ required: true, message: '请选择类型', trigger: 'blur' }],
|
||
layersNumber: [{ required: true, message: '请输入层数', trigger: 'blur' }],
|
||
locationNumber: [
|
||
{ required: true, message: '请输入排序', trigger: 'blur' },
|
||
{
|
||
type: 'number',
|
||
min: 0,
|
||
max: 10000000,
|
||
message: `不能超过10000000`,
|
||
trigger: 'blur'
|
||
}
|
||
],
|
||
deviceId: [{ required: true, message: '请选择设备编号', trigger: 'blur' }],
|
||
locationDeep: [
|
||
{ required: true, message: '请选择库位长度', trigger: 'blur' },
|
||
{
|
||
type: 'number',
|
||
min: 0,
|
||
max: Number(mapWidthCm.value),
|
||
message: `不能超过${Number(mapWidthCm.value)}cm`,
|
||
trigger: 'blur'
|
||
}
|
||
],
|
||
locationWide: [
|
||
{ required: true, message: '请选择库位宽度', trigger: 'blur' },
|
||
{
|
||
type: 'number',
|
||
min: 0,
|
||
max: Number(mapHeightCm.value),
|
||
message: `不能超过${Number(mapHeightCm.value)}cm`,
|
||
trigger: 'blur'
|
||
}
|
||
]
|
||
})
|
||
|
||
const emit = defineEmits(['submitNodeSuccess', 'addEventListener'])
|
||
const submit = async (formEl) => {
|
||
if (!formEl) return
|
||
await formEl.validate((valid, fields) => {
|
||
if (!valid) return
|
||
//在这边把数据处理好
|
||
if (form.value.type === 1 || form.value.type === 5 || form.value.type === 6) {
|
||
//不需要dataJson的类型
|
||
form.value.dataJson = ''
|
||
} else if (form.value.type === 2) {
|
||
//库位点 类型为数组
|
||
let list = []
|
||
for (let index = 0; index < form.value.layersNumber; index++) {
|
||
let item = {
|
||
positionMapId: props.positionMapId,
|
||
locationWide: form.value.locationWide || undefined,
|
||
locationDeep: form.value.locationDeep || undefined,
|
||
direction: form.value.direction || undefined, //方向
|
||
inDirection: form.value.inDirection || undefined, //进入方向
|
||
outDirection: form.value.outDirection || undefined, //离开方向
|
||
locationStorey: index + 1 //层数
|
||
}
|
||
if (
|
||
form.value.dataList.length > 0 &&
|
||
form.value.dataList[index] &&
|
||
form.value.dataList[index].id
|
||
) {
|
||
item.id = String(form.value.dataList[index].id)
|
||
item.locationNo = form.value.dataList[index].locationNo
|
||
item.mapItemId = form.value.dataList[index].mapItemId
|
||
item.areaId = form.value.dataList[index].areaId || ''
|
||
item.areaName = form.value.dataList[index].areaName || ''
|
||
item.laneId = form.value.dataList[index].laneId || ''
|
||
item.laneName = form.value.dataList[index].laneName || ''
|
||
}
|
||
list.push(item)
|
||
}
|
||
form.value.dataList = list
|
||
//dataJson数据
|
||
form.value.dataJson = JSON.stringify(form.value.dataList)
|
||
} else if (form.value.type === 3) {
|
||
//设备类型
|
||
form.value.dataObj.positionMapId = props.positionMapId
|
||
form.value.dataObj.locationWide = form.value.locationWide
|
||
form.value.dataObj.locationDeep = form.value.locationDeep
|
||
form.value.dataObj.direction = form.value.direction
|
||
form.value.dataObj.inDirection = form.value.inDirection
|
||
form.value.dataObj.outDirection = form.value.outDirection
|
||
form.value.dataObj.id = form.value.deviceId
|
||
form.value.dataObj.deviceType = deviceInfo.value.deviceType
|
||
form.value.dataObj.deviceNo = deviceInfo.value.deviceNo
|
||
form.value.dataObj.mapImageUrl = deviceInfo.value.mapImageUrl
|
||
form.value.mapImageUrl = deviceInfo.value.mapImageUrl
|
||
//dataJson数据
|
||
form.value.dataJson = JSON.stringify(form.value.dataObj)
|
||
} else {
|
||
//类型为路径点位 区域变更点 等待点 值为对象
|
||
form.value.dataObj.positionMapId = props.positionMapId
|
||
form.value.dataObj.locationWide = form.value.locationWide
|
||
form.value.dataObj.locationDeep = form.value.locationDeep
|
||
form.value.dataObj.direction = form.value.direction
|
||
form.value.dataObj.inDirection = form.value.inDirection
|
||
form.value.dataObj.outDirection = form.value.outDirection
|
||
//dataJson数据
|
||
form.value.dataJson = JSON.stringify(form.value.dataObj)
|
||
}
|
||
emit('submitNodeSuccess', form.value)
|
||
dialogFormVisible.value = false
|
||
})
|
||
}
|
||
|
||
const dialogClose = () => {
|
||
emit('addEventListener')
|
||
}
|
||
|
||
const equipmentList = ref([]) //用过的设备列表
|
||
const open = (item, list) => {
|
||
form.value = item
|
||
form.value.layersNumber = item.dataList?.length || ''
|
||
form.value.deviceId = item?.deviceId || item?.dataObj?.id || ''
|
||
form.value.positionMapId = props.positionMapId
|
||
deviceInfo.value.deviceNo = item?.deviceNo || item?.dataObj?.deviceNo || ''
|
||
deviceInfo.value.mapImageUrl = item?.mapImageUrl || item?.dataObj?.mapImageUrl || ''
|
||
|
||
equipmentList.value = list
|
||
if (item?.dataObj?.deviceType) {
|
||
deviceInfo.value.deviceType = item.dataObj.deviceType || ''
|
||
getDeviceList()
|
||
} else {
|
||
deviceInfo.value.deviceType = ''
|
||
}
|
||
dialogFormVisible.value = true
|
||
}
|
||
|
||
//类型改变
|
||
const typeChange = (type) => {
|
||
form.value.dataJson = null
|
||
form.value.dataObj = {}
|
||
form.value.dataList = []
|
||
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) {
|
||
form.value.locationNumber = null
|
||
form.value.locationDeep = 150
|
||
form.value.locationWide = 150
|
||
form.value.locationDeepPx = 30
|
||
form.value.locationWidePx = 30
|
||
} 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
|
||
form.value.locationDeep = 150
|
||
form.value.locationWide = 150
|
||
form.value.locationDeepPx = 30
|
||
form.value.locationWidePx = 30
|
||
}
|
||
}
|
||
//设备切换
|
||
const deviceChange = (deviceId) => {
|
||
deviceList.value.forEach((item) => {
|
||
if (item.id == deviceId) {
|
||
deviceInfo.value.mapImageUrl = item.mapImageUrl
|
||
deviceInfo.value.deviceNo = item.deviceNo
|
||
}
|
||
})
|
||
}
|
||
//方向改变
|
||
const directionChange = (e) => {
|
||
if (e === 1) {
|
||
form.value.inDirection = undefined
|
||
form.value.outDirection = undefined
|
||
}
|
||
}
|
||
//设备信息
|
||
const deviceInfo = ref({
|
||
positionMapId: '',
|
||
deviceType: '',
|
||
mapImageUrl: '',
|
||
deviceNo: ''
|
||
})
|
||
//设备列表
|
||
const deviceList = ref([])
|
||
//获取设备列表
|
||
const getDeviceList = async () => {
|
||
deviceInfo.value.positionMapId = props.positionMapId
|
||
let list = await MapApi.getDeviceInformationList(deviceInfo.value)
|
||
|
||
const deviceIds = equipmentList.value.map((item) => item.deviceId)
|
||
deviceList.value = list.map((item) => {
|
||
return {
|
||
...item,
|
||
idDisabled: deviceIds.includes(item.id)
|
||
}
|
||
})
|
||
}
|
||
//设备类型切换
|
||
const deviceTypeChange = () => {
|
||
form.value.deviceId = ''
|
||
getDeviceList()
|
||
}
|
||
|
||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.node-form-dialog {
|
||
.el-dialog__header {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.el-dialog__footer {
|
||
border-top: none !important;
|
||
}
|
||
}
|
||
</style>
|