自动化立体仓库 - WMS系统
zyh
13 小时以前 701542ac0a90cf0e3a0a81ec2bb8066b5de68e75
更新为正式部署许可证
5个文件已添加
50个文件已修改
2977 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/DigitalTwinController.java 1033 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/LocDetlController.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/LocMastController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/MesController.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/MobileController.java 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/OrderPakoutController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/OutController.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/RcsController.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/TaskController.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/CanFin.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/LocDetl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/Task.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/digitaltwin/AllLocationsVo.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/digitaltwin/DtDetainMatVo.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/digitaltwin/DtEquipmentVo.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesCallOutApply.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesMatInfo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesOutApply.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/TransParent.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/TransTask.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/AbnormalLocDetlParam.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/CombParam.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/rcs/RcsReporterTask.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/CanFinMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/DigitalTwinMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/DigitalTwinService.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/MesService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/MobileService.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/OrderPakoutService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/RcsService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/DigitalTwinServiceImpl.java 250 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MesServiceImpl.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/OrderPakoutServiceImpl.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/RcsServiceImpl.java 129 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/AGVTaskReportScheduler.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/BlockScheduler.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/ErrorStockScheduler.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/OrderSyncScheduler.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/WorkMastScheduler.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/AGVTaskReportHandler.java 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/AdminInterceptor.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/LogAspect.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/properties/StationProperties.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/service/CommonService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/WcsController.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/entity/license/LicenseCheckListener.java 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/timer/LoadingConfigTimer.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/license.lic 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/logback-spring.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/LocCountMapper.xml 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/ViewDigitalTwinMapper.xml 75 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/pakStore/groupinto.html 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/DigitalTwinController.java
@@ -1,25 +1,50 @@
package com.zy.asrs.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zy.asrs.entity.LocChartPie;
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.entity.digitaltwin.*;
import com.zy.asrs.mapper.LocDetlMapper;
import com.zy.asrs.mapper.ReportQueryMapper;
import com.zy.asrs.service.DigitalTwinService;
import com.zy.common.utils.HttpHandler;
import com.zy.common.web.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.core.type.TypeReference;
import javax.annotation.Resource;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RequestMapping("/digitalTwin")
@RestController
public class DigitalTwinController extends BaseController {
    @Value("${digitalTwins.jgUrl}")
    private String JG_URL;
    @Value("${digitalTwins.djUrl}")
    private String DJ_URL;
    @Value("${digitalTwins.ljqUrl}")
    private String LJQ_URL;
    @Resource
    private DigitalTwinService digitalTwinService;
    @Autowired
    ReportQueryMapper reportQueryMapper;
    @Autowired
    private LocDetlMapper locDetlMapper;
    /**
     * 数据总览
@@ -29,49 +54,232 @@
     */
    @RequestMapping(value = "/overview")
//    @ManagerAuth
    public R overview(@RequestParam(required = false) String areaId){
    public R overview(@RequestParam(required = false) String areaId) throws IOException {
        DtOverviewVo dtOverviewVo = digitalTwinService.overview(areaId);
        Map<String, Object> map = new HashMap<>();
        if (areaId != null) {
            map.put("areaId", areaId);
        }
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setPath("/digitalTwin/overview")
                .setParams(map);
//        DtOverviewVo dtOverviewVo = DtOverviewVo.builder()
//                .totalLoc(999)
//                .useLoc(900)
//                .idleLoc(99)
//                .todayOutbound(160)
//                .todayWarehousing(170)
//                .remainingStock(180)
//                .build();
        ObjectMapper objectMapper = new ObjectMapper();
        if (areaId != null) {
            switch (areaId) {
                case "A": {
                    String resA = builder.setUri(JG_URL).build().doGet();
        return R.ok().add(dtOverviewVo);
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    Map<String, Object> data = (Map<String, Object>) result.get("data");
                    return R.ok(data);
                }
                case "B": {
                    String resB = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resB, Map.class);
                    // 如果只需要data部分
                    Map<String, Object> data = (Map<String, Object>) result.get("data");
                    return R.ok(data);
                }
                case "C": {
                    String resC = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resC, Map.class);
                    // 如果只需要data部分
                    Map<String, Object> data = (Map<String, Object>) result.get("data");
                    return R.ok(data);
                }
                case "D": {
                    return R.ok(digitalTwinService.overview(areaId));
                }
                default:
                    Map<String, Object> mergedResult = new HashMap<>();
                    Map<String, Object> mergedData = new HashMap<>();
                    String resA = builder.setUri(JG_URL).build().doGet();
                    Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
                    if (resultA.get("data") != null) {
                        mergedData.put("A", resultA.get("data"));
                    }
                    String resB = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
                    if (resultB.get("data") != null) {
                        mergedData.put("B", resultB.get("data"));
                    }
                    String resC = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
                    if (resultC.get("data") != null) {
                        mergedData.put("C", resultC.get("data"));
                    }
                    Object resultD = digitalTwinService.overview(areaId);
                    if (resultD != null) {
                        mergedData.put("D", resultD);
                    }
                    return R.ok(mergedData);
            }
        } else {
            Map<String, Object> mergedResult = new HashMap<>();
            Map<String, Object> mergedData = new HashMap<>();
            String resA = builder.setUri(JG_URL).build().doGet();
            Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
            if (resultA.get("data") != null) {
                mergedData.put("A", resultA.get("data"));
            }
            String resB = builder.setUri(DJ_URL).build().doGet();
            Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
            if (resultB.get("data") != null) {
                mergedData.put("B", resultB.get("data"));
            }
            String resC = builder.setUri(LJQ_URL).build().doGet();
            Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
            if (resultC.get("data") != null) {
                mergedData.put("C", resultC.get("data"));
            }
            Object resultD = digitalTwinService.overview(areaId);
            if (resultD != null) {
                mergedData.put("D", resultD);
            }
            return R.ok(mergedData);
        }
    }
    /**
     * 近期订单(默认7天)
     *
     * @param areaId    库区编码
     * @param startDate 格式:yyyyMMdd,20251022
     * @param endDate   格式:yyyyMMdd,20251027
     * @return
     */
    @RequestMapping(value = "/recentOrder")
