货位分析、库存平面图

This commit is contained in:
猫猫guowen
2025-05-23 17:55:43 +08:00
parent 7a0f4606dc
commit 9559511e56
6 changed files with 607 additions and 9 deletions

View File

@@ -67,10 +67,65 @@ public class KpiController extends BaseController {
* 获取货位分析数据
*
* @param warehouseId 仓库ID
* @return 货位分析数据}
* @return 货位分析数据
*/
@GetMapping("/spaceAnalysis")
public AjaxResult getSpaceAnalysis(@RequestParam("warehouseId") String warehouseId) {
return success(kpiService.getSpaceAnalysis(warehouseId));
}
/**
* 获取货位巷道数据
*
* @param warehouseId 仓库ID
* @return 货位巷道数据
*/
@GetMapping("/getRoadways")
public AjaxResult getRoadways(@RequestParam("warehouseId") String warehouseId){
return success(kpiService.getRoadways(warehouseId));
}
/**
* 获取货位排数据
*
* @param warehouseId 仓库ID
* @param roadwayId 巷道ID
* @return 货位排数据
*/
@GetMapping("/getPlatoons")
public AjaxResult getPlatoons(@RequestParam("warehouseId") String warehouseId,
@RequestParam("roadwayId") String roadwayId){
return success(kpiService.getPlatoons(warehouseId,roadwayId));
}
/**
* 获取库存平面图
*
* @param warehouseId 仓库ID
* @param roadwayId 巷道ID
* @param thePlatoon 排
* @return 库存平面图数据
*/
@GetMapping("/getChartData")
public AjaxResult getChartData(@RequestParam("warehouseId") String warehouseId,
@RequestParam("roadwayId") String roadwayId,
@RequestParam("thePlatoon") String thePlatoon){
return success(kpiService.getChartData(warehouseId,roadwayId,thePlatoon));
}
/**
* 获取库存平面图信息
*
* @param warehouseId 仓库ID
* @param theColumn 列
* @param thePlatoon 排
* @param theFloor 层
* @return 库存平面图信息数据
*/
@GetMapping("/getChartMag")
public AjaxResult getChartMag(@RequestParam("warehouseId") String warehouseId,
@RequestParam("theColumn") String theColumn,
@RequestParam("theFloor") String theFloor,
@RequestParam("thePlatoon") String thePlatoon){
return success(kpiService.getChartMag(warehouseId,theColumn,theFloor,thePlatoon));
}
}

View File

@@ -33,4 +33,13 @@ public interface KpiService {
Map<String, Object> getSpaceAnalysis(String warehouseId);
Map<String, Object> getRoadways(String warehouseId);
Map<String, Object> getPlatoons(String warehouseId, String roadwayId);
Map<String,Object> getChartData(String warehouseId, String roadwayId, String thePlatoon);
Map<String,Object> getChartMag(String warehouseId, String theColumn, String theFloor, String thePlatoon);
}

View File

