物料区域管理、线库管理

地图设备不能有重复问题
This commit is contained in:
yyy 2025-02-20 16:02:24 +08:00
parent 830c158692
commit 0eb3ff029d
8 changed files with 434 additions and 62 deletions

View File

@ -110,3 +110,20 @@ export const getPositionMapLineById = async (id: number) => {
export const getPositionMapLineByPositionMapId = async (positionMapId: number) => {
return await request.get({ url: `/system/position-map-line/list?positionMapId=` + positionMapId })
}
//获取仓库点位地图节点列表
export const getWareHouseAreaPage = async (params) => {
return await request.get({ url: `/system/ware/house-area/page`, params })
}
//删除仓库点位地图
export const deleteWareHouseArea = async (id: number) => {
return await request.delete({ url: `/system/ware/house-area/delete?id=` + id })
}
//获得线库分页
export const getWareHouseLanePage = async (params) => {
return await request.get({ url: `/system/ware/house-lane/page`, params })
}
//删除仓库点位地图
export const deleteWareLaneArea = async (id: number) => {
return await request.delete({ url: `/system/ware/house-area/delete?id=` + id })
}

View File

@ -224,17 +224,21 @@ const submit = async (formEl) => {
})
}
const open = (item) => {
const equipmentList = ref([]) //
const open = (item, list) => {
console.log(item)
form.value = item
form.value.layersNumber = item.dataList.length || ''
form.value.deviceId = item.dataObj.id || ''
form.value.deviceId = item.deviceId || item.dataObj.id || ''
form.value.positionMapId = props.positionMapId
if (item.deviceType) {
deviceInfo.value.deviceType = item.deviceType
equipmentList.value = list
if (item.dataObj.deviceType) {
deviceInfo.value.deviceType = item.dataObj.deviceType || ''
getDeviceList()
} else {
deviceInfo.value.deviceType = ''
}
dialogFormVisible.value = true
console.log(form.value)
}
//
@ -287,7 +291,10 @@ const deviceList = ref([])
//
const getDeviceList = async () => {
deviceInfo.value.positionMapId = props.positionMapId
deviceList.value = await MapApi.getDeviceInformationList(deviceInfo.value)
let list = await MapApi.getDeviceInformationList(deviceInfo.value)
const deviceIds = equipmentList.value.map((item) => item.deviceId)
deviceList.value = list.filter((item) => !deviceIds.includes(item.id))
}
//
const deviceTypeChange = () => {

View File

@ -0,0 +1,103 @@
<template>
<Dialog
v-model="dialogFormVisible"
title="区域管理"
width="600"
class="item-area-management-dialog"
>
<el-table
:data="list"
style="width: 100%"
:header-cell-style="{ backgroundColor: '#EBF1FF', color: '#0D162A', padding: '13px 0' }"
v-loading="loading"
>
<el-table-column type="index" width="50" align="center" />
<el-table-column prop="areaName" label="库区名称" align="center" />
<el-table-column prop="areaMsg" label="库区说明" align="center" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button size="small" type="danger" @click="handleDelete(scope.row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination">
<el-pagination
size="small"
background
layout="prev, pager, next"
:total="total"
class="mt-4"
/>
</div>
</Dialog>
</template>
<script setup>
import { reactive, ref } from 'vue'
import * as MapApi from '@/api/map/map'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
const dialogFormVisible = ref(false) //
const message = useMessage() //
const props = defineProps({
positionMapId: {
type: String,
default: () => ''
}
})
const open = () => {
dialogFormVisible.value = true
queryParams.positionMapId = props.positionMapId
getWareHouseList()
}
const loading = ref(true) //
const total = ref(0) //
const list = ref()
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
positionMapId: ''
})
const getWareHouseList = async () => {
loading.value = true
try {
const data = await MapApi.getWareHouseAreaPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
const handleDelete = async (id) => {
try {
//
await message.delConfirm('请确认是否删除该物料区域?')
//
await MapApi.deleteWareHouseArea(id)
message.success('删除成功')
//
await getWareHouseList()
} catch {}
}
defineExpose({ open }) // open
</script>
<style lang="scss">
.item-area-management-dialog {
padding: 0px;
.pagination {
display: flex;
align-items: center;
justify-content: flex-end;
}
}
</style>

View File

@ -60,6 +60,8 @@ const open = (list) => {
dialogFormVisible.value = true
form.value.mapItemIds = list.map((item) => item.id)
form.value.areaNumber = form.value.mapItemIds.length
form.value.areaName = ''
form.value.skuInfo = ''
}
const submitForm = async (formEl) => {

View File

@ -0,0 +1,103 @@
<template>
<Dialog
v-model="dialogFormVisible"
title="线库管理"
width="600"
class="line-library-management-dialog"
>
<el-table
:data="list"
style="width: 100%"
:header-cell-style="{ backgroundColor: '#EBF1FF', color: '#0D162A', padding: '13px 0' }"
v-loading="loading"
>
<el-table-column type="index" width="50" align="center" />
<el-table-column prop="laneName" label="巷道名称" align="center" />
<el-table-column prop="laneMsg" label="巷道说明" align="center" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button size="small" type="danger" @click="handleDelete(scope.row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination">
<el-pagination
size="small"
background
layout="prev, pager, next"
:total="total"
class="mt-4"
/>
</div>
</Dialog>
</template>
<script setup>
import { reactive, ref } from 'vue'
import * as MapApi from '@/api/map/map'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
const dialogFormVisible = ref(false) //
const message = useMessage() //
const props = defineProps({
positionMapId: {
type: String,
default: () => ''
}
})
const open = () => {
dialogFormVisible.value = true
queryParams.positionMapId = props.positionMapId
getLineLibraryList()
}
const loading = ref(true) //
const total = ref(0) //
const list = ref()
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
positionMapId: ''
})
const getLineLibraryList = async () => {
loading.value = true
try {
const data = await MapApi.getWareHouseLanePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
const handleDelete = async (id) => {
try {
//
await message.delConfirm('请确认是否删除该物料区域?')
//
await MapApi.deleteWareLaneArea(id)
message.success('删除成功')
//
await getLineLibraryList()
} catch {}
}
defineExpose({ open }) // open
</script>
<style lang="scss">
.line-library-management-dialog {
padding: 0px;
.pagination {
display: flex;
align-items: center;
justify-content: flex-end;
}
}
</style>

View File

@ -1,11 +1,6 @@
<template>
<!-- 新增设备 -->
<Dialog
v-model="dialogFormVisible"
title="物料区域设置"
width="600"
class="equipment-form-dialog"
>
<Dialog v-model="dialogFormVisible" title="线库设置" width="600" class="equipment-form-dialog">
<el-form :model="form" label-width="110" ref="lineFormRef" :rules="rules">
<el-form-item label="线库名称" prop="laneName" required>
<el-input v-model="form.laneName" placeholder="请输入线库名称" />
@ -55,6 +50,7 @@ const open = (list) => {
dialogFormVisible.value = true
form.value.mapItemIds = list.map((item) => item.id)
form.value.areaNumber = form.value.mapItemIds.length
form.value.laneName = ''
}
const submitLineLibraryForm = async () => {

View File

@ -4,7 +4,7 @@
<div v-for="item in state.topToolList" :key="item.switchType" class="top-tool-item">
<el-popover
placement="bottom"
:width="80"
:width="170"
trigger="click"
v-if="item.switchType === 'move' || item.switchType === 'revolve'"
:disabled="currentItemIndex === -1"
@ -26,7 +26,7 @@
</div>
</template>
<!-- 位置 -->
<el-form :model="state.moveForm" v-if="item.switchType === 'move'">
<el-form :model="state.moveForm" v-if="item.switchType === 'move'" class="mt-2">
<el-form-item label="X">
<el-input v-model="state.moveForm.locationX" placeholder="请输入" />
</el-form-item>
@ -34,20 +34,111 @@
<el-input v-model="state.moveForm.y" placeholder="请输入" />
</el-form-item>
<div style="text-align: right">
<el-button size="small" color="#00329F" @click="moveFormSubmit">确认</el-button>
<el-button
size="small"
style="width: 64px; height: 30px; background: #00329f"
color="#00329F"
@click="moveFormSubmit"
>确认</el-button
>
</div>
</el-form>
<!-- 旋转 -->
<el-form :model="state.rotationForm" v-if="item.switchType === 'revolve'">
<el-form :model="state.rotationForm" v-if="item.switchType === 'revolve'" class="mt-2">
<el-form-item label="角度">
<el-input v-model="state.rotationForm.angle" placeholder="请输入" />
</el-form-item>
<div style="text-align: right">
<el-button size="small" color="#00329F" @click="rotationFormSubmit">确认</el-button>
<el-button
size="small"
style="width: 64px; height: 30px; background: #00329f"
color="#00329F"
@click="rotationFormSubmit"
>确认</el-button
>
</div>
</el-form>
</el-popover>
<!-- 线库 -->
<el-popover
placement="bottom"
trigger="click"
v-else-if="item.switchType === 'lineLibrary'"
:popper-style="{ padding: '0px' }"
>
<template #reference>
<div
class="tool-item"
:class="
toolbarSwitchType === 'lineLibrary' ||
toolbarSwitchType === 'createLineLibrary' ||
toolbarSwitchType === 'lineLibraryManage'
? 'tool-active'
: item.isActive
? 'right-tool-active'
: ''
"
@click="toolbarClick(item)"
>
<Icon :icon="item.icon" :size="24" />
<div class="name"> {{ item.name }} </div>
</div>
</template>
<div v-if="item.switchType === 'lineLibrary'" class="drop-down-menu">
<div
class="drop-down-menu-item"
:class="toolbarSwitchType === 'createLineLibrary' ? 'right-tool-active' : ''"
@click="toolbarClick({ switchType: 'createLineLibrary' })"
>生成线库</div
>
<div
class="drop-down-menu-item"
:class="toolbarSwitchType === 'lineLibraryManage' ? 'right-tool-active' : ''"
@click="toolbarClick({ switchType: 'lineLibraryManage' })"
>线库管理</div
>
</div>
</el-popover>
<!-- 区域 -->
<el-popover
placement="bottom"
trigger="click"
v-else-if="item.switchType === 'region'"
:popper-style="{ padding: '0px' }"
>
<template #reference>
<div
class="tool-item"
:class="
toolbarSwitchType === 'region' ||
toolbarSwitchType === 'createRegion' ||
toolbarSwitchType === 'regionManage'
? 'tool-active'
: item.isActive
? 'right-tool-active'
: ''
"
@click="toolbarClick(item)"
>
<Icon :icon="item.icon" :size="24" />
<div class="name"> {{ item.name }} </div>
</div>
</template>
<div v-if="item.switchType === 'region'" class="drop-down-menu">
<div
class="drop-down-menu-item"
:class="toolbarSwitchType === 'createRegion' ? 'right-tool-active' : ''"
@click="toolbarClick({ switchType: 'createRegion' })"
>生成物料区域</div
>
<div
class="drop-down-menu-item"
:class="toolbarSwitchType === 'regionManage' ? 'right-tool-active' : ''"
@click="toolbarClick({ switchType: 'regionManage' })"
>物料区域管理</div
>
</div>
</el-popover>
<div
v-else
class="tool-item"
@ -71,16 +162,16 @@
item.switchType === 'delete' ||
item.switchType === 'grid' ||
(item.switchType === 'next' &&
(toolbarSwitchType === 'lineLibrary' ||
toolbarSwitchType === 'region' ||
(toolbarSwitchType === 'createLineLibrary' ||
toolbarSwitchType === 'createRegion' ||
toolbarSwitchType === 'drawRoute'))
"
></div>
<el-button
v-if="
item.switchType === 'next' &&
(toolbarSwitchType === 'lineLibrary' ||
toolbarSwitchType === 'region' ||
(toolbarSwitchType === 'createLineLibrary' ||
toolbarSwitchType === 'createRegion' ||
toolbarSwitchType === 'drawRoute')
"
type="danger"
@ -139,10 +230,10 @@
v-for="(item, index) in allHistoryList[currentIndex]"
:key="item.locationX"
:parent="true"
:x="item.locationX"
:y="item.locationY"
:w="item.locationWide"
:h="item.locationDeep"
:x="Number(item.locationX) - Number(item.locationWide) / 2"
:y="Number(item.locationY) - Number(item.locationDeep) / 2"
:w="Number(item.locationWide)"
:h="Number(item.locationDeep)"
:r="item.angle"
@rotatestop="(degree) => rotateEnd(degree, item, index)"
@dragstop="(x, y) => dragEnd(x, y, item, index)"
@ -248,10 +339,10 @@
<!-- 直线 -->
<line
v-if="curve.method === 0"
:x1="Number(curve.startPointX) + Number(curve.beginWidth) / 2"
:y1="Number(curve.startPointY) + Number(curve.beginHigh) / 2"
:x2="Number(curve.endPointX) + Number(curve.endWidth) / 2"
:y2="Number(curve.endPointY) + Number(curve.endHigh) / 2"
:x1="Number(curve.startPointX)"
:y1="Number(curve.startPointY)"
:x2="Number(curve.endPointX)"
:y2="Number(curve.endPointY)"
:stroke="curve.isSelected ? '#f48924' : '#00329F'"
stroke-width="5"
@click="handleChooseRoute(curve, index)"
@ -269,8 +360,8 @@
/>
<!-- 第一条控制线 -->
<line
:x1="Number(curve.startPointX) + Number(curve.beginWidth) / 2"
:y1="Number(curve.startPointY) + Number(curve.beginHigh) / 2"
:x1="Number(curve.startPointX)"
:y1="Number(curve.startPointY)"
:x2="curve.beginControlX"
:y2="curve.beginControlY"
:stroke="curve.isSelected ? '#f48924' : '#00329F'"
@ -279,8 +370,8 @@
/>
<!-- 第二条控制线 -->
<line
:x1="Number(curve.endPointX) + Number(curve.endWidth) / 2"
:y1="Number(curve.endPointY) + Number(curve.endHigh) / 2"
:x1="Number(curve.endPointX)"
:y1="Number(curve.endPointY)"
:x2="curve.endControlX"
:y2="curve.endControlY"
:stroke="curve.isSelected ? '#f48924' : '#00329F'"
@ -400,7 +491,7 @@
<textFormToolDialog
ref="textFormToolDialogRef"
v-if="state.textFormToolShow"
:inputBoxStyle="inputBoxStyle"
:inputBoxStyle="state.inputBoxStyle"
@textFormSuccess="textFormSuccess"
/>
<!-- 图层选择 -->
@ -424,6 +515,16 @@
@editMapRouteDialogSubmit="editMapRouteDialogSubmit"
:imgBgObj="imgBgObj"
/>
<!-- 线库管理 -->
<lineLibraryManagementDialog
ref="lineLibraryManagementDialogRef"
:positionMapId="imgBgObj.positionMapId"
/>
<!-- 区域管理 -->
<itemAreaManagementDialog
ref="itemAreaManagementDialogRef"
:positionMapId="imgBgObj.positionMapId"
/>
</template>
<script setup>
@ -437,12 +538,16 @@ import equipmentToolDialog from './components-tool/equipmentToolDialog.vue'
import itemAreaSettingDialog from './components-tool/itemAreaSettingDialog.vue'
import lineLibrarySettingDialog from './components-tool/lineLibrarySettingDialog.vue'
import layerSelectionToolDialog from './components-tool/layerSelectionToolDialog.vue'
import itemAreaManagementDialog from './components-tool/itemAreaManagementDialog.vue'
import lineLibraryManagementDialog from './components-tool/lineLibraryManagementDialog.vue'
import * as MapApi from '@/api/map/map'
import cursorCollection from './cursorCollection'
defineOptions({ name: 'editMapPageRealTimeMap' })
const lineLibraryManagementDialogRef = ref() //线
const itemAreaManagementDialogRef = ref() //
const lineLibrarySettingDialogRef = ref() //线
const itemAreaSettingDialogRef = ref() //
const equipmentToolDialogRef = ref() //
@ -520,7 +625,8 @@ const activatedHandle = (item, index) => {
//
if (toolbarSwitchType.value === 'editNode') {
editNodePropertiesRef.value.open(JSON.parse(JSON.stringify(item)))
let list = allHistoryList.value[currentIndex.value].filter((item) => item.type === 3)
editNodePropertiesRef.value.open(JSON.parse(JSON.stringify(item)), list)
}
}
//
@ -579,7 +685,7 @@ const mapClick = (e) => {
locationWide: 10,
angle: 0,
draggable: true,
resizable: false,
resizable: true,
rotatable: false,
lockAspectRatio: false, //
mapImageUrl: '',
@ -912,7 +1018,10 @@ const toolbarClick = (item) => {
}
//
if (toolbarSwitchType.value !== 'lineLibrary' && toolbarSwitchType.value !== 'region') {
if (
toolbarSwitchType.value !== 'createLineLibrary' &&
toolbarSwitchType.value !== 'createRegion'
) {
state.drawSelectionAreaShow = false
state.allDrawSelectionAreaBox = []
state.drawSelectionPointList = []
@ -926,8 +1035,8 @@ const toolbarClick = (item) => {
//
if (
toolbarSwitchType.value === 'ranging' ||
toolbarSwitchType.value === 'lineLibrary' ||
toolbarSwitchType.value === 'region'
toolbarSwitchType.value === 'createLineLibrary' ||
toolbarSwitchType.value === 'createRegion'
) {
state.prohibitedOperation = true
} else {
@ -1020,6 +1129,20 @@ const toolbarClick = (item) => {
case 'region':
//
break
case 'createLineLibrary':
// 线
break
case 'createRegion':
//
break
case 'lineLibraryManage':
// 线
lineLibraryManagementDialogRef.value.open()
break
case 'regionManage':
itemAreaManagementDialogRef.value.open()
//
break
case 'text':
//
if (toolbarSwitchType.value === 'text') {
@ -1119,8 +1242,8 @@ const rotationFormSubmit = () => {
//
const startDrawSelection = (event) => {
if (
toolbarSwitchType.value !== 'lineLibrary' &&
toolbarSwitchType.value !== 'region' &&
toolbarSwitchType.value !== 'createLineLibrary' &&
toolbarSwitchType.value !== 'createRegion' &&
toolbarSwitchType.value !== 'drawRoute'
)
return
@ -1143,8 +1266,8 @@ const startDrawSelection = (event) => {
//
const updateDrawSelection = (event) => {
if (
toolbarSwitchType.value !== 'lineLibrary' &&
toolbarSwitchType.value !== 'region' &&
toolbarSwitchType.value !== 'createLineLibrary' &&
toolbarSwitchType.value !== 'createRegion' &&
toolbarSwitchType.value !== 'drawRoute'
)
return
@ -1161,8 +1284,8 @@ const updateDrawSelection = (event) => {
//
const endDrawSelection = (event) => {
if (
toolbarSwitchType.value !== 'lineLibrary' &&
toolbarSwitchType.value !== 'region' &&
toolbarSwitchType.value !== 'createLineLibrary' &&
toolbarSwitchType.value !== 'createRegion' &&
toolbarSwitchType.value !== 'drawRoute'
)
return
@ -1203,7 +1326,7 @@ const clickDrawSelectionArea = () => {
item.id
})
if (toolbarSwitchType.value === 'lineLibrary') {
if (toolbarSwitchType.value === 'createLineLibrary') {
//线
if (binLocation.length < 2) {
message.warning('至少选择两个库位')
@ -1223,7 +1346,7 @@ const clickDrawSelectionArea = () => {
lineLibrarySettingDialogRef.value.open(binLocation)
}
//
if (toolbarSwitchType.value === 'region') {
if (toolbarSwitchType.value === 'createRegion') {
if (binLocation.length < 1) {
message.warning('至少选择两个库位')
return
@ -1378,10 +1501,10 @@ const endDrag = () => {
}
// 线
const getCurvePath = (curve) => {
let startPointX = Number(curve.startPointX) + Number(curve.beginWidth) / 2
let startPointY = Number(curve.startPointY) + Number(curve.beginHigh) / 2
let endPointX = Number(curve.endPointX) + Number(curve.endWidth) / 2
let endPointY = Number(curve.endPointY) + Number(curve.endHigh) / 2
let startPointX = Number(curve.startPointX)
let startPointY = Number(curve.startPointY)
let endPointX = Number(curve.endPointX)
let endPointY = Number(curve.endPointY)
return `M ${startPointX} ${startPointY} C ${curve.beginControlX} ${curve.beginControlY}, ${curve.endControlX} ${curve.endControlY}, ${endPointX} ${endPointY}`
}
@ -1589,7 +1712,6 @@ const getAllNodeList = async () => {
item.locationWide = item.dataObj.locationWide
item.deviceId = item.dataObj.id
item.mapImageUrl = item.dataObj.mapImageUrl
item.deviceType = Number(item.dataObj.deviceType)
item.draggable = true
item.resizable = true
item.rotatable = false
@ -1829,15 +1951,6 @@ onMounted(() => {
}
}
}
.tool-active {
background: #ebf1ff;
border-bottom: 2px solid #1677ff;
}
.right-tool-active {
background: #ebf1ff;
}
}
.input-box-class {
@ -1871,4 +1984,34 @@ onMounted(() => {
}
}
}
.drop-down-menu {
.drop-down-menu-item {
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
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;
}
}
.tool-active {
background: #ebf1ff;
border-bottom: 2px solid #1677ff;
}
.right-tool-active {
background: #ebf1ff !important;
}
</style>

View File

@ -73,6 +73,7 @@
style="width: 100%"
row-class-name="table-row-class"
:header-cell-style="{ backgroundColor: '#EBF1FF', color: '#0D162A', padding: '13px 0' }"
v-loading="loading"
>
<el-table-column align="center" label="序号" type="expand" width="60">
<template #default="props">