项目初始化

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,66 @@
package com.ruoyi.api.controller;
import com.ruoyi.api.service.IJobStatisticsService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.stock.stock.domain.BasStock;
import com.ruoyi.stock.stock.service.IBasStockService;
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.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 作业统计 Controller-展示大屏
*/
@RestController
@RequestMapping("/api")
public class JobStatisticsController {
@Autowired
private IJobStatisticsService jobStatisticsService;
@Autowired
private IBasStockService basStockService;
/**
* 获取统计数据,包含:
* 1. 当日入库和出库数量统计
* 2. 货位状态统计
* 3. 当前任务列表
* 4. 当月每日入库和出库数量统计
*/
@GetMapping("/daily")
public AjaxResult getDailyStatistics() {
Map<String, Object> result = jobStatisticsService.getDailyStatistics();
return AjaxResult.success(result);
}
/**
* 获取库存信息(前50条)
*/
@GetMapping("/list")
public AjaxResult getStockList() {
// 查询所有库存数据
List<BasStock> list = basStockService.selectBasStockListApi(new BasStock());
// 截取前50条数据
List<BasStock> topList = list.stream()
.limit(50)
.collect(Collectors.toList());
// 构建返回结果
Map<String, Object> result = new HashMap<>();
result.put("stockMsg", topList);
return AjaxResult.success(result);
}
@GetMapping("/device/info")
public Object getDeviceInfo() {
// 获取设备信息
return jobStatisticsService.getDeviceInfo();
}
}

View File

@@ -0,0 +1,48 @@
package com.ruoyi.api.controller;
import com.ruoyi.api.domain.AgvMoveParam;
import com.ruoyi.api.service.IToWcsService;
import com.ruoyi.common.core.domain.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 作业统计 Controller
*/
@RestController
@RequestMapping("/api2wcs")
public class ToWcsApiController {
@Autowired
private IToWcsService toWcsService;
/**
* 推送CTU出库任务
*//*
//@PostMapping("/pushOutMydoJob")
@Scheduled(fixedDelay=10000)
public void pushOutMydoJob() {
toWcsService.pushOutMydoJob();
}
*//**
* 推送CTU流利架空料箱入库任务
*//*
@Scheduled(fixedDelay=10000)
public void pushInMydoJob() {
toWcsService.pushInMydoJob();
}*/
/**
* 推送agv搬运作业
* @return
*/
@PostMapping("/pushAgvMoveJob")
public AjaxResult pushAgvMoveJob(@RequestBody AgvMoveParam agvMoveParam) {
return toWcsService.pushAgvMoveJob(agvMoveParam);
}
}

View File