@@ -14,6 +14,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import com.ruoyi.kpi.service.KpiService;
@@ -220,7 +221,7 @@ public class KpiServiceImpl implements KpiService
}
/**
* 获取巷道均匀分析数据
* 获取货位分析数据
*
* @param warehouseId 仓库ID
* @return 货位分析
@@ -232,6 +233,13 @@ public class KpiServiceImpl implements KpiService
basCargoSpace.setWarehouseId(warehouseId);
List<BasCargoSpace> list = basCargoSpaceMapper.selectBasCargoSpaceList(basCargoSpace);
// 如果查询结果为空,返回空数据
if (list == null || list.isEmpty()) {
Map<String, Object> response = new HashMap<>();
response.put("data", new ArrayList<>());
return response;
}
// 按巷道和状态分类统计
Map<String, Map<String, Integer>> roadwayStats = new HashMap<>();
Set<String> roadwayIds = new HashSet<>();
@@ -277,5 +285,170 @@ public class KpiServiceImpl implements KpiService
return response;
}
@Override
public Map<String, Object> getRoadways(String warehouseId){
Map<String, Object> response = new HashMap<>();
// 查询指定仓库的巷道信息
BasCargoSpace queryParams = new BasCargoSpace();
queryParams.setWarehouseId(warehouseId);
List<BasCargoSpace> list = basCargoSpaceMapper.selectBasCargoSpaceList(queryParams);
// 使用Set去重并排序巷道ID
Set<String> roadwaySet = new TreeSet<>();
for (BasCargoSpace space : list) {
if (space.getRoadwayId() != null) {
roadwaySet.add(space.getRoadwayId());
}
}
// 转换为前端下拉框所需的格式
List<Map<String, String>> roadways = new ArrayList<>();
for (String roadwayId : roadwaySet) {
Map<String, String> roadway = new HashMap<>();
roadway.put("value", roadwayId);
roadway.put("label", "巷道" + roadwayId);
roadways.add(roadway);
}
response.put("data", roadways);
return response;
}
@Override
public Map<String,Object> getPlatoons(String warehouseId, String roadwayId){
Map<String, Object> response = new HashMap<>();
// 查询指定仓库和巷道的排号信息
BasCargoSpace queryParams = new BasCargoSpace();
queryParams.setWarehouseId(warehouseId);
queryParams.setRoadwayId(roadwayId);
List<BasCargoSpace> list = basCargoSpaceMapper.selectBasCargoSpaceList(queryParams);
// 使用TreeSet去重并排序排号
Set<Long> platoonSet = new TreeSet<>();
for (BasCargoSpace space : list) {
if (space.getThePlatoon() != null) {
platoonSet.add(space.getThePlatoon());
}
}
// 转换为前端下拉框所需的格式
List<Map<String, String>> platoons = new ArrayList<>();
for (Long platoon : platoonSet) {
Map<String, String> platoonMap = new HashMap<>();
platoonMap.put("value", platoon.toString());
platoonMap.put("label", platoon + "排");
platoons.add(platoonMap);
}
response.put("data", platoons);
return response;
}
@Override
public Map<String,Object> getChartData(String warehouseId, String roadwayId, String thePlatoon) {
// 查询指定仓库、巷道和排号的货位信息
BasCargoSpace queryParams = new BasCargoSpace();
queryParams.setWarehouseId(warehouseId);
queryParams.setRoadwayId(roadwayId);
if (thePlatoon != null) {
queryParams.setThePlatoon(Long.parseLong(thePlatoon));
}
List<BasCargoSpace> list = basCargoSpaceMapper.selectBasCargoSpaceList(queryParams);
// 用于存储不同状态的货位坐标
String empty = "";
String full = "";
String inAllot = "";
String outAllot = "";
String inCheck = "";
String outCheck = "";
// 用于存储列和层的集合
Set<Long> columnSet = new TreeSet<>();
Set<Long> floorSet = new TreeSet<>();
// 处理每个货位的状态
for (BasCargoSpace space : list) {
// 收集列和层信息
columnSet.add(space.getTheColumn());
floorSet.add(space.getTheFloor());
// 根据状态分类处理
if (space.getStatus() != null) {
String coordinate = "[" + space.getTheColumn() + "," + space.getTheFloor() + "," + space.getStatus() + "],";
switch (Integer.parseInt(space.getStatus())) {
case 1: empty += coordinate; break;
case 2: full += coordinate; break;
case 3: inAllot += coordinate; break;
case 4: outAllot += coordinate; break;
case 5: inCheck += coordinate; break;
case 6: outCheck += coordinate; break;
}
}
}
// 构建列和层的标签
StringBuilder columnLabels = new StringBuilder();
for (Long col : columnSet) {
columnLabels.append("'").append(col).append("列',");
}
String column = "[" + columnLabels.toString() + "]";
StringBuilder floorLabels = new StringBuilder();
for (Long floor : floorSet) {
floorLabels.append("'").append(floor).append("层',");
}
String floor = "[" + floorLabels.toString() + "]";
// 返回结果
Map<String, Object> map = new HashMap<>();
map.put("empty", "[" + empty + "]");
map.put("full", "[" + full + "]");
map.put("inAllot", "[" + inAllot + "]");
map.put("outAllot", "[" + outAllot + "]");
map.put("inCheck", "[" + inCheck + "]");
map.put("outCheck", "[" + outCheck + "]");
map.put("floor", floor);
map.put("column", column);
return map;
}
@Override
public Map<String,Object> getChartMag(String warehouseId,String theColumn,String theFloor,String thePlatoon){
Map<String, Object> response = new HashMap<>();
// 查询指定货位信息
BasCargoSpace queryParams = new BasCargoSpace();
queryParams.setWarehouseId(warehouseId);
queryParams.setTheColumn(Long.parseLong(theColumn));
queryParams.setTheFloor(Long.parseLong(theFloor));
queryParams.setThePlatoon(Long.parseLong(thePlatoon));
List<BasCargoSpace> list = basCargoSpaceMapper.selectBasCargoSpaceList(queryParams);
if (!list.isEmpty()) {
BasCargoSpace space = list.get(0);
StringBuilder info = new StringBuilder();
// 拼接货位信息
info.append("货位名称:").append(space.getCargoSpaceName()).append("<br>");
info.append("货位类型:").append(space.getTheTypeName()).append("<br>");
info.append("是否锁定:").append("Y".equals(space.getLocked()) ? "是" : "否").append("<br>");
info.append("托盘条码:").append(space.getTrayCode() != null ? space.getTrayCode() : "无").append("<br>");
info.append("货位高度:").append(space.getCargoHight() != null ? space.getCargoHight() : "无").append("<br>");
info.append("是否双伸:").append("Y".equals(space.getIssDouble()) ? "是" : "否").append("<br>");
response.put("msg", info.toString());
} else {
response.put("msg", "未找到货位信息");
}
return response;
}
}

View File

@@ -0,0 +1,35 @@
import request from '@/utils/request'
//获取巷道列表
export function getRoadways(query) {
return request({
url: '/kpi/getRoadways',
method: 'get',
params: query
})
}
//获取排列表
export function getPlatoons(query) {
return request({
url: '/kpi/getPlatoons',
method: 'get',
params:query
})
}
// 获取库存图表
export function getChartData(query) {
return request({
url: '/kpi/getChartData',
method: 'get',
params: query
})
}
export function getChartMag(query){
return request({
url: '/kpi/getChartMag',
method: 'get',
params: query
})
}

View File

@@ -45,12 +45,13 @@ export default {
chart: null,
// 图表数据(模拟数据,注意删除后echarts图初始化会报一下错)
chartData:[
{
"巷道2": 1,
"巷道1": 0,
"status": "出库分配"
}
]
{
"巷道2": 1,
"巷道1": 0,
"status": "出库分配"
}
],
dimensions:[]
}
}
,
@@ -102,6 +103,12 @@ export default {
,
/** 更新图表数据 */
updateChart() {
this.dimensions=[]
if (this.chartData[0].巷道1!=undefined&&this.chartData[0].巷道1!=null){
this.dimensions=['status', '巷道1', '巷道2']
}else {
this.dimensions=['status', '巷道3', '巷道4']
}
const option = {
title: {
text: '货位状态分析',
@@ -121,7 +128,7 @@ export default {
}
},
dataset: {
dimensions: ['status', '巷道1', '巷道2'],
dimensions: this.dimensions,
source: this.chartData
},
xAxis: {

View File

@@ -0,0 +1,319 @@
<template>
<div class="app-container">
<div class="search-box">
<el-form :model="queryParams" ref="queryForm" :inline="true">
<el-form-item label="仓库">
<el-select v-model="queryParams.warehouseId" style="width: 150px" @change="handleWarehouseChange">
<el-option label="仓库1" value="01"/>
<el-option label="仓库2" value="02"/>
</el-select>
</el-form-item>
<el-form-item label="巷道">
<el-select v-model="queryParams.roadwayId" style="width: 150px" @change="handleRoadwayChange">
<el-option v-for="item in roadwayOptions" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
</el-form-item>
<el-form-item label="排">
<el-select v-model="queryParams.thePlatoon" style="width: 150px" @change="handlePlatoonChange">
<el-option v-for="item in platoonOptions" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
</el-form-item>
</el-form>
</div>
<div class="chart-container">
<div id="container" v-show="queryParams.warehouseId !== '04'" style="height: 80vh"></div>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts'
import {getRoadways, getPlatoons, getChartData, getChartMag} from "@/api/kpi/spacePlan"
export default {
name: 'SpacePlan',
data() {
return {
// 查询参数
queryParams: {
warehouseId: '01',
roadwayId: '1',
thePlatoon: '',
platoon: '1',
specifications: '',
quantity_x: '',
quantity_j: '',
layer_quantity: '',
classgroup_number: '',
class_workshop_date_time: '',
class_now_date_time: '',
print_date: '',
lot_no: ''
},
// 巷道选项
roadwayOptions: [],
// 排号选项
platoonOptions: [],
// 图表实例
normalChart: null,
specialChart: null,
// 提示信息缓存
tooltipCache: {},
// 图表数据
chartData: {
x: [],
y: [],
empty: [],
full: [],
inAllot: [],
outAllot: [],
inCheck: [],
outCheck: [],
resultsOf: [],
outCargo: [],
theLocked: []
}
}
},
mounted() {
this.initCharts()
this.handleWarehouseChange()
},
methods: {
// 初始化图表
initCharts() {
this.normalChart = echarts.init(document.getElementById('container'))
},
// 仓库变化处理
handleWarehouseChange() {
// 重置巷道和排号
this.queryParams.roadwayId = ''
this.queryParams.thePlatoon = ''
this.roadwayOptions = []
this.platoonOptions = []
// 清空提示信息缓存
this.tooltipCache = {}
// 获取巷道列表
getRoadways(this.queryParams).then(response => {
const roadways = response.data.data
if (roadways && roadways.length > 0) {
this.roadwayOptions = roadways
this.queryParams.roadwayId = roadways[0].value
this.handleRoadwayChange()
}
})
},
// 巷道变化处理
handleRoadwayChange() {
// 重置排号
this.queryParams.thePlatoon = ''
this.platoonOptions = []
// 清空提示信息缓存
this.tooltipCache = {}
// 获取排号列表
getPlatoons(this.queryParams).then(response => {
const platoons = response.data.data
if (platoons && platoons.length > 0) {
this.platoonOptions = platoons
this.queryParams.thePlatoon = platoons[0].value
this.loadChartData()
}
})
},
handlePlatoonChange() {
// 清空提示信息缓存
this.tooltipCache = {}
this.loadChartData()
},
// 加载普通仓库图表数据
loadChartData() {
getChartData(this.queryParams).then(response => {
const data = response.data
// 调整坐标值以匹配实际位置
const adjustCoordinates = (data) => {
return data.map(item => [item[0] - 1, item[1] - 1, item[2]]);
};
this.chartData.x = eval('(' + data["column"] + ')');
this.chartData.y = eval('(' + data["floor"] + ')');
this.chartData.empty = adjustCoordinates(eval('(' + data["empty"] + ')'));
this.chartData.full = adjustCoordinates(eval('(' + data["full"] + ')'));
this.chartData.inAllot = adjustCoordinates(eval('(' + data["inAllot"] + ')'));
this.chartData.outAllot = adjustCoordinates(eval('(' + data["outAllot"] + ')'));
this.chartData.inCheck = adjustCoordinates(eval('(' + data["inCheck"] + ')'));
this.chartData.outCheck = adjustCoordinates(eval('(' + data["outCheck"] + ')'));
this.updateNormalChart()
})
},
// 更新普通仓库图表
updateNormalChart() {
const option = {
tooltip: {
trigger: 'item',
formatter: (params) => {
return this.formatTooltip(params)
}
},
title: {
text: '库位分布平面图',
subtext: this.queryParams.thePlatoon + '排'
},
grid: {
width: '90%',
height: '70%',
top: '20%',
left: '5%'
},
xAxis: {
type: 'category',
data: this.chartData.x,
splitArea: {show: true}
},
yAxis: {
type: 'category',
data: this.chartData.y,
splitArea: {show: true}
},
visualMap: {
show: false,
min: 1,
max: 6,
calculable: true,
orient: 'horizontal',
left: 'center',
inRange: {
color: ['#AEEEEE', '#FF9900', '#FFFF00', '#00CC00', '#FF0000', '#0000FF']
}
},
legend: {
data: ['空位', '满位', '入库分配', '出库分配', '入库需盘点', '出库需盘点']
},
series: [
{
name: '空位',
type: 'heatmap',
data: this.chartData.empty,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
},
{
name: '满位',
type: 'heatmap',
data: this.chartData.full,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
},
{
name: '入库分配',
type: 'heatmap',
data: this.chartData.inAllot,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
},
{
name: '出库分配',
type: 'heatmap',
data: this.chartData.outAllot,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
},
{
name: '入库需盘点',
type: 'heatmap',
data: this.chartData.inCheck,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
},
{
name: '出库需盘点',
type: 'heatmap',
data: this.chartData.outCheck,
itemStyle: {
borderColor: '#fff',
borderWidth: 2
}
}
]
}
this.normalChart.setOption(option)
},
// 格式化普通仓库提示信息
formatTooltip(params) {
return new Promise((resolve) => {
let str = '';
if (params.seriesName !== '满位') {
str = params.seriesName + '<br>' + this.queryParams.thePlatoon + '排' + (params.data[0] + 1) + '列' + (params.data[1] + 1) + '层';
resolve(str);
} else {
const key = `${this.queryParams.warehouseId}-${this.queryParams.thePlatoon}-${params.data[0] + 1}-${params.data[1] + 1}`;
// 如果缓存中存在数据,直接使用缓存
if (this.tooltipCache && this.tooltipCache[key]) {
str = `${params.seriesName}<br>${this.queryParams.thePlatoon}排${params.data[0] + 1}列${params.data[1] + 1}层<br>${this.tooltipCache[key]}`;
resolve(str);
return;
}
const returnData = {
"thePlatoon": this.queryParams.thePlatoon,
"theColumn": params.data[0] + 1,
"theFloor": params.data[1] + 1,
"warehouseId": this.queryParams.warehouseId
};
getChartMag(returnData)
.then(response => {
const msg = response.data.msg;
// 缓存响应数据
if (!this.tooltipCache) this.tooltipCache = {};
this.tooltipCache[key] = msg;
str = `${params.seriesName}<br>${this.queryParams.thePlatoon}排${params.data[0] + 1}列${params.data[1] + 1}层<br>${msg}`;
resolve(str);
})
.catch(error => {
console.error('获取货位信息失败:', error);
str = `${params.seriesName}<br>${this.queryParams.thePlatoon}排${params.data[0] + 1}列${params.data[1] + 1}层<br>获取详细信息失败`;
resolve(str);
});
}
});
},
}
}
</script>
<style scoped>
.app-container {
padding: 20px;
}
.search-box {
background-color: #fff;
padding: 20px;
margin-bottom: 20px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.chart-container {
background-color: #fff;
padding: 20px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style>