//    @ManagerAuth
    public R recentOrder(@RequestParam(required = false) String startDate,
                         @RequestParam(required = false) String endDate){
    public R recentOrder(@RequestParam(required = false) String areaId,
                         @RequestParam(required = false) String startDate,
                         @RequestParam(required = false) String endDate) throws IOException {
        List<DtOrderVo> orderVoList = digitalTwinService.order(startDate, endDate);
        Map<String, Object> map = new HashMap<>();
        if (areaId != null) {
            map.put("areaId", areaId);
        }
        if (startDate != null) {
            map.put("startDate", startDate);
        }
        if (endDate != null) {
            map.put("endDate", endDate);
        }
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setPath("/digitalTwin/recentOrder")
                .setParams(map);
//        DtOrderVo dtOrderVo = DtOrderVo.builder()
//                .orderDate("2025-10-22")
//                .orderNum(156)
//                .build();
//        DtOrderVo dtOrderVo2 = DtOrderVo.builder()
//                .orderDate("2025-10-23")
//                .orderNum(166)
//                .build();
//        List<DtOrderVo> orderVoList = new ArrayList<>();
//        orderVoList.add(dtOrderVo);
//        orderVoList.add(dtOrderVo2);
        ObjectMapper objectMapper = new ObjectMapper();
        if (areaId != null) {
            switch (areaId) {
                case "A": {
        return R.ok().add(orderVoList);
                    String resA = builder.setUri(JG_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "B": {
                    String resB = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resB, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "C": {
                    String resC = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resC, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "D": {
                    return R.ok(digitalTwinService.order(startDate, endDate));
                }
                default:
                    Map<String, Object> mergedResult = new HashMap<>();
                    Map<String, Object> mergedData = new HashMap<>();
                    String resA = builder.setUri(JG_URL).build().doGet();
                    Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
                    if (resultA.get("data") != null) {
                        mergedData.put("A", resultA.get("data"));
                    }
                    String resB = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
                    if (resultB.get("data") != null) {
                        mergedData.put("B", resultB.get("data"));
                    }
                    String resC = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
                    if (resultC.get("data") != null) {
                        mergedData.put("C", resultC.get("data"));
                    }
                    Object resultD = digitalTwinService.order(startDate, endDate);
                    if (resultD != null) {
                        mergedData.put("D", resultD);
                    }
                    return R.ok(mergedData);
            }
        } else {
            Map<String, Object> mergedResult = new HashMap<>();
            Map<String, Object> mergedData = new HashMap<>();
            String resA = builder.setUri(JG_URL).build().doGet();
            Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
            if (resultA.get("data") != null) {
                mergedData.put("A", resultA.get("data"));
            }
            String resB = builder.setUri(DJ_URL).build().doGet();
            Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
            if (resultB.get("data") != null) {
                mergedData.put("B", resultB.get("data"));
            }
            String resC = builder.setUri(LJQ_URL).build().doGet();
            Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
            if (resultC.get("data") != null) {
                mergedData.put("C", resultC.get("data"));
            }
            Object resultD = digitalTwinService.order(startDate, endDate);
            if (resultD != null) {
                mergedData.put("D", resultD);
            }
            return R.ok(mergedData);
        }
    }
    /**
@@ -86,23 +294,116 @@
//    @ManagerAuth
    public R recentIdleLoc(@RequestParam(required = false) String areaId,
                           @RequestParam(required = false) String startDate,
                         @RequestParam(required = false) String endDate){
                           @RequestParam(required = false) String endDate) throws IOException {
        List<DtLocVo> locVoList = digitalTwinService.recentLoc(areaId, startDate, endDate);
        Map<String, Object> map = new HashMap<>();
        if (areaId != null) {
            map.put("areaId", areaId);
        }
        if (startDate != null) {
            map.put("startDate", startDate);
        }
        if (endDate != null) {
            map.put("endDate", endDate);
        }
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setPath("/digitalTwin/recentIdleLoc")
                .setParams(map);
//        DtLocVo dtLocVo = DtLocVo.builder()
//                .locDate("2025-10-22")
//                .idleNum(208)
//                .build();
//        DtLocVo dtLocVo2 = DtLocVo.builder()
//                .locDate("2025-10-23")
//                .idleNum(177)
//                .build();
//        List<DtLocVo> locVoList = new ArrayList<>();
//        locVoList.add(dtLocVo);
//        locVoList.add(dtLocVo2);
        ObjectMapper objectMapper = new ObjectMapper();
        if (areaId != null) {
            switch (areaId) {
                case "A": {
        return R.ok().add(locVoList);
                    String resA = builder.setUri(JG_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "B": {
                    String resA = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "C": {
                    String resA = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "D": {
                    return R.ok(digitalTwinService.recentLoc(areaId, startDate, endDate));
                }
                default:
                    Map<String, Object> mergedResult = new HashMap<>();
                    Map<String, Object> mergedData = new HashMap<>();
                    String resA = builder.setUri(JG_URL).build().doGet();
                    Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
                    if (resultA.get("data") != null) {
                        mergedData.put("A", resultA.get("data"));
                    }
                    String resB = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
                    if (resultB.get("data") != null) {
                        mergedData.put("B", resultB.get("data"));
                    }
                    String resC = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
                    if (resultC.get("data") != null) {
                        mergedData.put("C", resultC.get("data"));
                    }
                    Object resultD = digitalTwinService.recentLoc(areaId, startDate, endDate);
                    if (resultD != null) {
                        mergedData.put("D", resultD);
                    }
                    return R.ok(mergedData);
            }
        } else {
            Map<String, Object> mergedResult = new HashMap<>();
            Map<String, Object> mergedData = new HashMap<>();
            String resA = builder.setUri(JG_URL).build().doGet();
            Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
            if (resultA.get("data") != null) {
                mergedData.put("A", resultA.get("data"));
            }
            String resB = builder.setUri(DJ_URL).build().doGet();
            Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
            if (resultB.get("data") != null) {
                mergedData.put("B", resultB.get("data"));
            }
            String resC = builder.setUri(LJQ_URL).build().doGet();
            Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
            if (resultC.get("data") != null) {
                mergedData.put("C", resultC.get("data"));
            }
            Object resultD = digitalTwinService.recentLoc(areaId, startDate, endDate);
            if (resultD != null) {
                mergedData.put("D", resultD);
            }
            return R.ok(mergedData);
        }
    }
    /**
@@ -116,27 +417,118 @@
    @RequestMapping(value = "/recentInAndOutBound")
//    @ManagerAuth
    public R recentInAndOutBound(@RequestParam(required = false) String areaId,
                           @RequestParam(required = false) String startDate,
                           @RequestParam(required = false) String endDate){
                                 @RequestParam(required = false) String startDate,
                                 @RequestParam(required = false) String endDate) throws ParseException, IOException {
        List<DtInAndOutBoundVo> inAndOutBoundVoList = digitalTwinService.inAndOutBound(areaId, startDate, endDate);
        Map<String, Object> map = new HashMap<>();
        if (areaId != null) {
            map.put("areaId", areaId);
        }
        if (startDate != null) {
            map.put("startDate", startDate);
        }
        if (endDate != null) {
            map.put("endDate", endDate);
        }
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setPath("/digitalTwin/recentInAndOutBound")
                .setParams(map);
        ObjectMapper objectMapper = new ObjectMapper();
        if (areaId != null) {
            switch (areaId) {
                case "A": {
//        DtInAndOutBoundVo dtInAndOutBoundVo = DtInAndOutBoundVo.builder()
//                .boundDate("2025-10-22")
//                .inBoundNum(237)
//                .outBoundNum(487)
//                .build();
//        DtInAndOutBoundVo dtInAndOutBoundVo2 = DtInAndOutBoundVo.builder()
//                .boundDate("2025-10-23")
//                .inBoundNum(187)
//                .outBoundNum(287)
//                .build();
//        List<DtInAndOutBoundVo> inAndOutBoundVoList = new ArrayList<>();
//        inAndOutBoundVoList.add(dtInAndOutBoundVo);
//        inAndOutBoundVoList.add(dtInAndOutBoundVo2);
                    String resA = builder.setUri(JG_URL).build().doGet();
        return R.ok().add(inAndOutBoundVoList);
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "B": {
                    String resA = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "C": {
                    String resA = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "D": {
                    return R.ok(digitalTwinService.inAndOutBound(areaId, startDate, endDate));
                }
                default:
                    Map<String, Object> mergedResult = new HashMap<>();
                    Map<String, Object> mergedData = new HashMap<>();
                    String resA = builder.setUri(JG_URL).build().doGet();
                    Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
                    if (resultA.get("data") != null) {
                        mergedData.put("A", resultA.get("data"));
                    }
                    String resB = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
                    if (resultB.get("data") != null) {
                        mergedData.put("B", resultB.get("data"));
                    }
                    String resC = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
                    if (resultC.get("data") != null) {
                        mergedData.put("C", resultC.get("data"));
                    }
                    Object resultD = digitalTwinService.inAndOutBound(areaId, startDate, endDate);
                    if (resultD != null) {
                        mergedData.put("D", resultD);
                    }
                    return R.ok(mergedData);
            }
        } else {
            // 如果没有提供areaId,默认调用本地服务
            Map<String, Object> mergedResult = new HashMap<>();
            Map<String, Object> mergedData = new HashMap<>();
            String resA = builder.setUri(JG_URL).build().doGet();
            Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
            if (resultA.get("data") != null) {
                mergedData.put("A", resultA.get("data"));
            }
            String resB = builder.setUri(DJ_URL).build().doGet();
            Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
            if (resultB.get("data") != null) {
                mergedData.put("B", resultB.get("data"));
            }
            String resC = builder.setUri(LJQ_URL).build().doGet();
            Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
            if (resultC.get("data") != null) {
                mergedData.put("C", resultC.get("data"));
            }
            Object resultD = digitalTwinService.inAndOutBound(areaId, startDate, endDate);
            if (resultD != null) {
                mergedData.put("D", resultD);
            }
            return R.ok(mergedData);
        }
    }
    /**
@@ -151,35 +543,121 @@
    public R recentDetainMat(@RequestParam(required = false) String areaId,
                             @RequestParam(required = false) Integer overDayNum,
                             @RequestParam(required = false) Integer pageIndex,
                             @RequestParam(required = false) Integer pageSize){
                             @RequestParam(required = false) Integer pageSize,
                             @RequestParam(required = false) String condition) throws IOException {
        List<DtDetainMatVo> detainMatVoList = digitalTwinService.recentDetainMat(areaId, overDayNum, pageIndex, pageSize);
        Map<String, Object> map = new HashMap<>();
        if (areaId != null) {
            map.put("areaId", areaId);
        }
        if (overDayNum != null) {
            map.put("overDayNum", overDayNum);
        }
        if (pageIndex != null) {
            map.put("pageIndex", pageIndex);
        }
        if (pageSize != null) {
            map.put("pageSize", pageSize);
        }
        if (condition != null) {
            map.put("condition", condition);
        }
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setPath("/digitalTwin/recentDetainMat")
                .setParams(map);
//        DtDetainMatVo dtDetainMatVo = DtDetainMatVo.builder()
//                .belongAreaId("A1")
//                .belongAreaName("刀具库")
//                .matId("mat10001")
//                .matName("道具把")
//                .lokId("loc1001")
//                .lokName("库位10001")
//                .detainTime(765)
//                .inBoundTime("2025-10-11T11:15:16")
//                .build();
//        DtDetainMatVo dtDetainMatVo2 = DtDetainMatVo.builder()
//                .belongAreaId("A1")
//                .belongAreaName("刀具库")
//                .matId("mat10002")
//                .matName("道具把")
//                .lokId("loc1002")
//                .lokName("库位10002")
//                .detainTime(665)
//                .inBoundTime("2025-10-10T11:15:16")
//                .build();
//        List<DtDetainMatVo> detainMatVoList = new ArrayList<>();
//        detainMatVoList.add(dtDetainMatVo);
//        detainMatVoList.add(dtDetainMatVo2);
        ObjectMapper objectMapper = new ObjectMapper();
        if (areaId != null) {
            switch (areaId) {
                case "A": {
                    String resA = builder.setUri(JG_URL).build().doGet();
        return R.ok().add(detainMatVoList);
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "B": {
                    String resA = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "C": {
                    String resA = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    // 如果只需要data部分
                    List data = (List) result.get("data");
                    return R.ok(data);
                }
                case "D": {
                    return R.ok(digitalTwinService.recentDetainMat(areaId, overDayNum, pageIndex, pageSize, condition));
                }
                default:
                    Map<String, Object> mergedResult = new HashMap<>();
                    Map<String, Object> mergedData = new HashMap<>();
                    String resA = builder.setUri(JG_URL).build().doGet();
                    Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
                    if (resultA.get("data") != null) {
                        mergedData.put("A", resultA.get("data"));
                    }
                    String resB = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
                    if (resultB.get("data") != null) {
                        mergedData.put("B", resultB.get("data"));
                    }
                    String resC = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
                    if (resultC.get("data") != null) {
                        mergedData.put("C", resultC.get("data"));
                    }
                    Object resultD = digitalTwinService.recentDetainMat(areaId, overDayNum, pageIndex, pageSize, condition);
                    if (resultD != null) {
                        mergedData.put("D", resultD);
                    }
                    return R.ok(mergedData);
            }
        } else {
            // 如果没有提供areaId,默认调用本地服务
            Map<String, Object> mergedResult = new HashMap<>();
            Map<String, Object> mergedData = new HashMap<>();
            String resA = builder.setUri(JG_URL).build().doGet();
            Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
            if (resultA.get("data") != null) {
                mergedData.put("A", resultA.get("data"));
            }
            String resB = builder.setUri(DJ_URL).build().doGet();
            Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
            if (resultB.get("data") != null) {
                mergedData.put("B", resultB.get("data"));
            }
            String resC = builder.setUri(LJQ_URL).build().doGet();
            Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
            if (resultC.get("data") != null) {
                mergedData.put("C", resultC.get("data"));
            }
            Object resultD = digitalTwinService.recentDetainMat(areaId, overDayNum, pageIndex, pageSize, condition);
            if (resultD != null) {
                mergedData.put("D", resultD);
            }
            return R.ok(mergedData);
        }
    }
    /**
@@ -190,37 +668,103 @@
     */
    @RequestMapping(value = "/equipment")
//    @ManagerAuth
    public R equipment(@RequestParam(required = false) String areaId){
    public R equipment(@RequestParam(required = false) String areaId) throws IOException {
        DtEquipmentVo dtDetainMatVo = DtEquipmentVo.builder()
                .equipmentId("eq1001")
                .equipmentName("堆垛机1")
                .equipmentType(1)
                .belongAreaId("A1")
                .belongAreaName("刀具库")
                .verticalSpeed(288)
                .horizontalSpeed(203)
                .voltage(48)
                .status(1)
                .operateMethod(1)
                .build();
        DtEquipmentVo dtDetainMatVo2 = DtEquipmentVo.builder()
                .equipmentId("eq1002")
                .equipmentName("堆垛机2")
                .equipmentType(1)
                .belongAreaId("A1")
                .belongAreaName("刀具库")
                .verticalSpeed(208)
                .horizontalSpeed(253)
                .voltage(48)
                .status(1)
                .operateMethod(1)
                .build();
        List<DtEquipmentVo> dtEquipmentVoList = new ArrayList<>();
        dtEquipmentVoList.add(dtDetainMatVo);
        dtEquipmentVoList.add(dtDetainMatVo2);
        Map<String, Object> map = new HashMap<>();
        map.put("areaId", areaId);
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setPath("/digitalTwin/equipment")
                .setParams(map);
        return R.ok().add(dtEquipmentVoList);
        ObjectMapper objectMapper = new ObjectMapper();
        if (areaId != null){
            switch (areaId) {
                case "A": {
                    String resA = builder.setUri(JG_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    DtEquipmentVo data = objectMapper.convertValue(result.get("data"), DtEquipmentVo.class);
                    // 如果只需要data部分
                    //DtEquipmentVo data = (DtEquipmentVo) result.get("data");
                    return R.ok(data);
                }
                case "B": {
                    String resA = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    DtEquipmentVo data = objectMapper.convertValue(result.get("data"), DtEquipmentVo.class);
                    // 如果只需要data部分
                    //DtEquipmentVo data = (DtEquipmentVo) result.get("data");
                    return R.ok(data);
                }
                case "C": {
                    String resA = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                    DtEquipmentVo data = objectMapper.convertValue(result.get("data"), DtEquipmentVo.class);
                    // 如果只需要data部分
                    //DtEquipmentVo data = (DtEquipmentVo) result.get("data");
                    return R.ok(data);
                }
                case "D": {
                    return R.ok(digitalTwinService.equipment(areaId));
                }
                default:
                    Map<String, Object> mergedResult = new HashMap<>();
                    Map<String, Object> mergedData = new HashMap<>();
                    String resA = builder.setUri(JG_URL).build().doGet();
                    Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
                    if (resultA.get("data") != null) {
                        mergedData.put("A", resultA.get("data"));
                    }
                    String resB = builder.setUri(DJ_URL).build().doGet();
                    Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
                    if (resultB.get("data") != null) {
                        mergedData.put("B", resultB.get("data"));
                    }
                    String resC = builder.setUri(LJQ_URL).build().doGet();
                    Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
                    if (resultC.get("data") != null) {
                        mergedData.put("C", resultC.get("data"));
                    }
                    Object resultD = digitalTwinService.equipment(areaId);
                    if (resultD != null) {
                        mergedData.put("D", resultD);
                    }
                    return R.ok(mergedData);
            }
        }else {
            Map<String, Object> mergedResult = new HashMap<>();
            Map<String, Object> mergedData = new HashMap<>();
            String resA = builder.setUri(JG_URL).build().doGet();
            Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
            if (resultA.get("data") != null) {
                mergedData.put("A", resultA.get("data"));
            }
            String resB = builder.setUri(DJ_URL).build().doGet();
            Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
            if (resultB.get("data") != null) {
                mergedData.put("B", resultB.get("data"));
            }
            String resC = builder.setUri(LJQ_URL).build().doGet();
            Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
            if (resultC.get("data") != null) {
                mergedData.put("C", resultC.get("data"));
            }
            Object resultD = digitalTwinService.equipment(areaId);
            if (resultD != null) {
                mergedData.put("D", resultD);
            }
            return R.ok(mergedData);
        }
    }
    /**
@@ -231,75 +775,202 @@
     */
    @RequestMapping(value = "/warehouseDetail")
//    @ManagerAuth
    public R warehouseDetail(@RequestParam(required = false) String areaId){
        List<DtLocDetailVo> dtLocDetailVoList = digitalTwinService.warehouseDetail(areaId);
    public R warehouseDetail(@RequestParam(required = false) String areaId) throws IOException {
        Map<String, Object> map = new HashMap<>();
        if (areaId != null) {
            map.put("areaId", areaId);
        }
        return R.ok().add(dtLocDetailVoList);
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setPath("/digitalTwin/warehouseDetail")
                .setParams(map);
        ObjectMapper objectMapper = new ObjectMapper();
        if (areaId != null) {
            switch (areaId) {
            case "A": {
                String resA = builder.setUri(JG_URL).build().doGet();
                Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                // 如果只需要data部分
                List data = (List) result.get("data");
                return R.ok(data);
            }
            case "B": {
                builder.setPath("/digitalTwin/warehouseDetail");
                String resA = builder.setUri(DJ_URL).build().doGet();
                Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                // 如果只需要data部分
                List data = (List) result.get("data");
                return R.ok(data);
            }
            case "C": {
                String resA = builder.setUri(LJQ_URL).build().doGet();
                Map<String, Object> result = objectMapper.readValue(resA, Map.class);
                // 如果只需要data部分
                List data = (List) result.get("data");
                return R.ok(data);
            }
            case "D": {
                return R.ok(digitalTwinService.warehouseDetail(areaId));
            }
            default:
                Map<String, Object> mergedResult = new HashMap<>();
                Map<String, Object> mergedData = new HashMap<>();
                String resA = builder.setUri(JG_URL).build().doGet();
                Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
                if (resultA.get("data") != null) {
                    mergedData.put("A", resultA.get("data"));
                }
                String resB = builder.setUri(DJ_URL).build().doGet();
                Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
                if (resultB.get("data") != null) {
                    mergedData.put("B", resultB.get("data"));
                }
                String resC = builder.setUri(LJQ_URL).build().doGet();
                Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
                if (resultC.get("data") != null) {
                    mergedData.put("C", resultC.get("data"));
                }
                Object resultD = digitalTwinService.warehouseDetail(areaId);
                if (resultD != null) {
                    mergedData.put("D", resultD);
                }
                return R.ok(mergedData);
        }
        } else {
            // 如果没有提供areaId,默认调用本地服务
            Map<String, Object> mergedResult = new HashMap<>();
            Map<String, Object> mergedData = new HashMap<>();
            String resA = builder.setUri(JG_URL).build().doGet();
            Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
            if (resultA.get("data") != null) {
                mergedData.put("A", resultA.get("data"));
            }
            String resB = builder.setUri(DJ_URL).build().doGet();
            Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
            if (resultB.get("data") != null) {
                mergedData.put("B", resultB.get("data"));
            }
            String resC = builder.setUri(LJQ_URL).build().doGet();
            Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
            if (resultC.get("data") != null) {
                mergedData.put("C", resultC.get("data"));
            }
            Object resultD = digitalTwinService.warehouseDetail(areaId);
            if (resultD != null) {
                mergedData.put("D", resultD);
            }
            return R.ok(mergedData);
        }
    }
//        List<DtLocDetailVo> dtLocDetailVoList = new ArrayList<>();
//        DtLocDetailVo dtLocDetailVo = new DtLocDetailVo();
//        dtLocDetailVo.setLocNo("CA0100202");
//        dtLocDetailVo.setLocSts("O");
//        dtLocDetailVo.setAreaId(10010L);
//        dtLocDetailVo.setAreaName("刀具库");
//        dtLocDetailVo.setRow1(1);
//        dtLocDetailVo.setBay1(2);
//        dtLocDetailVo.setLev1(2);
//
//        LocMast locMast = new LocMast();
//        locMast.setLocNo("CA0100202");
//        locMast.setLocSts("O");
//        locMast.setRow1(1);
//        locMast.setBay1(2);
//        locMast.setLev1(2);
//        dtLocDetailVo.setLocMast(locMast);
//
//        LocDetl locDetl = new LocDetl();
//        locDetl.setLocNo("CA0100202");
//        locDetl.setAreaId(10010L);
//        locDetl.setAreaName("刀具库");
//        locDetl.setMatnr("mat10001");
//        locDetl.setMaktx("刀把");
//        dtLocDetailVo.setLocDetl(locDetl);
//        dtLocDetailVoList.add(dtLocDetailVo);
//
//
//        DtLocDetailVo dtLocDetailVo2 = new DtLocDetailVo();
//        dtLocDetailVo2.setLocNo("CA0100202");
//        dtLocDetailVo2.setLocSts("O");
//        dtLocDetailVo2.setAreaId(10010L);
//        dtLocDetailVo2.setAreaName("刀具库");
//        dtLocDetailVo2.setRow1(1);
//        dtLocDetailVo2.setBay1(2);
//        dtLocDetailVo2.setLev1(2);
//
//        LocMast locMast2 = new LocMast();
//        locMast2.setLocNo("CA0100203");
//        locMast2.setLocSts("O");
//        locMast2.setRow1(1);
//        locMast2.setBay1(2);
//        locMast2.setLev1(3);
//        dtLocDetailVo2.setLocMast(locMast2);
//
//        LocDetl locDetl2 = new LocDetl();
//        locDetl2.setLocNo("CA0100203");
//        locDetl2.setAreaId(10010L);
//        locDetl2.setAreaName("刀具库");
//        locDetl2.setMatnr("mat10001");
//        locDetl2.setMaktx("刀把");
//        dtLocDetailVo2.setLocDetl(locDetl2);
//        dtLocDetailVoList.add(dtLocDetailVo2);
//
//
////        LocDetl locDetl2 = new LocDetl();
////        locDetl2.setLocNo("1001");
////        locDetl2.setAreaId(10010L);
////        locDetl2.setAreaName("刀具库");
////        locDetl2.setMatnr("mat10001");
////        locDetl2.setMaktx("刀把");
////
//////        List<LocDetl> locDetlList = new ArrayList<>();
//////        locDetlList.add(locDetl);
//////        locDetlList.add(locDetl2);
    /**
     * 查询所有库位状态和物料-二机床信息化数字孪生用
     */
    @RequestMapping(value = "/getAllLocations")
    public R getAllLocations() throws IOException {
        Map<String, Object> mergedData = new HashMap<>();
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setPath("/digitalTwin/getAllLocations");
        ObjectMapper objectMapper = new ObjectMapper();
        String resA = builder.setUri(JG_URL).build().doGet();
        Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
        if (resultA.get("data") != null) {
            mergedData.put("A", resultA.get("data"));
        }
        String resB = builder.setUri(DJ_URL).build().doGet();
        Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
        if (resultB.get("data") != null) {
            mergedData.put("B", resultB.get("data"));
        }
        String resC = builder.setUri(LJQ_URL).build().doGet();
        Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
        if (resultC.get("data") != null) {
            mergedData.put("C", resultC.get("data"));
        }
        mergedData.put("D",digitalTwinService.getAllLocations());
        return R.ok(mergedData);
    }
    /**
     * 查询所有库的库位利用率
     */
    @RequestMapping(value = "/getLocalInfo")
    public R getLocalInfo() throws IOException {
        Map<String, Object> mergedData = new HashMap<>();
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setPath("/digitalTwin/getLocalInfo");
        ObjectMapper objectMapper = new ObjectMapper();
        String resA = builder.setUri(JG_URL).build().doGet();
        Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
        mergedData.put("A", resultA);
        String resB = builder.setUri(DJ_URL).build().doGet();
        Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
        mergedData.put("B", resultB);
        String resC = builder.setUri(LJQ_URL).build().doGet();
        Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
        mergedData.put("C", resultC);
        LocChartPie locUseRate = reportQueryMapper.getLocUseRate();
        mergedData.put("D", locUseRate);
        return R.ok(mergedData);
    }
    /**
     * 查询所有库的库存明细
     */
    @RequestMapping(value = "/getLocalDetal")
    public R getLocalDetal() throws IOException {
        Map<String, Object> mergedData = new HashMap<>();
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setPath("/digitalTwin/getLocalDetal");
        ObjectMapper objectMapper = new ObjectMapper();
        String resA = builder.setUri(JG_URL).build().doGet();
        Map<String, Object> resultA = objectMapper.readValue(resA, Map.class);
        if (resultA.get("data") != null) {
            mergedData.put("A", resultA.get("data"));
        }
        String resB = builder.setUri(DJ_URL).build().doGet();
        Map<String, Object> resultB = objectMapper.readValue(resB, Map.class);
        if (resultB.get("data") != null) {
            mergedData.put("B", resultB.get("data"));
        }
        String resC = builder.setUri(LJQ_URL).build().doGet();
        Map<String, Object> resultC = objectMapper.readValue(resC, Map.class);
        if (resultC.get("data") != null) {
            mergedData.put("C", resultC.get("data"));
        }
        List<Map<String, Object>> detalList = digitalTwinService.getLocalDetal();
        mergedData.put("D", detalList);
        return R.ok(mergedData);
    }
}
src/main/java/com/zy/asrs/controller/LocDetlController.java
@@ -298,38 +298,48 @@
        List<LocDetl> list = locDetlService.selectList(wrapper);
        List<AbnormalLocDetlParam> result = new ArrayList<>();
        Page<LocDetl> groupLocDetl = locDetlService.getStockStatis2(toPage(1, 10000, param, LocDetl.class));
        for (LocDetl locDetl : groupLocDetl.getRecords()) {
        // 使用完整的明细数据,而不是分组数据
        for (LocDetl locDetl : list) {
            AbnormalLocDetlParam abnormalLocDetlParam = new AbnormalLocDetlParam();
            Mat mat = matService.selectOne(new EntityWrapper<Mat>()
                    .eq("matnr", locDetl.getMatnr()));
            if (Cools.isEmpty(mat)) {
                continue;
            }
            if (!Cools.isEmpty(mat                                                                          .getStoreMax()) || !Cools.isEmpty(mat.getStoreMin())) {
                abnormalLocDetlParam.setStoreMax(mat.getStoreMax());
                abnormalLocDetlParam.setStoreMaxDate(mat.getStoreMaxDate());
                abnormalLocDetlParam.setStoreMin(mat.getStoreMin());
                abnormalLocDetlParam.setAnfme(locDetl.getAnfme());
                abnormalLocDetlParam.setMaktx(mat.getMaktx());
                abnormalLocDetlParam.setMatnr(mat.getMatnr());
                abnormalLocDetlParam.setSpecs(mat.getSpecs());
                abnormalLocDetlParam.setBatch(locDetl.getBatch());
//                SimpleDateFormat simple = new SimpleDateFormat("yyyyMMdd");
//                Date maxDate = simple.parse(locDetl.getBatch());
//                long time = maxDate.getTime();
//                Date now = new Date();
//                long time1 = now.getTime();
//                abnormalLocDetlParam.setNowTime((int) ((time1 - time) / (1000 * 60 * 60 * 24)));
            // 设置基本信息(无论是否异常)
            abnormalLocDetlParam.setStoreMax(mat.getStoreMax());
            abnormalLocDetlParam.setStoreMaxDate(mat.getStoreMaxDate());
            abnormalLocDetlParam.setStoreMin(mat.getStoreMin());
            abnormalLocDetlParam.setAnfme(locDetl.getAnfme());
            abnormalLocDetlParam.setMaktx(mat.getMaktx());
            abnormalLocDetlParam.setMatnr(mat.getMatnr());
            abnormalLocDetlParam.setSpecs(mat.getSpecs());
            abnormalLocDetlParam.setBatch(locDetl.getBatch());
                if (!Cools.isEmpty(mat.getStoreMax()) && locDetl.getAnfme() > mat.getStoreMax()) {
                    result.add(abnormalLocDetlParam);
                } else if (!Cools.isEmpty(mat.getStoreMin()) && locDetl.getAnfme() < mat.getStoreMin()) {
                    result.add(abnormalLocDetlParam);
                }
            // 设置导出需要的其他字段
            abnormalLocDetlParam.setLocNo(locDetl.getLocNo());
            abnormalLocDetlParam.setZpallet(locDetl.getZpallet());
            abnormalLocDetlParam.setOrderNo(locDetl.getOrderNo());
            abnormalLocDetlParam.setModiTime(locDetl.getModiTime());
            // 计算库龄(实际在库天数)
            if (locDetl.getAppeTime() != null) {
                long diff = System.currentTimeMillis() - locDetl.getAppeTime().getTime();
                int days = (int) (diff / (1000 * 60 * 60 * 24));
                abnormalLocDetlParam.setNowTime(days);
            }
            // 确保所有字段都有值,避免空值导致导出异常
            if (abnormalLocDetlParam.getLocNo() == null) abnormalLocDetlParam.setLocNo("");
            if (abnormalLocDetlParam.getZpallet() == null) abnormalLocDetlParam.setZpallet("");
            if (abnormalLocDetlParam.getOrderNo() == null) abnormalLocDetlParam.setOrderNo("");
            if (abnormalLocDetlParam.getSpecs() == null) abnormalLocDetlParam.setSpecs("");
            // 总是添加到结果列表
            result.add(abnormalLocDetlParam);
        }
        return R.ok(exportSupport(result, fields));
    }
src/main/java/com/zy/asrs/controller/LocMastController.java
@@ -365,8 +365,8 @@
                locNoStr = split[1];
                picPath += "_" + locNoStr;
            }
            picList.add("http://" + WCS_URL + "/image/" + picPath + "-1.jpg");
            picList.add("http://" + WCS_URL + "/image/" + picPath + "-2.jpg");
            picList.add("http://172.26.4.184:8080//" + picPath + ".jpg.jpg");
            picList.add("http://172.26.4.184:8080//" + picPath + ".jpg.jpg");
            LocPicDto locPicDto = new LocPicDto();
            locPicDto.setLocNo(locNoStr);
src/main/java/com/zy/asrs/controller/MesController.java
@@ -1,23 +1,39 @@
package com.zy.asrs.controller;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.core.annotations.AppAuth;
import com.core.annotations.ManagerAuth;
import com.core.common.Cools;
import com.core.common.R;
import com.core.exception.CoolException;
import com.zy.asrs.entity.mes.*;
import com.zy.asrs.entity.param.CombParam;
import com.zy.asrs.service.MesService;
import com.zy.asrs.service.MobileService;
import com.zy.asrs.service.impl.RcsServiceImpl;
import com.zy.common.web.BaseController;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
@RestController
@Slf4j
public class MesController extends BaseController {
    // 海康RCS地址
    @Value("${hik.url}")
    private String HIK_URL;
    @Autowired
    private MobileService mobileService;
    @Resource
    private MesService mesService;
@@ -29,11 +45,15 @@
    // 物料信息同步
    @PostMapping("/api/mes/synMatInfo")
    @AppAuth(memo = "物料信息同步")
    public MesReturn synMatInfo(@RequestHeader(required = false) String appkey,@RequestBody MesMatRecvForm param, HttpServletRequest request){
        auth(appkey, param, request);
    //public MesReturn synMatInfo(@RequestHeader(required = false) String appkey, @RequestBody List<MesMatRecvForm> params, HttpServletRequest request){
    public MesReturn synMatInfo(@RequestHeader(required = false) String appkey, @RequestBody MesMatRecvForm params, HttpServletRequest request){
        auth(appkey, params, request);
        MesReturn mesReturn = new MesReturn();
        try {
            mesReturn = mesService.matInfoAndInBound(param);
//            for (MesMatRecvForm param : params){
//                mesReturn = mesService.matInfoAndInBound(param);
//            }
            mesReturn = mesService.matInfoAndInBound(params);
        } catch (Exception e) {
            mesReturn.setSuccess("2");
            mesReturn.setMessage("物料信息同步失败");
@@ -118,4 +138,45 @@
        return mesService.queryInventory(itemno,orderNo);
    }
    /**
     * MES调用PDA的AGV订单入库接口
     * @param combParam
     * @return
     */
    @RequestMapping("/comb/auth")
    @ManagerAuth(memo = "组托")
    public R comb(@RequestBody CombParam combParam){
        log.info("=============== MES下发组托订单 ===============");
        log.info("{}", combParam);
        log.info("=============== MES下发组托订单 ===============");
        if (combParam.getUserId() != null && !combParam.getUserId().equals(null)){
            mobileService.comb(combParam, combParam.getUserId());
        }else {
            mobileService.comb(combParam, getUserId());
        }
        return R.ok("组托成功");
    }
    @PostMapping("/api/mes/pauseAGV")
    public MesReturn AGVPause(@RequestBody JSONObject param){
        MesReturn mesReturn = new MesReturn();
        int AGVType;
        if (param.containsKey("zoneCode")){
            param.put("mapCode", "BB");
            param.put("invoke", "BLOCKADE");
            AGVType = 1;
        }else {
            AGVType = 2;
        }
        if (mesService.AGVPause(param, AGVType) == 1){
            mesReturn.setSuccess("1");
            mesReturn.setMessage("成功");
            return mesReturn;
        }else {
            mesReturn.setSuccess("2");
            mesReturn.setMessage("失败");
            return mesReturn;
        }
    }
}
src/main/java/com/zy/asrs/controller/MobileController.java
@@ -12,6 +12,7 @@
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.*;
import com.zy.asrs.entity.result.MobileAdjustResult;
import com.zy.asrs.mapper.CanFinMapper;
import com.zy.asrs.mapper.ManLocDetlMapper;
import com.zy.asrs.service.*;
import com.zy.asrs.service.impl.OrderDetlPakinServiceImpl;
@@ -63,6 +64,8 @@
    private ManLocDetlMapper manLocDetlMapper;
    @Autowired
    private WrkDetlLogService wrkDetlLogService;
    @Autowired
    private CanFinMapper canFinMapper;
    @Resource
    private StaDescService staDescService;
@@ -555,7 +558,8 @@
    @PostMapping("/callEmptyBinOutBound")
    @ManagerAuth(memo = "pda呼叫空料框出库")
    public synchronized R callEmptyBinOutBound(@RequestParam(required = false) String locNo
            , @RequestParam(required = false) String size) {
            , @RequestParam(required = false) String size
            , @RequestParam(required = false) String agvTaskNo) {
        if (Cools.isEmpty(locNo) || Cools.isEmpty(size)) {
            return R.error("站点或者大小不能为空");
        }
@@ -563,7 +567,7 @@
        if (wrkMast != null) {
            return R.error("该站点="+locNo+"已经有空板出库任务,为了不堵塞堆垛机接驳站点,禁止下发多个空板出库任务");
        }
        return mobileService.callEmptyBinOutBound(locNo,size,getUserId());
        return mobileService.callEmptyBinOutBound(locNo,size,getUserId(), agvTaskNo);
    }
    /**
@@ -619,7 +623,14 @@
                .setAppeTime(date)
                .setModiUser(9945L)
                .setModiTime(date);
        if (!taskService.insert(task)) {
        if (taskService.insert(task)) {
            Date now = new Date();
            CanFin canFin = new CanFin();
            canFin.setAgvType("agv-in");
            canFin.setInNo(TaskNo);
            canFin.setApplyTime(now);
            canFinMapper.insert(canFin);
        }else{
            throw new CoolException("保存工作档失败");
        }
@@ -652,20 +663,26 @@
    @RequestMapping("/orderOut")
    public synchronized R AGVOrderOutReturn() {
        List<OrderPakout> settle = orderPakoutService.selectList(new EntityWrapper<OrderPakout>().in("settle", 1, 2).eq("doc_type",11));
        List<OrderPakout> settle = orderPakoutService.selectList(new EntityWrapper<OrderPakout>().in("settle", 1, 2).eq("doc_type", 11));
        List<String> list = new ArrayList<>();
        for (OrderPakout orderPakout: settle) {
            if (orderPakout.getSettle()==2){
                List<OrderDetlPakout> orderId = orderDetlPakoutService.selectList(new EntityWrapper<OrderDetlPakout>().eq("order_id", orderPakout.getId()));
                Boolean boo=true;
                for (OrderDetlPakout orderDetlPakout: orderId) {
                    if (orderDetlPakout.getAnfme()>orderDetlPakout.getWorkQty()){
                        boo=false;
        // 使用迭代器遍历,可以安全删除
        Iterator<OrderPakout> iterator = settle.iterator();
        while (iterator.hasNext()) {
            OrderPakout orderPakout = iterator.next();
            if (orderPakout.getSettle() == 2) {
                List<OrderDetlPakout> orderId = orderDetlPakoutService.selectList(
                        new EntityWrapper<OrderDetlPakout>().eq("order_id", orderPakout.getId()));
                Boolean boo = true;
                for (OrderDetlPakout orderDetlPakout : orderId) {
                    if (orderDetlPakout.getAnfme() > orderDetlPakout.getWorkQty()) {
                        boo = false;
                        break;
                    }
                }
                if (boo) {
                    settle.remove(orderPakout);
                    iterator.remove();  // 使用迭代器的remove方法
                }else {
                    list.add(orderPakout.getOrderNo());
                }
src/main/java/com/zy/asrs/controller/OrderPakoutController.java
@@ -10,6 +10,7 @@
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.OrderDomainParam;
import com.zy.asrs.entity.result.WrkTraceVo;
import com.zy.asrs.mapper.CanFinMapper;
import com.zy.asrs.service.*;
import com.zy.common.model.DetlDto;
import com.zy.common.web.BaseController;
@@ -42,6 +43,8 @@
    private WrkMastService wrkMastService;
    @Autowired
    private WrkMastLogService wrkMastLogService;
    @Autowired
    private CanFinMapper canFinMapper;
    @RequestMapping(value = "/order/nav/list/auth")
    @ManagerAuth
@@ -375,6 +378,27 @@
    @ManagerAuth(memo = "手动删除订单")
    @Transactional
    public R delete(@RequestParam Long orderId){
        OrderPakout orderPakout = orderService.selectOne(new EntityWrapper<OrderPakout>()
                .eq("id", orderId));
        CanFin deleteCanFin = new CanFin();
        deleteCanFin.setOutNo(orderPakout.getOrderNo());
        List<CanFin> canFinList = canFinMapper.selectList(new EntityWrapper<CanFin>()
                .orderBy("apply_time", true)
                .isNotNull("out_no"));
        if (!canFinList.isEmpty()){
            for (CanFin canFin : canFinList){
                if (canFin.getOutNo().equals(deleteCanFin.getOutNo())){
                    canFinMapper.deleteById(canFin.getId());
                }
            }
        }
        List<CanFin> newCanFinList = canFinMapper.selectList(new EntityWrapper<CanFin>()
                .orderBy("apply_time", true));
        if (!newCanFinList.isEmpty()){
            CanFin firstCanFin = newCanFinList.get(0);
            firstCanFin.setTaskStatus("canout");
            canFinMapper.updateById(firstCanFin);
        }
        orderService.remove(orderId);
//        Order order = orderService.selectById(orderId);
//        if (order != null) {
src/main/java/com/zy/asrs/controller/OutController.java
@@ -312,7 +312,8 @@
                    }});
                    String agvSta = "";
                    if (locMast.getLocType3() == 2) {
                        agvSta = "Z-LZP26";
                    }else if (locType == 2){
                    } else {
                        agvSta = orderPakout.getCstmrName();//agv目标站点位置
                    }
@@ -378,16 +379,17 @@
                }
            }
            if (issued > 0) {
                LocDto locDto = new LocDto(null, orderDetl.getMatnr(), orderDetl.getMaktx(), orderDetl.getBatch(), orderDetl.getOrderNo(), issued);
                locDto.setBrand(orderDetl.getBrand());
                locDto.setStandby1(orderDetl.getStandby1());
                locDto.setStandby2(orderDetl.getStandby2());
                locDto.setStandby3(orderDetl.getStandby3());
                locDto.setBoxType1(orderDetl.getBoxType1());
                locDto.setBoxType2(orderDetl.getBoxType2());
                locDto.setBoxType3(orderDetl.getBoxType3());
                locDto.setLack(Boolean.TRUE);
                locDtos.add(locDto);
//                LocDto locDto = new LocDto(null, orderDetl.getMatnr(), orderDetl.getMaktx(), orderDetl.getBatch(), orderDetl.getOrderNo(), issued);
//                locDto.setBrand(orderDetl.getBrand());
//                locDto.setStandby1(orderDetl.getStandby1());
//                locDto.setStandby2(orderDetl.getStandby2());
//                locDto.setStandby3(orderDetl.getStandby3());
//                locDto.setBoxType1(orderDetl.getBoxType1());
//                locDto.setBoxType2(orderDetl.getBoxType2());
//                locDto.setBoxType3(orderDetl.getBoxType3());
//                locDto.setLack(Boolean.TRUE);
//                locDtos.add(locDto);
                return R.error("库存不足");
            }
        }
        R pakout = pakout(locDtos);
src/main/java/com/zy/asrs/controller/RcsController.java
@@ -23,7 +23,6 @@
    // 反馈任务执行结果
    @PostMapping("/api/robot/reporter/task")
    public RcsReturn reporterTask(@RequestBody RcsReporterTask param){
        return rcsService.reporterTask(param);
    }
@@ -41,4 +40,12 @@
        return rcsService.hxApplyInLine(param);
    }
    // 华晓AGV离开人员入侵检测区域
    @PostMapping("/api/robot/apply/station")
    public RcsReturn hxOutStation(@RequestBody TransParent param){
        return rcsService.hxOutStation(param);
    }
}
src/main/java/com/zy/asrs/controller/TaskController.java
@@ -6,7 +6,9 @@
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.core.common.DateUtils;
import com.zy.asrs.entity.CanFin;
import com.zy.asrs.entity.Task;
import com.zy.asrs.mapper.CanFinMapper;
import com.zy.asrs.service.TaskService;
import com.core.annotations.ManagerAuth;
import com.core.common.BaseRes;
@@ -23,6 +25,8 @@
    @Autowired
    private TaskService taskService;
    @Autowired
    private CanFinMapper canFinMapper;
    @RequestMapping(value = "/task/{id}/auth")
    @ManagerAuth
@@ -99,6 +103,29 @@
            taskService.completeWrkMast(workNo, getUserId());
            return R.ok("工作档已完成");
        } else if (type == 2) {
            Task task = taskService.selectOne(new EntityWrapper<Task>()
                    .eq("wrk_no", workNo));
            if (task != null){
                CanFin deleteCanFin = new CanFin();
                deleteCanFin.setInNo(task.getTaskNo());
                List<CanFin> canFinList = canFinMapper.selectList(new EntityWrapper<CanFin>()
                        .orderBy("apply_time", true)
                        .isNotNull("in_no"));
                if (!canFinList.isEmpty()){
                    for (CanFin canFin : canFinList){
                        if (canFin.getInNo().equals(deleteCanFin.getInNo())){
                            canFinMapper.deleteById(canFin.getId());
                        }
                    }
                }
                List<CanFin> newCanFinList = canFinMapper.selectList(new EntityWrapper<CanFin>()
                        .orderBy("apply_time", true));
                if (!newCanFinList.isEmpty()){
                    CanFin firstCanFin = newCanFinList.get(0);
                    firstCanFin.setTaskStatus("canout");
                    canFinMapper.updateById(firstCanFin);
                }
            }
            taskService.cancelWrkMast(workNo, getUserId());
            return R.ok("工作档已取消");
        } else if (type == 3) {
src/main/java/com/zy/asrs/entity/CanFin.java
New file
@@ -0,0 +1,65 @@
package com.zy.asrs.entity;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@TableName("can_fin")
public class CanFin {
    /**
     * 主键编号
     */
    @ApiModelProperty(value= "主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 入库单号
    */
    @TableField("in_no")
    private String inNo;
    /**
     * 出库号
     * */
    @TableField("out_no")
    private String outNo;
    /**
     * 插入时间
     */
    @TableField("apply_time")
    private Date applyTime;
    /**
     * 任务类型
     */
    @TableField("task_type")
    private String taskType;
    /**
     * 任务状态
     */
    @TableField("task_status")
    private String taskStatus;
    /**
     * 出库类型
     */
    @TableField("out_type")
    private String outType;
    /**
     * agv类型
     */
    @TableField("agv_type")
    private String agvType;
}
src/main/java/com/zy/asrs/entity/LocDetl.java
@@ -43,6 +43,7 @@
    private String locNo;
    @ApiModelProperty("area_id")
    @TableField("area_id")
    private Long areaId;
    @ApiModelProperty("area_name")
src/main/java/com/zy/asrs/entity/Task.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.annotations.TableField;
import com.core.common.SpringUtils;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.zy.asrs.service.*;
import com.zy.system.entity.User;
import com.zy.system.service.UserService;
@@ -344,6 +345,13 @@
    @TableField("task_no")
    private String taskNo;
    /**
     * 是否是pda发的
     */
    @ApiModelProperty(value= "是否是PDA发的任务")
    @TableField("is_PDA")
    private String isPda;
    public Task() {}
    public String getYmd$(){
src/main/java/com/zy/asrs/entity/digitaltwin/AllLocationsVo.java
New file
@@ -0,0 +1,36 @@
package com.zy.asrs.entity.digitaltwin;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
 * @author pang.jiabao
 * @description 查询所有库位状态和物料-二机床信息化数字孪生用
 * @createDate 2026/1/26 11:13
 */
@Data
public class AllLocationsVo {
    // 库位号
    private String locNo;
    // 库位状态,O空库位(英文不是数字);F 在库;D 空板;P 出库中;R 出库预约;S 入库预约;其他 其他;
    private String locSts;
    private List<LocDetl> locDetls  = new ArrayList<>();
    @Data
    public static class LocDetl {
        @ApiModelProperty(value = "商品编号")
        private String matnr;
        @ApiModelProperty(value = "商品名称")
        private String maktx;
        private Double anfme;
    }
}
src/main/java/com/zy/asrs/entity/digitaltwin/DtDetainMatVo.java
@@ -5,7 +5,6 @@
// 数字孪生:呆滞品信息
@Data
@Builder
public class DtDetainMatVo {
    // 归属库区ID
src/main/java/com/zy/asrs/entity/digitaltwin/DtEquipmentVo.java
@@ -1,10 +1,14 @@
package com.zy.asrs.entity.digitaltwin;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DtEquipmentVo {
    // 设备ID
src/main/java/com/zy/asrs/entity/mes/MesCallOutApply.java
@@ -56,7 +56,7 @@
        // 数量
        @JsonProperty("Qty")
        @JSONField(name = "Qty")
        private Integer Qty;
        private Double Qty;
        // 物料二维码
        @JsonProperty("ItemBarcode")
        @JSONField(name = "ItemBarcode")
src/main/java/com/zy/asrs/entity/mes/MesMatInfo.java
@@ -108,7 +108,7 @@
//    @NotNull
    @JsonProperty("qty")
    @JSONField(name = "qty")
    private Integer qty;
    private Double qty;
    // 零件二维码
    @JsonProperty("ItemBarcode")
src/main/java/com/zy/asrs/entity/mes/MesOutApply.java
@@ -56,7 +56,7 @@
        // 数量
        @JsonProperty("Qty")
        @JSONField(name = "Qty")
        private Integer Qty;
        private Double Qty;
        // 物料二维码
        @JsonProperty("ItemBarcode")
        @JSONField(name = "ItemBarcode")
src/main/java/com/zy/asrs/entity/mes/TransParent.java
@@ -33,7 +33,18 @@
    @JSONField(name = "TaskType")
    private String TaskType;
    // 空车或满载进出
    @JsonProperty("FullEmptyEnex")
    @JSONField(name = "FullEmptyEnex")
    private String FullEmptyEnex;
    // 华晓或是海康
    @JsonProperty("agvFactory")
    @JSONField(name = "agvFactory")
    private Integer agvFactory;
    //请求类型
    private String method;
    private String areaNo;
}
src/main/java/com/zy/asrs/entity/mes/TransTask.java
@@ -75,4 +75,6 @@
    @JSONField(name = "TuoPanId")
    private String TuoPanId;
    private String isPDA;
}
src/main/java/com/zy/asrs/entity/param/AbnormalLocDetlParam.java
@@ -174,6 +174,12 @@
     * 实际在库天数
     */
    private Integer nowTime;
    /**
     * 库龄(天),对应前端的 storeDate 字段
     */
    public Integer getStoreDate() {
        return this.nowTime;
    }
    public String getLocNo$() {
src/main/java/com/zy/asrs/entity/param/CombParam.java
@@ -24,6 +24,8 @@
    private List<CombMat> combMats;
    private Long userId;  // 新增字段
    @Data
    public static class CombMat {
src/main/java/com/zy/asrs/entity/rcs/RcsReporterTask.java
@@ -18,4 +18,7 @@
    //华晓AGV任务状态及请求
    private String method;
    private String AgvFactory;
    private String FullEmptyEnex;
}
src/main/java/com/zy/asrs/mapper/CanFinMapper.java
New file
@@ -0,0 +1,16 @@
package com.zy.asrs.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.zy.asrs.entity.CanFin;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface CanFinMapper extends BaseMapper<CanFin> {
    CanFin selectOne(Wrapper<CanFin> outNo);
    List<CanFin> selectOne(String taskNo);
}
src/main/java/com/zy/asrs/mapper/DigitalTwinMapper.java
@@ -7,6 +7,7 @@
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
@Mapper
@@ -15,12 +16,12 @@
    List<Double> overview(@Param("areaId")String areaId);
    List<DtOrderVo> recentOrder(@Param("startTime")String startTime, @Param("endTime")String endTime);
    List<DtOrderVo> recentOrder(@Param("startTime")Date startTime, @Param("endTime")Date endTime);
    List<DtInAndOutBoundVo> recentInBound(@Param("areaId")String areaId, @Param("startTime")String startTime, @Param("endTime")String endTime);
    List<DtInAndOutBoundVo> recentInBound(@Param("areaId")String areaId, @Param("startTime") Date startTime, @Param("endTime")Date endTime);
    List<DtInAndOutBoundVo> recentOutBound(@Param("areaId")String areaId, @Param("startTime")String startTime, @Param("endTime")String endTime);
    List<DtInAndOutBoundVo> recentOutBound(@Param("areaId")String areaId, @Param("startTime") Date startTime, @Param("endTime")Date endTime);
    List<DtDetainMatVo> recentDetainMat(@Param("areaId")String areaId, @Param("startTime")String startTime,
    List<DtDetainMatVo> recentDetainMat(@Param("areaId")String areaId, @Param("startTime")Date startTime,
                                        @Param("pageIndex")Integer pageIndex, @Param("pageSize")Integer pageSize);
}
src/main/java/com/zy/asrs/service/DigitalTwinService.java
@@ -1,8 +1,10 @@
package com.zy.asrs.service;
import com.core.common.R;
import com.zy.asrs.entity.digitaltwin.*;
import java.util.List;
import java.util.Map;
public interface DigitalTwinService {
@@ -40,9 +42,10 @@
     * @param overDayNum
     * @param pageIndex
     * @param pageSize
     * @param condition 搜索条件
     * @return
     */
    List<DtDetainMatVo> recentDetainMat(String areaId, Integer overDayNum, Integer pageIndex, Integer pageSize);
    List<DtDetainMatVo> recentDetainMat(String areaId, Integer overDayNum, Integer pageIndex, Integer pageSize, String condition);
    /**
     * 查询库存和库位详细信息
@@ -67,4 +70,13 @@
     *
     */
    void locNumCount();
    DtEquipmentVo equipment(String areaId);
    /**
     * 查询所有库位状态和物料-二机床信息化数字孪生用
     */
    List<AllLocationsVo> getAllLocations();
    List<Map<String, Object>> getLocalDetal();
}
src/main/java/com/zy/asrs/service/MesService.java
@@ -147,4 +147,6 @@
    int outStation(TransParent apply);
    MesReturn queryInventory(String itemno,String orderNo);
    int AGVPause(JSONObject params, int AGVType);
}
src/main/java/com/zy/asrs/service/MobileService.java
@@ -6,7 +6,6 @@
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.OrderDetl;
import com.zy.asrs.entity.param.*;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Date;
@@ -103,10 +102,12 @@
    /**
     * pda呼叫空料框出库
     * @param staNo 出库站点
     * @param locType 托盘类型 1.窄,2.宽
     * @param userId 用户id
     *
     * @param staNo     出库站点
     * @param locType   托盘类型 1.窄,2.宽
     * @param userId    用户id
     * @param agvTaskNo
     */
    R callEmptyBinOutBound(String staNo, String locType, Long userId);
    R callEmptyBinOutBound(String staNo, String locType, Long userId, String agvTaskNo);
}
src/main/java/com/zy/asrs/service/OrderPakoutService.java
@@ -1,10 +1,12 @@
package com.zy.asrs.service;
import com.baomidou.mybatisplus.service.IService;
import com.core.common.R;
import com.zy.asrs.entity.OrderPakout;
import com.zy.asrs.entity.OrderDetlPakout;
import com.zy.asrs.entity.WrkDetl;
import com.zy.asrs.entity.WrkMast;
import com.zy.common.model.LocDto;
import java.util.List;
@@ -33,5 +35,6 @@
    OrderPakout selectOrderMoveStatus();
    OrderPakout selectOrderMoveStatusInitial();
    R pakout(List<LocDto> locDtos);
}
src/main/java/com/zy/asrs/service/RcsService.java
@@ -63,4 +63,8 @@
     * @return
     */
    RcsReturn hxApplyInLine(TransParent apply);
    RcsReturn hxOutStation(TransParent param);
    int applyIn(JSONObject allow, int i);
}
src/main/java/com/zy/asrs/service/impl/DigitalTwinServiceImpl.java
@@ -1,20 +1,29 @@
package com.zy.asrs.service.impl;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Cools;
import com.core.common.R;
import com.zy.asrs.entity.BasCrnp;
import com.zy.asrs.entity.LocCount;
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.entity.digitaltwin.*;
import com.zy.asrs.mapper.DigitalTwinMapper;
import com.zy.asrs.mapper.LocCountMapper;
import com.zy.asrs.mapper.LocDetlMapper;
import com.zy.asrs.mapper.LocMastMapper;
import com.zy.asrs.service.BasCrnpService;
import com.zy.asrs.service.DigitalTwinService;
import com.zy.asrs.service.LocDetlService;
import com.zy.asrs.service.LocMastService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
@Service
@@ -24,6 +33,12 @@
    private DigitalTwinMapper digitalTwinMapper;
    @Resource
    private LocCountMapper locCountMapper;
    @Resource
    private LocMastMapper locMastMapper;
    @Resource
    private LocDetlMapper locDetlMapper;
    @Resource
    private LocMastService locMastService;
    /**
     * 总览:总库位、已用库位、剩余库位、今日出库、今日入库、剩余库位
@@ -57,21 +72,49 @@
     */
    public List<DtOrderVo> order(String startDate, String endDate) {
        String startTime;
        String endTime;
        Date startTime = new Date();
        Date endTime = new Date();
        if (startDate == null || endDate == null || startDate.isEmpty() || endDate.isEmpty()){
            Date now = new Date();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(now);
            calendar.add(Calendar.DAY_OF_MONTH, -7);
            Date start = calendar.getTime();
            startTime = calendar.getTime();
            endTime = now;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            endDate = sdf.format(now);
            startDate = sdf.format(start);
        } else {
            SimpleDateFormat sdf;
            try {
                // 尝试解析yyyyMMdd格式
                if (startDate.length() == 8 && endDate.length() == 8) {
                    sdf = new SimpleDateFormat("yyyyMMdd");
                    startTime = sdf.parse(startDate);
                    endTime = sdf.parse(endDate);
                    // 设置结束时间为当天的23:59:59.999
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(endTime);
                    calendar.set(Calendar.HOUR_OF_DAY, 23);
                    calendar.set(Calendar.MINUTE, 59);
                    calendar.set(Calendar.SECOND, 59);
                    calendar.set(Calendar.MILLISECOND, 999);
                    endTime = calendar.getTime();
                } else {
                    // 尝试解析yyyy-MM-dd HH:mm:ss.SSS格式
                    sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                    startTime = sdf.parse(startDate);
                    endTime = sdf.parse(endDate);
                }
            } catch (ParseException e) {
                e.printStackTrace();
                // 解析失败时使用默认的7天时间范围
                Date now = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(now);
                calendar.add(Calendar.DAY_OF_MONTH, -7);
                startTime = calendar.getTime();
                endTime = now;
            }
        }
        startTime = startDate.substring(0, 4) + "-" + startDate.substring(4, 6) + "-" + startDate.substring(6, 8) + "00:00:00";
        endTime = endDate.substring(0, 4) + "-" + endDate.substring(4, 6) + "-" + endDate.substring(6, 8) + "00:00:00";
        List<DtOrderVo> dbOrder = digitalTwinMapper.recentOrder(startTime, endTime);
        // 空日期补全
        for (DtOrderVo dtOrderVo : dbOrder) {
@@ -91,31 +134,59 @@
     */
    public List<DtInAndOutBoundVo> inAndOutBound(String areaId, String startDate, String endDate) {
        List<DtInAndOutBoundVo> dtInAndOutBoundVos = new ArrayList<>();
        String startTime;
        String endTime;
        Date startTime = new Date();
        Date endTime = new Date();
        if (startDate == null || endDate == null || startDate.isEmpty() || endDate.isEmpty()){
            Date now = new Date();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(now);
            calendar.add(Calendar.DAY_OF_MONTH, -7);
            Date start = calendar.getTime();
            startTime = calendar.getTime();
            endTime = now;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            endDate = sdf.format(now);
            startDate = sdf.format(start);
        } else {
            SimpleDateFormat sdf;
            try {
                // 尝试解析yyyyMMdd格式
                if (startDate.length() == 8 && endDate.length() == 8) {
                    sdf = new SimpleDateFormat("yyyyMMdd");
                    startTime = sdf.parse(startDate);
                    endTime = sdf.parse(endDate);
                    // 设置结束时间为当天的23:59:59.999
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(endTime);
                    calendar.set(Calendar.HOUR_OF_DAY, 23);
                    calendar.set(Calendar.MINUTE, 59);
                    calendar.set(Calendar.SECOND, 59);
                    calendar.set(Calendar.MILLISECOND, 999);
                    endTime = calendar.getTime();
                } else {
                    // 尝试解析yyyy-MM-dd HH:mm:ss.SSS格式
                    sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                    startTime = sdf.parse(startDate);
                    endTime = sdf.parse(endDate);
                }
            } catch (ParseException e) {
                e.printStackTrace();
                // 解析失败时使用默认的7天时间范围
                Date now = new Date();
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(now);
                calendar.add(Calendar.DAY_OF_MONTH, -7);
                startTime = calendar.getTime();
                endTime = now;
            }
        }
        startTime = startDate.substring(0, 4) + "-" + startDate.substring(4, 6) + "-" + startDate.substring(6, 8) + "00:00:00";
        endTime = endDate.substring(0, 4) + "-" + endDate.substring(4, 6) + "-" + endDate.substring(6, 8) + "00:00:00";
        List<DtInAndOutBoundVo> dtInBoundVos = digitalTwinMapper.recentInBound(areaId, startTime, endTime);
        List<DtInAndOutBoundVo> dtOutBoundVos = digitalTwinMapper.recentOutBound(areaId, startTime, endTime);
        // 格式整理
        List<DtInAndOutBoundVo> dtInAndOutBoundVos = new ArrayList<>(dtInBoundVos);
        dtInAndOutBoundVos.addAll(dtOutBoundVos);
        return dtInAndOutBoundVos;
    }
    /**
     * 近期近期呆滞品信息,默认超过30天为呆滞品
     *
@@ -123,9 +194,10 @@
     * @param overDayNum
     * @param pageIndex
     * @param pageSize
     * @param condition 搜索条件
     * @return
     */
    public List<DtDetainMatVo> recentDetainMat(String areaId, Integer overDayNum, Integer pageIndex, Integer pageSize) {
    public List<DtDetainMatVo> recentDetainMat(String areaId, Integer overDayNum, Integer pageIndex, Integer pageSize, String condition) {
        overDayNum = overDayNum == null ? 30 : overDayNum;
        pageIndex = pageIndex == null ? 1 : pageIndex;
@@ -136,10 +208,10 @@
        calendar.setTime(now);
        calendar.add(Calendar.DAY_OF_MONTH, -overDayNum);
        Date start = calendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startTime = sdf.format(start);
    /*    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startTime = sdf.format(start);*/
        List<DtDetainMatVo> dbDetainMats = digitalTwinMapper.recentDetainMat(areaId, startTime, pageIndex, pageSize);
        List<DtDetainMatVo> dbDetainMats = digitalTwinMapper.recentDetainMat(areaId, start, pageIndex, pageSize);
        return dbDetainMats;
    }
@@ -151,31 +223,15 @@
     * @return
     */
    public List<DtLocDetailVo> warehouseDetail(String areaId) {
        List<DtLocDetailVo> locDetailVos = new ArrayList<>();
        List<LocMast> locMasts = new ArrayList<>();
        List<LocDetl> locDetls = new ArrayList<>();
        for (LocMast locMast : locMasts) {
            DtLocDetailVo dtLocDetailVo = new DtLocDetailVo();
            dtLocDetailVo.setLocMast(locMast);
            dtLocDetailVo.setLocNo(locMast.getLocNo());
            dtLocDetailVo.setLocSts(locMast.getLocSts());
            dtLocDetailVo.setRow1(locMast.getRow1());
            dtLocDetailVo.setBay1(locMast.getBay1());
            dtLocDetailVo.setLev1(locMast.getLev1());
            for (LocDetl locDetl : locDetls) {
                List<LocDetl> locDetl1 = locDetls.parallelStream().filter(a -> a.getLocNo().equals(locDetl.getLocNo())).collect(Collectors.toList());
                if (locDetl1 != null && locDetl1.size() == 1) {
                    dtLocDetailVo.setLocDetl(locDetl1.get(0));
                    dtLocDetailVo.setAreaId(locDetl.getAreaId());
                    dtLocDetailVo.setAreaName(locDetl.getAreaName());
                }
            }
            locDetailVos.add(dtLocDetailVo);
        }
        return locDetailVos;
        List<LocMast> locMastList = locMastService.selectList(new EntityWrapper<>());
        return locMastList.stream()
                .map(loc -> {
                    DtLocDetailVo vo = new DtLocDetailVo();
                    BeanUtils.copyProperties(loc, vo);
                    return vo;
                })
                .collect(Collectors.toList());
    }
    /**
@@ -201,13 +257,13 @@
            endDate = sdf.format(now);
            startDate = sdf.format(start);
        }
        List<LocCount> locCounts;
        if(areaId.isEmpty()){
            locCounts = locCountMapper.getByDate(Integer.parseInt(startDate), Integer.parseInt(endDate));
        } else {
            locCounts = locCountMapper.getByAreaAndDate(areaId, Integer.parseInt(startDate), Integer.parseInt(endDate));
        }
//        if(areaId.isEmpty()){
        locCounts = locCountMapper.getByDate(Integer.parseInt(startDate), Integer.parseInt(endDate));
//        } else {
//            locCounts = locCountMapper.getByAreaAndDate(areaId, Integer.parseInt(startDate), Integer.parseInt(endDate));
//        }
        for (LocCount locCount : locCounts) {
            String date = locCount.getDate().toString();
@@ -226,30 +282,33 @@
     * 定期统计剩余库存
     *
     */
    @Transactional
    public void locNumCount() {
        List<LocCount> result = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String date = sdf.format(new Date());
        List<LocCount> totalLoc = locCountMapper.totalLoc();
        List<LocCount> useLoc = locCountMapper.useLoc();
        for (LocCount locCount : totalLoc) {
            LocCount locCount1 = new LocCount();
            locCount1.setDate(Integer.valueOf(date));
            locCount1.setAreaId(locCount.getAreaId());
            locCount1.setLocNum(locCount1.getLocNum());
            for (LocCount locCount2 : useLoc) {
                if(locCount1.getAreaId().equals(locCount2.getAreaId())){
                    locCount1.setRemainNum(locCount1.getLocNum() - locCount2.getLocNum());
                }
            }
            result.add(locCount1);
        }
        for (LocCount locCount  : result) {
            locCountMapper.insertOrUpdate(locCount);
        }
        LocCount locCount1 = new LocCount();
        locCount1.setDate(Integer.valueOf(date));
        locCount1.setLocNum(totalLoc.get(0).getLocNum());
        locCount1.setRemainNum(locCount1.getLocNum() - useLoc.get(0).getLocNum());
        locCountMapper.insertOrUpdate(locCount1);
    }
    @Resource
    private BasCrnpService basCrnpService;
    @Override
    public DtEquipmentVo equipment(String areaId) {
        BasCrnp crnp = basCrnpService.selectOne(new EntityWrapper<>());
        return DtEquipmentVo.builder()
                .equipmentId("1").equipmentName("堆垛机1").equipmentType(1)
                .belongAreaId("D").belongAreaName("滑块库").verticalSpeed(Integer.valueOf(Cools.isEmpty(crnp.getCtlHp())? "0" : crnp.getCtlHp()))
                .horizontalSpeed(Integer.valueOf(Cools.isEmpty(crnp.getCtlRest())? "0" : crnp.getCtlRest())).voltage(220).status(crnp.getCrnErr() == 0 ? 1 : 3).operateMethod(crnp.getCrnSts() == 3 ? 1 : 3).build();
    }
@@ -270,5 +329,50 @@
    // 输送线拍照、称重
    // endregion
    @Resource
    private LocDetlService locDetlService;
    @Override
    public List<AllLocationsVo> getAllLocations() {
        List<AllLocationsVo> allLocationsVos = new ArrayList<>();
        List<LocMast> locMastList = locMastService.selectList(new EntityWrapper<>());
        locMastList.forEach(locMast -> {
            AllLocationsVo allLocationsVo = new AllLocationsVo();
            allLocationsVo.setLocNo(locMast.getLocNo());
            String locSts = locMast.getLocSts();
            allLocationsVo.setLocSts(locSts);
            // 有库存
            if (locSts.equals("F") || locSts.equals("P") || locSts.equals("Q") || locSts.equals("R")) {
                List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", locMast.getLocNo()));
                if (!locDetls.isEmpty()) {
                    List<AllLocationsVo.LocDetl> locDetlList = locDetls.stream().map(locDetl -> {
                                AllLocationsVo.LocDetl locDetl1 = new AllLocationsVo.LocDetl();
                                BeanUtils.copyProperties(locDetl, locDetl1);
                                return locDetl1;
                            }
                    ).collect(Collectors.toList());
                    allLocationsVo.setLocDetls(locDetlList);
                }
            }
            allLocationsVos.add(allLocationsVo);
        });
        return allLocationsVos;
    }
    public List<Map<String, Object>> getLocalDetal() {
        List<LocDetl> locDetls = locDetlMapper.selectList(new EntityWrapper<>());
        List<Map<String, Object>> result = new ArrayList<>();
        for (LocDetl locDetl : locDetls) {
            Map<String, Object> item = new HashMap<>();
            item.put("zpallet", locDetl.getZpallet());
            item.put("anfme", locDetl.getAnfme());
            item.put("matnr", locDetl.getMatnr());
            item.put("maktx", locDetl.getMaktx());
            result.add(item);
        }
        return result;
    }
}
src/main/java/com/zy/asrs/service/impl/MesServiceImpl.java
@@ -2,6 +2,7 @@
import com.alibaba.excel.util.DateUtils;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
@@ -14,6 +15,7 @@
import com.zy.asrs.entity.param.EmptyPlateOutParam;
import com.zy.asrs.entity.rcs.*;
import com.zy.asrs.mapper.AgvInfoMapper;
import com.zy.asrs.mapper.CanFinMapper;
import com.zy.asrs.mapper.MatItemBarcodeMapper;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.OrderInAndOutUtil;
@@ -26,8 +28,11 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.annotation.Resource;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ExecutionException;
@@ -52,6 +57,14 @@
    public long defaultUserId;
    @Value("${wms.zpalletId}")
    public String WMS_ZPALLET_ID;
    // 海康RCS地址
    @Value("${hik.url}")
    private String HIK_URL;
    // 华晓RCS地址
    @Value("${hx.url}")
    private String HX_URL;
    @Resource
    private RcsService rcsService;
@@ -95,6 +108,8 @@
    private DocTypeService docTypeService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private CanFinMapper canFinMapper;
    // region MES接口
@@ -266,7 +281,7 @@
                    OrderDetlPakin orderDetlPakin = new OrderDetlPakin();
                    orderDetlPakin.setOrderId(orderPakin.getId());
                    orderDetlPakin.setOrderNo(orderPakin.getOrderNo());
                    orderDetlPakin.setAnfme(Double.valueOf(mesMatInfo.getQty()));
                    orderDetlPakin.setAnfme(mesMatInfo.getQty());
                    orderDetlPakin.setQty(0.0);
                    orderDetlPakin.setMatnr(mat.getMatnr());
                    orderDetlPakin.setMaktx(mat.getMaktx());
@@ -937,6 +952,27 @@
        if (docType == null) {
            return 0;
        }
/*
        // 查询can_fin表中apply_time最新的记录
        List<CanFin> canFinList = canFinMapper.selectList(new EntityWrapper<CanFin>()
                .orderBy("apply_time", false)
        );
        if (!canFinList.isEmpty()) {
            CanFin firstCanFin = canFinList.get(0);
            if (firstCanFin.getAgvType().equals("agv-in-out")) {
                // 只修改需要更新的字段
                firstCanFin.setOutType("waiting");
                firstCanFin.setOutNo(mesCallOutApply.getOrderNo());
                // 确保其他字段保持不变
                canFinMapper.updateById(firstCanFin);
                log.info("已更新can_fin表最早记录的out_no,ID:{},出库单号:{}",
                        firstCanFin.getId(), mesCallOutApply.getOrderNo());
            }
        }
*/
        //生成出库单
        if (docType.getPakout() == 1) {
            long settle = 1;
@@ -971,6 +1007,22 @@
                log.error("MES保存出库订单(叫料)主档失败");
                throw new CoolException("保存出库订单(叫料)主档失败");
            }
            if (mesCallOutApply.getTransType().equals("装配出库单")){
                CanFin canFin = new CanFin();
                Date time = now;
                canFin.setAgvType("agv-out");
                canFin.setOutNo(mesCallOutApply.getOrderNo());
                List<CanFin> canFinList = canFinMapper.selectList(new EntityWrapper<>());
                if (canFinList.isEmpty()){
                    canFin.setTaskStatus("canout");
                }else {
                    canFin.setTaskStatus("waiting");
                }
                canFin.setApplyTime(time);
                canFinMapper.insert(canFin);
            }
            Set<String> set = new HashSet<>();
            // 生成明细
            if (mesCallOutApply.getItemdata() != null && !mesCallOutApply.getItemdata().isEmpty()) {
@@ -978,6 +1030,10 @@
                    set.add(mesOutApplyItem.getTrayid());
                    Mat mat = matService.selectByMatnr(mesOutApplyItem.getItemno());
                    if (Cools.isEmpty(mat)) {
                        log.error("物料编号不存在: {}", mesOutApplyItem.getItemno());
                        throw new CoolException("物料编号不存在: " + mesOutApplyItem.getItemno());
                    }
                    OrderDetlPakout orderDetlPakout = new OrderDetlPakout();
                    orderDetlPakout.setOrderId(orderPakout.getId());
                    orderDetlPakout.setOrderNo(orderPakout.getOrderNo());
@@ -1109,6 +1165,15 @@
        Task task = new Task();
        task.setWrkNo(workNo);
        task.setTaskType("ZX-AGV");
        if (transTask.getTransType()!= null){
            if (transTask.getTransType().equals("08-1")){
                task.setTaskType("ZX-AGV-08-1");
            }else if (transTask.getTransType().equals("08-2")){
                task.setTaskType("ZX-AGV-08-2");
            }else if (transTask.getTransType().equals("11")){
                task.setTaskType("ZP-AGV");
            }
        }
        task.setWrkSts(301L);//301.AGV任务创建
        task.setIoType(3);//3.站到站
        task.setIoPri(10.00);
@@ -1126,11 +1191,22 @@
        task.setPltType(transTask.getAgvFactory());//华晓AGV
        task.setPacked(transTask.getRackNumber());//料架号
        task.setCtnType(1);
        task.setIsPda(transTask.getIsPDA());
        if (taskService.insert(task)) {
            if (transTask.getNextStationId().equals("402") || transTask.getNextStationId().equals("401")){
                CanFin canFin = new CanFin();
//            canFin.setAgvType("agv-in-out");
                canFin.setAgvType("agv-in");
                canFin.setTaskStatus("waiting");
                canFin.setInNo(transTask.getTaskno());
                canFin.setApplyTime(now);
                canFinMapper.insert(canFin);
                result.put("Success", "1");
                result.put("Message", "任务接收成功");
                result.put("Message", "任务下发给RCS成功");
            }
            result.put("Success", "1");
            result.put("Message", "任务下发给RCS成功");
        }else {
            result.put("Success", "2");
            result.put("Message", "任务下发给RCS失败");
@@ -1230,9 +1306,14 @@
        mesReturn.setSuccess("2");
        if ("Y".equals(allow.getStatus())) {
            Task task = taskService.selectOne(new EntityWrapper<Task>().eq("task_no", allow.getTaskno()));
            String taskNo = allow.getTaskno();
            if (taskNo.contains("-")) {
                taskNo = allow.getTaskno().substring(0, taskNo.lastIndexOf("-"));
            }
            Task task = taskService.selectOne(new EntityWrapper<Task>().eq("task_no", taskNo));
            if (Cools.isEmpty(task)) {
                mesReturn.setMessage("没有找个该任务编号=" + allow.getTaskno() + "的AGV移动任务");
                mesReturn.setMessage("没有找到该任务编号=" + allow.getTaskno() + "的AGV移动任务");
            } else {
                //查看申请站点的是海康还是华晓
                //海康
@@ -1248,13 +1329,23 @@
                    mesReturn.setSuccess(success == 1 ? "1" : "2");
                    mesReturn.setMessage(success == 1 ? "" : "转发给RCS失败");
                } else {
                    JSONObject params = new JSONObject();
                    params.put("EqptCode", allow.getStationId());
                    params.put("TaskCode", allow.getTaskno());
                    params.put("ActionStatus", "1");
                    allow.setMethod("APPLY_IN_STATION");
                    int success = rcsService.continueTask(allow, 2);
                    mesReturn.setSuccess(success == 1 ? "1" : "2");
                    mesReturn.setMessage(success == 1 ? "" : "转发给RCS失败");
                    int success1 = rcsService.applyIn(params, 2);
                    if (success1 == 1 || success == 1){
                        mesReturn.setSuccess("1");
                        mesReturn.setMessage("");
                    }else {
                        mesReturn.setSuccess(success1 == 1 ? "1" : "2");
                        mesReturn.setMessage(success1 == 1 ? "" : "转发给RCS失败");
                    }
                }
            }
        }
        return mesReturn;
@@ -1318,23 +1409,27 @@
        mesReturn.setSuccess("2");
        if ("Y".equals(allow.getStatus())) {
            Task task = taskService.selectOne(new EntityWrapper<Task>().eq("task_no", allow.getTaskno()));
            String taskNo = allow.getTaskno();
            if (taskNo.contains("-")) {
                taskNo = allow.getTaskno().substring(0, taskNo.lastIndexOf("-"));
            }
            Task task = taskService.selectOne(new EntityWrapper<Task>().eq("task_no", taskNo));
            if (Cools.isEmpty(task)) {
                mesReturn.setMessage("没有找个该任务编号=" + allow.getTaskno() + "的AGV移动任务");
            } else {
                //查看申请站点的是海康还是华晓
                //海康
                if (Cools.isEmpty(task.getPltType()) || task.getPltType() == 1) {
                if (Cools.isEmpty(task.getPltType()) || task.getPltType() == 1 || task.getPltType() == 0) {
                    RcsTaskContinue rcsTaskContinue = new RcsTaskContinue();
                    rcsTaskContinue.setRobotTaskCode(allow.getTaskno());
                    rcsTaskContinue.setTriggerType("TASK");
                    rcsTaskContinue.setTriggerCode(allow.getTaskno());
//            rcsTaskContinue.setTriggerType("ROBOT");
//            rcsTaskContinue.setTriggerCode(allow.getAgvCode());
                    int success = rcsService.continueTask(rcsTaskContinue, 1);
                    mesReturn.setSuccess(success == 1 ? "1" : "2");
                    mesReturn.setMessage(success == 1 ? "" : "转发给RCS失败");
                } else {
                    allow.setMethod("APPLY_OFF_STATION");
                    int success = rcsService.continueTask(allow, 2);
@@ -1382,6 +1477,7 @@
        return mesReturn;
    }
    // endregion
    /**
@@ -1395,5 +1491,39 @@
        AgvInfo agvInfo = agvInfoMapper.selectById(agvNo);
        return agvInfo.getAgvFactory();
    }
    @Override
    public int AGVPause(JSONObject params, int AGVType){
        MesReturn mesReturn = new MesReturn();
        String hik_blockUrl = "api/robot/controller/zone/blockade";
        String hik_pauseUrl = "api/robot/controller/zone/pause";
        String hx_url = "robot/controller/notify/isstop";
        if (AGVType == 1){
            String BLOCK_URL = HIK_URL + hik_blockUrl;
            String PAUSE_URL = HIK_URL + hik_pauseUrl;
            String blockResponse = RcsServiceImpl.sendPost(BLOCK_URL, JSONObject.toJSONString(params));
            JSONObject jsonObject = JSON.parseObject(blockResponse);
            if (!StringUtils.isEmpty(blockResponse) && (jsonObject.getString("code").equals("SUCCESS") || jsonObject.getInteger("code") == 200)) {
                String PauseResponse = RcsServiceImpl.sendPost(PAUSE_URL, JSONObject.toJSONString(params));
                JSONObject pauseJsonObject = JSON.parseObject(PauseResponse);
                if (!StringUtils.isEmpty(PauseResponse) && (jsonObject.getString("code").equals("SUCCESS") || jsonObject.getInteger("code") == 200)) {
                    return 1;
                }else
                    return 2;
            }else
                return 2;
        }else {
            String URL = "";
            URL = HX_URL + hx_url;
            String PauseResponse = RcsServiceImpl.sendPost(URL, JSONObject.toJSONString(params));
            JSONObject jsonObject = JSON.parseObject(PauseResponse);
            if (!StringUtils.isEmpty(PauseResponse) && (jsonObject.getString("code").equals("SUCCESS") || jsonObject.getInteger("code") == 200)) {
                return 1;
            }else
                return 2;
        }
    }
}
src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java
@@ -8,8 +8,8 @@
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.*;
import com.zy.asrs.enums.CommonEnum;
import com.zy.asrs.enums.LocStsType;
import com.zy.asrs.mapper.CanFinMapper;
import com.zy.asrs.mapper.LocMastMapper;
import com.zy.asrs.mapper.ManLocDetlMapper;
import com.zy.asrs.service.*;
@@ -22,7 +22,6 @@
import com.zy.common.model.enums.WorkNoType;
import com.zy.common.service.CommonService;
import com.zy.common.utils.HttpHandler;
import com.zy.system.entity.Config;
import com.zy.system.service.impl.ConfigServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
@@ -31,8 +30,6 @@
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
@@ -118,6 +115,8 @@
    private BasContainerService basContainerService;
    @Autowired
    private ConfigServiceImpl configService;
    @Autowired
    private CanFinMapper canFinMapper;
    @Override
    @Transactional
@@ -771,7 +770,13 @@
                        .setAppeTime(date)
                        .setModiUser(9945L)
                        .setModiTime(date);
                if (!taskService.insert(task)) {
                if (taskService.insert(task)) {
                    CanFin canFin = new CanFin();
                    canFin.setApplyTime(now);
                    canFin.setAgvType("agv-in");
                    canFin.setInNo(detlDtos.get(0).getOrderNo());
                    canFinMapper.insert(canFin);
                }else {
                    throw new CoolException("保存工作档失败");
                }
            }
@@ -1329,7 +1334,7 @@
    @Override
    @Transactional
    public R callEmptyBinOutBound(String staNo, String locType, Long userId) {
    public R callEmptyBinOutBound(String staNo, String locType, Long userId, String agvTaskNo) {
        LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_sts", 'D').eq("loc_type2", locType));
        if(locMast == null) {
            return R.parse("该类型:" + locType +"空托盘不存在");
@@ -1373,12 +1378,23 @@
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk("Y"); // 空板
        wrkMast.setLinkMis("N");
        if (agvTaskNo!=null){
            wrkMast.setUserNo(agvTaskNo);
        }else {
            Date date = new Date();
            wrkMast.setUserNo(staNo + "aa" + date.getTime());
        }
        wrkMast.setAppeUser(userId);
        wrkMast.setAppeTime(now);
        wrkMast.setModiUser(userId);
        wrkMast.setModiTime(now);
        wrkMast.setMemo(staNo);
        wrkMastService.insert(wrkMast);
        CanFin canFin = new CanFin();
        canFin.setAgvType("agv-out");
        canFin.setApplyTime(now);
        canFin.setOutNo(wrkMast.getUserNo());
        canFinMapper.insert(canFin);
        // 更新库位状态
        if (locMast.getLocSts().equals("D")) {
@@ -1549,3 +1565,4 @@
        }
    }
}
src/main/java/com/zy/asrs/service/impl/OrderPakoutServiceImpl.java
@@ -2,21 +2,23 @@
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.core.common.Cools;
import com.core.common.DateUtils;
import com.core.common.SnowflakeIdWorker;
import com.core.common.*;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.EmptyPlateOutParam;
import com.zy.asrs.entity.param.OpenOrderPakinParam;
import com.zy.asrs.entity.param.OpenOrderPakoutParam;
import com.zy.asrs.mapper.OrderDetlPakoutMapper;
import com.zy.asrs.mapper.OrderPakoutMapper;
import com.zy.asrs.service.*;
import com.zy.common.model.DetlDto;
import com.zy.common.model.LocDto;
import com.zy.common.model.TaskDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@@ -38,6 +40,19 @@
    private WrkDetlService wrkDetlService;
    @Autowired
    private OrderDetlPakoutServiceImpl orderDetlPakoutService;
    @Autowired
    private LocDetlService locDetlService;
    @Autowired
    private LocMastService locMastService;
    @Autowired
    private StaDescService staDescService;
    @Autowired
    private WorkService workService;
    @Autowired
    private BasDevpService basDevpService;
    @Resource
    private OrderPakoutService orderPakOutService;
    @Override
    public OrderPakout selectByNo(String orderNo) {
@@ -203,4 +218,153 @@
        return this.baseMapper.selectOrderMoveStatusInitial();
    }
    @Override
    public R pakout(List<LocDto> locDtos) {
        if (Cools.isEmpty(locDtos)) {
            return R.parse(BaseRes.PARAM);
        }
        List<LocDto> locDtoArrayList = new ArrayList<>();
        for (LocDto locDto : locDtos) {
            if (locDto.getFrozen() != 1 && locDto.getFrozenLoc() != 1) {
                locDtoArrayList.add(locDto);
            }
        }
        locDtos = locDtoArrayList;
        if (Cools.isEmpty(locDtos)) {
            return R.parse("库存/库位被冻结,请处理后出库!!!");
        }
        boolean lack = true;
        for (LocDto locDto : locDtos) {
            if (!locDto.isLack()) {
                lack = false;
                break;
            }
        }
        if (lack) {
            return R.error("库存不足");
        }
        List<TaskDto> taskDtos = new ArrayList<>();
        // 根据 (库位 & 出库站) 分组; 理想状态:一组为一次出库任务
        for (LocDto locDto : locDtos) {
            if (locDto.isLack()) {
                continue;
            }
            TaskDto taskDto = new TaskDto(locDto.getLocNo(), locDto.getStaNo(), locDto);
            if (TaskDto.has(taskDtos, taskDto)) {
                TaskDto dto = TaskDto.find(taskDtos, taskDto);
                assert dto != null;
                dto.getLocDtos().addAll(taskDto.getLocDtos());
            } else {
                taskDtos.add(taskDto);
            }
        }
        OrderPakout orderPakout = orderPakOutService.selectByNo(locDtos.get(0).getOrderNo());
        //配盘出库单用, i=5时或者出库到最后时下发空板出库任务
        int i = 0;
        //需要出库的托盘数量
        int size = taskDtos.size();
        //优先级
        int ioPri = 50;
        //已下空板出库任务数量
        int j = 1;
        // -----------------------------------------------------------------------------------------------
        for (TaskDto taskDto : taskDtos) {
            BasDevp staNo = basDevpService.checkSiteStatus(taskDto.getStaNo());
            workService.stockOut(staNo, taskDto, 9995L, ioPri);
            ioPri--;
            i++;
            //配盘出库单使用,下发需要出的空板任务
            if (orderPakout.getDocType() == 11) {
                if (i == size) {
                    for (; j <= orderPakout.getPayType(); j++) {
                        LocMast locMast1 = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", taskDto.getLocNo()));
                        Integer locType = Integer.valueOf(locMast1.getLocType2());
                        //配盘 出库单出库区域时Q-L4时,出大托盘空板
                        if(!Cools.isEmpty(orderPakout.getCstmrName())&&orderPakout.getCstmrName().equals("Q-L4")){
                            locType = 2;
                        }
                        String bar = "";
                        //具体待定
//                        if(!Cools.isEmpty(orderPakout.getShipCode())&&orderPakout.getShipCode().equals("A01")){
//                            bar = "A01";
//                        }
                        LocMast locMast = new LocMast();
                        if (Cools.isEmpty(bar)) {
                            locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                                    .eq("loc_sts", "D").eq("loc_type2", locType).orderBy("row1",false));
                        } else {
                            locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                                    .eq("loc_sts", "D").eq("loc_type2", locType).like("barcode", bar).orderBy("row1",false));
                        }
                        if (Cools.isEmpty(locMast)) {
                            return R.error("库存没有空板");
                        }
                        String locNo = locMast.getLocNo();
                        EmptyPlateOutParam emptyPlateOutParam = new EmptyPlateOutParam();
                        emptyPlateOutParam.setOutSite(303);
                        emptyPlateOutParam.setLocNos(new ArrayList<String>() {{
                            add(locNo);
                        }});
                        String agvSta = "";
                        if (locMast.getLocType3() == 2) {
                            agvSta = "Z-LZP26";
                        }else if(locType ==2){
                        } else {
                            agvSta = orderPakout.getCstmrName();//agv目标站点位置
                        }
                        WrkMast wrkMast = workService.emptyPlateOut(emptyPlateOutParam, ioPri, agvSta);
                        ioPri--;
                    }
                } else if (i == 4) {
                    LocMast locMast1 = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", taskDto.getLocNo()));
                    Integer locType = Integer.valueOf(locMast1.getLocType2());
                    //配盘 出库单出库区域时Q-L4时,出大托盘空板
                    if(orderPakout.getCstmrName().equals("Q-L4")){
                        locType = 2;
                    }
                    String bar = "";
                    if (!Cools.isEmpty(orderPakout.getShipCode()) && orderPakout.getShipCode().equals("A01")) {
                        bar = "A01";
                    }
                    LocMast locMast = null;
                    if (Cools.isEmpty(bar)) {
                        locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                                .eq("loc_sts", "D").eq("loc_type2", locType).orderBy("row1",false));
                    } else {
                        locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                                .eq("loc_sts", "D").eq("loc_type2", locType).like("barcode", bar).orderBy("row1",false));
                    }
                    if (Cools.isEmpty(locMast)) {
                        return R.error("库存没有空板");
                    }
                    String locNo = locMast.getLocNo();
                    EmptyPlateOutParam emptyPlateOutParam = new EmptyPlateOutParam();
                    emptyPlateOutParam.setOutSite(303);
                    emptyPlateOutParam.setLocNos(new ArrayList<String>() {{
                        add(locNo);
                    }});
                    String agvSta = "";
                    if (locMast.getLocType3() == 2) {
                        agvSta = "Z-LZP26";
                    }else if(locType ==2){
                    } else {
                        agvSta = orderPakout.getCstmrName();//agv目标站点位置
                    }
                    WrkMast wrkMast = workService.emptyPlateOut(emptyPlateOutParam, ioPri, agvSta);
                    ioPri--;
                    j++;
                }
            }
        }
        return R.ok();
    }
}
src/main/java/com/zy/asrs/service/impl/RcsServiceImpl.java
@@ -5,13 +5,16 @@
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Cools;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.mes.MesReturn;
import com.zy.asrs.entity.mes.TransArrivalStation;
import com.zy.asrs.entity.mes.TransInOutStationAllow;
import com.zy.asrs.entity.mes.TransParent;
import com.zy.asrs.entity.rcs.*;
import com.zy.asrs.enums.RcsRetMethodEnum;
import com.zy.asrs.mapper.BlockStationMapper;
import com.zy.asrs.mapper.BlockTaskMapper;
import com.zy.asrs.service.*;
import com.zy.asrs.task.core.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@@ -26,10 +29,7 @@
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -51,6 +51,8 @@
    private String inOk;
    @Value("${mes.defaultUserId}")
    public long defaultUserId;
    @Value("${mes.url}")
    private String url;
    @Resource
@@ -232,11 +234,7 @@
        if (!StringUtils.isEmpty(response) && response.contains("code")){
            RcsReturn rcsReturn = JSONObject.parseObject(response, RcsReturn.class);
            if("SUCCESS".equals(rcsReturn.getCode())||"200".equals(rcsReturn.getCode())) {
                JSONObject data = rcsReturn.getData();
                String robotTaskCode = data.getString("robotTaskCode");
                if (robotTaskCode.equals(rcsTaskSubmit.getRobotTaskCode())){
                    return 1;
                }
                return 1;
            }
        }
@@ -253,10 +251,11 @@
    public int continueTask(Object rcsTaskContinue, int rcsFactory){
        String url = rcsFactory == 2 ? HX_URL+inOk :HIK_URL + "api/robot/controller/task/extend/continue";
        String response = sendPost(url, JSONObject.toJSONString(rcsTaskContinue));
        if (!StringUtils.isEmpty(response) && response.contains("code")){
            RcsReturn rcsReturn = JSONObject.parseObject(response, RcsReturn.class);
            if("200".equals(rcsReturn.getCode())) {
            if("SUCCESS".equals(rcsReturn.getCode())||"200".equals(rcsReturn.getCode())) {
                return 1;
            }
        }
@@ -264,6 +263,20 @@
        return 0;
    }
    public int applyIn(JSONObject rcsTaskContinue, int rcsFactory){
        String url = rcsFactory == 2 ? HX_URL+"eqpt/notify/traffic" :HIK_URL + "api/robot/controller/task/extend/continue";
        String response = sendPost(url, JSONObject.toJSONString(rcsTaskContinue));
        if (!StringUtils.isEmpty(response) && response.contains("code")){
            RcsReturn rcsReturn = JSONObject.parseObject(response, RcsReturn.class);
            if("SUCCESS".equals(rcsReturn.getCode())||"200".equals(rcsReturn.getCode())) {
                return 1;
            }
        }
        return 0;
    }
    /**
     * 2.1.4任务取消接口
     *
@@ -324,11 +337,13 @@
    public RcsReturn reporterTask(RcsReporterTask rcsReporterTask) {
        RcsReturn rcsReturn = new RcsReturn();
        String robotTaskCode = rcsReporterTask.getRobotTaskCode();
        String singleRobotCode = rcsReporterTask.getSingleRobotCode();
        String[] split = robotTaskCode.split("-");
        robotTaskCode = split[0];
        // 修改后的逻辑:有"-"则去掉最后一个"-"及后面内容,没有则保持原样
        String robotTaskCode = rcsReporterTask.getRobotTaskCode();
        if (robotTaskCode.contains("-")) {
            robotTaskCode = robotTaskCode.substring(0, robotTaskCode.lastIndexOf("-"));
        }
        //华晓AGV状态反馈,及申请
        if(Cools.isEmpty(rcsReporterTask.getExtra())){
            if(Cools.isEmpty(rcsReporterTask.getMethod())){
@@ -365,11 +380,33 @@
                            rcsReturn.setData(data);
                            return rcsReturn;
                        }
                        // 更新任务状态等内部逻辑
                        task.setWrkSts(304L);   // 301 任务下发、302 任务执行、303 任务中断、304 任务结束
                        task.setModiTime(new Date());
                        task.setModiUser(defaultUserId);
                        taskService.updateById(task);
                        HashMap<String,Object> map = new HashMap<>();
                        map.put("taskno", task.getTaskNo());
                        map.put("agvFactory", "2");
                        String mesUrl = url+"AGVArrivalCompletedFit";
                        String response = RcsServiceImpl.sendPost(mesUrl, JSONObject.toJSONString(map));
                        if (!StringUtils.isEmpty(response) && response.contains("Success")){
                            MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
                            if("1".equals(mesReturn.getSuccess())) {
                                task.setWrkSts(305L);//任务状态从304--》305
                                task.setModiTime(new Date());
                                taskService.updateById(task);
                            }else {
                                rcsReturn.setCode("Err_RobotCodeNotMatch");
                                rcsReturn.setMessage("");
                                JSONObject data = new JSONObject();
                                data.put("robotTaskCode", robotTaskCode);
                                rcsReturn.setData(data);
                                return rcsReturn;
                            }
                        }else {
                            rcsReturn.setCode("Err_RobotCodeNotMatch");
                            rcsReturn.setMessage("");
                            JSONObject data = new JSONObject();
                            data.put("robotTaskCode", robotTaskCode);
                            rcsReturn.setData(data);
                            return rcsReturn;
                        }
                    } break;
                    case "APPLY_IN_STATION":
                    case "APPLY_OFF_STATION":
@@ -380,6 +417,7 @@
                        apply.setAgvCode(singleRobotCode);
                        String transType = memo.getString("TransType");
                        apply.setTransType(transType);
                        apply.setAgvFactory(1);
                        apply.setProductLineId(memo.getString("ProductLineId"));
                        apply.setStationId(task.getSourceStaNo());
                        //agv入站申请
@@ -660,11 +698,13 @@
     * @return
     */
    public RcsReturn hxApplyInLine(TransParent apply) {
        RcsReturn rcsReturn = new RcsReturn();
        String robotTaskCode = apply.getTaskno();
        String singleRobotCode = apply.getAgvCode();
        apply.setAgvCode("1");
        apply.setAgvFactory(2);
        String fullEmptyEnex = apply.getFullEmptyEnex();
        int allowInOrOut = 0;
        //华晓AGV申请
            if(Cools.isEmpty(apply.getMethod())){
                log.error("华晓AGV上报状态Method为空!");
@@ -704,10 +744,55 @@
            data.put("robotTaskCode", robotTaskCode);
            rcsReturn.setData(data);
            //海康AGV状态反馈,及申请
        return rcsReturn;
    }
    public RcsReturn hxOutStation(TransParent param) {
        RcsReturn rcsReturn = new RcsReturn();
        String robotTaskCode = param.getTaskno();
        if (Cools.isEmpty(param.getMethod())) {
            log.error("华晓AGV上报状态Method为空!");
            rcsReturn.setCode("Err_Internal");
            rcsReturn.setMessage("华晓AGV上报状态Method为空");
            JSONObject data = new JSONObject();
            data.put("robotTaskCode", robotTaskCode);
            rcsReturn.setData(data);
        } else {
            String method = param.getMethod();
            param.setStationId(param.getAreaNo());
            param.setAgvCode("1");
            if (method.equals("APPLY_OUT_STATION")) {
                if (mesService.outStation(param) == 1) {
                    // 返回RCS
                    rcsReturn.setCode("SUCCESS");
                    rcsReturn.setMessage("华晓AGV上报状态成功");
                    JSONObject data = new JSONObject();
                    data.put("robotTaskCode", robotTaskCode);
                    rcsReturn.setData(data);
                    return rcsReturn;
                }
            }else if (method.equals("APPLY_IN_STATION")) {
                if (mesService.applyInStation(param) == 1) {
                    // 返回RCS
                    rcsReturn.setCode("SUCCESS");
                    rcsReturn.setMessage("华晓AGV上报状态成功");
                    JSONObject data = new JSONObject();
                    data.put("robotTaskCode", robotTaskCode);
                    rcsReturn.setData(data);
                    return rcsReturn;
                }
            }
        }
        log.error("华晓AGV上报状态失败!");
        rcsReturn.setCode("Err_Internal");
        rcsReturn.setMessage("华晓AGV上报状态Method失败");
        JSONObject data = new JSONObject();
        data.put("robotTaskCode", robotTaskCode);
        rcsReturn.setData(data);
        return rcsReturn;
    }
    // endregion
    // region httpUtil
src/main/java/com/zy/asrs/task/AGVTaskReportScheduler.java
@@ -1,14 +1,19 @@
package com.zy.asrs.task;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.entity.Task;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.mes.MesReturn;
import com.zy.asrs.mapper.CanFinMapper;
import com.zy.asrs.service.OrderPakoutService;
import com.zy.asrs.service.TaskService;
import com.zy.asrs.service.WrkDetlService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.service.impl.BasDevpServiceImpl;
import com.zy.asrs.service.impl.RcsServiceImpl;
import com.zy.asrs.task.core.ReturnT;
import com.zy.asrs.task.handler.AGVTaskReportHandler;
import org.slf4j.Logger;
@@ -32,9 +37,17 @@
    @Value("${hik.switch}")
    private Boolean switchErpReportOld;
    @Autowired
    private WrkDetlService wrkDetlService;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private BasDevpServiceImpl basDevpService;
    @Autowired
    private OrderPakoutService orderPakoutService;
    @Autowired
    private CanFinMapper canFinMapper;
    @Value("${mes.url}")
    private String MES_URL;
    /**
     * 满板和空板出库任务,出到输送线后创建AGV搬运任务
@@ -67,13 +80,31 @@
                // 保存工作档
                Task task = new Task();
                Date date = new Date();
                String TaskNo = wrkMast.getWrkNo() + "aa" + date.getTime();
                String TaskNo = wrkMast.getUserNo();
                String taskType = "AGV";
                List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(wrkMast.getWrkNo());
                if (wrkMast.getIoType()==110){
                    taskType = "ZX-AGV-08-1";
                }else{
                    if (wrkDetls != null && !Cools.isEmpty(wrkDetls.get(0).getOrderNo())){
                        TaskNo = wrkDetls.get(0).getOrderNo();
//                        OrderPakout orderPakout = orderPakoutService.selectByNo(wrkDetls.get(0).getOrderNo());
//                        if (orderPakout.getDocType()==11){
//                            taskType = "PP-AGV";
//                        }else if (orderPakout.getDocType()==12){
//                            taskType = "ZP-AGV";
//                        }
                        taskType = "ZP-AGV";
                    }
                }
                task.setWrkNo(wrkMast.getWrkNo())
                        .setTaskNo(TaskNo)
                        .setIoTime(date)
                        .setWrkSts(301L) // 工作状态:301.任务下发
                        .setIoType(ioType) // 入出库状态: 3.站到站  4.站到区域
                        .setTaskType("agv")
                        .setTaskType(taskType)
                        .setIoPri(10D)
                        .setFullPlt("Y") // 满板:Y
                        .setPicking("N") // 拣料
@@ -90,6 +121,24 @@
                if (!taskService.insert(task)) {
                    throw new CoolException("保存工作档失败");
                } else {
                    if (!wrkMast.getBarcode().isEmpty() && !wrkMast.getMemo().isEmpty()) {
                        JSONObject map = new JSONObject();
                        map.put("taskNo", TaskNo);
                        map.put("barCode", wrkMast.getBarcode());
                        map.put("staNo", wrkMast.getStaNo());
                        log.info("本次出库托盘:{}, 目标站{}", wrkMast.getBarcode(), wrkMast.getMemo());
                        String url = "ReceiveFinishedPalletCode";
                        String URL = MES_URL + url;
                        String response = RcsServiceImpl.sendPost(URL, JSONObject.toJSONString(map));
                        if (!StringUtils.isEmpty(response) && response.contains("Success")){
                            MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
                            if("1".equals(mesReturn.getSuccess())) {
                                log.info("上报完成 ==> 本次出库托盘:{}, 目标站{}", wrkMast.getBarcode(), wrkMast.getMemo());
                            }else {
                                log.error("上报失败 ==> 本次出库托盘:{}, 目标站{}", wrkMast.getBarcode(), wrkMast.getMemo());
                            }
                        }
                    }
                    wrkMast.setWrkSts(31L);//31.AGV搬运任务创建成功
                    wrkMast.setModiTime(date);
                    wrkMastService.updateById(wrkMast);
@@ -101,7 +150,7 @@
    /**
     * AGV 任务下发接口,定时给AGV下发任务
     */
    @Scheduled(cron = "0/3 * * * * ? ")
    @Scheduled(cron = "0/5 * * * * ? ")
    private void execute() {
        if (!switchErpReportOld) {
            return;
@@ -110,6 +159,45 @@
        List<Task> wrkSts = taskService.selectList(new EntityWrapper<Task>().eq("wrk_sts", 301).orderBy("appe_time"));
        if (wrkSts != null && !wrkSts.isEmpty()) {
            for (Task task : wrkSts) {
                if (!task.getTaskType().equals("AGV空料架回缓存区") && !task.getTaskType().equals("AGV补空料架")){
                    if((task.getStaNo().equals("402") || task.getStaNo().equals("401")) && task.getTaskType().equals("")){
                        //筛选全部还未完成的出库任务
                        List<OrderPakout> orderPakouts = orderPakoutService.selectList(new EntityWrapper<OrderPakout>()
                                .in("settle", 1, 2)     // 1表示还未开始,2表示正在执行
                                .eq("doc_type", 12)
                                .orderBy("order_time", true));
                        if (!orderPakouts.isEmpty()) {
                            //获取第一条入库单
                            OrderPakout orderPakout = orderPakouts.get(0);
                            // 如果第一条还未开始的出库任务时间早于第一条未完成的入库任务时间,跳过,不执行
                            if (orderPakout.getCreateTime().getTime() < task.getWrkDate().getTime()){
                                continue;
                            }
                        }
                    }
                }
//                List<CanFin> canFinList = canFinMapper.selectList(new EntityWrapper<CanFin>()
//                        .orderBy("apply_time", true)
//                );
//                if (!canFinList.isEmpty()) {
//                    CanFin firstCanFin = canFinList.get(0);
//                    // 检查 InNo 是否为空
//                    if (firstCanFin.getInNo() != null) {
//                        // 检查当前任务是否与转序任务相关
//                        if (task.getStaNo().equals("401") || task.getStaNo().equals("402")){
//                            List<WrkMast> wrkMasts1 = wrkMastService.selectList(new EntityWrapper<WrkMast>()
//                                    .in("io_type", 1, 10));
//                            BasDevp basDevp = basDevpService.checkSiteStatus(Integer.parseInt(task.getStaNo()));
//                            if (basDevp.getWrkNo() != 0 || !wrkMasts1.isEmpty()){
//                                continue;
//                            }
//
//                        }
//                    }
//                }
                //查询是否有正在作业的源站和目标站有一样的agv搬运任务
                //如果有则跳过本次agv搬运任务下发
                Task task1 = taskService.selectOne(new EntityWrapper<Task>()
@@ -124,6 +212,7 @@
                    //如果是接驳站点则需要判断接驳站点是否有空料架
                    //如果有空料架需要判断是否有出库任务
                    //有出库任务则禁止下发本次搬运任务
                    if (task.getStaNo().equals("401") || task.getStaNo().equals("402") || task.getStaNo().equals("307")) {
                        flag = false;
                        BasDevp basDevp = basDevpService.checkSiteStatus(Integer.parseInt(task.getStaNo()));
src/main/java/com/zy/asrs/task/BlockScheduler.java
@@ -18,9 +18,9 @@
     * 管理封锁区请求
     *
     */
    @Scheduled(cron = "0/3 * * * * ? ")
    //@Scheduled(cron = "0/3 * * * * ? ")
    private void execute(){
//        rcsService.managerBlock();
        rcsService.managerBlock();
    }
}
src/main/java/com/zy/asrs/task/ErrorStockScheduler.java
@@ -1,18 +1,37 @@
package com.zy.asrs.task;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Cools;
import com.zy.asrs.entity.BasErrLog;
import com.zy.asrs.entity.mes.MesReturn;
import com.zy.asrs.service.BasErrLogService;
import com.zy.asrs.service.impl.RcsServiceImpl;
import com.zy.asrs.task.core.ReturnT;
import com.zy.asrs.task.handler.ErrorStockHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
 * Created by vincent on 2020/7/7
 */
@Component
public class ErrorStockScheduler {
    @Value("${mes.url}")
    public String MES_URL;
    @Autowired
    private BasErrLogService basErrLogService;
    private static final Logger log = LoggerFactory.getLogger(ErrorStockScheduler.class);
@@ -27,4 +46,59 @@
        }
    }
    /**
     * 每日故障信息上报
     */
    @Scheduled(cron = "0 0 20 * * ? ")
    public void faultReport() {
        // 获取今天的开始时间
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date todayStart = calendar.getTime();
        // 获取今天的结束时间
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        Date todayEnd = calendar.getTime();
        List<BasErrLog> basErrLogs = basErrLogService.selectList(
                new EntityWrapper<BasErrLog>()
                        .between("create_time", todayStart, todayEnd)
                        .orderBy("create_time", false)
        );
        int totalCount = basErrLogs.size();
        long totalTime = 0;
        for (BasErrLog basErrLog : basErrLogs) {
            if (basErrLog.getStartTime() != null && basErrLog.getEndTime() != null) {
                totalTime += basErrLog.getEndTime().getTime() - basErrLog.getStartTime().getTime();
            }
        }
        JSONObject params = new JSONObject();
        params.put("totalCount", totalCount);
        params.put("totalTime", totalTime / 1000);
        String url = "ErrorLogReport";
        String URL = MES_URL + url;
        String response = RcsServiceImpl.sendPost(URL, JSONObject.toJSONString(params));
        if (!StringUtils.isEmpty(response) && response.contains("Success")){
            MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
            if("1".equals(mesReturn.getSuccess())) {
                log.info("上报完成 ==> 故障次数:{}, 总时长:{}", totalCount, totalTime);
            }else {
                log.error("上报失败 ==> 故障次数:{}, 总时长:{}", totalCount, totalTime);
            }
        }
    }
}
src/main/java/com/zy/asrs/task/OrderSyncScheduler.java
@@ -4,14 +4,18 @@
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Cools;
import com.core.common.R;
import com.zy.asrs.controller.OutController;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.mes.*;
import com.zy.asrs.mapper.CanFinMapper;
import com.zy.asrs.service.*;
import com.zy.asrs.service.impl.RcsServiceImpl;
import com.zy.asrs.task.core.ReturnT;
import com.zy.asrs.task.handler.OrderSyncHandler;
import com.zy.asrs.utils.OrderInAndOutUtil;
import com.zy.common.entity.Parameter;
import com.zy.common.model.LocDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -20,8 +24,7 @@
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -38,6 +41,8 @@
    private OrderService orderService;
    @Autowired
    private ApiLogService apiLogService;
    @Autowired
    private CanFinMapper canFinMapper;
    @Resource
    private OrderPakinService orderPakinService;
    @Resource
@@ -45,6 +50,8 @@
    @Resource
    private MesService mesService;
    @Autowired
    private TaskService taskService;
    @Resource
    private OrderDetlPakinService orderDetlPakinService;
    @Resource
@@ -55,6 +62,19 @@
    @Value("${erp.switch.ErpReportOld}")
    private boolean ErpReportOld;
    @Autowired
    private LocDetlService locDetlService;
    @Autowired
    private LocMastService locMastService;
    @Autowired
    private StaDescService staDescService;
    @Autowired
    private OutController outController;
    @Scheduled(cron = "0 0 1 * * ? ")
    public void clearApiLog() {
@@ -284,4 +304,101 @@
//            }
//        }
    }
    // 装配单自动出库
    @Scheduled(cron = "0/1 * * * * ? ")
//    @Async("orderThreadPool")
    void AutoOutOrderPinOut() throws InterruptedException {
        String erpReport = Parameter.get().getErpReport();
        if (!Cools.isEmpty(erpReport) && erpReport.equals("true")) {
            List<OrderPakout> orderPakouts = orderPakoutService.selectList(new EntityWrapper<OrderPakout>()
                    .eq("settle", 1)
                    .eq("doc_type", 12)
                    .orderBy("update_time"));
            if (orderPakouts.isEmpty()) {
                return;
            }
            for (OrderPakout orderPakout : orderPakouts) {
//                // 查询can_fin表中相同单号的内容
//                List<CanFin> conntOut = canFinMapper.selectList(
//                        new EntityWrapper<CanFin>()
//                                .eq("out_no", orderPakout.getOrderNo())
//                );
//                if (!conntOut.isEmpty()) {
//                    // 检查是否满足继续执行的条件:agv_type为agv-in-out且task_type为canout
//                    boolean canContinue = false;
//                    for (CanFin canFin : conntOut) {
////                        if ("agv-in-out".equals(canFin.getAgvType()) && "canout".equals(canFin.getTaskStatus())) {
//                        if ("agv-out".equals(canFin.getAgvType()) && "canout".equals(canFin.getTaskStatus())) {
//                            log.info("can_fin表有满足条件的记录,执行出库单:{}", orderPakout.getOrderNo());
//                            canContinue = true;
//                            break;
//                        }
//                    }
//                    if (!canContinue) {
//                        // 不满足条件,跳过出库单
//                        continue;
//                    }
//                }
                String sourceNo = orderPakout.getCstmrName();
                List<Task> tasks = taskService.selectList(new EntityWrapper<Task>()
                        .eq("source_sta_no", sourceNo)
                        .in("wrk_sts", 301, 302, 303));
                if (!tasks.isEmpty() && tasks != null){
                    continue;
                }
                List<LocDto> locDtos = new ArrayList<>();
                Boolean boo = false;
                Set<String> exist = new HashSet<>();
                List<OrderDetlPakout> orderDetlPakouts = orderDetlPakoutService.selectList(new EntityWrapper<OrderDetlPakout>().eq("order_no", orderPakout.getOrderNo()));
                for (OrderDetlPakout orderDetl : orderDetlPakouts) {
                    double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getWorkQty()).orElse(0.0D);
                    if (issued <= 0.0D) {
                        continue;
                    }
                    List<LocDetl> locDetls = locDetlService.queryStockAll(null, exist, orderDetl.getMatnr(), orderDetl.getBatch(),
                            orderDetl.getBrand(), orderPakout.getDocType() == 11 ? null : orderDetl.getStandby1(), orderDetl.getStandby2(), orderDetl.getStandby3(), orderDetl.getBoxType1(), orderDetl.getBoxType2(), orderDetl.getBoxType3());
                    for (LocDetl locDetl : locDetls) {
                        if (issued > 0) {
                            LocDto locDto = new LocDto(locDetl.getLocNo(), locDetl.getMatnr(), locDetl.getMaktx(), locDetl.getBatch(), orderDetl.getOrderNo(),
                                    issued >= locDetl.getAnfme() ? locDetl.getAnfme() : issued);
                            LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", locDetl.getLocNo()));
                            locDto.setFrozen(locDetl.getFrozen());
                            locDto.setFrozenLoc(locMast.getFrozen());
                            List<Integer> staNos = staDescService.queryOutStaNosByLocNo(locDetl.getLocNo(), issued >= locDetl.getAnfme() ? 101 : 103);
                            locDto.setStaNos(staNos);
                            locDto.setBrand(orderDetl.getBrand());
                            locDto.setStandby1(orderDetl.getStandby1());
                            locDto.setStandby2(orderDetl.getStandby2());
                            locDto.setStandby3(orderDetl.getStandby3());
                            locDto.setBoxType1(orderDetl.getBoxType1());
                            locDto.setBoxType2(orderDetl.getBoxType2());
                            locDto.setBoxType3(orderDetl.getBoxType3());
                            locDtos.add(locDto);
                            exist.add(locDetl.getLocNo());
                            // 剩余待出数量递减
                            issued = issued - locDetl.getAnfme();
                        } else {
                            break;
                        }
                    }
                    if (issued > 0) {
                        boo = true;
                        continue;
                    }
                }
                if (boo){
                    continue;
                }
                R pakout = orderPakoutService.pakout(locDtos);
                break;
            }
        }
    }
}
src/main/java/com/zy/asrs/task/WorkMastScheduler.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.zy.asrs.entity.Task;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.DigitalTwinService;
import com.zy.asrs.service.MesService;
import com.zy.asrs.service.TaskService;
import com.zy.asrs.service.WrkMastService;
@@ -35,6 +36,16 @@
    @Resource
    private MesService mesService;
    // TODO:reporterTask()
    @Resource
    private DigitalTwinService digitalTwinService;
    /**
     * 定时统计每天剩余库存
     */
    @Scheduled(cron = "0 50 23 * * ?")
    private void locNumCount() {
        digitalTwinService.locNumCount();
    }
    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute(){
src/main/java/com/zy/asrs/task/handler/AGVTaskReportHandler.java
@@ -7,6 +7,7 @@
import com.zy.asrs.service.RcsService;
import com.zy.asrs.task.AbstractHandler;
import com.zy.asrs.task.core.ReturnT;
import com.zy.common.properties.StationProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -20,6 +21,9 @@
@Service
@Transactional
public class AGVTaskReportHandler extends AbstractHandler<String> {
    @Resource
    private StationProperties stationProperties;
    @Resource
    private RcsService rcsService;
@@ -37,20 +41,37 @@
        }else if(task.getIoType()==5){
            SourceStaNoType = "ZONE";
        }
        String taskType = "PP";
        String taskType = "NB";
        Boolean flag1 = false;
        Boolean flag2 = false;
        if(task.getStaNo().equals("401")|| task.getStaNo().equals("402")|| task.getStaNo().equals("307")){
        if(stationProperties.getStation().contains(task.getStaNo())){
            taskType = "YLIN";
            flag1 = true;
        }
        if (task.getSourceStaNo().equals("401")|| task.getSourceStaNo().equals("402")|| task.getSourceStaNo().equals("307")){
        if (stationProperties.getStation().contains(task.getSourceStaNo())){
            taskType = "YLOUT";
            flag2 = true;
        }
        if(flag1&&flag2){
            taskType = "YLBOTH";
        }
        if (task.getSourceStaNo().equals("Z-LVL20")||task.getSourceStaNo().equals("Z-LVL21")||task.getSourceStaNo().equals("Z-LVL22")||
                task.getSourceStaNo().equals("Z-LVL23")||task.getSourceStaNo().equals("Z-LVL24")||task.getSourceStaNo().equals("Z-LVL25")||
                task.getSourceStaNo().equals("Z-LVL26")||task.getSourceStaNo().equals("Z-LVL27")||task.getSourceStaNo().equals("Z-LVL28")||
                task.getSourceStaNo().equals("Z-LVL29")||task.getSourceStaNo().equals("Z-LVL30")||task.getSourceStaNo().equals("Z-LVL31")){
            taskType = "HKCPIN";
        }
        if (task.getStaNo().equals("Z-LVL20")||task.getStaNo().equals("Z-LVL21")||task.getStaNo().equals("Z-LVL22")||
                task.getStaNo().equals("Z-LVL23")||task.getStaNo().equals("Z-LVL24")||task.getStaNo().equals("Z-LVL25")||
                task.getStaNo().equals("Z-LVL26")||task.getStaNo().equals("Z-LVL27")||task.getStaNo().equals("Z-LVL28")||
                task.getStaNo().equals("Z-LVL29")||task.getStaNo().equals("Z-LVL30")||task.getStaNo().equals("Z-LVL31")
        ){
            taskType = "HKCPOUT";
        }
        if (task.getIsPda() !=null && task.getIsPda().equals("Y")){
            taskType = "NB";
        }
        //AGV区域中无法用-
        String StaNo = task.getStaNo();
        String SourceStaNo = task.getSourceStaNo();
src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java
@@ -3,11 +3,13 @@
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.mes.MesReturn;
import com.zy.asrs.enums.LocStsType;
import com.zy.asrs.mapper.CanFinMapper;
import com.zy.asrs.service.*;
import com.zy.asrs.service.impl.*;
import com.zy.asrs.task.AbstractHandler;
@@ -57,6 +59,11 @@
    private TaskDetlService taskDetlService;
    @Autowired
    private BasStationServiceImpl basStationService;
    @Autowired
    private CanFinMapper canFinMapper;
    @Autowired
    private OrderPakoutService orderPakoutService;
    @Value("${mes.url}")
    private String url;
@@ -455,11 +462,51 @@
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return FAIL.setMsg("更新入库完成状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]");
            }
            // 将waitPakin表中的数据标记为已处理
            if (wrkMast.getIoType() == 1) { // 全板入库
                Wrapper<WaitPakin> wrapper = new EntityWrapper<WaitPakin>().eq("zpallet", wrkMast.getBarcode());
                WaitPakin setParam = new WaitPakin();
                setParam.setStatus("N");
                setParam.setModiTime(new Date());
                waitPakinService.update(setParam, wrapper);
                log.info("更新库存成功!托盘码:{}", wrkMast.getBarcode());
            }
        } catch (Exception e) {
            log.error("fail", e);
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return FAIL.setMsg(e.getMessage());
        }
        try{
            CanFin canFin = new CanFin();
            List<CanFin> canFinList = canFinMapper.selectList(
                    new EntityWrapper<CanFin>()
                            .orderBy("apply_time", true)
            );
            if (canFinList != null){
                CanFin firstCanFin = canFinList.get(0);
                if (firstCanFin.getAgvType().equals("agv-in")){
//                    if (firstCanFin.getAgvType().equals("agv-in-out")){
                    canFinMapper.deleteById(firstCanFin.getId());
                    if (canFinList.size() > 1){
                        CanFin firstCanFin1 = canFinList.get(1);
                        firstCanFin1.setTaskStatus("canout");
                        log.info("can_fin表已更新,入库单状态{}", firstCanFin1.getOutType());
                        canFinMapper.updateById(firstCanFin1);
                    }
                }
//                    else if(firstCanFin.getAgvType().equals("agv-in")){
//                        canFinMapper.deleteById(firstCanFin.getId());
//                    }
            }
        } catch (Exception e) {
            log.error("本次入库没有任务单");
        }
        return SUCCESS;
@@ -598,6 +645,69 @@
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return FAIL.setMsg(e.getMessage());
        }
        try{
            List<CanFin> firstCanFinList = canFinMapper.selectList(
                    new EntityWrapper<CanFin>()
                            .orderBy("apply_time", true)
            );
            CanFin firstCanfin = firstCanFinList.get(0);
            if (firstCanfin.getOutNo() != null && firstCanfin.getAgvType().equals("agv-out")){
                log.info("can_fin表已更新,出库单{}已删除",firstCanfin.getOutNo());
                canFinMapper.deleteById(firstCanfin.getId());
            }
            if (firstCanfin.getOutNo() == null && firstCanfin.getAgvType().equals("agv-out")){
                log.info("can_fin表已更新,出库任务已删除,当前出库无任务单");
                canFinMapper.deleteById(firstCanfin.getId());
            }
            if (firstCanFinList.size() > 1){
                CanFin secondCanFin = firstCanFinList.get(1);
                secondCanFin.setTaskStatus("canout");
                canFinMapper.updateById(secondCanFin);
            }
//                else {
//                OrderPakout isOut = orderPakoutService.selectOne(
//                                        new EntityWrapper<OrderPakout>()
//                                                .eq("settle", 2L)
//                                                .eq("doc_type", 12L));
//                String outOrderNo = isOut.getOrderNo();
//                    List<CanFin> canFinList = canFinMapper.selectList(
//                            new EntityWrapper<CanFin>()
//                                    .eq("agv_type", "agv-in-out")
//                                    .orderBy("apply_time", true)
//                    );
//                    if (canFinList != null){
//                        CanFin firstCanFin = canFinList.get(0);
//
//                        OrderPakout isOut = orderPakoutService.selectOne(
//                                new EntityWrapper<OrderPakout>()
//                                        .eq("orderNo", firstCanFin.getOutNo()));
//
//                        String outOrderNo = isOut.getOrderNo();
//                        if (outOrderNo.equals(firstCanFin.getOutNo())){
//                            log.info("can_fin表已更新,转序出库单{}已删除", firstCanFin.getOutNo());
//                            canFinMapper.deleteById(firstCanFin.getId());
//                        }else {
//                            log.info("未找到该出库单,can_fin表未更新");
//                        }
//                        List<CanFin> canFinList1 = canFinMapper.selectList(
//                                new EntityWrapper<CanFin>()
//                                        .eq("agv_type", "agv-in-out")
//                                        .orderBy("apply_time", true));
//                        if (!canFinList1.isEmpty()){
//                            CanFin firstCanFin2 = canFinList.get(0);
//                            firstCanFin2.setTaskType("Y");
//                            log.info("can_fin表已更新,转序出库单可以转序", firstCanFin2.getOutNo());
//                            canFinMapper.updateById(firstCanFin2);
//                        }
//                    }
//                }
        } catch (Exception e) {
            log.error("本次出库没有任务单");
            return null;
        }
        return SUCCESS;
    }
@@ -613,13 +723,14 @@
        WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", task.getWrkNo()));
        if (wrkMast != null) {
            if (wrkMast.getIoType()==110&& wrkMast.getWrkSts()>12){
                wrkMast.setWrkSts(32L);//32.等待组托
            }else if (wrkMast.getIoType()==101){
                wrkMast.setWrkSts(15L);//32.等待组托
            }else if (wrkMast.getIoType()==101 && wrkMast.getWrkSts()>12){
                wrkMast.setWrkSts(15L);//15.出库更新完成
            }else if (wrkMast.getIoType()==103 && wrkMast.getWrkSts()>12){
                wrkMast.setWrkSts(20L);//20.等待回库
            }
            wrkMast.setModiTime(new Date());
            wrkMast.setOveMk("Y");
            wrkMastService.updateById(wrkMast);
            task.setWrkSts(305L);//任务状态从304--》305
            task.setModiTime(new Date());
@@ -629,6 +740,7 @@
        }else if(task.getTaskType().equals("ZX-AGV")){
            HashMap<String,Object> map = new HashMap<>();
            map.put("taskno", task.getTaskNo());
            map.put("agvFactory", "2");
            String mesUrl = url+"AGVArrivalCompletedFit";
            String response = RcsServiceImpl.sendPost(mesUrl, JSONObject.toJSONString(map));
            if (!StringUtils.isEmpty(response) && response.contains("Success")){
src/main/java/com/zy/common/config/AdminInterceptor.java
@@ -123,7 +123,7 @@
//            String deToken = Cools.deTokn(token, user.getPassword());
//            long timestamp = Long.parseLong(deToken.substring(0, 13));
            // 15分钟后过期
            if (System.currentTimeMillis() - userLogin.getCreateTime().getTime() > 900000){
            if (System.currentTimeMillis() - userLogin.getCreateTime().getTime() > 3600000){
                Http.response(response, BaseRes.DENIED);
                return false;
            }
src/main/java/com/zy/common/config/LogAspect.java
@@ -28,7 +28,7 @@
@Order(2)
public class LogAspect {
    private final List<String> logApiList = Stream.of("digitalTwin", "api/mes", "api/robot")
    private final List<String> logApiList = Stream.of("api/mes", "api/robot")
            .collect(Collectors.toList());
    public LogAspect() {
@@ -108,5 +108,4 @@
        }
        return have;
    }
}
src/main/java/com/zy/common/properties/StationProperties.java
New file
@@ -0,0 +1,16 @@
package com.zy.common.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
@Data
@Configuration
@ConfigurationProperties(prefix = "hik")
public class StationProperties {
    // 双深库位排号
    private List<String> station = new ArrayList<>();
}
src/main/java/com/zy/common/service/CommonService.java
@@ -180,7 +180,7 @@
        if (locMast == null && locTypeDto.getLocType1() ==1) {
            LocMast locMast1 = locMastService.selectOne(new EntityWrapper<LocMast>()
                    .eq("loc_sts", "O")
                    .eq("loc_type1", locTypeDto.getLocType1() + 1)
                    .ge("loc_type1", locTypeDto.getLocType1())
                    .eq("loc_type2", locTypeDto.getLocType2())
                    .orderBy("lev1")
                    .orderBy("bay1")
src/main/java/com/zy/common/web/WcsController.java
@@ -66,6 +66,9 @@
        if (Cools.isEmpty(param.getSourceStaNo())) {
            return R.error("源站编号不能为空");
        }
        if (Cools.isEmpty(param.getSourceStaNo())) {
            return R.error("托盘不能为空或者托盘码不为八位");
        }
        List<WaitPakin> waitPakins = null;
        if (param.getIoType() == 1) {
            if (Cools.isEmpty(param.getBarcode())) {
@@ -90,7 +93,7 @@
        }
        //入库时对空板出库任务进行完成
        WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("barcode", param.getBarcode()).eq("io_type",110));
        WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("barcode", param.getBarcode()).eq("wrk_sts",110));
        if (!Cools.isEmpty(wrkMast)) {
            wrkMast.setWrkSts(15L);//空板出库任务转历史档
            wrkMastService.updateById(wrkMast);
@@ -257,7 +260,7 @@
        // 检索库位
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        StartupDto dto = commonService.getLocNo( 10, devpNo, findLocNoAttributeVo, locTypeDto);
        StartupDto dto =commonService.getLocNoNew(10,devpNo,locTypeDto);
        int workNo = dto.getWorkNo();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
src/main/java/com/zy/system/entity/license/LicenseCheckListener.java
@@ -83,30 +83,30 @@
                param.setPublicKeysStorePath(publicKeysStorePath);
                LicenseVerify licenseVerify = new LicenseVerify();
                //安装证书
//                LicenseContent install = licenseVerify.install(param);
//                安装证书
                LicenseContent install = licenseVerify.install(param);
                logger.info("++++++++ 许可证加载结束 ++++++++");
                logger.info("++++++++ 许可证加载标记,搜索修改 ++++++++");
                licenseTimer.setSystemSupport(true);
                licenseTimer.setLicenseDays(9999);
                return true;
//                licenseTimer.setSystemSupport(true);
//                licenseTimer.setLicenseDays(9999);
//                return true;
//                licenseTimer.setSystemSupport(install!=null);
//
//                if (install != null) {
//                    Date start = new Date();
//                    Date end = install.getNotAfter();
//                    Long starTime = start.getTime();
//                    Long endTime = end.getTime();
//                    Long num = endTime - starTime;//时间戳相差的毫秒数
//                    int day = (int) (num / 24 / 60 / 60 / 1000);
//                    licenseTimer.setLicenseDays(day);
//                }
//
//
//                return install != null;
                licenseTimer.setSystemSupport(install!=null);
                if (install != null) {
                    Date start = new Date();
                    Date end = install.getNotAfter();
                    Long starTime = start.getTime();
                    Long endTime = end.getTime();
                    Long num = endTime - starTime;//时间戳相差的毫秒数
                    int day = (int) (num / 24 / 60 / 60 / 1000);
                    licenseTimer.setLicenseDays(day);
                }
                return install != null;
            } catch (Exception e) {
                return false;
            }
src/main/java/com/zy/system/timer/LoadingConfigTimer.java
@@ -18,7 +18,7 @@
    /**
     * token有效期时间
     */
    private Integer tokenExpire = 1000 * 30 * 60;
    private Integer tokenExpire = 1000 * 60 * 60 * 5;
    /**
     * token数量限制
     */
src/main/resources/application-dev.yml
@@ -50,7 +50,7 @@
#License相关配置
license:
  subject: jnejc-ljqasrs
  subject: jnejc-hkwms
  publicAlias: publicCert
  storePass: public_zhongyang_123456789
  licensePath: license.lic
@@ -136,6 +136,8 @@
mes:
  url: http://192.9.100.173:8088/prod-api/basicmodel/WmsFit/Api/
#  url: http://172.26.160.73:8080/basicmodel/WmsFit/Api/
#  url: http://172.26.160.5:8080/basicmodel/WmsFit/Api/
  #默认接口操作人员id
  defaultUserId: 30
@@ -143,6 +145,7 @@
hik:
  switch: true
  url: http://172.26.11.98:80/rcs/rtas/
  station: 402,401,307,Z-LZH19,Z-LZH20,Z-LZH21,Z-LZH22,Z-LZH23,Z-LZH24,Z-LZH25,Z-LZH26,Z-LZH27,Z-LZH28,Z-LZH29,Z-LZH30,Z-LZH31,Z-LZH32,Z-LZH33,Z-LZH34,Z-LZH35,Z-LZH36,Z-LZH37,Z-LZH38,Z-LZH39,L-LZH40,L-LZH41,L-LZH42
#华晓对接
hx:
@@ -155,3 +158,8 @@
  #离站完成
#wcs地址 数字孪生
digitalTwins:
  jgUrl: http://172.26.11.88:8089/jgwms
  djUrl: http://172.26.11.88:8088/djwms
  ljqUrl: http://172.26.11.80:8083/ljqwms
src/main/resources/license.lic
Binary files differ
src/main/resources/logback-spring.xml
@@ -20,7 +20,7 @@
    </appender>
    <!-- 日志保存路径 -->
    <property name="LOG_PATH" value="D:/wmslogs/jg" />
    <property name="LOG_PATH" value="D:/hkwmslogs/hk" />
    <!--info级别-->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
src/main/resources/mapper/LocCountMapper.xml
@@ -22,11 +22,18 @@
    </select>
    <insert id="insertOrUpdate" parameterType="com.zy.asrs.entity.LocCount">
        IF EXISTS (SELECT date FROM asr_loc_count WHERE date = #{model.date} AND area_id = #{model.areaId})
            INSERT INTO asr_loc_count(date, area_id, loc_num, remain_num)
            VALUES (#{model.date}, #{model.areaId}, #{model.locNum}, #{model.remainNum})
        IF EXISTS (SELECT 1 FROM asr_loc_count WHERE date = #{model.date})
            BEGIN
                UPDATE asr_loc_count
                SET loc_num = #{model.locNum},
                    remain_num = #{model.remainNum}
                WHERE date = #{model.date}
            END
        ELSE
            UPDATE asr_loc_count SET loc_num = #{model.locNum}, remain_num = #{model.remainNum}
            BEGIN
                INSERT INTO asr_loc_count(date, area_id, loc_num, remain_num)
                VALUES (#{model.date}, #{model.areaId}, #{model.locNum}, #{model.remainNum})
            END
    </insert>
    <select id="totalLoc" resultType="com.zy.asrs.entity.LocCount">
src/main/resources/mapper/ViewDigitalTwinMapper.xml
@@ -13,29 +13,29 @@
    <!--总览:总库位、已用库位、今日库存、今日出库、今日入库-->
    <select id="overview" resultType="Double">
        SELECT COUNT(*) FROM asr_loc_mast WHERE loc_sts != 'Z'
            <if test="areaId != null">
                and area_id = #{areaId}
            </if>
<!--            <if test="areaId != null">-->
<!--                and area_id = #{areaId}-->
<!--            </if>-->
        UNION ALL
        SELECT COUNT(*) FROM asr_loc_mast WHERE loc_sts = 'F' or loc_sts = 'P' or loc_sts = 'Q' or loc_sts = 'R' or loc_sts = 'S' or loc_sts = 'X'
        <if test="areaId != null">
            and area_id = #{areaId}
        </if>
<!--        <if test="areaId != null">-->
<!--            and area_id = #{areaId}-->
<!--        </if>-->
        UNION ALL
        SELECT ISNULL(SUM(anfme), 0) FROM asr_loc_detl
        <if test="areaId != null">
            WHERE area_id = #{areaId}
        </if>
<!--        <if test="areaId != null">-->
<!--            WHERE area_id = #{areaId}-->
<!--        </if>-->
        UNION ALL
        SELECT ISNULL(SUM(anfme), 0) FROM asr_wrkin_view WHERE CONVERT(VARCHAR, io_time, 23) = CONVERT(VARCHAR, GETDATE(), 23)
        <if test="areaId != null">
            and area_id = #{areaId}
        </if>
<!--        <if test="areaId != null">-->
<!--            and area_id = #{areaId}-->
<!--        </if>-->
        UNION ALL
        SELECT ISNULL(SUM(anfme), 0) FROM asr_wrkout_view WHERE CONVERT(VARCHAR, io_time, 23) = CONVERT(VARCHAR, GETDATE(), 23)
        <if test="areaId != null">
            and area_id = #{areaId}
        </if>
<!--        <if test="areaId != null">-->
<!--            and area_id = #{areaId}-->
<!--        </if>-->
    </select>
    <select id="recentOrder" resultType="com.zy.asrs.entity.digitaltwin.DtOrderVo">
@@ -65,9 +65,9 @@
        SELECT CONVERT(VARCHAR, io_time, 23) AS boundDate, SUM(anfme) AS inBoundNum
        FROM asr_wrkin_view
        WHERE io_time BETWEEN #{startTime} AND #{endTime}
        <if test="areaId != null">
            and area_id = #{areaId}
        </if>
<!--        <if test="areaId != null">-->
<!--            and area_id = #{areaId}-->
<!--        </if>-->
        GROUP BY CONVERT(VARCHAR, io_time, 23)
    </select>
@@ -75,28 +75,31 @@
        SELECT CONVERT(VARCHAR, io_time, 23) AS boundDate, SUM(anfme) AS outBoundNum
        FROM asr_wrkout_view
        WHERE io_time BETWEEN #{startTime} AND #{endTime}
        <if test="areaId != null">
            and area_id = #{areaId}
        </if>
<!--        <if test="areaId != null">-->
<!--            and area_id = #{areaId}-->
<!--        </if>-->
        GROUP BY CONVERT(VARCHAR, io_time, 23)
    </select>
    <select id="recentDetainMat" resultType="com.zy.asrs.entity.digitaltwin.DtDetainMatVo">
        select
        *
        from (
            select
                ROW_NUMBER() OVER(Order by t.io_time desc) as row , *
            from (
                SELECT area_id AS belongAreaId, area_name AS belongAreaName, matnr AS matId, maktx AS matName,
                       loc_no AS lokId, '' AS lokName,
                       DATEDIFF(MINUTE, appe_time, GETDATE()) AS detainTime, appe_time AS inBoundTime
                    FROM asr_loc_detl WHERE appe_time &lt; #{startTime}
                <if test="areaId != null">
                    and area_id = #{areaId}
                </if>
                ) t
        ) a where 1=1 and a.row between ((#{pageIndex}-1)*#{pageSize}+1) and (#{pageIndex}*#{pageSize})
        SELECT *
        FROM (
                 SELECT
                     ROW_NUMBER() OVER(ORDER BY t.inBoundTime DESC) AS rownum,
                     t.*
                 FROM (
                          SELECT
                              matnr AS matId,
                              maktx AS matName,
                              loc_no AS lokId,
                              '' AS lokName,
                              DATEDIFF(MINUTE, appe_time, GETDATE()) AS detainTime,
                              appe_time AS inBoundTime
                          FROM asr_loc_detl
                          WHERE appe_time &lt;= #{startTime}
                      ) t
             ) a
        WHERE a.rownum BETWEEN ((#{pageIndex}-1)*#{pageSize}+1) AND (#{pageIndex}*#{pageSize})
    </select>
</mapper>
src/main/webapp/views/pakStore/groupinto.html
New file
@@ -0,0 +1,134 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        html {
            height: 100%;
            padding: 10px;
            background-color: #f1f1f1;
            box-sizing: border-box;
        }
        body {
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 0 3px rgba(0,0,0,.3);
        }
        .function-area {
            padding: 20px 50px;
        }
        .function-btn {
            font-size: 16px;
            padding: 1px 2px;
            width: 100px;
            height: 50px;
            border-color: #2b425b;
            border-radius: 4px;
            border-width: 2px;
            background: none;
            border-style: solid;
            transition: 0.4s;
            cursor: pointer;
            letter-spacing: 1.5px;
        }
        .function-btn:hover {
            background-color: #2b425b;
            color: #fff;
        }
        .layui-layer-page .layui-layer-content {
            position: relative;
            overflow: visible !important;
        }
        #mat-query {
            display: none;
        }
        #staNoSpan {
            text-align: center;
            display: inline-block;
            width: 100px;
            font-size: 13px;
        }
        .layui-btn-container .layui-form-select {
            display: inline-block;
            width: 150px;
            height: 30px;
        }
        .layui-btn-container .layui-form-select.layui-form-selected {
            display: inline-block;
            width: 150px;
        }
        .layui-btn-container .layui-select-title input {
            font-size: 13px;
        }
        .layui-btn-container .layui-anim.layui-anim-upbit dd {
            font-size: 13px;
        }
        #btn-comb {
            margin-left: 60px;
            display: none;
        }
    </style>
</head>
<body>
<!-- 功能区 -->
<div class="function-area">
    <button id="mat-query" class="function-btn">提取商品</button>
</div>
<hr>
<!-- 表格 -->
<div style="padding-bottom: 5px; margin-bottom: 45px">
    <!-- 头部 -->
    <script type="text/html" id="toolbar">
        <div class="layui-form">
            <div class="layui-btn-container">
                <!-- 1.选择入库口 -->
                <span id="staNoSpan">入库口:</span>
                <select id="putSiteSelect" lay-verify="required">
                    <option value="">请选择站点</option>
                </select>
                <!-- 2.启动入库 -->
                <button class="layui-btn layui-btn-normal layui-btn-lg" id="btn-comb" lay-event="comb" style="">启动入库</button>
            </div>
        </div>
    </script>
    <!-- 行 -->
    <script type="text/html" id="operate">
        <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="remove">移除</a>
    </script>
    <table class="layui-table" id="chooseData" lay-filter="chooseData"></table>
</div>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
<script type="text/javascript" src="../../static/js/pakStore/pakStore.js" charset="utf-8"></script>
<script type="text/template" id="putSiteSelectTemplate">
    {{#each data}}
        <option value="{{this}}">{{this}}</option>
    {{/each}}
</script>
</body>
</html>