feat(kpi): 调整库位分析与计划功能以支持按层数筛选

- 修改库位平面图查询逻辑,将巷道+排号筛选改为层数筛选
- 更新后端接口getPlatoons和getChartData,参数从roadwayId改为theFloor
- 新增getFloors接口用于获取指定仓库的楼层数据
- 前端页面替换巷道/排号选择器为层数选择器
- 优化图表标题和提示信息显示逻辑,适配新的筛选方式
- 修复部分坐标轴标签生成逻辑,确保正确展示行列信息
- 调整物料编码字段宽度,改善表格布局
- 注释掉空间分析页面中的巷道筛选项
- 修正产品导入时字段映射错误的问题
This commit is contained in:
liuhanqing
2025-12-08 11:58:19 +08:00
parent 20bbc6019a
commit 6f392fef57
9 changed files with 131 additions and 80 deletions

View File

@@ -115,10 +115,10 @@ public class ToErpServiceImpl implements IToErpService {
AspResponse responseBean = JSONUtil.toBean(body, AspResponse.class);
for (List<String> row : responseBean.getBody().getSource().getTable().getRows()) {
BasProduct product = new BasProduct();
product.setProductGuid(row.get(0));
product.setProductId(row.get(0));
product.setProductGuid(row.get(2));
product.setProductId(row.get(2));
product.setProductName(row.get(1));
product.setCargoNo(row.get(2));
product.setCargoNo(row.get(0));
product.setSpec(row.get(3));
product.setUnit(row.get(4));
product.setSpare1(row.get(5));

View File

@@ -107,6 +107,18 @@ public class KpiController extends BaseController {
return success(kpiService.getRoadways(warehouseId));
}
/**
* 获取货位楼层数据
*
* @param warehouseId 仓库ID
* @return 货位楼层数据
*/
@GetMapping("/getFloors")
public AjaxResult getFloors(@RequestParam("warehouseId") String warehouseId){
return success(kpiService.getFloors(warehouseId));
}
/**
* 获取货位排数据
*
@@ -116,23 +128,22 @@ public class KpiController extends BaseController {
*/
@GetMapping("/getPlatoons")
public AjaxResult getPlatoons(@RequestParam("warehouseId") String warehouseId,
@RequestParam("roadwayId") String roadwayId){
return success(kpiService.getPlatoons(warehouseId,roadwayId));
@RequestParam("theFloor") String theFloor){
return success(kpiService.getPlatoons(warehouseId,theFloor));
}
/**
* 获取库存平面图
*
* @param warehouseId 仓库ID
* @param roadwayId 巷道ID
* @param thePlatoon 排
* @param theFloor 层数
* @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));
@RequestParam("theFloor") String theFloor
){
return success(kpiService.getChartData(warehouseId,theFloor));
}
/**

View File

@@ -40,7 +40,7 @@ public interface KpiService {
Map<String, Object> getPlatoons(String warehouseId, String roadwayId);
Map<String,Object> getChartData(String warehouseId, String roadwayId, String thePlatoon);
Map<String,Object> getChartData(String warehouseId, String theFloor);
Map<String,Object> getChartMag(String warehouseId, String theColumn, String theFloor, String thePlatoon);
@@ -48,4 +48,6 @@ public interface KpiService {
// 新增:根据仓库和巷道统计各状态货位数量
Map<String, Object> getSpaceStatusCounts(String warehouseId, String roadwayId);
Map<String, Object> getFloors(String warehouseId);
}

View File

@@ -33,7 +33,7 @@ public class KpiServiceImpl implements KpiService
@Autowired
private BasCargoSpaceMapper basCargoSpaceMapper;
@Autowired
private BasStockMapper basStockMapper;
/**
@@ -317,6 +317,36 @@ public class KpiServiceImpl implements KpiService
return res;
}
@Override
public Map<String, Object> getFloors(String warehouseId) {
Map<String, Object> response = new HashMap<>();
// 查询指定仓库和巷道的排号信息
BasCargoSpace queryParams = new BasCargoSpace();
queryParams.setWarehouseId(warehouseId);
List<BasCargoSpace> list = basCargoSpaceMapper.selectBasCargoSpaceList(queryParams);
// 使用TreeSet去重并排序排号
Set<Long> platoonSet = new TreeSet<>();
for (BasCargoSpace space : list) {
if (space.getTheFloor() != null) {
platoonSet.add(space.getTheFloor());
}
}
// 转换为前端下拉框所需的格式
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> getRoadways(String warehouseId){
Map<String, Object> response = new HashMap<>();
@@ -348,13 +378,13 @@ public class KpiServiceImpl implements KpiService
}
@Override
public Map<String,Object> getPlatoons(String warehouseId, String roadwayId){
public Map<String,Object> getPlatoons(String warehouseId, String theFloor){
Map<String, Object> response = new HashMap<>();
// 查询指定仓库和巷道的排号信息
BasCargoSpace queryParams = new BasCargoSpace();
queryParams.setWarehouseId(warehouseId);
queryParams.setRoadwayId(roadwayId);
queryParams.setTheFloor(Long.valueOf(theFloor));
List<BasCargoSpace> list = basCargoSpaceMapper.selectBasCargoSpaceList(queryParams);
// 使用TreeSet去重并排序排号
@@ -379,14 +409,11 @@ public class KpiServiceImpl implements KpiService
}
@Override
public Map<String,Object> getChartData(String warehouseId, String roadwayId, String thePlatoon) {
public Map<String,Object> getChartData(String warehouseId, String theFloor) {
// 查询指定仓库、巷道和排号的货位信息
BasCargoSpace queryParams = new BasCargoSpace();
queryParams.setWarehouseId(warehouseId);
queryParams.setRoadwayId(roadwayId);
if (thePlatoon != null) {
queryParams.setThePlatoon(Long.parseLong(thePlatoon));
}
queryParams.setTheFloor(Long.valueOf(theFloor));
List<BasCargoSpace> list = basCargoSpaceMapper.selectBasCargoSpaceList(queryParams);
// 用于存储不同状态的货位坐标
@@ -405,11 +432,11 @@ public class KpiServiceImpl implements KpiService
for (BasCargoSpace space : list) {
// 收集列和层信息
columnSet.add(space.getTheColumn());
floorSet.add(space.getTheFloor());
floorSet.add(space.getThePlatoon());
// 根据状态分类处理
if (space.getStatus() != null) {
String coordinate = "[" + space.getTheColumn() + "," + space.getTheFloor() + "," + space.getStatus() + "],";
String coordinate = "[" + space.getTheColumn() + "," + space.getThePlatoon() + "," + space.getStatus() + "],";
switch (Integer.parseInt(space.getStatus())) {
case 1: empty += coordinate; break;
case 2: full += coordinate; break;
@@ -424,15 +451,19 @@ public class KpiServiceImpl implements KpiService
// 构建列和层的标签
StringBuilder columnLabels = new StringBuilder();
for (Long col : columnSet) {
columnLabels.append("'").append(col).append(MessageUtils.message("kpi.spacePlan.column")).append("',");
columnLabels.append("'").append(col).append("列").append("',");
}
String column = "[" + columnLabels.toString() + "]";
String column = "[" + columnLabels + "]";
StringBuilder floorLabels = new StringBuilder();
for (Long floor : floorSet) {
floorLabels.append("'").append(floor).append(MessageUtils.message("kpi.spacePlan.floor")).append("',");
if (floor==7){
floorLabels.append("'").append(6).append("排").append("',");
}
floorLabels.append("'").append(floor).append("排").append("',");
}
String floor = "[" + floorLabels.toString() + "]";
//floorLabels.append("6排");
String floor = "[" + floorLabels + "]";
// 返回结果
Map<String, Object> map = new HashMap<>();
@@ -469,7 +500,7 @@ public class KpiServiceImpl implements KpiService
info.append("货位名称:").append(space.getCargoSpaceName()).append("<br>");
info.append("是否锁定:").append("Y".equals(space.getLocked()) ? "是" : "否").append("<br>");
info.append("托盘条码:").append(space.getTrayCode() != null ? space.getTrayCode() : "无").append("<br>");
// 根据cargoSpaceId查询BasStock表,获取productId和productName
BasStock stockQuery = new BasStock();
stockQuery.setCargoSpaceId(space.getCargoSpaceId());
@@ -499,13 +530,13 @@ public class KpiServiceImpl implements KpiService
mydoJobParam.setInOut(inOut);
List<DateTime> datesBetween = DateUtil.rangeToList(DateUtil.parseDate(startTime), DateUtil.parseDate(endTime), DateField.DAY_OF_MONTH);
List<MydoJob> list = mydoJobFinishMapper.selectMydoJobFinishListByMydoJob(mydoJobParam);
// 获取所有巷道ID(1和2)
List<String> roadwayIds = Arrays.asList("1", "2");
List<String> xAxis = new ArrayList<>();
List<Map<String, Object>> series = new ArrayList<>();
// 为每个巷道创建一个系列
for (String roadwayId : roadwayIds) {
Map<String, Object> seriesItem = new HashMap<>();
@@ -515,25 +546,25 @@ public class KpiServiceImpl implements KpiService
seriesItem.put("data", data);
series.add(seriesItem);
}
// 按日期统计每个巷道的数量
for (DateTime dateTime : datesBetween) {
xAxis.add(DateUtil.format(dateTime, "yyyy-MM-dd"));
// 统计每个巷道在当天的数量
for (int i = 0; i < roadwayIds.size(); i++) {
String roadwayId = roadwayIds.get(i);
long count = list.stream()
.filter(mydoJob -> roadwayId.equals(mydoJob.getRoadwayId())
.filter(mydoJob -> roadwayId.equals(mydoJob.getRoadwayId())
&& DateUtil.isIn(mydoJob.getCreateTime(), DateUtil.beginOfDay(dateTime), DateUtil.endOfDay(dateTime)))
.count();
@SuppressWarnings("unchecked")
List<Long> data = (List<Long>) series.get(i).get("data");
data.add(count);
}
}
res.put("xAxis", xAxis);
res.put("series", series);
return AjaxResult.success(res);

View File

@@ -155,7 +155,7 @@ public class OutStockoutServiceImpl implements IOutStockoutService
public String updateOutStockoutStatus(String[] stockoutIds, String status, String newStatus,String exitId) {
HashMap<String, String> map = new HashMap<>();
StringBuilder stringBuilder = new StringBuilder();
if (status.equals("4")){
if ("4".equals(status)){
for(String stockoutId:stockoutIds){
ReceiveOutStockConfirm receiveOutStockConfirm = new ReceiveOutStockConfirm();
OutStockout outStockout = selectOutStockoutByStockoutGuid(stockoutId);

View File

@@ -9,6 +9,13 @@ export function getRoadways(query) {
params: query
})
}
export function getFloors(query) {
return request({
url: '/kpi/getFloors',
method: 'get',
params: query
})
}
//获取排列表
export function getPlatoons(query) {
return request({

View File

@@ -98,7 +98,7 @@
<!-- <el-table-column type="selection" width="55" align="center" />-->
<!-- 主键列注释保留 -->
<!-- <el-table-column label="主键" align="center" prop="productGuid" /> -->
<el-table-column label="物料编码" align="center" prop="productId" />
<el-table-column label="物料编码" align="center" prop="productId" width="260" />
<el-table-column label="产品编码" align="center" prop="cargoNo" width="160"/>
<!-- 物料名称列:修改为自定义模板,用v-html渲染HTML样式 -->
<el-table-column label="物料名称" align="center" width="260">

View File

@@ -13,7 +13,7 @@
</el-select>
</el-form-item>
<!-- 巷道 -->
<el-form-item label="巷道" prop="roadwayId">
<!-- <el-form-item label="巷道" prop="roadwayId">
<el-select v-model="queryParams.roadwayId" placeholder="请选择巷道" clearable @change="handleQuery">
<el-option
v-for="item in roadwayOptions"
@@ -22,7 +22,7 @@
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form-item>-->
<el-form-item>
<!-- 【搜索】按钮 -->
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>

View File

@@ -13,18 +13,18 @@
/>
</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-form-item label="层数">
<el-select v-model="queryParams.theFloor" style="width: 150px" @change="handleFloorChange">
<el-option v-for="item in floorOptions" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
</el-form-item>
<!-- 排 -->
<el-form-item label="排">
<!-- <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-item>-->
</el-form>
</div>
@@ -36,7 +36,7 @@
<script>
import * as echarts from 'echarts'
import {getRoadways, getPlatoons, getChartData, getChartMag} from "@/api/kpi/spacePlan"
import {getRoadways, getPlatoons, getChartData, getChartMag, getFloors} from "@/api/kpi/spacePlan"
import {listWarehouse} from "@/api/bas/warehouse";
import VueI18n from 'vue-i18n';
@@ -46,9 +46,10 @@ export default {
return {
// 查询参数
queryParams: {
warehouseId: '01',
warehouseId: '1',
roadwayId: '1',
thePlatoon: '',
theFloor: '1',
platoon: '1',
specifications: '',
quantity_x: '',
@@ -65,6 +66,7 @@ export default {
warehouseOptions: [],
// 巷道选项
roadwayOptions: [],
floorOptions: [],
// 排号选项
platoonOptions: [],
// 图表实例
@@ -116,34 +118,28 @@ this.getWarehouseList()
// 重置巷道和排号
this.queryParams.roadwayId = ''
this.queryParams.thePlatoon = ''
this.roadwayOptions = []
this.floorOptions = []
this.platoonOptions = []
// 获取巷道列表
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()
// 获取层数列表
getFloors({ warehouseId: this.queryParams.warehouseId }).then(response => {
const floors = response.data.data || []
if (floors && floors.length > 0) {
this.floorOptions = floors.map(f => {
const lbl = f.label != null ? f.label : (f.name != null ? f.name : (f.title != null ? f.title : (f.value != null ? (String(f.value) + '排') : '')))
const val = f.value != null ? String(f.value) : String((lbl || '').replace(/[^\d]/g, ''))
return { label: lbl, value: val }
})
this.queryParams.theFloor = this.floorOptions[0].value
this.loadChartData()
} else {
this.floorOptions = []
this.queryParams.theFloor = null
}
})
},
// 巷道变化处理
handleRoadwayChange() {
// 重置排号
this.queryParams.thePlatoon = ''
this.platoonOptions = []
// 获取排号列表
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() {
handleFloorChange() {
console.log( this.queryParams.theFloor)
this.loadChartData()
},
// 加载普通仓库图表数据
@@ -178,10 +174,11 @@ this.getWarehouseList()
}
},
title: {
// 标题:库位分布平面图
text: '库位分布平面图',
// 子标题:排
subtext: this.queryParams.thePlatoon + '排'
subtext: (() => {
const sel = this.floorOptions.find(o => String(o.value) === String(this.queryParams.theFloor))
return sel && sel.label ? sel.label : ''
})()
},
grid: {
width: '90%',
@@ -327,35 +324,39 @@ this.getWarehouseList()
if (params.seriesName !== '满位') {
// 排
if (this.$i18n.locale ==='zh-cn') {
return params.seriesName + '<br>排' + this.queryParams.thePlatoon + '列' + (params.data[0] + 1) + '层' + (params.data[1] + 1);
return params.seriesName + '<br>' + (params.data[1] + 1) + '排' + (params.data[0] + 1) + '列' + this.queryParams.theFloor+ '层';
}
else{
return params.seriesName + '<br>' + this.queryParams.thePlatoon + '排 ' + (params.data[0] + 1) + '列 ' + (params.data[1] + 1) + '层';
return params.seriesName + '<br>' + (params.data[1] + 1) + '排' + (params.data[0] + 1) + '列' + this.queryParams.theFloor+ '层';
}
}
const returnData = {
"thePlatoon": this.queryParams.thePlatoon,
"thePlatoon": params.data[1] + 1,
"theColumn": params.data[0] + 1,
"theFloor": params.data[1] + 1,
"theFloor": this.queryParams.theFloor,
"warehouseId": this.queryParams.warehouseId
};
// 生成唯一标识
const key = `${params.seriesName}-${params.data[0]}-${params.data[1]}`;
// 如果已经在加载中,返回基本信息
if (this.loadingKeys && this.loadingKeys[key]) {
if (this.$i18n.locale === 'zh-cn') {
return `${params.seriesName}<br>${this.queryParams.thePlatoon}排${params.data[0] + 1}列${params.data[1] + 1}层<br>加载中...`;
return params.seriesName + '<br>' + (params.data[1] + 1) + '排' + (params.data[0] + 1) + '列' + this.queryParams.theFloor + '层';
} else {
return `${params.seriesName}<br>${this.queryParams.thePlatoon}排 ${params.data[0] + 1}列 ${params.data[1] + 1}层<br>加载中...`;
return params.seriesName + '<br>' + (params.data[1] + 1) + '排' + (params.data[0] + 1) + '列' + this.queryParams.theFloor+ '层';
}
}
// 返回基本信息
const baseStr = `${params.seriesName}<br>${this.queryParams.thePlatoon}排${params.data[0] + 1}列${params.data[1] + 1}层`;
const baseStr = `${params.seriesName}<br>${(params.data[1] + 1)}排${params.data[0] + 1}列${this.queryParams.theFloor}层`;
// 设置加载状态
if (!this.loadingKeys) this.loadingKeys = {};
@@ -417,4 +418,3 @@ this.getWarehouseList()
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style>