Files
klp-oa/klp-ui/src/views/wms/warehouse/components/WarehouseBird.vue

276 lines
6.3 KiB
Vue
Raw Normal View History

<template>
<div class="bird-container">
<!-- 统计信息卡片 -->
<div class="statistics-card">
<el-card shadow="hover">
<div class="statistics-item">
<span class="label">总库位数</span>
<span class="value">{{ statistics.total }}</span>
</div>
<div class="statistics-item">
<span class="label">总层数</span>
<span class="value">{{ statistics.layerCount }}</span>
</div>
<div class="statistics-item">
<span class="label">各层库位分布</span>
<span class="value">
<span v-for="(count, layer) in statistics.layerDetail" :key="layer">
{{ layer }}{{ count }}
</span>
</span>
</div>
</el-card>
</div>
<!-- 图例 -->
<div class="legend-container">
<div class="legend-item">
<div class="legend-color normal"></div>
<span class="legend-text">正常未占用</span>
</div>
<div class="legend-item">
<div class="legend-color occupied"></div>
<span class="legend-text">已占用</span>
</div>
</div>
<!-- 分层库位容器 -->
<div class="layers-container">
<!-- 遍历每层渲染 Grid 组件 -->
<div v-for="(layerData, layer) in layers" :key="layer" class="layer-section">
<WarehouseGrid :layer="layer" :layer-data="layerData" />
</div>
<!-- 无数据提示 -->
<div class="empty-tip" v-if="Object.keys(layers).length === 0 && warehouseList.length > 0">
暂无解析到有效的库位分层数据
</div>
<div class="empty-tip" v-if="warehouseList.length === 0">
<div class="empty-text">该分类下暂无库位数据</div>
<el-button type="primary" icon="el-icon-plus" @click="openInitDialog">初始化库位</el-button>
</div>
</div>
</div>
</template>
<script>
import WarehouseGrid from './WarehouseGrid.vue';
export default {
name: "WarehouseBird",
components: { WarehouseGrid },
props: {
// 原始库位列表
warehouseList: {
type: Array,
default: () => []
}
},
data() {
return {
// 分层库位数据
layers: {},
// 统计信息
statistics: {
total: 0,
layerCount: 0,
layerDetail: {}
}
};
},
watch: {
// 监听库位列表变化,重新构建分层数据
warehouseList: {
immediate: true,
handler(newVal) {
this.buildWarehouseBox(newVal);
}
}
},
methods: {
/**
* 解析库位编码
*/
parseWarehouseCode(code) {
if (!code) return null;
const reg = /^([A-Za-z])(\d+[A-Za-z])(\d)(\d{2})-(\d+)$/;
const match = code.match(reg);
if (!match) {
console.warn(`库位编码解析失败:${code},格式不符合规范`);
return null;
}
return {
warehouseFirst: match[1],
warehouseSecond: match[2],
column: Number(match[3]),
row: Number(match[4]),
layer: match[5],
};
},
/**
* 构建分层库位数据结构
*/
buildWarehouseBox(list) {
const layerMap = {};
const statistics = {
total: list.length,
layerCount: 0,
layerDetail: {},
};
// 按层分组
list.forEach((warehouse) => {
const codeInfo = this.parseWarehouseCode(warehouse.actualWarehouseCode);
if (!codeInfo) return;
const { layer, row, column } = codeInfo;
warehouse.parsedInfo = codeInfo;
if (!layerMap[layer]) {
layerMap[layer] = {
maxRow: 0,
maxColumn: 0,
warehouses: [],
emptyCount: 0
};
}
layerMap[layer].maxRow = Math.max(layerMap[layer].maxRow, row);
layerMap[layer].maxColumn = Math.max(layerMap[layer].maxColumn, column);
layerMap[layer].warehouses.push(warehouse);
});
// 处理空占位和排序
Object.keys(layerMap).forEach((layer) => {
const layerData = layerMap[layer];
const totalGrid = layerData.maxRow * layerData.maxColumn;
layerData.emptyCount = Math.max(0, totalGrid - layerData.warehouses.length);
// 按行号+列号排序
layerData.warehouses.sort((a, b) => {
if (a.parsedInfo.row !== b.parsedInfo.row) {
return a.parsedInfo.row - b.parsedInfo.row;
}
return a.parsedInfo.column - b.parsedInfo.column;
});
});
// 更新统计信息
statistics.layerCount = Object.keys(layerMap).length;
Object.keys(layerMap).forEach((layer) => {
statistics.layerDetail[layer] = layerMap[layer].warehouses.length;
});
this.layers = layerMap;
this.statistics = statistics;
},
/**
* 打开初始化弹窗透传至根组件
*/
openInitDialog() {
this.$emit('open-init-dialog');
}
},
};
</script>
<style scoped lang="scss">
.bird-container {
width: 100%;
height: 100%;
}
// 统计卡片样式
.statistics-card {
margin-bottom: 16px;
.statistics-item {
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
.label {
color: #606266;
font-size: 14px;
}
.value {
color: #303133;
font-size: 14px;
font-weight: 500;
margin-left: 8px;
}
}
}
// 图例样式
.legend-container {
display: flex;
align-items: center;
margin-bottom: 16px;
padding: 8px 12px;
background: #f8f9fa;
border-radius: 4px;
.legend-item {
display: flex;
align-items: center;
margin-right: 24px;
&:last-child {
margin-right: 0;
}
.legend-color {
width: 16px;
height: 16px;
border-radius: 2px;
margin-right: 8px;
border: 1px solid #e6e6e6;
}
.normal {
background-color: #ffffff;
}
.occupied {
background-color: #eeff6f;
}
.legend-text {
font-size: 14px;
color: #606266;
}
}
}
// 分层容器样式
.layers-container {
display: flex;
.layer-section {
flex: 1;
max-width: 50%;
margin-bottom: 24px;
}
.empty-tip {
text-align: center;
padding: 32px;
color: #909399;
font-size: 14px;
background: #fff;
border-radius: 8px;
.empty-text {
margin-bottom: 16px;
}
}
}
</style>