diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/checklog/vo/CheckLogSaveReqVO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/checklog/vo/CheckLogSaveReqVO.java index 2ded1c2..320d8c9 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/checklog/vo/CheckLogSaveReqVO.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/checklog/vo/CheckLogSaveReqVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.camera.controller.admin.checklog.vo; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; +import lombok.Data; @Schema(description = "管理后台 - 盘点新增/修改 Request VO") @Data diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/OrderController.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/OrderController.java index c13c3fb..4c7b96d 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/OrderController.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/OrderController.java @@ -9,8 +9,12 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderPageReqVO; import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderRespVO; import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderSaveReqVO; +import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderStatistics; import cn.iocoder.yudao.module.camera.dal.dataobject.order.OrderDO; +import cn.iocoder.yudao.module.camera.dal.entity.echarts.EChartsOption; +import cn.iocoder.yudao.module.camera.service.checklog.CheckLogService; import cn.iocoder.yudao.module.camera.service.order.OrderService; +import cn.iocoder.yudao.module.camera.service.stock.StockService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -22,6 +26,10 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAdjusters; import java.util.List; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; @@ -35,6 +43,11 @@ public class OrderController { @Resource private OrderService orderService; + @Resource + private CheckLogService checkLogService; + + @Resource + private StockService stockService; @PostMapping("/create") @Operation(summary = "创建随行记录") @@ -43,6 +56,45 @@ public class OrderController { return success(orderService.createOrder(createReqVO)); } + @PostMapping("/statistics") + @Operation(summary = "首页个数统计") + @PreAuthorize("@ss.hasPermission('logistics:order:statistics')") + public CommonResult statistics() { + // 获取当前日期 + LocalDate today = LocalDate.now(); +// 获取本月1号 + LocalDate firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth()); +// 设置时间为0点0分0秒 + LocalDateTime firstDayOfMonthStart = firstDayOfMonth.atStartOfDay(); +// 定义日期格式 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); +// 格式化日期为字符串 + String firstDayOfMonthStr = firstDayOfMonthStart.format(formatter); + OrderStatistics orderStatistics = new OrderStatistics(); + orderStatistics.setOrderCount(orderService.count(null,null)); + orderStatistics.setOrderMonthCount(orderService.count(firstDayOfMonthStr,null)); + orderStatistics.setCheckLogCount(checkLogService.count(null,null)); + orderStatistics.setCheckLogMonthCount(checkLogService.count(firstDayOfMonthStr,null)); + return success(orderStatistics); + } + + @PostMapping("/laneInventoryStatistics") + @Operation(summary = "首页巷道随行统计") + @PreAuthorize("@ss.hasPermission('logistics:order:laneInventoryStatistics')") + public CommonResult laneInventoryStatistics() { + EChartsOption bars = orderService.laneInventoryStatistics(); + return success(bars); + } + + @PostMapping("/laneInventoryLine") + @Operation(summary = "首页巷道随行折线图") + @PreAuthorize("@ss.hasPermission('logistics:order:laneInventoryLine')") + public CommonResult laneInventoryLine() { + EChartsOption bars = orderService.laneInventoryLine(); + return success(bars); + } + + @PutMapping("/update") @Operation(summary = "更新随行记录") @PreAuthorize("@ss.hasPermission('logistics:order:update')") diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/vo/OrderStatistics.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/vo/OrderStatistics.java new file mode 100644 index 0000000..2feb8f4 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/vo/OrderStatistics.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.camera.controller.admin.order.vo; + +import lombok.Data; + +@Data +public class OrderStatistics { + private Long orderCount; + private Long checkLogCount; + private Long checkLogMonthCount; + private Long orderMonthCount; +} diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/stock/StockController.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/stock/StockController.java index 898343d..2da8ff2 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/stock/StockController.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/stock/StockController.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.camera.dal.dataobject.resources.URLResourcesDo; import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO; import cn.iocoder.yudao.module.camera.dal.entity.ScanData; import cn.iocoder.yudao.module.camera.dal.entity.ScanStatus; +import cn.iocoder.yudao.module.camera.dal.entity.echarts.EChartsOption; import cn.iocoder.yudao.module.camera.service.checklog.CheckLogService; import cn.iocoder.yudao.module.camera.service.plc.PLCServiceImpl; import cn.iocoder.yudao.module.camera.service.resources.URLResourcesService; @@ -95,6 +96,13 @@ public class StockController { return success(stock); } + @PostMapping("/laneInventoryStatistics") + @Operation(summary = "首页巷道盘点统计") + @PreAuthorize("@ss.hasPermission('logistics:order:laneInventoryStatistics')") + public CommonResult laneInventoryStatistics() { + EChartsOption bars = stockService.laneInventoryStatistics(); + return success(bars); + } @Resource private DictDataService dictDataService; @@ -104,8 +112,8 @@ public class StockController { @PreAuthorize("@ss.hasPermission('logistics:stock:getStreetList')") public CommonResult> getStreetStatus(@RequestBody ScanData scanData) { List stockStreetList = stockService.list(new QueryWrapper() - .eq("street_Id", scanData.getStreetId()) - .eq("direction", scanData.getDirection())); + .eq(scanData.getStreetId()!=null,"street_Id", scanData.getStreetId()) + .eq(scanData.getDirection()!=null,"direction", scanData.getDirection())); Map dictValueMap = dictDataService.getDictValueMap("check_status"); List scanDataList = BeanUtils.toBean(stockStreetList, ScanData.class); for (ScanData scan:scanDataList){ diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Axis.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Axis.java new file mode 100644 index 0000000..8aba8d3 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Axis.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.camera.dal.entity.echarts; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class Axis { + private String type = "value"; + private boolean boundaryGap = true; + private int interval= 1; // 设置步长为 1 + private int splitNumber =5; + private List data = new ArrayList<>(); +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Bar.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Bar.java new file mode 100644 index 0000000..146c87d --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Bar.java @@ -0,0 +1,8 @@ +package cn.iocoder.yudao.module.camera.dal.entity.echarts; + +import lombok.Data; + +@Data +public class Bar extends Series{ + +} diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/EChartsOption.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/EChartsOption.java new file mode 100644 index 0000000..2582809 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/EChartsOption.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.camera.dal.entity.echarts; + +import lombok.Data; + +import java.util.List; + +@Data +public class EChartsOption { + private Axis xAxis; + private Axis yAxis; + private Legend legend; + private List series; +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Legend.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Legend.java new file mode 100644 index 0000000..3c416b7 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Legend.java @@ -0,0 +1,10 @@ +package cn.iocoder.yudao.module.camera.dal.entity.echarts; + +import lombok.Data; + +import java.util.List; + +@Data +public class Legend { + private List data; +} diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Series.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Series.java new file mode 100644 index 0000000..9b1bbe0 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/entity/echarts/Series.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.camera.dal.entity.echarts; + +import lombok.Data; + +import java.util.List; + +@Data +public class Series { + private String name; + private String type; + private String stack; + private String color; + private Label label; + private Emphasis emphasis; + private List data; + + @Data + public static class Label { + private boolean show = true; + } + + @Data + public static class Emphasis { + private String focus; + } +} diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/checklog/CheckLogService.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/checklog/CheckLogService.java index 5fa2312..f8becf4 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/checklog/CheckLogService.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/checklog/CheckLogService.java @@ -52,4 +52,5 @@ public interface CheckLogService extends IService { */ PageResult getCheckLogPage(CheckLogPageReqVO pageReqVO); + Long count(String startTime, String endTime); } \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/checklog/CheckLogServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/checklog/CheckLogServiceImpl.java index 1c7051c..f41491a 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/checklog/CheckLogServiceImpl.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/checklog/CheckLogServiceImpl.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.camera.service.resources.URLResourcesService; import cn.iocoder.yudao.module.camera.service.street.StreetService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import de.danielbechler.util.Strings; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -73,6 +74,13 @@ public class CheckLogServiceImpl extends ServiceImpl return checkLogMapper.selectById(id); } + @Override + public Long count(String startTime, String endTime) { + return checkLogMapper.selectCount(new QueryWrapper() + .ge(Strings.hasText(startTime),"create_time",startTime) + .le(Strings.hasText(endTime),"create_time",endTime)); + } + @Resource private URLResourcesService urlResourcesService; @Override diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderService.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderService.java index a1215ba..3f8e096 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderService.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderService.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderPageReqVO; import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderSaveReqVO; import cn.iocoder.yudao.module.camera.dal.dataobject.order.OrderDO; +import cn.iocoder.yudao.module.camera.dal.entity.echarts.EChartsOption; import jakarta.validation.Valid; /** @@ -52,4 +53,10 @@ public interface OrderService { */ PageResult getOrderPage(OrderPageReqVO pageReqVO); + + Long count(String startTime, String endTime); + + EChartsOption laneInventoryStatistics(); + + EChartsOption laneInventoryLine(); } \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java index ff2e7ec..eb7a47c 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.camera.dal.dataobject.order.OrderDO; import cn.iocoder.yudao.module.camera.dal.dataobject.sensorgun.SensorGunDO; import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO; import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO; +import cn.iocoder.yudao.module.camera.dal.entity.echarts.*; import cn.iocoder.yudao.module.camera.dal.mysql.order.OrderMapper; import cn.iocoder.yudao.module.camera.dal.mysql.sensorgun.SensorGunMapper; import cn.iocoder.yudao.module.camera.service.checklog.CheckLogService; @@ -19,12 +20,19 @@ import cn.iocoder.yudao.module.camera.service.street.StreetService; import cn.iocoder.yudao.module.camera.service.threeInOneCode.ScanningGun; import cn.iocoder.yudao.module.camera.service.threeInOneCode.SpecificationsAndOCR; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import de.danielbechler.util.Strings; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAdjusters; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.ORDER_NOT_EXISTS; @@ -149,4 +157,122 @@ public class OrderServiceImpl implements OrderService { return orderMapper.selectPage(pageReqVO); } + @Override + public Long count(String startTime, String endTime) { + return orderMapper.selectCount(new QueryWrapper() + .ge(Strings.hasText(startTime),"create_time",startTime) + .le(Strings.hasText(endTime),"create_time",endTime)); + } + + @Override + public EChartsOption laneInventoryStatistics() { + // 创建ECharts图表的配置对象 + EChartsOption eChartsOption = new EChartsOption(); + + // 创建X轴对象并设置其类型为"category",表示类别轴 + Axis xAxis = new Axis(); + xAxis.setType("category"); + // 将X轴配置添加到图表配置中 + eChartsOption.setXAxis(xAxis); + + // 初始化系列列表,用于存放多个数据系列 + List seriesList = new ArrayList<>(); + + // 获取街道列表 + List streets = streetService.list(); + + // 初始化数据序列对象,并设置其类型为"bar",表示柱状图 + Series series = new Series(); + series.setName("bar"); + series.setType("bar"); + // 获取当前日期 + LocalDate today = LocalDate.now(); +// 获取本月1号 + LocalDate firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth()); +// 设置时间为0点0分0秒 + LocalDateTime firstDayOfMonthStart = firstDayOfMonth.atStartOfDay(); +// 设置当前时间为23点59分59秒 + LocalDateTime nowEnd = today.atTime(23, 59, 59); + + // 获取订单列表 + List orderDOS = orderMapper.selectList(new QueryWrapper() + .ge("create_time", firstDayOfMonthStart) + .le("create_time", nowEnd)); + // 使用流处理,按srmNumber分组并计算每个组的数量,存储到Map中 + Map stocksMap = orderDOS.stream().collect(Collectors.groupingBy(OrderDO::getSrmNumber,Collectors.counting())); + List data = new ArrayList<>(); + xAxis.setData(new ArrayList<>()); + // 遍历街道列表,为X轴添加类别数据,并收集对应的数据到数据序列中 + for (StreetDO street : streets) { + xAxis.getData().add(street.getName()); + data.add(stocksMap.get(street.getPlcId())); + } + series.setData(data); + seriesList.add(series); + // 创建Y轴对象并设置其类型为"value",表示数值轴 + Axis yAxis = new Axis(); + yAxis.setType("value"); + // 将Y轴配置添加到图表配置中 + eChartsOption.setYAxis(yAxis); + + // 将数据序列添加到系列列表中 + eChartsOption.setSeries(seriesList); + return eChartsOption; + } + + @Override + public EChartsOption laneInventoryLine() { + EChartsOption eChartsOption = new EChartsOption(); + Axis xAxis = new Axis(); + xAxis.setType("category"); + xAxis.setBoundaryGap(false); + // 创建一个包含从今天开始前7天日期的列表 + List data = new ArrayList<>(); + LocalDate today = LocalDate.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + for (int i = 0; i < 7; i++) { + LocalDate date = today.minusDays(i); + data.add(date.format(formatter)); + } + xAxis.setData(data); + Axis yAxis = new Axis(); + yAxis.setType("value"); + eChartsOption.setYAxis(yAxis); + eChartsOption.setXAxis(xAxis); + List orderDOS = orderMapper.selectList(new QueryWrapper() + .ge("create_time",LocalDate.now().minusDays(7))); + + // 填充数据 + + // 根据srmNumber分组,然后根据create_time的日期字符串计算当天的订单数量 + Map> map = orderDOS.stream() + .collect(Collectors.groupingBy(OrderDO::getSrmNumber, + Collectors.groupingBy(order -> order.getCreateTime().toLocalDate().format(formatter), + Collectors.counting()))); + Legend legend = new Legend(); + List legendDate = new ArrayList<>(); + List streets = streetService.list(); +// 相关值 + List seriesList = new ArrayList<>(); + for (StreetDO street : streets) { + Series series = new Series(); + legendDate.add(street.getName()); + series.setName(street.getName()); + series.setType("line"); + series.setData(new ArrayList<>()); + seriesList.add(series); + for (String date : data) { + Map countMap = map.get(street.getPlcId()); + Long count = countMap != null ? countMap.get(date) : 0L; + series.getData().add(count); + } + } + legend.setData(legendDate); + eChartsOption.setLegend(legend); + eChartsOption.setSeries(seriesList); + + return eChartsOption; + } + } \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java index b649711..c28aec4 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java @@ -31,6 +31,7 @@ import cn.iocoder.yudao.module.camera.service.threeInOneCode.ScanningGun; import cn.iocoder.yudao.module.camera.util.PathUtil; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.module.system.service.dict.DictDataService; +import cn.iocoder.yudao.module.system.service.sse.SseClient; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import de.danielbechler.util.Strings; @@ -72,6 +73,8 @@ public class PLCServiceImpl implements PLCService { StockLogMapper stockLogMapper; @Resource CheckLogService checkLogService; + @Resource + SseClient sseClient; // public void gyrateCamera(KescEntity kescEntity ,String code){ // StreetDO street = streetService.getStreetByPlcId(kescEntity.getData().getSRMNumber()); diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/stock/StockService.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/stock/StockService.java index 9024a16..eb9921f 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/stock/StockService.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/stock/StockService.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.camera.controller.admin.stock.vo.StockPageReqVO; import cn.iocoder.yudao.module.camera.controller.admin.stock.vo.StockSaveReqVO; import cn.iocoder.yudao.module.camera.controller.admin.stock.vo.StockStreetList; import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO; +import cn.iocoder.yudao.module.camera.dal.entity.echarts.EChartsOption; import com.baomidou.mybatisplus.extension.service.IService; import jakarta.validation.Valid; @@ -54,4 +55,6 @@ public interface StockService extends IService< StockDO> { PageResult getStockPage(StockPageReqVO pageReqVO); StockStreetList getStreetList(StockStreetList stockSaveReqVO); + + EChartsOption laneInventoryStatistics(); } \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/stock/StockServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/stock/StockServiceImpl.java index cadf597..69ae7a8 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/stock/StockServiceImpl.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/stock/StockServiceImpl.java @@ -7,15 +7,21 @@ import cn.iocoder.yudao.module.camera.controller.admin.stock.vo.StockSaveReqVO; import cn.iocoder.yudao.module.camera.controller.admin.stock.vo.StockStreetList; import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO; import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO; +import cn.iocoder.yudao.module.camera.dal.entity.echarts.*; import cn.iocoder.yudao.module.camera.dal.mysql.stock.StockMapper; import cn.iocoder.yudao.module.camera.service.street.StreetService; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; +import cn.iocoder.yudao.module.system.service.dict.DictDataService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.STOCK_NOT_EXISTS; @@ -92,4 +98,56 @@ public class StockServiceImpl extends ServiceImpl implement return stockStreetList; } + @Resource + private DictDataService dictDataService; + @Override + public EChartsOption laneInventoryStatistics() { + EChartsOption eChartsOption = new EChartsOption(); + eChartsOption.setXAxis(new Axis()); + List bars = new ArrayList<>(); + List streets = streetService.list(); + List stocks = list(); + Map> stocksMap = stocks.stream().collect(Collectors.groupingBy(StockDO::getStatus,Collectors.groupingBy(StockDO::getStreetId,Collectors.counting()))); + Map dictDataMap = dictDataService.getDictDataList("check_status"); + Axis yAxis = new Axis(); + yAxis.setType("category"); + yAxis.setData(new ArrayList<>()); + for (StreetDO street : streets) { + yAxis.getData().add(street.getName()); + } + eChartsOption.setYAxis(yAxis); + for (String entry : dictDataMap.keySet()) { + Series bar = new Series(); + bar.setName(entry); + bar.setType("bar"); + bar.setStack("total"); + switch (Integer.parseInt(dictDataMap.get(entry).getValue())) { +// 未盘点 + case 0 -> bar.setColor("#fccc5c"); + +// 盘点异常 + case 1 -> bar.setColor("#ec6464"); + +// 盘点正确 + case 2 -> bar.setColor("#94cc74"); + +// 人工核对正确 + case 3 -> bar.setColor("#5474c4"); + default -> bar.setColor(""); + } + List values = new ArrayList<>(); + for (StreetDO street : streets) { + if (stocksMap.get(dictDataMap.get(entry).getValue())==null){ + values.add(null); + }else values.add(stocksMap.get(dictDataMap.get(entry).getValue()).get(street.getId())); + } + bar.setData(values); + bars.add(bar); + } + + eChartsOption.setSeries(bars); + + return eChartsOption; + } + } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/sse/SseController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/sse/SseController.java new file mode 100644 index 0000000..7e06bb4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/sse/SseController.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.system.controller.app.sse; + +import cn.hutool.core.util.IdUtil; +import cn.iocoder.yudao.module.system.service.sse.SseClient; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.security.PermitAll; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ui.ModelMap; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + + +@Tag(name = "管理后台 - sse") +@RestController +@RequestMapping("/sse") +@Validated +public class SseController { + @Autowired + private SseClient sseClient; + @GetMapping("/") + @PermitAll + public String index(ModelMap model) { + String uid = IdUtil.fastUUID(); + model.put("uid",uid); + return "index"; + } + + @CrossOrigin + @GetMapping("/createSse") + @PermitAll + public SseEmitter createConnect(String uid) { + return sseClient.createSse(uid); + } + @CrossOrigin + @GetMapping("/sendMsg") + @ResponseBody + @PermitAll + public String sseChat(String uid) { + for (int i = 0; i < 10; i++) { + sseClient.sendMessage(uid, "no"+i,IdUtil.fastUUID()); + } + return "ok"; + } + + /** + * 关闭连接 + */ + @CrossOrigin + @GetMapping("/closeSse") + public void closeConnect(String uid ){ + + sseClient.closeSse(uid); + } +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/sse/vo/SseVo.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/sse/vo/SseVo.java new file mode 100644 index 0000000..10538c5 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/sse/vo/SseVo.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.system.controller.app.sse.vo; + +import lombok.Data; + +@Data +public class SseVo { + private String message; + private String id; +// 随行order 盘点check + private String type; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sse/SseClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sse/SseClient.java new file mode 100644 index 0000000..ed94417 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sse/SseClient.java @@ -0,0 +1,131 @@ +package cn.iocoder.yudao.module.system.service.sse; + +import cn.hutool.core.util.StrUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import static org.bouncycastle.asn1.x500.style.RFC4519Style.uid; + +@Slf4j +@Component +public class SseClient { + private static final Map sseEmitterMap = new ConcurrentHashMap<>(); + + /** + * 创建连接 + */ + public SseEmitter createSse(String uid) { + //默认30秒超时,设置为0L则永不超时 + SseEmitter sseEmitter = new SseEmitter(0l); + //完成后回调 + sseEmitter.onCompletion(() -> { + log.info("[{}]结束连接...................", uid); + sseEmitterMap.remove(uid); + }); + //超时回调 + sseEmitter.onTimeout(() -> { + log.info("[{}]连接超时...................", uid); + }); + //异常回调 + sseEmitter.onError( + throwable -> { + try { + log.info("[{}]连接异常,{}", uid, throwable.toString()); + sseEmitter.send(SseEmitter.event() + .id(uid) + .name("发生异常!") + .data("发生异常请重试!") + .reconnectTime(3000)); + sseEmitterMap.put(uid, sseEmitter); + } catch (IOException e) { + e.printStackTrace(); + } + } + ); + try { + sseEmitter.send(SseEmitter.event().reconnectTime(5000)); + } catch (IOException e) { + e.printStackTrace(); + } + sseEmitterMap.put(uid, sseEmitter); + log.info("[{}]创建sse连接成功!", uid); + return sseEmitter; + } + + /** + * 给全部用户发送消息 + */ + public boolean sendMessage(Object message) { + + String uuid = UUID.randomUUID().toString(); + Collection sseEmitterCollection = sseEmitterMap.values(); + for (SseEmitter sseEmitter : sseEmitterCollection) { + try { + + if (sseEmitter == null) { + log.info("消息推送失败uid:[{}],没有创建连接,请重试。", uid); + return false; + } + sseEmitter.send(SseEmitter.event().id(uuid).reconnectTime(60 * 1000L).data(message)); + log.info("用户{},消息id:{},推送成功:{}", uid, uuid, message); + + } catch (Exception e) { + sseEmitterMap.remove(uid); + log.info("用户{},消息id:{},推送异常:{}", uid,uuid, e.getMessage()); + sseEmitter.complete(); + return false; + } + } + + return true; + } + + /** + * 给指定用户发送消息 + */ + public boolean sendMessage(String uid, String messageId, String message) { + if (StrUtil.isBlank(message)) { + log.info("参数异常,msg为null", uid); + return false; + } + SseEmitter sseEmitter = sseEmitterMap.get(uid); + if (sseEmitter == null) { + log.info("消息推送失败uid:[{}],没有创建连接,请重试。", uid); + return false; + } + try { + sseEmitter.send(SseEmitter.event().id(messageId).reconnectTime(1 * 60 * 1000L).data(message)); + log.info("用户{},消息id:{},推送成功:{}", uid, messageId, message); + return true; + } catch (Exception e) { + sseEmitterMap.remove(uid); + log.info("用户{},消息id:{},推送异常:{}", uid, messageId, e.getMessage()); + sseEmitter.complete(); + return false; + } + } + + /** + * 断开 + * + * @param uid + */ + public void closeSse(String uid) { + if (sseEmitterMap.containsKey(uid)) { + SseEmitter sseEmitter = sseEmitterMap.get(uid); + sseEmitter.complete(); + sseEmitterMap.remove(uid); + } else { + log.info("用户{} 连接已关闭", uid); + } + + } + +} diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java index a9e6908..7dbeb2c 100644 --- a/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java +++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java @@ -1,8 +1,12 @@ package cn.iocoder.yudao.server.controller; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import java.io.IOException; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED; @@ -15,6 +19,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @RestController public class DefaultController { + @RequestMapping("/admin-api/bpm/**") public CommonResult bpm404() { return CommonResult.error(NOT_IMPLEMENTED.getCode(),