项目初始化

This commit is contained in:
liuhanqing
2025-09-11 11:19:00 +08:00
parent 13df9e0355
commit d53f41223b
1194 changed files with 245831 additions and 34 deletions

View File

@@ -0,0 +1,145 @@
package com.ruoyi.kpi.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.kpi.service.KpiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* KPI 统计分析
*
* @author gw
* @date 2025-05-21
*/
@RestController
@RequestMapping("/kpi")
public class KpiController extends BaseController {
@Autowired
private KpiService kpiService;
/**
* 获取入库均匀分析数据
*
* @param warehouseId 仓库ID
* @param yearMonth 年月,格式:yyyy-MM
* @return 入库均匀分析数据
*/
@GetMapping("/inAnalysis")
public AjaxResult getInAnalysis(@RequestParam("warehouseId") String warehouseId,
@RequestParam(value = "yearMonth", required = false) String yearMonth) {
return success(kpiService.getInAnalysis(warehouseId, yearMonth));
}
/**
* 按时间维度获取入库均匀分析数据
* @param warehouseId
* @return
*/
@GetMapping("/inAnalysisByData")
public AjaxResult getInAnalysisByData(@RequestParam(required = false) String warehouseId,
@RequestParam String startTime,
@RequestParam String endTime,
@RequestParam String inOut) {
return kpiService.getInAnalysisByData(warehouseId, startTime,endTime,inOut);
}
/**
* 获取出库均匀分析数据
*
* @param warehouseId 仓库ID
* @param yearMonth 年月,格式:yyyy-MM
* @return 入库均匀分析数据
*/
@GetMapping("/outAnalysis")
public AjaxResult getOutAnalysis(@RequestParam("warehouseId") String warehouseId,
@RequestParam(value = "yearMonth", required = false) String yearMonth) {
return success(kpiService.getOutAnalysis(warehouseId, yearMonth));
}
/**
* 获取巷道均匀分析数据
*
* @param warehouseId 仓库ID
* @param startTime 开始时间,格式:yyyy-MM-dd HH:mm:ss
* @param endTime 结束时间,格式:yyyy-MM-dd HH:mm:ss
* @return 巷道分析数据,格式:{tunnels: [巷道名称列表], inCounts: [入库数量列表], outCounts: [出库数量列表]}
*/
@GetMapping("/roadwayAnalysis")
public AjaxResult getRoadwayAnalysis(@RequestParam("warehouseId") String warehouseId,
@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime) {
return success(kpiService.getRoadwayAnalysis(warehouseId, startTime, endTime));
}
/**
* 获取货位分析数据
*
* @param warehouseId 仓库ID
* @return 货位分析数据
*/
@GetMapping("/spaceAnalysis")
public AjaxResult getSpaceAnalysis(@RequestParam(value = "warehouseId",required = false) 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

@@ -0,0 +1,20 @@
# 数据报表图示目录说明
## 目录用途
存放数据统计分析和报表展示相关的代码
## 主要功能
- 生成各类业务数据报表
- 数据可视化图表展示
- 业务指标统计分析
- 数据趋势监控和预警
## 目录结构
```
kpi/
├── config/ # 报表配置文件
├── controller/ # 报表控制器
├── model/ # 报表数据模型
├── service/ # 报表业务逻辑
└── utils/ # 报表工具类
```

View File

@@ -0,0 +1,50 @@
package com.ruoyi.kpi.service;
import com.ruoyi.common.core.domain.AjaxResult;
import java.util.Map;
/**
* KPI 统计分析服务
*
* @author gw
* @date 2025-05-21
*/
public interface KpiService {
/**
* 获取入库均匀分析数据
*
* @param warehouseId 仓库ID
* @param yearMonth 年月,格式:yyyy-MM
* @return 入库均匀分析数据,包含每个巷道的入库数量
*/
Map<String, Object> getInAnalysis(String warehouseId, String yearMonth);
Map<String, Object> getOutAnalysis(String warehouseId, String yearMonth);
/**
* 获取巷道均匀分析数据
*
* @param warehouseId 仓库ID
* @param startTime 开始时间,格式:yyyy-MM-dd HH:mm:ss
* @param endTime 结束时间,格式:yyyy-MM-dd HH:mm:ss
* @return 巷道分析数据,包含巷道名称列表和对应的入库、出库数量列表
*/
Map<String, Object> getRoadwayAnalysis(String warehouseId, String startTime, String endTime);
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);
AjaxResult getInAnalysisByData(String warehouseId, String startTime, String endTime,String inOut);
}

View File

@@ -0,0 +1,473 @@
package com.ruoyi.kpi.service.impl;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.bas.cargoSpace.domain.BasCargoSpace;
import com.ruoyi.bas.cargoSpace.mapper.BasCargoSpaceMapper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.job.mydojob.domain.MydoJob;
import com.ruoyi.job.mydojobfinish.domain.MydoJobFinish;
import com.ruoyi.job.mydojobfinish.mapper.MydoJobFinishMapper;
import com.ruoyi.kpi.service.KpiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* KPI 统计分析 服务实现类
*
* @author gw
* @date 2025-05-21
*/
@Service
public class KpiServiceImpl implements KpiService
{
@Autowired
private MydoJobFinishMapper mydoJobFinishMapper;
@Autowired
private BasCargoSpaceMapper basCargoSpaceMapper;
/**
* 获取入库均匀分析数据
*
* @param warehouseId 仓库ID
* @param yearMonth 年月(格式:yyyy-MM)
* @return 入库均匀分析数据
*/
@Override
public Map<String, Object> getInAnalysis(String warehouseId, String yearMonth)
{
MydoJob mydoJob = new MydoJob();
List<MydoJob> list = mydoJobFinishMapper.selectMydoJobFinishListByMydoJob(mydoJob);
Map<String, Integer> roadwayCount = new HashMap<>();
for (MydoJob job : list) {
// 检查入库作业标识是否小于10
if (job.getInOrOut() == null || Integer.parseInt(job.getInOrOut()) >= 20) {
continue;
}
// 按仓库ID筛选
if (!warehouseId.equals(job.getWarehouseId())) {
continue;
}
// 如果指定了年月,则按年月筛选
if (yearMonth != null && !yearMonth.isEmpty()) {
if (job.getStartTime() == null || !job.getStartTime().startsWith(yearMonth)) {
continue;
}
}
String roadwayId = job.getRoadwayId();
if (roadwayId != null) {
roadwayCount.put(roadwayId, roadwayCount.getOrDefault(roadwayId, 0) + 1);
}
}
// 将结果转换为指定格式
List<String> tunnels = new ArrayList<>();
List<Integer> counts = new ArrayList<>();
for (Map.Entry<String, Integer> entry : roadwayCount.entrySet()) {
tunnels.add(entry.getKey() + MessageUtils.message("kpi.spacePlan.roadway"));
counts.add(entry.getValue());
}
Map<String, Object> result = new HashMap<>();
result.put("tunnels", tunnels);
result.put("counts", counts);
return result;
}
/**
* 获取出库均匀分析数据
*
* @param warehouseId 仓库ID
* @param yearMonth 年月(格式:yyyy-MM)
* @return 出库均匀分析数据
*/
@Override
public Map<String, Object> getOutAnalysis(String warehouseId, String yearMonth)
{
MydoJobFinish mydoJobFinish = new MydoJobFinish();
List<MydoJobFinish> list = mydoJobFinishMapper.selectMydoJobFinishList(mydoJobFinish);
Map<String, Integer> roadwayCount = new HashMap<>();
for (MydoJobFinish job : list) {
// 检查出入库作业标识是否大于10
if (job.getInOrOut() == null || Integer.parseInt(job.getInOrOut()) < 20) {
continue;
}
// 按仓库ID筛选
if (!warehouseId.equals(job.getWarehouseId())) {
continue;
}
// 如果指定了年月,则按年月筛选
if (yearMonth != null && !yearMonth.isEmpty()) {
if (job.getStartTime() == null || !job.getStartTime().startsWith(yearMonth)) {
continue;
}
}
String roadwayId = job.getRoadwayId();
if (roadwayId != null) {
roadwayCount.put(roadwayId, roadwayCount.getOrDefault(roadwayId, 0) + 1);
}
}
// 将结果转换为指定格式
List<String> tunnels = new ArrayList<>();
List<Integer> counts = new ArrayList<>();
for (Map.Entry<String, Integer> entry : roadwayCount.entrySet()) {
tunnels.add(entry.getKey() + MessageUtils.message("kpi.spacePlan.roadway"));
counts.add(entry.getValue());
}
Map<String, Object> result = new HashMap<>();
result.put("tunnels", tunnels);
result.put("counts", counts);
return result;
}
/**
* 获取巷道均匀分析数据
*
* @param warehouseId 仓库ID
* @param startTime 开始时间,格式:yyyy-MM-dd HH:mm:ss
* @param endTime 结束时间,格式:yyyy-MM-dd HH:mm:ss
* @return 巷道分析数据
*/
@Override
public Map<String, Object> getRoadwayAnalysis(String warehouseId, String startTime, String endTime)
{
MydoJobFinish mydoJobFinish = new MydoJobFinish();
List<MydoJobFinish> list = mydoJobFinishMapper.selectMydoJobFinishList(mydoJobFinish);
// 用于存储每个巷道的入库和出库数量
Map<String, Integer> inCounts = new HashMap<>();
Map<String, Integer> outCounts = new HashMap<>();
for (MydoJobFinish job : list) {
// 按仓库ID筛选
if (!warehouseId.equals(job.getWarehouseId())) {
continue;
}
// 按时间范围筛选
if (startTime != null && !startTime.isEmpty()) {
if (job.getStartTime() == null || job.getStartTime().compareTo(startTime) < 0) {
continue;
}
}
if (endTime != null && !endTime.isEmpty()) {
if (job.getStartTime() == null || job.getStartTime().compareTo(endTime) > 0) {
continue;
}
}
String roadwayId = job.getRoadwayId();
if (roadwayId != null) {
// 区分入库和出库作业
if (job.getInOrOut() != null) {
int inOrOut = Integer.parseInt(job.getInOrOut());
if (inOrOut < 20) {
// 入库作业
inCounts.put(roadwayId, inCounts.getOrDefault(roadwayId, 0) + 1);
} else {
// 出库作业
outCounts.put(roadwayId, outCounts.getOrDefault(roadwayId, 0) + 1);
}
}
}
}
// 合并所有巷道ID
Set<String> allRoadways = new HashSet<>();
allRoadways.addAll(inCounts.keySet());
allRoadways.addAll(outCounts.keySet());
// 将结果转换为指定格式
List<String> tunnels = new ArrayList<>();
List<Integer> inCountsList = new ArrayList<>();
List<Integer> outCountsList = new ArrayList<>();
for (String roadwayId : allRoadways) {
tunnels.add(roadwayId + MessageUtils.message("kpi.spacePlan.roadway"));
inCountsList.add(inCounts.getOrDefault(roadwayId, 0));
outCountsList.add(outCounts.getOrDefault(roadwayId, 0));
}
Map<String, Object> result = new HashMap<>();
result.put("tunnels", tunnels);
result.put("inCounts", inCountsList);
result.put("outCounts", outCountsList);
return result;
}
/**
* 获取货位分析数据
*
* @param warehouseId 仓库ID
* @return 货位分析
*/
@Override
public Map<String, Object> getSpaceAnalysis(String warehouseId)
{
BasCargoSpace basCargoSpace = new BasCargoSpace();
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<>();
for (BasCargoSpace space : list) {
String roadwayId = space.getRoadwayId();
String status = space.getStatus();
if (roadwayId != null && status != null) {
roadwayIds.add(roadwayId);
String statusName;
switch (Integer.parseInt(status)) {
case 1: statusName = "1"; break; // 空货位
case 2: statusName = "2"; break; // 满货位
case 3: statusName = "3"; break; // 入库分配
case 4: statusName = "4"; break; // 出库分配
case 5: statusName = "5"; break; // 入库需盘点
case 6: statusName = "6"; break; // 出库需盘点
default: continue;
}
roadwayStats.computeIfAbsent(statusName, k -> new HashMap<>());
Map<String, Integer> statusMap = roadwayStats.get(statusName);
statusMap.merge(roadwayId, 1, Integer::sum);
}
}
// 构建前端所需的数据格式
List<Map<String, Object>> result = new ArrayList<>();
for (Map.Entry<String, Map<String, Integer>> entry : roadwayStats.entrySet()) {
Map<String, Object> statusData = new HashMap<>();
statusData.put("status", entry.getKey());
// 为每个巷道添加数量,如果没有数据则为0
for (String roadwayId : roadwayIds) {
statusData.put(MessageUtils.message("kpi.spacePlan.roadway") + roadwayId, entry.getValue().getOrDefault(roadwayId, 0));
}
result.add(statusData);
}
Map<String, Object> response = new HashMap<>();
response.put("data", result);
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", MessageUtils.message("kpi.spacePlan.roadway") + 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 + MessageUtils.message("kpi.spacePlan.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(MessageUtils.message("kpi.spacePlan.column")).append("',");
}
String column = "[" + columnLabels.toString() + "]";
StringBuilder floorLabels = new StringBuilder();
for (Long floor : floorSet) {
floorLabels.append("'").append(floor).append(MessageUtils.message("kpi.spacePlan.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(MessageUtils.message("kpi.spacePlan.CargoSpaceName")).append(space.getCargoSpaceName()).append("<br>");
info.append(MessageUtils.message("kpi.spacePlan.TheTypeName")).append(space.getTheTypeName()).append("<br>");
info.append(MessageUtils.message("kpi.spacePlan.Locked")).append("Y".equals(space.getLocked()) ? MessageUtils.message("kpi.spacePlan.Y") : MessageUtils.message("kpi.spacePlan.N")).append("<br>");
info.append(MessageUtils.message("kpi.spacePlan.TrayCode")).append(space.getTrayCode() != null ? space.getTrayCode() : MessageUtils.message("kpi.spacePlan.W")).append("<br>");
info.append(MessageUtils.message("kpi.spacePlan.CargoHight")).append(space.getCargoHight() != null ? space.getCargoHight() : MessageUtils.message("kpi.spacePlan.W")).append("<br>");
info.append(MessageUtils.message("kpi.spacePlan.IssDouble")).append("Y".equals(space.getIssDouble()) ? MessageUtils.message("kpi.spacePlan.Y") : MessageUtils.message("kpi.spacePlan.N")).append("<br>");
response.put("msg", info.toString());
} else {
response.put("msg", MessageUtils.message("kpi.spacePlan.msg"));
}
return response;
}
@Override
public AjaxResult getInAnalysisByData(String warehouseId, String startTime, String endTime,String inOut) {
Map<String,Object> res = new HashMap<>();
MydoJob mydoJobParam = new MydoJob();
mydoJobParam.setWarehouseId(warehouseId);
mydoJobParam.setCreateLeftTime(startTime);
mydoJobParam.setCreateRightTime(endTime);
mydoJobParam.setInOut(inOut);
List<DateTime> datesBetween = DateUtil.rangeToList(DateUtil.parseDate(mydoJobParam.getCreateLeftTime()), DateUtil.parseDate(mydoJobParam.getCreateRightTime()), DateField.DAY_OF_MONTH);
List<MydoJob> list = mydoJobFinishMapper.selectMydoJobFinishListByMydoJob(mydoJobParam);
List<String> x = new ArrayList<>();
List<Long> y = new ArrayList<>();
for (DateTime dateTime : datesBetween) {
//筛选每一日的数量
x.add(DateUtil.format(dateTime, "yyyy-MM-dd"));
y.add(list.stream().filter(mydoJob -> DateUtil.isIn(mydoJob.getCreateTime(), DateUtil.beginOfDay(dateTime),DateUtil.endOfDay(dateTime))).count());
}
res.put("xAxis",x);
res.put("series",y);
return AjaxResult.success(res);
}
}