diff --git a/pom.xml b/pom.xml
index f83c8f2..ba108a7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -235,6 +235,7 @@
${mybatis-plus.version}
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/kpi/controller/KpiController.java b/ruoyi-admin/src/main/java/com/ruoyi/kpi/controller/KpiController.java
new file mode 100644
index 0000000..b692500
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/kpi/controller/KpiController.java
@@ -0,0 +1,76 @@
+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 仓库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("warehouseId") String warehouseId) {
+ return success(kpiService.getSpaceAnalysis(warehouseId));
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/kpi/domain/BasCargoSpace.java b/ruoyi-admin/src/main/java/com/ruoyi/kpi/domain/BasCargoSpace.java
new file mode 100644
index 0000000..607e59e
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/kpi/domain/BasCargoSpace.java
@@ -0,0 +1,309 @@
+package com.ruoyi.kpi.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 库存信息对象 bas_cargo_space
+ *
+ * @author lsy
+ * @date 2025-05-22
+ */
+public class BasCargoSpace extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 货位id 主键 */
+ private String cargoSpaceId;
+
+ /** 仓库id(不允许为空) */
+ @Excel(name = "仓库id", readConverterExp = "不=允许为空")
+ private String warehouseId;
+
+ /** 巷道id(允许为空) */
+ @Excel(name = "巷道id", readConverterExp = "允=许为空")
+ private String roadwayId;
+
+ /** 货区id(允许为空) */
+ @Excel(name = "货区id", readConverterExp = "允=许为空")
+ private String cargoAreaId;
+
+ /** 货位类型(允许为空) */
+ @Excel(name = "货位类型", readConverterExp = "允=许为空")
+ private String theType;
+
+ /** 货位类型名称 */
+ @Excel(name = "货位类型名称")
+ private String theTypeName;
+
+ /** 货位名称(不允许为空) */
+ @Excel(name = "货位名称", readConverterExp = "不=允许为空")
+ private String cargoSpaceName;
+
+ /** 排(不允许为空) */
+ @Excel(name = "排", readConverterExp = "不=允许为空")
+ private Long thePlatoon;
+
+ /** 列(不允许为空) */
+ @Excel(name = "列", readConverterExp = "不=允许为空")
+ private Long theColumn;
+
+ /** 层(不允许为空) */
+ @Excel(name = "层", readConverterExp = "不=允许为空")
+ private Long theFloor;
+
+ /** 货位状态1空2满 */
+ @Excel(name = "货位状态1空2满")
+ private String status;
+
+ /** 是否锁定(不允许为空)
+Y锁、N开 */
+ @Excel(name = "是否锁定", readConverterExp = "不=允许为空")
+ private String locked;
+
+ /** 托盘条码(允许为空) */
+ @Excel(name = "托盘条码", readConverterExp = "允=许为空")
+ private String trayCode;
+
+ /** 货位高度 */
+ @Excel(name = "货位高度")
+ private String cargoHight;
+
+ /** 是否双伸 Y N */
+ @Excel(name = "是否双伸 Y N ")
+ private String issDouble;
+
+ /** 双货位分组编码(标识区分) */
+ @Excel(name = "双货位分组编码", readConverterExp = "标=识区分")
+ private String groupCodingNo;
+
+ /** 双货位分组编码1、2… */
+ @Excel(name = "双货位分组编码1、2… ")
+ private String groupCoding;
+
+ /** 双货位标识 0 外1内 */
+ @Excel(name = "双货位标识 0 外1内")
+ private String cargoSpaceLogo;
+
+ /** 本仓库区域 1--8 A
+9--15 B */
+ @Excel(name = "本仓库区域 1--8 A 9--15 B")
+ private String thisCargoArea;
+
+ public void setCargoSpaceId(String cargoSpaceId)
+ {
+ this.cargoSpaceId = cargoSpaceId;
+ }
+
+ public String getCargoSpaceId()
+ {
+ return cargoSpaceId;
+ }
+
+ public void setWarehouseId(String warehouseId)
+ {
+ this.warehouseId = warehouseId;
+ }
+
+ public String getWarehouseId()
+ {
+ return warehouseId;
+ }
+
+ public void setRoadwayId(String roadwayId)
+ {
+ this.roadwayId = roadwayId;
+ }
+
+ public String getRoadwayId()
+ {
+ return roadwayId;
+ }
+
+ public void setCargoAreaId(String cargoAreaId)
+ {
+ this.cargoAreaId = cargoAreaId;
+ }
+
+ public String getCargoAreaId()
+ {
+ return cargoAreaId;
+ }
+
+ public void setTheType(String theType)
+ {
+ this.theType = theType;
+ }
+
+ public String getTheType()
+ {
+ return theType;
+ }
+
+ public void setTheTypeName(String theTypeName)
+ {
+ this.theTypeName = theTypeName;
+ }
+
+ public String getTheTypeName()
+ {
+ return theTypeName;
+ }
+
+ public void setCargoSpaceName(String cargoSpaceName)
+ {
+ this.cargoSpaceName = cargoSpaceName;
+ }
+
+ public String getCargoSpaceName()
+ {
+ return cargoSpaceName;
+ }
+
+ public void setThePlatoon(Long thePlatoon)
+ {
+ this.thePlatoon = thePlatoon;
+ }
+
+ public Long getThePlatoon()
+ {
+ return thePlatoon;
+ }
+
+ public void setTheColumn(Long theColumn)
+ {
+ this.theColumn = theColumn;
+ }
+
+ public Long getTheColumn()
+ {
+ return theColumn;
+ }
+
+ public void setTheFloor(Long theFloor)
+ {
+ this.theFloor = theFloor;
+ }
+
+ public Long getTheFloor()
+ {
+ return theFloor;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setLocked(String locked)
+ {
+ this.locked = locked;
+ }
+
+ public String getLocked()
+ {
+ return locked;
+ }
+
+ public void setTrayCode(String trayCode)
+ {
+ this.trayCode = trayCode;
+ }
+
+ public String getTrayCode()
+ {
+ return trayCode;
+ }
+
+ public void setCargoHight(String cargoHight)
+ {
+ this.cargoHight = cargoHight;
+ }
+
+ public String getCargoHight()
+ {
+ return cargoHight;
+ }
+
+ public void setIssDouble(String issDouble)
+ {
+ this.issDouble = issDouble;
+ }
+
+ public String getIssDouble()
+ {
+ return issDouble;
+ }
+
+ public void setGroupCodingNo(String groupCodingNo)
+ {
+ this.groupCodingNo = groupCodingNo;
+ }
+
+ public String getGroupCodingNo()
+ {
+ return groupCodingNo;
+ }
+
+ public void setGroupCoding(String groupCoding)
+ {
+ this.groupCoding = groupCoding;
+ }
+
+ public String getGroupCoding()
+ {
+ return groupCoding;
+ }
+
+ public void setCargoSpaceLogo(String cargoSpaceLogo)
+ {
+ this.cargoSpaceLogo = cargoSpaceLogo;
+ }
+
+ public String getCargoSpaceLogo()
+ {
+ return cargoSpaceLogo;
+ }
+
+ public void setThisCargoArea(String thisCargoArea)
+ {
+ this.thisCargoArea = thisCargoArea;
+ }
+
+ public String getThisCargoArea()
+ {
+ return thisCargoArea;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("cargoSpaceId", getCargoSpaceId())
+ .append("warehouseId", getWarehouseId())
+ .append("roadwayId", getRoadwayId())
+ .append("cargoAreaId", getCargoAreaId())
+ .append("theType", getTheType())
+ .append("theTypeName", getTheTypeName())
+ .append("cargoSpaceName", getCargoSpaceName())
+ .append("thePlatoon", getThePlatoon())
+ .append("theColumn", getTheColumn())
+ .append("theFloor", getTheFloor())
+ .append("status", getStatus())
+ .append("locked", getLocked())
+ .append("trayCode", getTrayCode())
+ .append("cargoHight", getCargoHight())
+ .append("issDouble", getIssDouble())
+ .append("groupCodingNo", getGroupCodingNo())
+ .append("groupCoding", getGroupCoding())
+ .append("cargoSpaceLogo", getCargoSpaceLogo())
+ .append("thisCargoArea", getThisCargoArea())
+ .toString();
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/kpi/domain/MydoJobFinish.java b/ruoyi-admin/src/main/java/com/ruoyi/kpi/domain/MydoJobFinish.java
new file mode 100644
index 0000000..b8dd3f6
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/kpi/domain/MydoJobFinish.java
@@ -0,0 +1,714 @@
+package com.ruoyi.kpi.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * MydoJobFinish对象 mydo_job_finish
+ *
+ * @author gw
+ * @date 2025-05-21
+ */
+public class MydoJobFinish extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String jobId;
+
+ /** 1未执行 2 待执行 3正执行 4已完成 5 已作废 */
+ @Excel(name = "1未执行 2 待执行 3正执行 4已完成 5 已作废")
+ private String status;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String onLineType;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String taskNo;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String supplierId;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String customerId;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String departmentId;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String trayCode;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String roadwayId;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String cargoSpaceId;
+
+ /** 445旧任务号 */
+ @Excel(name = "445旧任务号")
+ private String targetRoadwayId;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String targetCargoSpaceId;
+
+ /** 445产线 */
+ @Excel(name = "445产线")
+ private String lineId;
+
+ /** 445车间 */
+ @Excel(name = "445车间")
+ private String workshopId;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private Long priority;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String executionPhase;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String inOrOut;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String startTime;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String finishTime;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String entranceId;
+
+ /** 445装车口,出库过程自动选择 */
+ @Excel(name = "445装车口,出库过程自动选择")
+ private String exitId;
+
+ /** 445单据指定出号 */
+ @Excel(name = "445单据指定出号")
+ private String classNowName;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String classWorkshopName;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String classgroupNumber;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String classWorkshopDateTime;
+
+ /** 445成品库异常口提示信息 默认0,提示值重 */
+ @Excel(name = "445成品库异常口提示信息 默认0,提示值重")
+ private String classId;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String classNowDateTime;
+
+ /** 445仓库 */
+ @Excel(name = "445仓库")
+ private String warehouseId;
+
+ /** 445装车顺序,分配指定 */
+ @Excel(name = "445装车顺序,分配指定")
+ private String outId;
+
+ /** 445出库去向(输送机目标),wcs分配 (使用下发数字) */
+ @Excel(name = "445出库去向(输送机目标),wcs分配 (使用下发数字)")
+ private String siteId;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String carNumber;
+
+ /** 445异常作业 0正常 1异常 2异常待处理 */
+ @Excel(name = "445异常作业 0正常 1异常 2异常待处理")
+ private String faultFlag;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String devId;
+
+ /** $column.columnComment */
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+ private String stockSource;
+
+ /** 470高度 */
+ @Excel(name = "470高度")
+ private String floor;
+
+ /** 445原料库拣选台位置编号,agv取走后置为空 */
+ @Excel(name = "445原料库拣选台位置编号,agv取走后置为空")
+ private String location;
+
+ /** 445是否拣选,出库任务必填 0默认 1拣选 2不拣选 3拣完配送 4拣完入库 5拣完去称重 */
+ @Excel(name = "445是否拣选,出库任务必填 0默认 1拣选 2不拣选 3拣完配送 4拣完入库 5拣完去称重")
+ private String dwTime;
+
+ /** 445标记是否时合箱的托盘 0没有 1有 */
+ @Excel(name = "445标记是否时合箱的托盘 0没有 1有")
+ private String countId;
+
+ /** 445出库堆垛机放货完成 0默认 1出库放完成 */
+ @Excel(name = "445出库堆垛机放货完成 0默认 1出库放完成")
+ private String xdTime;
+
+ /** 下发标志 1:允许 2:下发完成 */
+ @Excel(name = "下发标志 1:允许 2:下发完成")
+ private String sendFlag;
+
+ /** agv状态 1:小车允许,3小车已执行 */
+ @Excel(name = "agv状态 1:小车允许,3小车已执行")
+ private String agvStatus;
+
+ /** 当前货物所在输送机,RGV接驳必用 */
+ @Excel(name = "当前货物所在输送机,RGV接驳必用")
+ private String wcsNo;
+
+ /** 445AGV原站点(拣选时必填) */
+ @Excel(name = "445AGV原站点(拣选时必填)")
+ private String srcAgv;
+
+ /** 445Agv目标站点 */
+ @Excel(name = "445Agv目标站点")
+ private String tarAgv;
+
+ /** 445自动分配组编号 */
+ @Excel(name = "445自动分配组编号")
+ private String groupGuid;
+
+ /** 470 照片位置 */
+ @Excel(name = "470 照片位置")
+ private String photoPath;
+
+ public void setJobId(String jobId)
+ {
+ this.jobId = jobId;
+ }
+
+ public String getJobId()
+ {
+ return jobId;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setOnLineType(String onLineType)
+ {
+ this.onLineType = onLineType;
+ }
+
+ public String getOnLineType()
+ {
+ return onLineType;
+ }
+
+ public void setTaskNo(String taskNo)
+ {
+ this.taskNo = taskNo;
+ }
+
+ public String getTaskNo()
+ {
+ return taskNo;
+ }
+
+ public void setSupplierId(String supplierId)
+ {
+ this.supplierId = supplierId;
+ }
+
+ public String getSupplierId()
+ {
+ return supplierId;
+ }
+
+ public void setCustomerId(String customerId)
+ {
+ this.customerId = customerId;
+ }
+
+ public String getCustomerId()
+ {
+ return customerId;
+ }
+
+ public void setDepartmentId(String departmentId)
+ {
+ this.departmentId = departmentId;
+ }
+
+ public String getDepartmentId()
+ {
+ return departmentId;
+ }
+
+ public void setTrayCode(String trayCode)
+ {
+ this.trayCode = trayCode;
+ }
+
+ public String getTrayCode()
+ {
+ return trayCode;
+ }
+
+ public void setRoadwayId(String roadwayId)
+ {
+ this.roadwayId = roadwayId;
+ }
+
+ public String getRoadwayId()
+ {
+ return roadwayId;
+ }
+
+ public void setCargoSpaceId(String cargoSpaceId)
+ {
+ this.cargoSpaceId = cargoSpaceId;
+ }
+
+ public String getCargoSpaceId()
+ {
+ return cargoSpaceId;
+ }
+
+ public void setTargetRoadwayId(String targetRoadwayId)
+ {
+ this.targetRoadwayId = targetRoadwayId;
+ }
+
+ public String getTargetRoadwayId()
+ {
+ return targetRoadwayId;
+ }
+
+ public void setTargetCargoSpaceId(String targetCargoSpaceId)
+ {
+ this.targetCargoSpaceId = targetCargoSpaceId;
+ }
+
+ public String getTargetCargoSpaceId()
+ {
+ return targetCargoSpaceId;
+ }
+
+ public void setLineId(String lineId)
+ {
+ this.lineId = lineId;
+ }
+
+ public String getLineId()
+ {
+ return lineId;
+ }
+
+ public void setWorkshopId(String workshopId)
+ {
+ this.workshopId = workshopId;
+ }
+
+ public String getWorkshopId()
+ {
+ return workshopId;
+ }
+
+ public void setPriority(Long priority)
+ {
+ this.priority = priority;
+ }
+
+ public Long getPriority()
+ {
+ return priority;
+ }
+
+ public void setExecutionPhase(String executionPhase)
+ {
+ this.executionPhase = executionPhase;
+ }
+
+ public String getExecutionPhase()
+ {
+ return executionPhase;
+ }
+
+ public void setInOrOut(String inOrOut)
+ {
+ this.inOrOut = inOrOut;
+ }
+
+ public String getInOrOut()
+ {
+ return inOrOut;
+ }
+
+ public void setStartTime(String startTime)
+ {
+ this.startTime = startTime;
+ }
+
+ public String getStartTime()
+ {
+ return startTime;
+ }
+
+ public void setFinishTime(String finishTime)
+ {
+ this.finishTime = finishTime;
+ }
+
+ public String getFinishTime()
+ {
+ return finishTime;
+ }
+
+ public void setEntranceId(String entranceId)
+ {
+ this.entranceId = entranceId;
+ }
+
+ public String getEntranceId()
+ {
+ return entranceId;
+ }
+
+ public void setExitId(String exitId)
+ {
+ this.exitId = exitId;
+ }
+
+ public String getExitId()
+ {
+ return exitId;
+ }
+
+ public void setClassNowName(String classNowName)
+ {
+ this.classNowName = classNowName;
+ }
+
+ public String getClassNowName()
+ {
+ return classNowName;
+ }
+
+ public void setClassWorkshopName(String classWorkshopName)
+ {
+ this.classWorkshopName = classWorkshopName;
+ }
+
+ public String getClassWorkshopName()
+ {
+ return classWorkshopName;
+ }
+
+ public void setClassgroupNumber(String classgroupNumber)
+ {
+ this.classgroupNumber = classgroupNumber;
+ }
+
+ public String getClassgroupNumber()
+ {
+ return classgroupNumber;
+ }
+
+ public void setClassWorkshopDateTime(String classWorkshopDateTime)
+ {
+ this.classWorkshopDateTime = classWorkshopDateTime;
+ }
+
+ public String getClassWorkshopDateTime()
+ {
+ return classWorkshopDateTime;
+ }
+
+ public void setClassId(String classId)
+ {
+ this.classId = classId;
+ }
+
+ public String getClassId()
+ {
+ return classId;
+ }
+
+ public void setClassNowDateTime(String classNowDateTime)
+ {
+ this.classNowDateTime = classNowDateTime;
+ }
+
+ public String getClassNowDateTime()
+ {
+ return classNowDateTime;
+ }
+
+ public void setWarehouseId(String warehouseId)
+ {
+ this.warehouseId = warehouseId;
+ }
+
+ public String getWarehouseId()
+ {
+ return warehouseId;
+ }
+
+ public void setOutId(String outId)
+ {
+ this.outId = outId;
+ }
+
+ public String getOutId()
+ {
+ return outId;
+ }
+
+ public void setSiteId(String siteId)
+ {
+ this.siteId = siteId;
+ }
+
+ public String getSiteId()
+ {
+ return siteId;
+ }
+
+ public void setCarNumber(String carNumber)
+ {
+ this.carNumber = carNumber;
+ }
+
+ public String getCarNumber()
+ {
+ return carNumber;
+ }
+
+ public void setFaultFlag(String faultFlag)
+ {
+ this.faultFlag = faultFlag;
+ }
+
+ public String getFaultFlag()
+ {
+ return faultFlag;
+ }
+
+ public void setDevId(String devId)
+ {
+ this.devId = devId;
+ }
+
+ public String getDevId()
+ {
+ return devId;
+ }
+
+ public void setStockSource(String stockSource)
+ {
+ this.stockSource = stockSource;
+ }
+
+ public String getStockSource()
+ {
+ return stockSource;
+ }
+
+ public void setFloor(String floor)
+ {
+ this.floor = floor;
+ }
+
+ public String getFloor()
+ {
+ return floor;
+ }
+
+ public void setLocation(String location)
+ {
+ this.location = location;
+ }
+
+ public String getLocation()
+ {
+ return location;
+ }
+
+ public void setDwTime(String dwTime)
+ {
+ this.dwTime = dwTime;
+ }
+
+ public String getDwTime()
+ {
+ return dwTime;
+ }
+
+ public void setCountId(String countId)
+ {
+ this.countId = countId;
+ }
+
+ public String getCountId()
+ {
+ return countId;
+ }
+
+ public void setXdTime(String xdTime)
+ {
+ this.xdTime = xdTime;
+ }
+
+ public String getXdTime()
+ {
+ return xdTime;
+ }
+
+ public void setSendFlag(String sendFlag)
+ {
+ this.sendFlag = sendFlag;
+ }
+
+ public String getSendFlag()
+ {
+ return sendFlag;
+ }
+
+ public void setAgvStatus(String agvStatus)
+ {
+ this.agvStatus = agvStatus;
+ }
+
+ public String getAgvStatus()
+ {
+ return agvStatus;
+ }
+
+ public void setWcsNo(String wcsNo)
+ {
+ this.wcsNo = wcsNo;
+ }
+
+ public String getWcsNo()
+ {
+ return wcsNo;
+ }
+
+ public void setSrcAgv(String srcAgv)
+ {
+ this.srcAgv = srcAgv;
+ }
+
+ public String getSrcAgv()
+ {
+ return srcAgv;
+ }
+
+ public void setTarAgv(String tarAgv)
+ {
+ this.tarAgv = tarAgv;
+ }
+
+ public String getTarAgv()
+ {
+ return tarAgv;
+ }
+
+ public void setGroupGuid(String groupGuid)
+ {
+ this.groupGuid = groupGuid;
+ }
+
+ public String getGroupGuid()
+ {
+ return groupGuid;
+ }
+
+ public void setPhotoPath(String photoPath)
+ {
+ this.photoPath = photoPath;
+ }
+
+ public String getPhotoPath()
+ {
+ return photoPath;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("jobId", getJobId())
+ .append("status", getStatus())
+ .append("onLineType", getOnLineType())
+ .append("taskNo", getTaskNo())
+ .append("supplierId", getSupplierId())
+ .append("customerId", getCustomerId())
+ .append("departmentId", getDepartmentId())
+ .append("trayCode", getTrayCode())
+ .append("roadwayId", getRoadwayId())
+ .append("cargoSpaceId", getCargoSpaceId())
+ .append("targetRoadwayId", getTargetRoadwayId())
+ .append("targetCargoSpaceId", getTargetCargoSpaceId())
+ .append("lineId", getLineId())
+ .append("workshopId", getWorkshopId())
+ .append("priority", getPriority())
+ .append("executionPhase", getExecutionPhase())
+ .append("inOrOut", getInOrOut())
+ .append("createTime", getCreateTime())
+ .append("startTime", getStartTime())
+ .append("finishTime", getFinishTime())
+ .append("entranceId", getEntranceId())
+ .append("exitId", getExitId())
+ .append("classNowName", getClassNowName())
+ .append("classWorkshopName", getClassWorkshopName())
+ .append("classgroupNumber", getClassgroupNumber())
+ .append("classWorkshopDateTime", getClassWorkshopDateTime())
+ .append("classId", getClassId())
+ .append("classNowDateTime", getClassNowDateTime())
+ .append("warehouseId", getWarehouseId())
+ .append("outId", getOutId())
+ .append("siteId", getSiteId())
+ .append("carNumber", getCarNumber())
+ .append("faultFlag", getFaultFlag())
+ .append("devId", getDevId())
+ .append("stockSource", getStockSource())
+ .append("floor", getFloor())
+ .append("location", getLocation())
+ .append("dwTime", getDwTime())
+ .append("countId", getCountId())
+ .append("xdTime", getXdTime())
+ .append("sendFlag", getSendFlag())
+ .append("agvStatus", getAgvStatus())
+ .append("wcsNo", getWcsNo())
+ .append("srcAgv", getSrcAgv())
+ .append("tarAgv", getTarAgv())
+ .append("groupGuid", getGroupGuid())
+ .append("photoPath", getPhotoPath())
+ .toString();
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/kpi/mapper/BasCargoSpaceMapper.java b/ruoyi-admin/src/main/java/com/ruoyi/kpi/mapper/BasCargoSpaceMapper.java
new file mode 100644
index 0000000..a9aae39
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/kpi/mapper/BasCargoSpaceMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.kpi.mapper;
+
+import java.util.List;
+import com.ruoyi.kpi.domain.BasCargoSpace;
+
+/**
+ * 库存信息Mapper接口
+ *
+ * @author lsy
+ * @date 2025-05-22
+ */
+public interface BasCargoSpaceMapper
+{
+
+ /**
+ * 查询库存信息列表
+ *
+ * @param basCargoSpace 库存信息
+ * @return 库存信息集合
+ */
+ public List selectBasCargoSpaceList(BasCargoSpace basCargoSpace);
+
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/kpi/mapper/MydoJobFinishMapper.java b/ruoyi-admin/src/main/java/com/ruoyi/kpi/mapper/MydoJobFinishMapper.java
new file mode 100644
index 0000000..20e5b75
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/kpi/mapper/MydoJobFinishMapper.java
@@ -0,0 +1,22 @@
+package com.ruoyi.kpi.mapper;
+
+import java.util.List;
+import com.ruoyi.kpi.domain.MydoJobFinish;
+
+/**
+ * MydoJobFinish Mapper 接口
+ *
+ * @author gw
+ * @date 2025-05-21
+ */
+public interface MydoJobFinishMapper
+{
+ /**
+ * 查询 MydoJobFinish 列表
+ *
+ * @param mydoJobFinish MydoJobFinish
+ * @return MydoJobFinish 集合
+ */
+ public List selectMydoJobFinishList(MydoJobFinish mydoJobFinish);
+}
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/kpi/service/KpiService.java b/ruoyi-admin/src/main/java/com/ruoyi/kpi/service/KpiService.java
new file mode 100644
index 0000000..9386cd6
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/kpi/service/KpiService.java
@@ -0,0 +1,36 @@
+package com.ruoyi.kpi.service;
+
+import java.util.Map;
+
+/**
+ * KPI 统计分析服务
+ *
+ * @author gw
+ * @date 2025-05-21
+ */
+public interface KpiService {
+ /**
+ * 获取入库均匀分析数据
+ *
+ * @param warehouseId 仓库ID
+ * @param yearMonth 年月,格式:yyyy-MM
+ * @return 入库均匀分析数据,包含每个巷道的入库数量
+ */
+ Map getInAnalysis(String warehouseId, String yearMonth);
+
+ Map 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 getRoadwayAnalysis(String warehouseId, String startTime, String endTime);
+
+
+
+ Map getSpaceAnalysis(String warehouseId);
+}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/kpi/service/impl/KpiServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/kpi/service/impl/KpiServiceImpl.java
new file mode 100644
index 0000000..603cdb1
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/kpi/service/impl/KpiServiceImpl.java
@@ -0,0 +1,280 @@
+package com.ruoyi.kpi.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.kpi.mapper.BasCargoSpaceMapper;
+import com.ruoyi.kpi.domain.BasCargoSpace;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.ruoyi.kpi.mapper.MydoJobFinishMapper;
+import com.ruoyi.kpi.domain.MydoJobFinish;
+import com.ruoyi.kpi.service.KpiService;
+
+/**
+ * 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 getInAnalysis(String warehouseId, String yearMonth)
+ {
+ MydoJobFinish mydoJobFinish = new MydoJobFinish();
+
+ List list = mydoJobFinishMapper.selectMydoJobFinishList(mydoJobFinish);
+
+ Map roadwayCount = new HashMap<>();
+
+ for (MydoJobFinish job : list) {
+ // 检查入库作业标识是否小于10
+ if (job.getInOrOut() == null || Integer.parseInt(job.getInOrOut()) >= 10) {
+ 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 tunnels = new ArrayList<>();
+ List counts = new ArrayList<>();
+
+ for (Map.Entry entry : roadwayCount.entrySet()) {
+ tunnels.add(entry.getKey() + "巷道");
+ counts.add(entry.getValue());
+ }
+
+ Map result = new HashMap<>();
+ result.put("tunnels", tunnels);
+ result.put("counts", counts);
+
+ return result;
+ }
+
+ /**
+ * 获取入库均匀分析数据
+ *
+ * @param warehouseId 仓库ID
+ * @param yearMonth 年月(格式:yyyy-MM)
+ * @return 入库均匀分析数据
+ */
+ @Override
+ public Map getOutAnalysis(String warehouseId, String yearMonth)
+ {
+ MydoJobFinish mydoJobFinish = new MydoJobFinish();
+
+ List list = mydoJobFinishMapper.selectMydoJobFinishList(mydoJobFinish);
+
+ Map roadwayCount = new HashMap<>();
+
+ for (MydoJobFinish job : list) {
+ // 检查出入库作业标识是否大于10
+ if (job.getInOrOut() == null || Integer.parseInt(job.getInOrOut()) < 10) {
+ 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 tunnels = new ArrayList<>();
+ List counts = new ArrayList<>();
+
+ for (Map.Entry entry : roadwayCount.entrySet()) {
+ tunnels.add(entry.getKey() + "巷道");
+ counts.add(entry.getValue());
+ }
+
+ Map 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 getRoadwayAnalysis(String warehouseId, String startTime, String endTime)
+ {
+ MydoJobFinish mydoJobFinish = new MydoJobFinish();
+ List list = mydoJobFinishMapper.selectMydoJobFinishList(mydoJobFinish);
+
+ // 用于存储每个巷道的入库和出库数量
+ Map inCounts = new HashMap<>();
+ Map 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 < 10) {
+ // 入库作业
+ inCounts.put(roadwayId, inCounts.getOrDefault(roadwayId, 0) + 1);
+ } else {
+ // 出库作业
+ outCounts.put(roadwayId, outCounts.getOrDefault(roadwayId, 0) + 1);
+ }
+ }
+ }
+ }
+
+ // 合并所有巷道ID
+ Set allRoadways = new HashSet<>();
+ allRoadways.addAll(inCounts.keySet());
+ allRoadways.addAll(outCounts.keySet());
+
+ // 将结果转换为指定格式
+ List tunnels = new ArrayList<>();
+ List inCountsList = new ArrayList<>();
+ List outCountsList = new ArrayList<>();
+
+ for (String roadwayId : allRoadways) {
+ tunnels.add(roadwayId + "巷道");
+ inCountsList.add(inCounts.getOrDefault(roadwayId, 0));
+ outCountsList.add(outCounts.getOrDefault(roadwayId, 0));
+ }
+
+ Map result = new HashMap<>();
+ result.put("tunnels", tunnels);
+ result.put("inCounts", inCountsList);
+ result.put("outCounts", outCountsList);
+
+ return result;
+ }
+
+ /**
+ * 获取巷道均匀分析数据
+ *
+ * @param warehouseId 仓库ID
+ * @return 货位分析
+ */
+ @Override
+ public Map getSpaceAnalysis(String warehouseId)
+ {
+ BasCargoSpace basCargoSpace = new BasCargoSpace();
+ basCargoSpace.setWarehouseId(warehouseId);
+ List list = basCargoSpaceMapper.selectBasCargoSpaceList(basCargoSpace);
+
+ // 按巷道和状态分类统计
+ Map> roadwayStats = new HashMap<>();
+ Set 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 = "空货位"; break;
+ case 2: statusName = "满货位"; break;
+ case 3: statusName = "入库分配"; break;
+ case 4: statusName = "出库分配"; break;
+ case 5: statusName = "入库需盘点"; break;
+ case 6: statusName = "出库需盘点"; break;
+ default: continue;
+ }
+
+ roadwayStats.computeIfAbsent(statusName, k -> new HashMap<>());
+ Map statusMap = roadwayStats.get(statusName);
+ statusMap.merge(roadwayId, 1, Integer::sum);
+ }
+ }
+
+ // 构建前端所需的数据格式
+ List