316 lines
9.6 KiB
Vue
316 lines
9.6 KiB
Vue
<template>
|
|
<Dialog
|
|
v-model="dialogFormVisible"
|
|
title="库区选择"
|
|
width="1200"
|
|
class="location-selection-dialog"
|
|
:fullscreen="false"
|
|
top="4vh"
|
|
>
|
|
<div class="location-selection-dialog-map">
|
|
<div
|
|
class="location-selection-map"
|
|
:style="{
|
|
width: imgBgObj.showWidth + 'px',
|
|
height: imgBgObj.showHeight + 'px',
|
|
backgroundImage: `url(${imgBgObj.imgUrl})`
|
|
}"
|
|
>
|
|
<div
|
|
v-for="(item, index) in allMapPointInfo"
|
|
:key="index"
|
|
class="location-selection-map-item"
|
|
>
|
|
<template v-if="locationTypeNumber == 1">
|
|
<el-popover placement="top" trigger="click" :popper-style="{ padding: '0px' }">
|
|
<template #reference>
|
|
<img
|
|
src="https://api.znkjfw.com/admin-api/infra/file/4/get/库位库存_png_179_1739326653035.png"
|
|
alt=""
|
|
: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
|
|
}"
|
|
/>
|
|
</template>
|
|
<div class="drop-down-menu">
|
|
<!-- 楼层展开 -->
|
|
<div
|
|
v-for="(floor, floorIndex) in item.dataList"
|
|
:key="floorIndex"
|
|
class="drop-down-menu-item"
|
|
:class="currentItem && currentItem.id == floor.id ? 'tool-active' : ''"
|
|
@click="choosePoint(floor)"
|
|
>
|
|
{{ floor.locationNo }}
|
|
</div>
|
|
</div>
|
|
</el-popover>
|
|
</template>
|
|
<template v-else>
|
|
<el-popover placement="top" trigger="click" :popper-style="{ padding: '0px' }">
|
|
<template #reference>
|
|
<img
|
|
@click="choosePoint(item)"
|
|
src="https://api.znkjfw.com/admin-api/infra/file/4/get/库位库存_png_179_1739326653035.png"
|
|
alt=""
|
|
: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,
|
|
border:
|
|
(currentItem &&
|
|
locationTypeNumber == 2 &&
|
|
currentItem.laneId == item.laneId) ||
|
|
(locationTypeNumber == 3 && currentItem.areaId == item.areaId)
|
|
? '1px dashed #000'
|
|
: 'none'
|
|
}"
|
|
/>
|
|
</template>
|
|
<div class="drop-down-menu">
|
|
<div class="drop-down-menu" v-if="locationTypeNumber == 2">
|
|
<div class="drop-down-menu-item"> {{ item.laneName }} </div>
|
|
</div>
|
|
<div class="drop-down-menu" v-if="locationTypeNumber == 3">
|
|
<div class="drop-down-menu-item">{{ item.areaName }}</div>
|
|
</div>
|
|
</div>
|
|
</el-popover>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="location-selection-dialog-footer">
|
|
<el-button style="width: 90px" @click="dialogFormVisible = false">取消</el-button>
|
|
<el-button style="width: 90px" type="primary" @click="submitAddForm"> 确定 </el-button>
|
|
</div>
|
|
</Dialog>
|
|
</template>
|
|
|
|
<script setup>
|
|
import JSONBigInt from 'json-bigint'
|
|
import { reactive, ref } from 'vue'
|
|
import * as MapApi from '@/api/map/map'
|
|
|
|
const dialogFormVisible = ref(false) //列表的
|
|
const message = useMessage() // 消息弹窗
|
|
|
|
const props = defineProps({
|
|
positionMapId: {
|
|
type: String,
|
|
default: () => ''
|
|
}
|
|
})
|
|
|
|
const locationTypeNumber = ref(1)
|
|
const open = (locationTypeNum) => {
|
|
dialogFormVisible.value = true
|
|
currentItem.value = null
|
|
locationTypeNumber.value = locationTypeNum
|
|
imgBgObj.positionMapId = props.positionMapId
|
|
getMapList()
|
|
}
|
|
|
|
const allMapPointInfo = ref([]) //点位信息
|
|
const imgBgObj = reactive({
|
|
imgUrl: '',
|
|
positionMapId: '',
|
|
width: '',
|
|
height: '',
|
|
floor: '',
|
|
area: '',
|
|
resolution: 0,
|
|
origin: null,
|
|
showWidth: 1150,
|
|
showHeight: 0
|
|
})
|
|
const getMapList = async () => {
|
|
if (props.positionMapId) {
|
|
let res = await MapApi.getPositionMap(props.positionMapId)
|
|
let yamlJson = JSON.parse(res.yamlJson)
|
|
imgBgObj.positionMapId = res.id
|
|
imgBgObj.floor = res.floor
|
|
imgBgObj.area = res.area
|
|
imgBgObj.width = yamlJson.width
|
|
imgBgObj.height = yamlJson.height
|
|
imgBgObj.origin = yamlJson.origin
|
|
imgBgObj.resolution = yamlJson.resolution
|
|
imgBgObj.showHeight = (imgBgObj.showWidth * imgBgObj.height) / imgBgObj.width
|
|
} else {
|
|
}
|
|
|
|
getMapData()
|
|
getAllNodeList()
|
|
}
|
|
|
|
//调转换成png的接口
|
|
const getMapData = async () => {
|
|
let data = await MapApi.getPositionMapdDwnloadPngBase64({
|
|
floor: imgBgObj.floor,
|
|
area: imgBgObj.area
|
|
})
|
|
imgBgObj.imgUrl = data
|
|
}
|
|
|
|
const currentItem = ref(null)
|
|
const getAllNodeList = async () => {
|
|
let list = await MapApi.getPositionMapItemList({
|
|
positionMapId: imgBgObj.positionMapId
|
|
})
|
|
allMapPointInfo.value = []
|
|
|
|
list.forEach((item) => {
|
|
//只要库位
|
|
if (locationTypeNumber.value == 1 && item.type === 2) {
|
|
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)
|
|
item.locationDeep = item.dataList[0].locationDeep
|
|
item.locationWide = item.dataList[0].locationWide
|
|
|
|
//要将实际的cm改成px
|
|
if (item.locationWide && item.locationDeep) {
|
|
let pxObj = cmConversionPx(item.locationWide, item.locationDeep)
|
|
item.locationWidePx = pxObj.pWidth
|
|
item.locationDeepPx = pxObj.pHeight
|
|
}
|
|
allMapPointInfo.value.push(item)
|
|
}
|
|
|
|
//线库 laneId
|
|
if (locationTypeNumber.value == 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)
|
|
item.locationDeep = item.dataList[0].locationDeep
|
|
item.locationWide = item.dataList[0].locationWide
|
|
item.laneName = item.dataList[0].laneName
|
|
|
|
//要将实际的cm改成px
|
|
if (item.locationWide && item.locationDeep) {
|
|
let pxObj = cmConversionPx(item.locationWide, item.locationDeep)
|
|
item.locationWidePx = pxObj.pWidth
|
|
item.locationDeepPx = pxObj.pHeight
|
|
}
|
|
allMapPointInfo.value.push(item)
|
|
}
|
|
|
|
//区域 areaId
|
|
if (locationTypeNumber.value == 3 && 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)
|
|
item.locationDeep = item.dataList[0].locationDeep
|
|
item.locationWide = item.dataList[0].locationWide
|
|
item.areaName = item.dataList[0].areaName
|
|
|
|
//要将实际的cm改成px
|
|
if (item.locationWide && item.locationDeep) {
|
|
let pxObj = cmConversionPx(item.locationWide, item.locationDeep)
|
|
item.locationWidePx = pxObj.pWidth
|
|
item.locationDeepPx = pxObj.pHeight
|
|
}
|
|
allMapPointInfo.value.push(item)
|
|
}
|
|
})
|
|
}
|
|
//将节点实际宽高cm转换成px
|
|
const cmConversionPx = (cWidth, cHeight) => {
|
|
let pWidth = (Number(cWidth) / imgBgObj.resolution / 100) * (imgBgObj.showWidth / imgBgObj.width)
|
|
let pHeight =
|
|
(Number(cHeight) / imgBgObj.resolution / 100) * (imgBgObj.showWidth / imgBgObj.width)
|
|
|
|
return {
|
|
pWidth,
|
|
pHeight
|
|
}
|
|
}
|
|
|
|
const choosePoint = (item) => {
|
|
currentItem.value = item
|
|
}
|
|
|
|
const submitAddForm = () => {
|
|
if (currentItem.value) {
|
|
emit('locationSelectionDialogSuccess', currentItem.value)
|
|
dialogFormVisible.value = false
|
|
} else {
|
|
message.warning('请选择一个位置')
|
|
}
|
|
}
|
|
|
|
const emit = defineEmits(['locationSelectionDialogSuccess'])
|
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.location-selection-dialog {
|
|
padding: 0px;
|
|
position: relative;
|
|
|
|
.el-dialog__footer {
|
|
padding: 10px 20px 20px 0;
|
|
border-top: none !important;
|
|
}
|
|
|
|
.location-selection-dialog-map {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 80vh;
|
|
overflow: auto;
|
|
|
|
.location-selection-map {
|
|
position: relative;
|
|
width: 100%;
|
|
|
|
.location-selection-map-item {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
.location-selection-dialog-footer {
|
|
position: absolute;
|
|
bottom: 30px;
|
|
right: 60px;
|
|
}
|
|
}
|
|
.drop-down-menu {
|
|
.drop-down-menu-item {
|
|
cursor: pointer;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding: 11px 0;
|
|
font-family:
|
|
PingFangSC,
|
|
PingFang SC;
|
|
font-weight: 400;
|
|
font-size: 14px;
|
|
color: #0d162a;
|
|
line-height: 20px;
|
|
text-align: left;
|
|
font-style: normal;
|
|
border-bottom: 1px solid #e9e9e9;
|
|
}
|
|
|
|
:last-child {
|
|
border-bottom: none;
|
|
}
|
|
}
|
|
|
|
.tool-active {
|
|
background: #ebf1ff !important;
|
|
}
|
|
</style>
|