@@ -0,0 +1,111 @@
package com.ruoyi.api.controller;
import cn.hutool.json.JSONUtil;
import com.ruoyi.api.domain.ReMaterialParam;
import com.ruoyi.api.domain.RequestEnter;
import com.ruoyi.api.domain.WmsJobRequest;
import com.ruoyi.api.service.IToWmsService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.log.domain.RequestLog;
import com.ruoyi.log.service.IRequestLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* 作业统计 Controller
*/
@RestController
@RequestMapping("/api2wms")
public class ToWmsApiController {
@Autowired
private IToWmsService toWmsService;
@Autowired
private IRequestLogService requestLogService;
/**
* 入库任务请求
*/
@PostMapping("/requestEnterByTrayCode")
public AjaxResult requestEnterByTrayCode(@RequestBody RequestEnter requestEnter) {
AjaxResult ajaxResult = toWmsService.requestEnterByTrayCode(requestEnter);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(requestEnter), "入库任务请求(托盘)",ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
/**
* 小车接收开始信号
*/
@PostMapping("/startSignal")
public AjaxResult startSignal(@RequestBody RequestEnter requestEnter) {
AjaxResult ajaxResult = toWmsService.startSignal(requestEnter);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(requestEnter), "startSignal",ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
/**
* 入库、出库 任务完成回传
* Map<String, String>
* "wmsType": "任务类型" 1-入库 2-出库 3-agv搬运,
* taskNo:出库 入库任务号
* trayCode:托盘码
* positionCode1:起点
* positionCode2:终点
* containerCode:容器编码
*
*/
@PostMapping("/jobFinish")
public AjaxResult jobFinish(@RequestBody WmsJobRequest wmsJobRequest) {
AjaxResult ajaxResult = toWmsService.jobFinish(wmsJobRequest);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(wmsJobRequest), "jobFinish",ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
/**
* 放货有货,重新分配货位
*/
@PostMapping("/reAssign")
public AjaxResult reAssign(@RequestBody ReMaterialParam reMaterialParam) {
AjaxResult ajaxResult = toWmsService.reAssign(reMaterialParam);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(reMaterialParam), "reAssign",ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
/**
* 取货无货,重新分配物料
*/
@PostMapping("/reMaterial")
public AjaxResult reMaterial(@RequestBody ReMaterialParam reMaterialParam) {
AjaxResult ajaxResult = toWmsService.reMaterial(reMaterialParam);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(reMaterialParam), "reMaterial",ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
/**
* ctu取完箱子反馈
* @param map{
* "portCode"
* "wmsType"
* }
* @return
*/
@PostMapping("/takeCompleted")
public AjaxResult takeCompleted(@RequestBody Map<String, Object> map) {
AjaxResult ajaxResult = toWmsService.takeCompleted(map);
RequestLog requestLog = requestLogService.getRequestLog(JSONUtil.toJsonStr(map), "takeCompleted",ajaxResult);
requestLogService.insertRequestLog(requestLog);
return ajaxResult;
}
}

View File

@@ -0,0 +1,118 @@
package com.ruoyi.api.controller;
import com.ruoyi.api.service.IProductPortService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 仓库和点位API接口--拣选大屏
*
* @author lsy
* @date 2025-06-23
*/
@RestController
@RequestMapping("/api/warehouse")
public class WarehousePortController extends BaseController {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private IProductPortService productPortService;
/**
* 获取仓库列表
*/
@GetMapping("/list")
public AjaxResult getWarehouseList() {
try {
String sql = "SELECT warehouse_id, warehouse_no, warehouse_name, address, c_desc " +
"FROM bas_warehouse " +
"WHERE is_current = 'Y' " +
"ORDER BY warehouse_no";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
return success(list);
} catch (Exception e) {
logger.error("查询仓库列表失败:", e);
return error("查询仓库列表失败");
}
}
/**
* 根据仓库ID获取点位列表
*/
@GetMapping("/port/{warehouseId}")
public AjaxResult getPortList( @PathVariable("warehouseId") String warehouseId) {
if (warehouseId == null || warehouseId.trim().isEmpty()) {
return error("仓库ID不能为空");
}
try {
Map<String, Object> params = new HashMap<>();
params.put("warehouseId", warehouseId);
params.put("portType", 2);
List<Map<String, Object>> portList = productPortService.selectPortListByParams(params);
return success(portList);
} catch (Exception e) {
logger.error("查询点位列表失败:", e);
return error("查询点位列表失败");
}
}
/**
* 根据工位号数组查询任务数据
*/
@PostMapping("/workstation/jobs")
public AjaxResult getJobsByWorkstations(@RequestBody Map<String, Object> request) {
try {
@SuppressWarnings("unchecked")
List<String> workstationNumbers = (List<String>) request.get("workstationNumbers");
String warehouseId = (String) request.get("warehouseId");
if (workstationNumbers == null || workstationNumbers.isEmpty()) {
return error("工位号数组不能为空");
}
if (warehouseId == null || warehouseId.trim().isEmpty()) {
return error("仓库ID不能为空");
}
StringBuilder placeholders = new StringBuilder();
for (int i = 0; i < workstationNumbers.size(); i++) {
placeholders.append(i == 0 ? "?" : ", ?");
}
String sql = "SELECT j.*, jd.out_quantity, jd.product_id, bp.product_name " +
"FROM mydo_job j " +
"LEFT JOIN mydo_job_detail jd ON j.job_id = jd.job_id " +
"LEFT JOIN bas_product bp ON jd.product_id = bp.product_id " +
"WHERE j.exit_id IN (" + placeholders.toString() + ") " +
"AND j.warehouse_id = ? ";
Object[] params = new Object[workstationNumbers.size() + 1];
for (int i = 0; i < workstationNumbers.size(); i++) {
params[i] = workstationNumbers.get(i);
}
params[workstationNumbers.size()] = warehouseId;
List<Map<String, Object>> queryResult = jdbcTemplate.queryForList(sql, params);
// 按工位号分组
Map<String, List<Map<String, Object>>> groupedResult = new HashMap<>();
for (Map<String, Object> job : queryResult) {
String exitId = (String) job.get("exit_id");
groupedResult.computeIfAbsent(exitId, k -> new ArrayList<>()).add(job);
}
return success(groupedResult);
} catch (Exception e) {
logger.error("查询工位任务数据失败:", e);
return error("查询工位任务数据失败");
}
}
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.api.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AgvMoveParam {
private String startPoint;
private String endPoint;
private String containerCode;
private String taskNo;
}

View File

@@ -0,0 +1,156 @@
package com.ruoyi.api.domain;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;
/**
* 【生成AGV任务】请求接口
*/
@Data
public class GenAgvSchedulingTaskRequest {
/**
* 请求编号
* 同一个请求重复提交, 使用同一编号
*/
@NotNull
private String reqCode = UUID.randomUUID().toString();
/**
* 请求时间
* 格式: “yyyy-MM-dd HH:mm:ss”
*/
private String reqTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).toString();
/**
* 客户端编号
* 客户端编号,如PDA,HCWMS等
*/
private String clientCode;
/**
* 令牌号
* 由调度系统颁发
*/
private String tokenCode;
/**
* 任务类型
* 内置任务类型:
* 厂内货架搬运: F01
* 厂内货架空满交换: F02
* 辊筒搬运接驳:F03
* 厂内货架出库AGV待命:F04
* 旋转货架: F05
* 厂内电梯任务: F06
* 以下为叉车专用任务类型
* 高位货架到工作台: F11
* 工作台到高位货架: F12
* 巷道到工作台: F13
* 工作台到巷道: F14
* 高位货架到工作台(接驳) : F15
* 工作台到高位货架 (接驳) : F16
* 巷道到工作台(接驳) : F17
* 工作台到巷道(接驳) : F18
* 叉车电梯主任务: F20
*/
@NotNull
private String taskTyp;
/**
* 容器类型(叉车/CTU专用) 叉车项目必传
*/
private String ctnrTyp;
/**
* 容器编号 (叉车/CTU专用)
*/
private String ctnrCode; //
/**
* 容器数量(叉车堆叠专用),默认值1,仅记录堆叠的数量不记录堆叠的每个容器号
*/
private String ctnrNum;
/**
* 任务模式
* 0-普通move 1-出库move 2-入库move 3-移库move
*/
private String taskMode;
/**
* 工作位
* 与RCS-2000端配置的位置名称一致, 工作位名称为字母\数字\或组合
*/
private String wbCode;
/**
* 位置路径
* AGV关键路径位置集合,与任务类型中模板配置的位置路径一一对应。待现场地图部署、配置完成后可获取
*/
private List<PositionCodeData> positionCodePath;
/**
* 货架编号
* 不指定货架可以为空
*/
private String podCode;
/**
* 货架方向
* “180”,”0”,”90”,”-90” 分别对应地图的”左”,”右”,”上”,”下”
* 不指定方向可以为空
* 如果终点不是工作台或工作台未配置操作方向则货架拣货方向podDir作为终点方向
* 如果工作台配有操作方向,则系统会根据货架拣货方向podDir和工作台操作方向计算货架终点方向
*/
private String podDir;
/**
* 货架类型, 传空时表示随机找个货架
* 找空货架传参方式如下:
* -1: 代表不关心货架类型, 找到空货架即可.
* -2: 代表从工作位获取关联货架类型, 如果未配置, 只找空货架.
* 货架类型编号: 只找该货架类型的空货架
*/
private String podTyp;
/**
* 物料批次
* 物料批次或货架上的物料唯一编码,生成任务单时,货架与物料直接绑定时使用. (通过同时传podCode和materialLot来绑定或通过 wbCode 找到位置上的货架和materialLot来绑定)
* 如果是区域/策略内查找货架,可以匹配对应物料批次的货架,支持以下值:
* 0:区域/策略内查找空货架
* 1:区域/策略内查找满货架
* 其他值:查找指定物料批次对应的货架
* 巷道任务通过该字段传入特征值
*/
private String materialLot;
/**
* 优先级
* 从(1~127)级,最大优先级最高。为空时,采用任务模板的优先级
*/
private String priority;
/**
* AGV编号
* 填写表示指定某一编号的AGV执行该任务
*/
private String agvCode;
/**
* 任务单号
* 选填, 不填系统自动生成
*/
private String taskCode;
/**
* 组编号
* CTU场景下用于按组出库,同组任务优先拼车。 如业务需要任务组间或组内按顺序出库,则需调用料箱顺序出库(CTU)接口。
* 潜伏式场景下,通过组号来管理顺序出库的顺序,组号小的优先出库。
*/
private String groupId;
/**
* 设备类型
*/
private String agvTyp;
/**
* 选择策略
* 区域/策略中挑选货架以及根据物料批次挑选货架时的先进先出规则,支持以下4个值:
* 1:按照货架到达储位的时间顺序,先进先出
* 2:按照货架到达储位的时间顺序,先进后出
* 9:按照货架绑定物料批次的时间顺序,先进先出
* 10:按照货架绑定物料批次的时间顺序,先进后出
*/
private String positionSelStrategy;
/**
* 自定义数据
*/
private String data;
}

View File

@@ -0,0 +1,35 @@
package com.ruoyi.api.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PositionCodeData {
/**
* 位置编号 - 单个编号不超过64位
*/
private String positionCode;
/**
* 类型
*
* 位置类型说明:
* 00表示:位置编号
* 01表示:物料批次号
* 02表示:策略编号(含多个区域) 如:第一个区域放不下, 可以放第二个区域
* 03表示:货架编号,通过货架编号找到货架所在位置
* 04表示:区域编号,在区域中查找可用位置
* 05表示:仓位编号(叉车/CTU专用)
* 06表示:巷道编号
* 07表示:容器编号
* 08表示:巷道策略
* 09表示:巷道区域
* 10表示:巷道仓位
* 11表示:输送线(机台)编号
* 12表示:CTU工作台(梳齿工作站)编号
* 13表示:搬运巷道指定货架出库
*/
private String type;
}

View File

@@ -0,0 +1,12 @@
package com.ruoyi.api.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReMaterialParam {
private String jobId;
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.api.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RequestEnter {
private String entranceId;
private String trayCode;
private String taskNo;
private String wmsType;
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.api.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RequestEnterResponse {
private String cargoSpaceId;
private String trayCode;
private String taskNo;
}

View File

@@ -0,0 +1,25 @@
package com.ruoyi.api.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class WmsJobRequest {
//wms任务类型 1 入库 2-出库 3-agv任务
private String wmsType;
//wms任务号
private String taskNo;
//托盘编码
private String trayCode;
//拣选输送机
private String pickSsj;
//料架编码
private String containerCode;
//起点
private String positionCode1;
//终点
private String positionCode2;
}

View File

@@ -0,0 +1,38 @@
package com.ruoyi.api.mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 作业统计 Mapper 接口
*/
public interface JobStatisticsMapper {
/**
* 查询当日入库数量(inOrOut < 20)
*
* @param createTime 创建日期
* @return 入库数量
*/
public int selectDailyInCount(@Param("createTime") String createTime);
/**
* 查询当日出库数量(inOrOut >= 20)
*
* @param createTime 创建日期
* @return 出库数量
*/
public int selectDailyOutCount(@Param("createTime") String createTime);
/**
* 查询当月每日入库出库统计
*
* @param year 年份
* @param month 月份
* @return 每日入库出库统计列表
*/
public List<Map<String, Object>> selectMonthlyStatistics(@Param("year") int year, @Param("month") int month);
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.api.service;
import java.util.Map;
/**
* 作业统计 Service 接口
*/
public interface IJobStatisticsService {
/**
* 获取统计数据,包含:
* 1. 当日入库和出库数量统计
* 2. 货位状态统计
* 3. 当前任务列表
*
* @return 统计结果
*/
public Map<String, Object> getDailyStatistics();
Object getDeviceInfo();
}

View File

@@ -0,0 +1,29 @@
package com.ruoyi.api.service;
import java.util.List;
import java.util.Map;
/**
* 点位查询Service接口
*
* @author lsy
* @date 2025-06-23
*/
public interface IProductPortService {
/**
* 根据仓库ID查询点位列表
*
* @param warehouseId 仓库ID
* @return 点位列表
*/
public List<Map<String, Object>> selectPortListByWarehouseId(String warehouseId);
/**
* 根据查询条件获取点位列表
*
* @param params 查询参数,包含 warehouseId(仓库ID)和 portType(点位类型)
* @return 点位列表
*/
public List<Map<String, Object>> selectPortListByParams(Map<String, Object> params);
}

View File

@@ -0,0 +1,41 @@
package com.ruoyi.api.service;
import com.ruoyi.api.domain.AgvMoveParam;
import com.ruoyi.common.core.domain.AjaxResult;
import java.util.HashMap;
/**
* 作业统计 Service 接口
*/
public interface IToWcsService {
/**
* 推送CTU出库任务
*/
void pushOutMydoJob();
/**
* 推送agv搬运作业
* @return
*/
AjaxResult pushAgvMoveJob(AgvMoveParam agvMoveParam);
/**
* 推送流利架入库任务
*/
void pushInMydoJob();
/**
* 出库作业确认
* @param outMydojobMakeSureParam
* @return
*/
AjaxResult outMydojobMakeSure(HashMap<String, String> outMydojobMakeSureParam);
/**
* 取消任务
* @param taskNo
* @return
*/
AjaxResult cancelTaskByTaskNo(String taskNo);
}

View File

@@ -0,0 +1,51 @@
package com.ruoyi.api.service;
import com.ruoyi.api.domain.ReMaterialParam;
import com.ruoyi.api.domain.RequestEnter;
import com.ruoyi.api.domain.WmsJobRequest;
import com.ruoyi.common.core.domain.AjaxResult;
import java.util.Map;
/**
* 作业统计 Service 接口
*/
public interface IToWmsService {
/**
* 入库任务请求根据托盘码
*/
AjaxResult requestEnterByTrayCode(RequestEnter requestEnter);
/**
* 入库、出库 任务完成回传
* Map<String, String>
* "wmsType": "任务类型" 1-入库 2-出库 3-agv搬运,
* taskNo:出库 入库任务号
* trayCode:托盘码
* positionCode1:起点
* positionCode2:终点
* containerCode:容器编码
*
*/
AjaxResult jobFinish(WmsJobRequest wmsJobRequest);
/**
* 放货有货,重新分配货位
*/
AjaxResult reAssign(ReMaterialParam reMaterialParam);
/**
* 取货无货,重新分配物料
*/
AjaxResult reMaterial(ReMaterialParam reMaterialParam);
/**
* 小车接收开始信号
*/
AjaxResult startSignal(RequestEnter requestEnter);
/**
* ctu取完箱子反馈
* @param map{
* "lljCode"
* }
* @return
*/
AjaxResult takeCompleted(Map<String, Object> map);
}

View File

@@ -0,0 +1,103 @@
package com.ruoyi.api.service.impl;
import cn.hutool.http.HttpUtil;
import com.ruoyi.api.mapper.JobStatisticsMapper;
import com.ruoyi.api.service.IJobStatisticsService;
import com.ruoyi.bas.cargoSpace.mapper.BasCargoSpaceMapper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.job.mydojob.domain.MydoJob;
import com.ruoyi.job.mydojob.mapper.MydoJobMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 作业统计 Service 实现
*/
@Service
public class JobStatisticsServiceImpl implements IJobStatisticsService {
@Autowired
private JobStatisticsMapper jobStatisticsMapper;
@Autowired
private BasCargoSpaceMapper basCargoSpaceMapper;
@Autowired
private MydoJobMapper mydoJobMapper;
private String deviceUrl = "http://127.0.0.1:8081/device/api/devicecar/list";
/**
* 获取当日入库和出库数量统计
*/
@Override
public Map<String, Object> getDailyStatistics() {
// 获取当前日期
String today = DateUtils.getDate();
// 查询当日入库数量
int inCount = jobStatisticsMapper.selectDailyInCount(today);
// 查询当日出库数量
int outCount = jobStatisticsMapper.selectDailyOutCount(today);
// 获取货位状态统计
List<Map<String, Object>> statusCounts = basCargoSpaceMapper.selectStatusCount();
List<Map<String, Object>> cargoSpaceStatus = new ArrayList<>();
Map<String, String> statusNameMap = new HashMap<>();
statusNameMap.put("1", "空货位");
statusNameMap.put("2", "满货位");
statusNameMap.put("3", "入库已分配");
statusNameMap.put("4", "出库已分配");
statusNameMap.put("5", "入库需盘点");
statusNameMap.put("6", "出库需盘点");
for (Map.Entry<String, String> entry : statusNameMap.entrySet()) {
Map<String, Object> item = new HashMap<>();
String status = entry.getKey();
item.put("name", entry.getValue());
item.put("value", 0);
for (Map<String, Object> count : statusCounts) {
if (status.equals(String.valueOf(count.get("status")))) {
item.put("value", count.get("count"));
break;
}
}
cargoSpaceStatus.add(item);
}
// 获取当前任务列表
List<MydoJob> currentTasks = mydoJobMapper.selectCurrentTasks();
// 获取当前年月
int year = Integer.parseInt(DateUtils.dateTimeNow("yyyy"));
int month = Integer.parseInt(DateUtils.dateTimeNow("MM"));
// 获取当月每日统计数据
List<Map<String, Object>> dailyStats = jobStatisticsMapper.selectMonthlyStatistics(year, month);
// 返回统计结果
Map<String, Object> result = new HashMap<>();
result.put("drrk", String.valueOf(inCount));
result.put("drck", String.valueOf(outCount));
result.put("cargoSpaceStatus", cargoSpaceStatus);
result.put("currentTask", currentTasks);
result.put("statistic", dailyStats);
return result;
}
@Override
public Object getDeviceInfo() {
//String s = HttpUtil.get(deviceUrl);
return HttpUtil.get(deviceUrl);
}
}

View File

@@ -0,0 +1,46 @@
package com.ruoyi.api.service.impl;
import com.ruoyi.api.service.IProductPortService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* 点位查询Service实现
*
* @author lsy
* @date 2025-06-23
*/
@Service
public class ProductPortServiceImpl implements IProductPortService {
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 根据仓库ID查询点位列表
*
* @param warehouseId 仓库ID
* @return 点位列表
*/
@Override
public List<Map<String, Object>> selectPortListByWarehouseId(String warehouseId) {
String sql = "SELECT port_name, port_desc FROM bas_product_port WHERE warehouse_id = ?";
return jdbcTemplate.queryForList(sql, warehouseId);
}
/**
* 根据查询条件获取点位列表
*
* @param params 查询参数
* @return 点位列表
*/
@Override
public List<Map<String, Object>> selectPortListByParams(Map<String, Object> params) {
String sql = "SELECT port_name, port_desc FROM bas_product_port WHERE warehouse_id = ? AND port_type = ?";
return jdbcTemplate.queryForList(sql, params.get("warehouseId"), params.get("portType"));
}
}

View File

@@ -0,0 +1,126 @@
package com.ruoyi.api.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.api.domain.AgvMoveParam;
import com.ruoyi.api.service.IToWcsService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.device.agv.domain.AgvContainerTask;
import com.ruoyi.device.agv.service.IAgvContainerTaskService;
import com.ruoyi.job.mydojob.domain.MydoJob;
import com.ruoyi.job.mydojob.service.IMydoJobService;
import com.ruoyi.log.domain.RequestLog;
import com.ruoyi.log.service.IRequestLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* 作业统计 Service 实现
*/
@Service
public class ToWcsServiceImpl implements IToWcsService {
@Autowired
private IRequestLogService requestLogService;
@Autowired
private IMydoJobService mydoJobService;
@Autowired
private IAgvContainerTaskService agvContainerTaskService;
public static final String PUSH_OUT_MYDO_JOB = "http://localhost:8081/wcs2Wms/api/receiveOutMydoJob";
public static final String PUSH_IN_MYDO_JOB = "http://localhost:8081/wcs2Wms/api/receiveInMydoJob";
public static final String PUSH_AGV_MOVE_JOB = "http://localhost:8081/agv/api/receiveAgvMoveJob";
public static final String OUT_MYDOJOB_MS = "http://localhost:8081/wcs2Wms/api/outMydojobMakesure";
public static final String CANCEL_MYDOJOB = "http://localhost:8081/wcs2Wms/api/cancelMydoJob";
@Override
public void pushOutMydoJob() {
//查询所有未推送的料箱出库作业
MydoJob mydoJobParam = new MydoJob();
mydoJobParam.setStatus("1");
List<String> list = new ArrayList<>();
list.add("21");
list.add("23");
list.add("25");
mydoJobParam.setInOutIds(list);
List<MydoJob> outMydoJobs = mydoJobService.selectMydoJobListApi(mydoJobParam);
for (MydoJob outMydoJob : outMydoJobs) {
RequestLog requestLog = requestLogService.getRequestLog(PUSH_OUT_MYDO_JOB, JSONUtil.toJsonStr(outMydoJob), "推送出库任务");
if ("1".equals(requestLog.getIsSuccessful())){
outMydoJob.setStatus("2");
//outMydoJob.setStartTime(DateUtil.formatDateTime(DateUtil.date()));
mydoJobService.updateMydoJob(outMydoJob);
}
}
}
@Override
public AjaxResult pushAgvMoveJob(AgvMoveParam agvMoveParam) {
agvMoveParam.setTaskNo(IdUtil.fastSimpleUUID());
RequestLog requestLog = requestLogService.getRequestLog(PUSH_AGV_MOVE_JOB, JSONUtil.toJsonStr(agvMoveParam), "推送搬运任务");
if ("1".equals(requestLog.getIsSuccessful())){
AgvContainerTask agvContainerTask = new AgvContainerTask();
agvContainerTask.setContainer(agvMoveParam.getContainerCode());
agvContainerTask.setStartPoint(agvMoveParam.getStartPoint());
agvContainerTask.setEndPoint(agvMoveParam.getEndPoint());
agvContainerTask.setStatus("0");
agvContainerTask.setTaskNo(agvMoveParam.getTaskNo());
agvContainerTask.setCreateTime(new Date());
agvContainerTaskService.insertAgvContainerTask(agvContainerTask);
return AjaxResult.success();
}
return AjaxResult.error(requestLog.getErrorDetails());
}
@Override
public void pushInMydoJob() {
MydoJob mydoJobParam = new MydoJob();
mydoJobParam.setInOrOut("1");
mydoJobParam.setStatus("1");
List<MydoJob> mydoJobs = mydoJobService.selectMydoJobListApi(mydoJobParam);
if (CollUtil.isNotEmpty(mydoJobs)){
for (MydoJob mydoJob : mydoJobs) {
RequestLog requestLog = requestLogService.getRequestLog(PUSH_IN_MYDO_JOB, JSONUtil.toJsonStr(mydoJob), "推送出库任务");
if ("1".equals(requestLog.getIsSuccessful())){
mydoJob.setStatus("2");
mydoJobService.updateMydoJob(mydoJob);
}
}
}
mydoJobParam.setEntranceId("fluent");
mydoJobs = mydoJobService.selectMydoJobListApi(mydoJobParam);
if (CollUtil.isNotEmpty(mydoJobs)){
for (MydoJob mydoJob : mydoJobs) {
RequestLog requestLog = requestLogService.getRequestLog(PUSH_IN_MYDO_JOB, JSONUtil.toJsonStr(mydoJob), "推送出库任务");
if ("1".equals(requestLog.getIsSuccessful())){
mydoJob.setStatus("2");
mydoJobService.updateMydoJob(mydoJob);
}
}
}
}
@Override
public AjaxResult outMydojobMakeSure(HashMap<String, String> outMydojobMakeSureParam) {
RequestLog requestLog = requestLogService.getRequestLog(OUT_MYDOJOB_MS, JSONUtil.toJsonStr(outMydojobMakeSureParam), "推送出库任务");
if ("1".equals(requestLog.getIsSuccessful())){
return AjaxResult.success();
}
return AjaxResult.error(requestLog.getDuration());
}
@Override
public AjaxResult cancelTaskByTaskNo(String taskNo) {
Map<String,String> map = new HashMap<>();
map.put("taskNo", taskNo);
RequestLog requestLog = requestLogService.getRequestLog(CANCEL_MYDOJOB, JSONUtil.toJsonStr(map), "取消任务");
if ("1".equals(requestLog.getIsSuccessful())){
return AjaxResult.success();
}
return AjaxResult.error(MessageUtils.message("error.message17"));
}
}

View File

@@ -0,0 +1,313 @@
package com.ruoyi.api.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.api.domain.ReMaterialParam;
import com.ruoyi.api.domain.RequestEnter;
import com.ruoyi.api.domain.RequestEnterResponse;
import com.ruoyi.api.domain.WmsJobRequest;
import com.ruoyi.api.service.IToWmsService;
import com.ruoyi.bas.cargoSpace.domain.BasCargoSpace;
import com.ruoyi.bas.cargoSpace.service.IBasCargoSpaceService;
import com.ruoyi.bas.container.domain.BasContainer;
import com.ruoyi.bas.container.service.IBasContainerService;
import com.ruoyi.bas.tag.domain.BasTag;
import com.ruoyi.bas.tag.service.IBasTagService;
import com.ruoyi.bas.taskNo.service.IBasTaskNoService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.device.agv.domain.AgvContainerTask;
import com.ruoyi.device.agv.service.IAgvContainerTaskService;
import com.ruoyi.job.mydojob.domain.MydoJob;
import com.ruoyi.job.mydojob.service.IMydoJobService;
import com.ruoyi.job.mydojobdetail.domain.MydoJobDetail;
import com.ruoyi.job.mydojobdetail.service.IMydoJobDetailService;
import com.ruoyi.out.outStockout.service.IOutStockoutService;
import com.ruoyi.out.outStockoutDetail.service.IOutStockoutDetailService;
import com.ruoyi.out.tagTask.domain.TagTask;
import com.ruoyi.out.tagTask.service.ITagTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 作业统计 Service 实现
*/
@Service
@Slf4j
public class ToWmsServiceImpl implements IToWmsService {
@Autowired
private IMydoJobService mydoJobService;
@Autowired
private IMydoJobDetailService mydoJobDetailService;
@Autowired
private IBasContainerService basContainerService;
@Autowired
private ITagTaskService tagTaskService;
@Autowired
private IBasTaskNoService basTaskNoService;
@Autowired
private IBasTagService iBasTagService;
@Autowired
private IBasCargoSpaceService basCargoSpaceService;
@Autowired
private IOutStockoutDetailService outStockoutDetailService;
@Autowired
private IOutStockoutService outStockoutService;
@Autowired
private IAgvContainerTaskService agvContainerTaskService;
@Override
public AjaxResult requestEnterByTrayCode(RequestEnter requestEnter) {
MydoJob mydoJobParam = new MydoJob();
mydoJobParam.setTrayCode(requestEnter.getTrayCode());
List<MydoJob> mydoJobs = mydoJobService.selectMydoJobListApi(mydoJobParam);
if(mydoJobs.isEmpty()){
return AjaxResult.warn(MessageUtils.message("warn.message"));
}
MydoJob mydoJob = mydoJobs.get(0);
if ("1".equals(mydoJob.getExecutionPhase())){
mydoJob.setExecutionPhase("2");
mydoJob.setEntranceId(requestEnter.getEntranceId());
mydoJob.setStatus("2");
mydoJobService.updateMydoJob(mydoJob);
}
return AjaxResult.success(new RequestEnterResponse(mydoJob.getCargoSpaceId(),mydoJob.getTrayCode(),mydoJob.getTaskNo()));
}
@Override
public AjaxResult jobFinish(WmsJobRequest wmsJobRequest) {
MydoJob mydoJobParam = new MydoJob();
switch (wmsJobRequest.getWmsType()){
case "1":
if (StrUtil.isEmpty(wmsJobRequest.getTrayCode())){
return AjaxResult.error(MessageUtils.message("error.message1"));
}
if (StrUtil.isEmpty(wmsJobRequest.getTaskNo())){
return AjaxResult.error(MessageUtils.message("error.message2"));
}
//入库
mydoJobParam.setTaskNo(wmsJobRequest.getTaskNo());
mydoJobParam.setTrayCode(wmsJobRequest.getTrayCode());
List<MydoJob> inMydoJobs = mydoJobService.selectMydoJobListApi(mydoJobParam);
if (inMydoJobs.isEmpty()){
return AjaxResult.error(MessageUtils.message("warn.message"));
}
MydoJob inMydoJob = inMydoJobs.get(0);
mydoJobService.manualCompleted(inMydoJob,1);
break;
case "2":
if (StrUtil.isEmpty(wmsJobRequest.getPickSsj())){
return AjaxResult.error(MessageUtils.message("error.message3"));
}
if (StrUtil.isEmpty(wmsJobRequest.getTaskNo())){
return AjaxResult.error(MessageUtils.message("error.message2"));
}
//出库
mydoJobParam.setTaskNo(wmsJobRequest.getTaskNo());
//mydoJobParam.setTrayCode(wmsJobRequest.getTrayCode());
List<MydoJob> outMydoJobs = mydoJobService.selectMydoJobListApi(mydoJobParam);
if (outMydoJobs.isEmpty()){
return AjaxResult.error(MessageUtils.message("warn.message"));
}
MydoJob outJob = outMydoJobs.get(0);
//料箱出库 需同步电子标签
if("23".equals(outJob.getInOrOut())){
//查询拣选工位绑定的电子标签
BasTag tagParam = new BasTag();
tagParam.setPickAdd(wmsJobRequest.getPickSsj());
tagParam.setSpare3("1");
List<BasTag> tags = iBasTagService.selectBasTagList(tagParam);
if (tags.isEmpty()){
return AjaxResult.error(MessageUtils.message("error.message4"));
}
BasTag basTag = tags.get(0);
basTag.setTrayCode(outJob.getTrayCode());
iBasTagService.updateBasTag(basTag);
//同步电子标签
MydoJobDetail param = new MydoJobDetail();
param.setJobId(outMydoJobs.get(0).getJobId());
List<MydoJobDetail> mydoJobDetails = mydoJobDetailService.selectMydoJobDetailList(param);
for (MydoJobDetail mydoJobDetail : mydoJobDetails) {
TagTask tagTask = new TagTask();
tagTask.setTagId(basTag.getId());
tagTask.setJobDetailId(mydoJobDetail.getJobDetailId());
tagTask.setProductId(mydoJobDetail.getProductId());
tagTask.setNum(mydoJobDetail.getOutQuantity());
tagTask.setStatus("0");
tagTask.setColor("0");
tagTask.setFloor("0");
tagTaskService.insertTagTask(tagTask);
}
//开启线程
//new Thread(new TagOutReadThread(basTag.getIp())).start();
}
break;
case "3":
if (StrUtil.isEmpty(wmsJobRequest.getContainerCode())){
return AjaxResult.error(MessageUtils.message("error.message5"));
}
if (StrUtil.isEmpty(wmsJobRequest.getPositionCode1())){
return AjaxResult.error(MessageUtils.message("error.message6"));
}
if (StrUtil.isEmpty(wmsJobRequest.getPositionCode2())){
return AjaxResult.error(MessageUtils.message("error.message7"));
}
//agv搬运作业
//绑定料架和点位
BasContainer basContainerParam = new BasContainer();
basContainerParam.setContainerId(wmsJobRequest.getContainerCode());
//basContainerParam.setPortName(wmsJobRequest.getPositionCode2());
List<BasContainer> basContainers = basContainerService.selectBasContainerList(basContainerParam);
if (basContainers.isEmpty()){
log.error("没有该料架 {}", wmsJobRequest.getContainerCode());
return AjaxResult.error(MessageUtils.message("error.message11"));
}
//修改绑定点位
BasContainer basContainer = basContainers.get(0);
basContainer.setPortName(wmsJobRequest.getPositionCode2());
basContainerService.updateBasContainer(basContainer);
//删除agv任务
AgvContainerTask agvContainerTaskParam = new AgvContainerTask();
agvContainerTaskParam.setContainer(basContainer.getContainerId());
List<AgvContainerTask> agvContainerTasks = agvContainerTaskService.selectAgvContainerTaskList(agvContainerTaskParam);
if (CollUtil.isNotEmpty(agvContainerTasks)){
for (AgvContainerTask agvContainerTask : agvContainerTasks) {
agvContainerTask.setStatus("2");
agvContainerTask.setFinishTime(DateUtil.formatDateTime(new Date()));
agvContainerTaskService.updateAgvContainerTask(agvContainerTask);
agvContainerTaskService.insertHistory(agvContainerTask.getId());
agvContainerTaskService.deleteAgvContainerTaskById(agvContainerTask.getId());
}
}
break;
default:
log.error("作业类型错误");
return AjaxResult.error(MessageUtils.message("error.message12"));
}
return AjaxResult.success();
}
@Override
public AjaxResult reAssign(ReMaterialParam reMaterialParam) {
//重新分配货位
MydoJob mydoJob = mydoJobService.selectMydoJobByJobId(reMaterialParam.getJobId());
String warehouseId = mydoJob.getWarehouseId();
BasCargoSpace basCargoSpace = basCargoSpaceService.selectEmptyCargoSpaceByWarehouseId(warehouseId);
if (basCargoSpace == null){
log.error("没有空货位");
return AjaxResult.error(MessageUtils.message("error.message20"));
}else {
mydoJob.setCargoSpaceId(basCargoSpace.getCargoSpaceId());
mydoJob.setFaultFlag("1");
mydoJobService.updateMydoJob(mydoJob);
return AjaxResult.success(new RequestEnterResponse(basCargoSpace.getCargoSpaceId(), null, mydoJob.getJobId()));
}
}
@Override
public AjaxResult reMaterial(ReMaterialParam reMaterialParam) {
//重新分配物料
MydoJob mydoJob = mydoJobService.selectMydoJobByJobId(reMaterialParam.getJobId());
MydoJobDetail mydoJobDetailParam = new MydoJobDetail();
mydoJobDetailParam.setJobId(mydoJob.getJobId());
List<MydoJobDetail> mydoJobDetails = mydoJobDetailService.selectMydoJobDetailList(mydoJobDetailParam);
String stockOutId = mydoJobDetails.get(0).getInOrOutId();
// 作废作业
mydoJobService.OuthandInvalidation(new String[]{mydoJob.getJobId()});
//调用自动分配
return outStockoutService.autoAllot(stockOutId);
}
/**
* 小车接收开始信号
*/
@Override
public AjaxResult startSignal(RequestEnter requestEnter) {
switch (requestEnter.getWmsType()){
case "1":
case "2":
MydoJob mydoJobParam = new MydoJob();
mydoJobParam.setTaskNo(requestEnter.getTaskNo());
List<MydoJob> mydoJobs = mydoJobService.selectMydoJobListApi(mydoJobParam);
if (mydoJobs.isEmpty()){
return AjaxResult.error();
}
for (MydoJob mydoJob1 : mydoJobs) {
mydoJob1.setStatus("3");
mydoJob1.setStartTime(DateUtil.formatDateTime(DateUtil.date()));
mydoJobService.updateMydoJob(mydoJob1);
}
return AjaxResult.success();
case "3":
AgvContainerTask agvContainerTaskParam = new AgvContainerTask();
agvContainerTaskParam.setTaskNo(requestEnter.getTaskNo());
List<AgvContainerTask> agvContainerTasks = agvContainerTaskService.selectAgvContainerTaskList(agvContainerTaskParam);
if (CollUtil.isEmpty(agvContainerTasks)){
return AjaxResult.error();
}
for (AgvContainerTask agvContainerTask : agvContainerTasks) {
agvContainerTask.setStatus("2");
agvContainerTask.setStartTime(DateUtil.formatDateTime(DateUtil.date()));
agvContainerTaskService.updateAgvContainerTask(agvContainerTask);
}
return AjaxResult.success();
default:
return AjaxResult.error();
}
}
/**
* ctu取完箱子反馈
* @param map{
* "portCode"
* "wmsType"
* }
* @return
*/
@Override
public AjaxResult takeCompleted(Map<String, Object> map) {
String wmsType = Convert.toStr(map.get("wmsType"));
switch (wmsType){
case "1":
//流利架入库
String lljCode = Convert.toStr(map.get("portCode"));
BasTag basTagParam = new BasTag();
basTagParam.setPickAdd(lljCode);
List<BasTag> basTags = iBasTagService.selectBasTagList(basTagParam);
for (BasTag basTag : basTags) {
basTag.setSpare2("2");
iBasTagService.updateBasTag(basTag);
}
case "2":
break;
case "3":
//小车搬运料架
String startPoint = Convert.toStr(map.get("portCode"));
BasContainer basContainerParam = new BasContainer();
basContainerParam.setPortName(startPoint);
List<BasContainer> basContainers = basContainerService.selectBasContainerList(basContainerParam);
for (BasContainer basContainer : basContainers) {
basContainer.setPortName("");
basContainerService.updateBasContainer(basContainer);
}
break;
default:
throw new RuntimeException("wmsType错误");
}
return AjaxResult.success();
}
}