自动化立体仓库 - WMS系统
#
pang.jiabao
4 天以前 2dc12d419733c094bb0bbc7ef4f7a32d5067cfb9
#
57个文件已添加
23个文件已修改
2 文件已重命名
4910 ■■■■■ 已修改文件
pom.xml 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/META-INF/MANIFEST.MF 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/DigitalTwinController.java 310 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/MesController.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/NodeController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/RcsController.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/AgvInfo.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BlockStation.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BlockTask.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/LocCount.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/LocDetl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/Task.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/WrkMast.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/digitaltwin/DtDetainMatVo.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/digitaltwin/DtEquipmentVo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/digitaltwin/DtInAndOutBoundVo.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/digitaltwin/DtLocDetailVo.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/digitaltwin/DtLocVo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/digitaltwin/DtOrderVo.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/digitaltwin/DtOverviewVo.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesCallOutApply.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesInApply.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesItemBarCode.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesItemDetails.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesMatInfo.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesMatRecvForm.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesOutApply.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesOutFeedback.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesParent.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesRecvFeedback.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/MesReturn.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/TransArrivalStation.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/TransInOutStationAllow.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/TransParent.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/TransTask.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/mes/TransTaskFeedback.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/rcs/RcsEqptNotify.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/rcs/RcsReporterEqpt.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/rcs/RcsReporterTask.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/rcs/RcsReturn.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/rcs/RcsTaskCancel.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/rcs/RcsTaskContinue.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/rcs/RcsTaskSubmit.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/rcs/RcsTaskTargetRoute.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/enums/RcsRetMethodEnum.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/AgvInfoMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BlockStationMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BlockTaskMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/DigitalTwinMapper.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/LocCountMapper.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/DigitalTwinService.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/MesService.java 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/RcsService.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/DigitalTwinServiceImpl.java 272 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MatServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MesServiceImpl.java 1090 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/RcsServiceImpl.java 614 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WrkDetlServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/BlockScheduler.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/OrderSyncScheduler.java 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/WorkMastScheduler.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/OrderSyncHandler.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/LogAspect.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/config/WebConfig.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/route/RouteFilter.java 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/web/WcsController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/system/timer/LicenseTimer.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/libs/framework-3.2.0.jar 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/logback-spring.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BlockStationMapper.xml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BlockTaskMapper.xml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/LocCountMapper.xml 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/ViewDigitalTwinMapper.xml 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/common.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/mat/mat.js 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/basWhs/basWhs.html 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/pda/comb.html 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/pda/login.html 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/pda/matQuery.html 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -9,13 +9,13 @@
        <relativePath/>
    </parent>
    <groupId>com.zy</groupId>
    <artifactId>asrs</artifactId>t
    <artifactId>asrs</artifactId>
    <version>1.1.1</version>
    <packaging>war</packaging>
    <properties>
        <java.version>1.8</java.version>
        <cool.version>3.4.0</cool.version>
        <cool.version>3.2.0</cool.version>
        <mysql-driver.version>5.1.47</mysql-driver.version>
        <mybatis-plus.version>2.3.2</mybatis-plus.version>
        <fastjson.version>1.2.58</fastjson.version>
@@ -44,6 +44,8 @@
            <groupId>cn.cool</groupId>
            <artifactId>framework</artifactId>
            <version>${cool.version}</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/libs/framework-3.2.0.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>org.apache.tika</groupId>
@@ -103,6 +105,8 @@
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
<!--            <version>1.18.30</version>-->
<!--            <optional>true</optional>-->
            <version>1.16.22</version>
            <scope>provided</scope>
        </dependency>
@@ -120,13 +124,42 @@
    </dependencies>
    <build>
        <finalName>wms</finalName>
        <finalName>djwms</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
<!--            <plugin>-->
<!--                <groupId>org.apache.maven.plugins</groupId>-->
<!--                <artifactId>maven-compiler-plugin</artifactId>-->
<!--                <version>3.10.1</version>-->
<!--                <configuration>-->
<!--                    <source>1.8</source>-->
<!--                    <target>1.8</target>-->
<!--                    <encoding>UTF-8</encoding>-->
<!--                    <compilerArgs>-->
<!--                        <arg>-parameters</arg>-->
<!--                    </compilerArgs>-->
<!--                    <compilerArguments>-->
<!--                        <extdirs>${project.basedir}/src/main/resources/libs</extdirs>-->
<!--                    </compilerArguments>-->
<!--                </configuration>-->
<!--            </plugin>-->
        </plugins>
<!--        <resources>-->
<!--            <resource>-->
<!--                <directory>src/main/resources</directory>-->
<!--                <includes>-->
<!--&lt;!&ndash;                    <include>**/log/**</include>&ndash;&gt;-->
<!--                    <include>**/libs/**</include>-->
<!--&lt;!&ndash;                    <include>**/*.properties</include>&ndash;&gt;-->
<!--&lt;!&ndash;                    <include>**/*.xml</include>&ndash;&gt;-->
<!--                </includes>-->
<!--                <filtering>false</filtering>-->
<!--            </resource>-->
<!--        </resources>-->
    </build>
</project>
src/main/java/META-INF/MANIFEST.MF
New file
@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: com.zy.Boot
src/main/java/com/zy/asrs/controller/DigitalTwinController.java
New file
@@ -0,0 +1,310 @@
package com.zy.asrs.controller;
import com.core.common.R;
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.entity.digitaltwin.*;
import com.zy.asrs.service.DigitalTwinService;
import com.zy.common.web.BaseController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@RequestMapping("/digitalTwin")
@RestController
public class DigitalTwinController extends BaseController {
    @Resource
    private DigitalTwinService digitalTwinService;
    /**
     * 数据总览
     *
     * @param areaId    库区编码
     * @return
     */
    @RequestMapping(value = "/overview")
//    @ManagerAuth
    public R overview(@RequestParam(required = false) String areaId){
        //digitalTwinService.overview(areaId);
        DtOverviewVo dtOverviewVo = DtOverviewVo.builder()
                .totalLoc(999)
                .useLoc(900)
                .idleLoc(99)
                .todayOutbound(160)
                .todayWarehousing(170)
                .remainingStock(180)
                .build();
        return R.ok().add(dtOverviewVo);
    }
    /**
     * 近期订单(默认7天)
     *
     * @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){
//        digitalTwinService.order(startDate, endDate);
        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);
        return R.ok().add(orderVoList);
    }
    /**
     * 近期剩余库位(默认7天)
     *
     * @param areaId    库区编码
     * @param startDate 格式:yyyyMMdd,20251022
     * @param endDate   格式:yyyyMMdd,20251027
     * @return
     */
    @RequestMapping(value = "/recentIdleLoc")
//    @ManagerAuth
    public R recentIdleLoc(@RequestParam(required = false) String areaId,
                           @RequestParam(required = false) String startDate,
                         @RequestParam(required = false) String endDate){
//        digitalTwinService.recentLoc(areaId, startDate, endDate);
        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);
        return R.ok().add(locVoList);
    }
    /**
     * 近期出入库(默认7天)
     *
     * @param areaId    库区编码
     * @param startDate 格式:yyyyMMdd,20251022
     * @param endDate   格式:yyyyMMdd,20251027
     * @return
     */
    @RequestMapping(value = "/recentInAndOutBound")
//    @ManagerAuth
    public R recentInAndOutBound(@RequestParam(required = false) String areaId,
                           @RequestParam(required = false) String startDate,
                           @RequestParam(required = false) String endDate){
//        digitalTwinService.inAndOutBound(areaId, startDate, endDate);
        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);
        return R.ok().add(inAndOutBoundVoList);
    }
    /**
     * 近期呆滞品(默认超30天)
     *
     * @param areaId    库区编码
     * @param overDayNum 呆滞品天数,默认30天
     * @return
     */
    @RequestMapping(value = "/recentDetainMat")
//    @ManagerAuth
    public R recentDetainMat(@RequestParam(required = false) String areaId,
                             @RequestParam(required = false) Integer overDayNum,
                             @RequestParam(required = false) Integer pageIndex,
                             @RequestParam(required = false) Integer pageSize){
//        digitalTwinService.recentDetainMat(areaId, overDayNum, pageIndex, pageSize);
        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);
        return R.ok().add(detainMatVoList);
    }
    /**
     * 设备运行信息
     *
     * @param areaId
     * @return
     */
    @RequestMapping(value = "/equipment")
//    @ManagerAuth
    public R equipment(@RequestParam(required = false) String areaId){
        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);
        return R.ok().add(dtEquipmentVoList);
    }
    /**
     * 库位和库存详情
     *
     * @param areaId
     * @return
     */
    @RequestMapping(value = "/warehouseDetail")
//    @ManagerAuth
    public R warehouseDetail(@RequestParam(required = false) String areaId){
//        digitalTwinService.warehouseDetail(areaId);
        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("物料名称");
        locDetl.setAnfme(100.0);
        locDetl.setStandby3("AAA,BBB,CCC");
        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("刀具库");
        locDetl.setMatnr("mat10001");
        locDetl.setMaktx("物料名称");
        locDetl.setAnfme(100.0);
        locDetl.setStandby3("AAA1,BBB1,CCC1");
        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);
        return R.ok().add(dtLocDetailVoList);
    }
}
src/main/java/com/zy/asrs/controller/MesController.java
New file
@@ -0,0 +1,100 @@
package com.zy.asrs.controller;
import com.alibaba.fastjson.JSONObject;
import com.core.common.R;
import com.zy.asrs.entity.mes.*;
import com.zy.asrs.service.MesService;
import com.zy.common.web.BaseController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
public class MesController extends BaseController {
    @Resource
    private MesService mesService;
    // 物料信息同步
    @PostMapping("/api/mes/synMatInfo")
    public MesReturn synMatInfo(@RequestBody MesMatInfo param){
        MesReturn mesReturn = new MesReturn();
        mesReturn.setSuccess(mesService.synMatInfo(param) == 1 ? "1" : "2");
        return mesReturn;
    }
    // 出库申请
    @PostMapping("/api/mes/outBoundOrder")
    public MesReturn outBoundOrder(@RequestBody MesInApply param){
        MesReturn mesReturn = new MesReturn();
        mesReturn.setSuccess(mesService.outBoundOrder(param) == 1 ? "1" : "2");
        return mesReturn;
    }
//    // 出库申请(叫料),装配库、滑块库
//    @PostMapping("/api/mes/callOutBoundOrder")
//    public MesReturn callOutBoundOrder(@RequestBody MesCallOutApply param){
//
//        MesReturn mesReturn = new MesReturn();
//        mesReturn.setSuccess(mesService.callOutBoundOrder(param) == 1 ? "1" : "2");
//        return mesReturn;
//    }
    // 入库申请
    @PostMapping("/api/mes/inBoundOrder")
    public MesReturn inBoundOrder(@RequestBody MesInApply param){
        MesReturn mesReturn = new MesReturn();
        mesReturn.setSuccess(mesService.inBoundOrder(param, 0) == 1 ? "1" : "2");
        return mesReturn;
    }
    // 入站允许
    @PostMapping("/api/mes/allowInStation")
    public MesReturn allowInStation(@RequestBody TransInOutStationAllow param){
        return mesService.allowInStation(param);
    }
    // 离站允许,装配库、滑块库
    @PostMapping("/api/mes/allowOutStation")
    public MesReturn allowOutStation(@RequestBody TransInOutStationAllow param){
        return mesService.allowOutStation(param);
    }
    // 下发运输任务
    @PostMapping("/api/mes/submitTask")
    public JSONObject submitTask(@RequestBody TransTask param){
        return mesService.submitTask(param);
    }
    // 接受成品刀可以入库二维码
    @PostMapping("/api/mes/inBoundItemBarcode")
    public MesReturn inBoundItemBarcode(@RequestBody MesItemBarCode param){
        MesReturn mesReturn = new MesReturn();
        mesReturn.setSuccess("1"); // TODO:待缓存成品刀二维码;
        return mesReturn;
    }
    // region 测试
    @GetMapping("/api/mes/transDj")
    public int transDj(@RequestParam String taskNo,@RequestParam String djNo){
        return mesService.transDj(taskNo,djNo);
    }
    // 退空托盘返回产线 pda上操作空托返回产线
    @GetMapping("/tkt")
    public R tkt(@RequestParam String taskNo){
         return mesService.tkt(taskNo);
    }
    // endregion
}
src/main/java/com/zy/asrs/controller/NodeController.java
@@ -35,7 +35,7 @@
import java.net.URLEncoder;
import java.util.*;
import static jdk.nashorn.api.scripting.ScriptUtils.convert;
//import static jdk.nashorn.api.scripting.ScriptUtils.convert;
@RestController
public class NodeController extends BaseController {
src/main/java/com/zy/asrs/controller/RcsController.java
New file
@@ -0,0 +1,44 @@
package com.zy.asrs.controller;
import com.alibaba.fastjson.JSONObject;
import com.zy.asrs.entity.mes.TransParent;
import com.zy.asrs.entity.rcs.RcsReporterEqpt;
import com.zy.asrs.entity.rcs.RcsReporterTask;
import com.zy.asrs.entity.rcs.RcsReturn;
import com.zy.asrs.service.RcsService;
import com.zy.common.web.BaseController;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class RcsController extends BaseController {
    @Resource
    private RcsService rcsService;
    // 反馈任务执行结果
    @PostMapping("/api/robot/reporter/task")
    public RcsReturn reporterTask(@RequestBody RcsReporterTask param){
        return rcsService.reporterTask(param);
    }
    // 反馈封锁区(自动门)申请
    @PostMapping("/api/robot/reporter/eqpt")
    public RcsReturn reporterEqpt(@RequestBody RcsReporterEqpt param){
        return rcsService.reporterEqpt(param);
    }
    // 华晓AGV申请进入产线(光幕)
    @PostMapping("/api/robot/apply/inLine")
    public JSONObject hxApplyInLine(@RequestBody TransParent param){
        return rcsService.hxApplyInLine(param);
    }
}
src/main/java/com/zy/asrs/entity/AgvInfo.java
New file
@@ -0,0 +1,53 @@
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.io.Serializable;
@Data
@TableName("agv_info")
public class AgvInfo implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 主键,设备编号
     */
    @ApiModelProperty(value= "主键")
    @TableId(value = "agvNo", type = IdType.AUTO)
    private String agvNo;
    /**
     * 设备名称
     */
    @ApiModelProperty(value= "设备名称")
    @TableField("agv_name")
    private String agvName;
    /**
     * 设备类型,1 agv;2 ctu;
     */
    @ApiModelProperty(value= "设备类型")
    @TableField("agv_type")
    private String agvType;
    /**
     * 设备厂家,1 海康;2 华晓;
     */
    @ApiModelProperty(value= "设备类型")
    @TableField("agv_factory")
    private Integer agvFactory;
    /**
     * 所属库区
     */
    @ApiModelProperty(value= "所属库区")
    @TableField("belong_area")
    private String belongArea;
}
src/main/java/com/zy/asrs/entity/BlockStation.java
New file
@@ -0,0 +1,81 @@
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.io.Serializable;
@Data
@TableName("agv_block_station")
public class BlockStation implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 主键
     */
    @ApiModelProperty(value= "主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 站点编号
     */
    @ApiModelProperty(value= "站点id")
    @TableField("dev_no")
    private String devNo;
    /**
     * 站点名称
     */
    @ApiModelProperty(value= "站点名称")
    @TableField("dec_name")
    private String decName;
    /**
     * 封锁区id
     */
    @ApiModelProperty(value= "封锁区id")
    @TableField("block_no")
    private String blockNo;
    /**
     * 封锁区名称
     */
    @ApiModelProperty(value= "封锁区名称")
    @TableField("block_name")
    private String blockName;
    /**
     * 所属库区id
     */
    @ApiModelProperty(value= "所属库区id")
    @TableField("area_id")
    private String areaId;
    /**
     * 所属库区名称
     */
    @ApiModelProperty(value= "所属库区名称")
    @TableField("area_name")
    private String areaName;
    /**
     * 状态,0 空闲;1 海康封锁中;2 华晓封锁中;-1 异常;
     */
    @ApiModelProperty(value= "状态")
    @TableField("status")
    private Integer status;
    /**
     * 封锁区内agv数量
     */
    @ApiModelProperty(value= "状态")
    @TableField("agv_num")
    private Integer agvNum;
}
src/main/java/com/zy/asrs/entity/BlockTask.java
New file
@@ -0,0 +1,74 @@
package com.zy.asrs.entity;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
@TableName("agv_block_task")
public class BlockTask implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 主键,请求号
     */
    @ApiModelProperty(value= "主键")
    @TableId(value = "task_code")
    private String taskCode;
    /**
     * 请求时间
     */
    @ApiModelProperty(value= "请求时间")
    @TableField("apply_time")
    private Date applyTime;
    /**
     * 封锁区id
     */
    @ApiModelProperty(value= "封锁区id")
    @TableField("block_no")
    private String blockNo;
    /**
     * 封锁区名称
     */
    @ApiModelProperty(value= "封锁区名称")
    @TableField("block_name")
    private String blockName;
    /**
     * 进入方法,APPLY_LOCK 申请封锁区;RELEASE_EQPT 释放封锁区;
     */
    @ApiModelProperty(value= "进入方法")
    @TableField("method")
    private String method;
    /**
     * 是否完成,1 完成;0 未完成;
     */
    @ApiModelProperty(value= "是否完成")
    @TableField("completed")
    private Integer completed;
    /**
     * 完成时间
     */
    @ApiModelProperty(value= "完成时间")
    @TableField("completed_time")
    private Date completedTime;
    /**
     * agv厂家,1 海康;2 华晓;
     */
    @ApiModelProperty(value= "agv厂家")
    @TableField("agv_factory")
    private Integer agvFactory;
}
src/main/java/com/zy/asrs/entity/LocCount.java
New file
@@ -0,0 +1,41 @@
package com.zy.asrs.entity;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@TableName("asr_loc_count")
public class LocCount {
    private static final long serialVersionUID = 1L;
    /**
     * 日期
     */
    @ApiModelProperty(value= "日期,格式:20250101")
    @TableField("date")
    private Integer date;
    /**
     * 库区号
     */
    @ApiModelProperty(value= "库区号")
    @TableField("area_id")
    private String areaId;
    /**
     * 库位数量
     */
    @ApiModelProperty(value= "库位数量")
    @TableField("loc_num")
    private Integer locNum;
    /**
     * 剩余库位数量
     */
    @ApiModelProperty(value= "剩余库位数量")
    @TableField("remain_num")
    private Integer remainNum;
}
src/main/java/com/zy/asrs/entity/LocDetl.java
@@ -121,7 +121,8 @@
    private Double weight;
    @ApiModelProperty(value= "长度")
    private Double man_length;
    @TableField("man_length")
    private Double manLength;
    @ApiModelProperty(value= "体积")
    private Double volume;
src/main/java/com/zy/asrs/entity/Task.java
@@ -334,6 +334,13 @@
    @TableField("take_none")
    private String takeNone;
    /**
     * 外部任务编号
     */
    @ApiModelProperty(value= "外部任务编号")
    @TableField("task_no")
    private String taskNo;
    public Task() {}
    public String getYmd$(){
src/main/java/com/zy/asrs/entity/WrkMast.java
@@ -325,6 +325,13 @@
    @TableField("take_none")
    private String takeNone;
    /**
     * 外部任务编号
     */
    @ApiModelProperty(value= "外部任务编号")
    @TableField("task_no")
    private String taskNo;
    public WrkMast() {}
    public String getYmd$(){
src/main/java/com/zy/asrs/entity/digitaltwin/DtDetainMatVo.java
New file
@@ -0,0 +1,28 @@
package com.zy.asrs.entity.digitaltwin;
import lombok.Builder;
import lombok.Data;
// 数字孪生:呆滞品信息
@Data
@Builder
public class DtDetainMatVo {
    // 归属库区ID
    private String belongAreaId;
    // 归属库区名称
    private String belongAreaName;
    // 物料ID
    private String matId;
    // 物料名称
    private String matName;
    // 所属库位ID
    private String lokId;
    // 所属库位名称
    private String lokName;
    // 呆滞时间,计算单位:分钟
    private Integer detainTime;
    // 入库时间,格式:2025-10-11T11:15:16,预留
    private String inBoundTime;
}
src/main/java/com/zy/asrs/entity/digitaltwin/DtEquipmentVo.java
File was renamed from src/main/java/com/zy/asrs/entity/result/DtEquipmentVo.java
@@ -1,4 +1,4 @@
package com.zy.asrs.entity.result;
package com.zy.asrs.entity.digitaltwin;
import lombok.Builder;
import lombok.Data;
src/main/java/com/zy/asrs/entity/digitaltwin/DtInAndOutBoundVo.java
New file
@@ -0,0 +1,17 @@
package com.zy.asrs.entity.digitaltwin;
import lombok.Builder;
import lombok.Data;
// 数字孪生:按天出入库数量
@Data
@Builder
public class DtInAndOutBoundVo {
    // 日期
    private String boundDate;
    // 入库数量
    private Integer inBoundNum;
    // 出库数量
    private Integer outBoundNum;
}
src/main/java/com/zy/asrs/entity/digitaltwin/DtLocDetailVo.java
New file
@@ -0,0 +1,30 @@
package com.zy.asrs.entity.digitaltwin;
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.LocMast;
import lombok.Data;
@Data
public class DtLocDetailVo  {
    // 库位号
    private String locNo;
    // 库位状态,O空库位(英文不是数字);F 在库;D 空板;P 出库中;R 出库预约;S 入库预约;其他 其他;
    private String locSts;
    // 库区id
    private Long areaId;
    // 库区名称
    private String areaName;
    // 排
    private Integer row1;
    // 列
    private Integer bay1;
    // 层
    private Integer lev1;
    // 库位信息
    private LocMast locMast;
    // 库存信息
    private LocDetl locDetl;
}
src/main/java/com/zy/asrs/entity/digitaltwin/DtLocVo.java
File was renamed from src/main/java/com/zy/asrs/entity/result/DtLocVo.java
@@ -1,4 +1,4 @@
package com.zy.asrs.entity.result;
package com.zy.asrs.entity.digitaltwin;
import lombok.Builder;
import lombok.Data;
src/main/java/com/zy/asrs/entity/digitaltwin/DtOrderVo.java
New file
@@ -0,0 +1,15 @@
package com.zy.asrs.entity.digitaltwin;
import lombok.Builder;
import lombok.Data;
// 数字孪生:按天订单数量
@Data
@Builder
public class DtOrderVo {
    // 日期
    private String orderDate;
    // 订单数量
    private Integer orderNum;
}
src/main/java/com/zy/asrs/entity/digitaltwin/DtOverviewVo.java
New file
@@ -0,0 +1,24 @@
package com.zy.asrs.entity.digitaltwin;
import lombok.Builder;
import lombok.Data;
// 数字孪生:按天出库、入库数量
@Data
@Builder
public class DtOverviewVo {
    // 总库位
    private Integer totalLoc;
    // 已用库位
    private Integer useLoc;
    // 剩余库位
    private Integer idleLoc;
    // 今日出库
    private Integer todayOutbound;
    // 今日入库
    private Integer todayWarehousing;
    // 剩余库存
    private Integer remainingStock;
}
src/main/java/com/zy/asrs/entity/mes/MesCallOutApply.java
New file
@@ -0,0 +1,61 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
// 出库申请(叫料)
@EqualsAndHashCode(callSuper = true)
@Data
public class MesCallOutApply extends MesParent {
//    // 任务编号
//    private String taskno;
//    // 任务名称
//    private String taskname;
//    // 生产订单号
//    @JsonProperty("OrderNo")
//    private String OrderNo;
    // 运输类型,字典值(wms_tranfs_type) 06 装配领料;01:空托
    @JsonProperty("TransType")
    @JSONField(name = "TransType")
    private String TransType;
//    // 生产线编码
//    @JsonProperty("ProductLineId")
//    private String ProductLineId;
//    // 工位编码
//    @JsonProperty("StationId")
//    private String StationId;
    // 当前工序
    @JsonProperty("CurProcess")
    @JSONField(name = "CurProcess")
    private String CurProcess;
    // 配盘信息
    @JsonProperty("Itemdata")
    @JSONField(name = "Itemdata")
    private List<MesOutApplyItem> Itemdata;
    // (sfc_shop_route_consume)mes中配盘表名
    @Data
    public static class MesOutApplyItem {
        // 配盘号
        private String trayid;
        // 零件编码
        @JsonProperty("Itemno")
        @JSONField(name = "Itemno")
        private String Itemno;
        // 数量
        @JsonProperty("Qty")
        @JSONField(name = "Qty")
        private Integer Qty;
        // 物料二维码
        @JsonProperty("ItemBarcode")
        @JSONField(name = "ItemBarcode")
        private String ItemBarcode;
    }
}
src/main/java/com/zy/asrs/entity/mes/MesInApply.java
New file
@@ -0,0 +1,124 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
// MES入库申请\入库完成
//@EqualsAndHashCode(callSuper = true)
@Data
public class MesInApply  {  //extends MesParent
//    public MesInApply() {
//        Details = new ArrayList<>();
//    }
    // 单据类型,0 采购入库;1 生产入库;2 退货入库;
    @JsonProperty("billType")
    @JSONField(name = "billType")
    private String billType;
    //    // 生产线编码
    @JsonProperty("productLineId")
    private String productLineId;
//    // 工位编码
    @JsonProperty("stationId")
    private String stationId;
    // 生产订单号
    @JsonProperty("orderNo")
    @JSONField(name = "orderNo")
    private String orderNo;
    // agv任务号
    @JsonProperty("taskNo")
    @JSONField(name = "taskNo")
    private String taskNo;
    // agv运输类型
    @JsonProperty("transType")
    @JSONField(name = "transType")
    private String transType;
    // 时间,格式:2025-11-19 10:11:12
    @JsonProperty("createTime")
    @JSONField(name = "createTime")
    private String createTime;
    // 入库详情
    @JsonProperty("details")
    @JSONField(name = "details")
    private List<MesItemDetails> details;
//    @Data
//    @NoArgsConstructor
//    public static class ItemDetails {
//
//        // 物料编码
//        @JsonProperty("itemNo")
//        @JSONField(name = "itemNo")
//        private String itemNo;
//
//        // 数量
//        @JsonProperty("anfme")
//        @JSONField(name = "anfme")
//        private String anfme;
//    }
//
////    // 任务编号
////    private String taskno;
////    // 任务名称
////    private String taskname;
////    // 生产线编码
////    @JsonProperty("ProductLineId")
////    private String ProductLineId;
////    // 工位编码
////    @JsonProperty("StationId")
////    private String StationId;
//    // 零件编码
//    @JsonProperty("Itemno")
//    @JSONField(name = "Itemno")
//    private String Itemno;
////    // 托盘条码
////    @JsonProperty("TuoPanId")
////    @JSONField(name = "TuoPanId")
////    private String TuoPanId;
//    // 数量,托盘零件数量
//    @JsonProperty("Qty")
//    @JSONField(name = "Qty")
//    private Float Qty;
//    // 版本号
//    @JsonProperty("VersionNo")
//    @JSONField(name = "VersionNo")
//    private String VersionNo;
////    // 生产订单号
////    @JsonProperty("OrderNo")
////    private String OrderNo;
//    // 配盘信息
//    @JsonProperty("ProductInfo")
//    @JSONField(name = "ProductInfo")
//    private List<ProductInfo> ProductInfo;
//
//    @Data
//    @NoArgsConstructor
//    public static class ProductInfo {
//
//        // 物料二维码
//        @JsonProperty("ItemBarcode")
//        @JSONField(name = "ItemBarcode")
//        private String ItemBarcode;
//        // 质量状态
//        @JsonProperty("QualityStatus")
//        @JSONField(name = "QualityStatus")
//        private Integer QualityStatus;
//    }
}
src/main/java/com/zy/asrs/entity/mes/MesItemBarCode.java
New file
@@ -0,0 +1,34 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class MesItemBarCode {
    // 刀具RFID码
    @JSONField(name = "ToolRfidCode")
    @JsonProperty("ToolRfidCode")
    private String ToolRfidCode;
    // 刀具名称
    @JSONField(name = "ToolName")
    @JsonProperty("ToolName")
    private String ToolName;
    // 刀具种类编码
    @JSONField(name = "ToolCode")
    @JsonProperty("ToolCode")
    private String ToolCode;
    // 机床刀号
    @JSONField(name = "MachineToolNo")
    @JsonProperty("MachineToolNo")
    private String MachineToolNo;
    // 版本
    @JSONField(name = "Version")
    @JsonProperty("Version")
    private String Version;
}
src/main/java/com/zy/asrs/entity/mes/MesItemDetails.java
New file
@@ -0,0 +1,19 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class MesItemDetails {
    // 物料编码
    @JsonProperty("itemNo")
    @JSONField(name = "itemNo")
    private String itemNo;
    // 数量
    @JsonProperty("anfme")
    @JSONField(name = "anfme")
    private Double anfme;
}
src/main/java/com/zy/asrs/entity/mes/MesMatInfo.java
New file
@@ -0,0 +1,67 @@
package com.zy.asrs.entity.mes;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
// MES物料信息
@Data
public class MesMatInfo {
    // 物料编码,唯一标识
    @NotNull
    private String item_no;
    // 物料名称
    @NotNull
    private String description;
    // 单位
    private String unit_of_measure;
    // 物料类型
    @NotNull
    private String item_type;
    // 材质
    private String cz;
    // 重量
    private float weight;
    // 物料属性
    @NotNull
    private String classification_code;
    // 图号
    private String drawing_no;
    // 设计备注
    private String item_comments;
    // 创建时间,timestamp
    private String create_date;
    // 最近一次修改时间,timestamp
    private String modified_date1;
    // 最近修改人
    private String modified_operator1;
    // 生产单位
    private String dept;
    // 是否关键件
    private String gt_code;
    // 规格型号
    private String specification;
    // 工艺备注
    private String proc_comments;
    // 工艺修改人
    private String proc_operator;
    // 工艺修改时间,timestamp
    private String proc_modified_date;
    // ABC码
    private String abc_code;
    // 供应商编码
    private String vendor_no;
    // 版本号
    private String drawing_version;
    // 生产订单号
    @NotNull
    @JsonProperty("OrderNo")
//    @JSONField(name = "OrderNo")
    private String OrderNo;
    // 本单入库数量
    @NotNull
    private Float qty;
}
src/main/java/com/zy/asrs/entity/mes/MesMatRecvForm.java
New file
@@ -0,0 +1,17 @@
package com.zy.asrs.entity.mes;
import lombok.Data;
// MES发出的领料入库单
@Data
public class MesMatRecvForm {
    // 来源单号
    private String source_no;
    // 来源单名称
    private String source_name;
    // 操作人
    private String operuser;
    // 物料信息
    private MesMatInfo itemdata;
}
src/main/java/com/zy/asrs/entity/mes/MesOutApply.java
New file
@@ -0,0 +1,46 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
// 出库申请
@EqualsAndHashCode(callSuper = true)
@Data
public class MesOutApply extends MesParent {
//    // 任务编号
//    private String taskno;
//    // 任务名称
//    private String taskname;
//    // 生产订单号
//    @JsonProperty("OrderNo")
//    @JSONField(name = "OrderNo")
//    private String OrderNo;
    // 运输类型,字典值(wms_tranfs_type) 06 装配领料;01:空托
    @JsonProperty("TransType")
    @JSONField(name = "TransType")
    private String TransType;
    // 零件编码
    @JsonProperty("Itemno")
    @JSONField(name = "Itemno")
    private String Itemno;
    // 数量
    @JsonProperty("Qty")
    @JSONField(name = "Qty")
    private Integer Qty;
//    // 生产线编码
//    @JsonProperty("ProductLineId")
//    @JSONField(name = "ProductLineId")
//    private String ProductLineId;
//    // 工位编码
//    @JsonProperty("StationId")
//    @JSONField(name = "StationId")
//    private String StationId;
    // 物料二维码
    @JsonProperty("ItemBarcode")
    @JSONField(name = "ItemBarcode")
    private String ItemBarcode;
}
src/main/java/com/zy/asrs/entity/mes/MesOutFeedback.java
New file
@@ -0,0 +1,45 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
// 返回MES出库完成
@EqualsAndHashCode(callSuper = true)
@Data
public class MesOutFeedback extends MesParent {
//    // 任务编号
//    private String taskno;
//    // 任务名称
//    private String taskname;
//    // 生产线编码
//    @JsonProperty("ProductLineId")
//    @JSONField(name = "ProductLineId")
//    private String ProductLineId;
//    // 工位编码
//    @JsonProperty("StationId")
//    @JSONField(name = "StationId")
//    private String StationId;
    // 零件编码
    @JsonProperty("Itemno")
    @JSONField(name = "Itemno")
    private String Itemno;
    // 托盘条码
    @JsonProperty("TuoPanId")
    @JSONField(name = "TuoPanId")
    private String TuoPanId;
    // 数量,托盘零件数量
    @JsonProperty("Qty")
    @JSONField(name = "Qty")
    private Integer Qty;
    // 物料二维码
    @JsonProperty("ItemBarcode")
    @JSONField(name = "ItemBarcode")
    private String ItemBarcode;
//    // 生产订单号
//    @JsonProperty("OrderNo")
//    @JSONField(name = "OrderNo")
//    private String OrderNo;
}
src/main/java/com/zy/asrs/entity/mes/MesParent.java
New file
@@ -0,0 +1,39 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class MesParent {
    // 任务编号
    @JsonProperty("taskno")
    @JSONField(name = "taskno")
    private String taskno;
    // 任务名称
    @JsonProperty("taskname")
    @JSONField(name = "taskname")
    private String taskname;
    // 生产订单号
    @JsonProperty("OrderNo")
    @JSONField(name = "OrderNo")
    private String OrderNo;
    // 生产线编码
    @JsonProperty("ProductLineId")
    @JSONField(name = "ProductLineId")
    private String ProductLineId;
    // 工位编码
    @JsonProperty("StationId")
    @JSONField(name = "StationId")
    private String StationId;
//    // 零件编码
//    @JsonProperty("Itemno")
//    @JSONField(name = "Itemno")
//    private String Itemno;
//    // 数量,托盘零件数量
//    @JsonProperty("Qty")
//    @JSONField(name = "Qty")
//    private Float Qty;
}
src/main/java/com/zy/asrs/entity/mes/MesRecvFeedback.java
New file
@@ -0,0 +1,32 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import java.util.List;
// 入库反馈
@Data
public class MesRecvFeedback {
    // 来源单号
    private String source_no;
    // 操作人
    private String operuser;
    // 反馈信息
    private List<MesRecvFeedbackItem> itemdata;
    @Data
    public static class MesRecvFeedbackItem {
        // 物料编码
        private String item_no;
        // 生产订单号
        @JSONField(name = "OrderNo")
        private String OrderNo;
        // 本单入库数量
        private Integer qty;
        // 本单实际数量
        private Integer real_qty;
    }
}
src/main/java/com/zy/asrs/entity/mes/MesReturn.java
New file
@@ -0,0 +1,38 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
// MES接口返回结果
public class MesReturn {
    // 1:成功;2:失败
    @JsonProperty("Success")
    private String Success;
    // 失败消息
    @JsonProperty("Message")
    private String Message;
    @JsonProperty("Success")
    public String getSuccess() {
        return Success;
    }
    @JsonProperty("Success")
    public void setSuccess(String success) {
        this.Success = success;
    }
    @JsonProperty("Message")
    public String getMessage() {
        return Message;
    }
    @JsonProperty("Message")
    public void setMessage(String message) {
        this.Message = message;
    }
}
src/main/java/com/zy/asrs/entity/mes/TransArrivalStation.java
New file
@@ -0,0 +1,61 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
// 到站完成
//@EqualsAndHashCode(callSuper = true)
@Data
public class TransArrivalStation {
    // 任务编号
    @JsonProperty("taskno")
    @JSONField(name = "taskno")
    private String taskno;
    // 任务名称
    @JsonProperty("taskname")
    @JSONField(name = "taskname")
    private String taskname;
    // 生产订单号
    @JsonProperty("OrderNo")
    @JSONField(name = "OrderNo")
    private String OrderNo;
    // 生产线编码
    @JsonProperty("ProductLineId")
    @JSONField(name = "ProductLineId")
    private String ProductLineId;
    // 工位编码
    @JsonProperty("StationID")
    @JSONField(name = "StationID")
    private String StationID;
    // 到站类型,06:装配领料,07:装配入库,08:装配转序
    @JsonProperty("Daotype")
    @JSONField(name = "Daotype")
    private String Daotype;
    // 托盘条码
    @JsonProperty("TuoPanId")
    @JSONField(name = "TuoPanId")
    private String TuoPanId;
    // AGV编码
    @JsonProperty("AgvCode")
    @JSONField(name = "AgvCode")
    private String AgvCode;
    // 物料编码
    @JsonProperty("Itemno")
    @JSONField(name = "Itemno")
    private String Itemno;
    // 零件码
    @JsonProperty("ItemBarcode")
    @JSONField(name = "ItemBarcode")
    private List<String> ItemBarcode;
    // 刀架编号
    @JsonProperty("DJNo")
    @JSONField(name = "DJNo")
    private String DJNo;
}
src/main/java/com/zy/asrs/entity/mes/TransInOutStationAllow.java
New file
@@ -0,0 +1,13 @@
package com.zy.asrs.entity.mes;
import lombok.Data;
import lombok.EqualsAndHashCode;
// 入站允许、离站允许
@EqualsAndHashCode(callSuper = true)
@Data
public class TransInOutStationAllow extends TransParent {
    // 是否允许,Y 允许;N,不允许
    private String status;
}
src/main/java/com/zy/asrs/entity/mes/TransParent.java
New file
@@ -0,0 +1,31 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
// 出入站请求继承父类:入站请求、入站允许、离站请求、离站允许、离站完成
@Data
public class TransParent {
    // 任务编号,wcs_task_header表中的task_no
    private String taskno;
    // 任务名称,wcs_task_header表中的task_name
    private String taskname;
    // AGV编码
    @JsonProperty("AgvCode")
    @JSONField(name = "AgvCode")
    private String AgvCode;
    // 运输类型
    @JsonProperty("TransType")
    @JSONField(name = "TransType")
    private String TransType;
    // 生产线编码
    @JsonProperty("ProductLineId")
    @JSONField(name = "ProductLineId")
    private String ProductLineId;
    // 工位编码
    @JsonProperty("StationId")
    @JSONField(name = "StationId")
    private String StationId;
}
src/main/java/com/zy/asrs/entity/mes/TransTask.java
New file
@@ -0,0 +1,68 @@
package com.zy.asrs.entity.mes;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
// MES运输任务
@Data
public class TransTask {
    // 任务编号,wcs_task_header表中的task_no
    private String taskno;
    // 任务名称,wcs_task_header表中的task_name
    private String taskname;
    // 生产订单号
    @JsonProperty("OrderNo")
    @JSONField(name = "OrderNo")
    private String OrderNo;
    // 运输类型,01:空托,02:毛坯,03:成品,04:转序,本接口为转序
    @JsonProperty("TransType")
    @JSONField(name = "TransType")
    private String TransType;
    // 当前工序,通过当前任务
    @JsonProperty("CurProcess")
    @JSONField(name = "CurProcess")
    private String CurProcess;
    // 起点编码
    @JsonProperty("CurStationId")
    @JSONField(name = "CurStationId")
    private String CurStationId;
    // 下一工位,默认计划下一工序,可手工调整
    @JsonProperty("NextProcess")
    @JSONField(name = "NextProcess")
    private String NextProcess;
    // 终点编码
    @JsonProperty("NextStationId")
    @JSONField(name = "NextStationId")
    private String NextStationId;
    // 零件编码
    @JsonProperty("Itemno")
    @JSONField(name = "Itemno")
    private String Itemno;
    // 数量
    @JsonProperty("Qty")
    @JSONField(name = "Qty")
    private Integer Qty;
    // 生产线编码
    @JsonProperty("ProductLineId")
    @JSONField(name = "ProductLineId")
    private String ProductLineId;
    // 物料二维码
    @JsonProperty("ItemBarcode")
    @JSONField(name = "ItemBarcode")
    private String ItemBarcode;
    // 操作类型,1 新增任务;2 修改任务;3 取消任务;(RCS执行后无法取消)
    @JsonProperty("OperateType")
    @JSONField(name = "OperateType")
    private Integer OperateType;
    // 指定AGV厂家,1 海康;2 华晓;华晓与海康AGV运载能力不同,MES可按需求指定
    @JsonProperty("AgvFactory")
    @JSONField(name = "AgvFactory")
    private Integer AgvFactory;
    // 刀架编号
    @JsonProperty("DJNo")
    private String djNo;
}
src/main/java/com/zy/asrs/entity/mes/TransTaskFeedback.java
New file
@@ -0,0 +1,17 @@
package com.zy.asrs.entity.mes;
import lombok.Data;
// MES运输任务反馈
@Data
public class TransTaskFeedback {
    // 任务编号,wcs_task_header表中的task_no
    private String taskno;
    // 任务名称,wcs_task_header表中的task_name
    private String taskname;
    // 任务执行结果,1 完成;2 失败;
    private Integer result;
    // 失败原因
    private String failMsg;
}
src/main/java/com/zy/asrs/entity/rcs/RcsEqptNotify.java
New file
@@ -0,0 +1,16 @@
package com.zy.asrs.entity.rcs;
import lombok.Data;
// 通知进入
@Data
public class RcsEqptNotify {
    // 封锁区编号
    private String eqptCode;
    // 申请编号,可使用 UUID
    private String taskCode;
    // 任务执行状态:可扩展枚举值。预制枚举值:1 可以进入封锁区;
    private String actionStatus;
}
src/main/java/com/zy/asrs/entity/rcs/RcsReporterEqpt.java
New file
@@ -0,0 +1,20 @@
package com.zy.asrs.entity.rcs;
import lombok.Data;
// 请求进入封锁区、入站、离站等
@Data
public class RcsReporterEqpt {
    // 封锁区编号
    private String eqptCode;
    // 封锁区名称
    private String eqptName;
    // 申请编号,可使用 UUID
    private String taskCode;
    // 任务执行方法,与设备相关,可扩展枚举值。 预制枚举值:APPLY_LOCK 申请封锁区;RELEASE_EQPT 释放封锁区;
    private String method;
    // agv厂家,1 海康;2 华晓
    private Integer agvFactory;
}
src/main/java/com/zy/asrs/entity/rcs/RcsReporterTask.java
New file
@@ -0,0 +1,18 @@
package com.zy.asrs.entity.rcs;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
// 任务执行反馈
@Data
public class RcsReporterTask {
    // 任务号
    private String robotTaskCode;
    // 当前执行任务的机器人唯一标识。
    private String singleRobotCode;
    // 目标路径序列,0 起点序号,1 终点序号。
    private Integer currentSeq;
    // 详细信息
    private JSONObject extra;
}
src/main/java/com/zy/asrs/entity/rcs/RcsReturn.java
New file
@@ -0,0 +1,20 @@
package com.zy.asrs.entity.rcs;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
// 海康返回
@Data
public class RcsReturn {
    // SUCCESS 成功
//    Err_TaskTypeNotSupport 任务类型不支持
//    Err_RobotGroupsNotMatch 机器人资源组编号与任务不匹配,无法调度
//    Err_RobotCodeNotMatch 机器人编号与任务不匹配,无法调度
//    Err_TargetRouteError 任务路径参数有误
    private String code;
    private String message;
    private JSONObject data;
}
src/main/java/com/zy/asrs/entity/rcs/RcsTaskCancel.java
New file
@@ -0,0 +1,17 @@
package com.zy.asrs.entity.rcs;
import lombok.Data;
// 取消任务
@Data
public class RcsTaskCancel {
    // 任务号,全局唯一
    private String robotTaskCode;
    // 任务取消类型
    //取消(原软取消)
    //CANCEL
    //人工介入(原硬取消)
    //DROP
    private String cancelType;
}
src/main/java/com/zy/asrs/entity/rcs/RcsTaskContinue.java
New file
@@ -0,0 +1,20 @@
package com.zy.asrs.entity.rcs;
import lombok.Data;
// 继续执行任务
@Data
public class RcsTaskContinue {
    // 任务链编号
    private String robotTaskCode;
    // 触发类型:
    //SITE 站点编号触发
    //CARRIER 载具编号触发
    //ROBOT 车号触发
    //TASK 任务链编号触发
    private String triggerType;
    // 与 triggerType 对应的触发编号
    private String triggerCode;
}
src/main/java/com/zy/asrs/entity/rcs/RcsTaskSubmit.java
New file
@@ -0,0 +1,29 @@
package com.zy.asrs.entity.rcs;
import lombok.Data;
import java.util.List;
// RCS任务下发
@Data
public class RcsTaskSubmit {
    // 任务类型,枚举值:TRANSPORT搬运。
    private String taskType = "TRANSPORT";
    // 执行步骤集合。本次任务机器人需要执行的关键路径,序号0代表起点,序号1代表终点。
    private List<RcsTaskTargetRoute> targetRoute;
    // 任务唯一编号,如果为空,系统生成任务号并返回。
    private String robotTaskCode;
    // 任务执行的初始优先顺序,数值越大,优先级越高。
    private Integer initPriority;
    // 要求调度系统仅在当前指定的范围内选择机器人执行该任务。可能出现任务与机器人类型不匹配的异常,需要业务系统确保任务与机器人类型的匹配。如果不指定,则调度系统会在所有可用机器人的范围内寻找最优方案。
    // 固定枚举值: GROUPS 机器人资源组编号;ROBOTS 机器人编号;
    private String robotType;
    // 与 robotType 匹配的资源类型唯一标识。支持单个和多个编号。若写入多个编号时,之间用逗号隔开。
    private String robotCode;
    // 能否打断,1:可打断,该货架中途有其他任务时,打断当前任务。0:不可打断,该货架中途有其他任务时,不能打断当前任务。默认不可打断。
    private String interrupt;
    // 任务组编号,全局唯一。
    private String groupCode;
}
src/main/java/com/zy/asrs/entity/rcs/RcsTaskTargetRoute.java
New file
@@ -0,0 +1,22 @@
package com.zy.asrs.entity.rcs;
import lombok.Data;
// 任务路线
@Data
public class RcsTaskTargetRoute {
    // 目标路径序列。0 起点序号; 1 终点序号。
    private Integer seq;
    // 目标类型。可扩展枚举值。预制枚举值:SITE 站点别名;
    private String type = "SITE";
    // 站点编号
    private String code;
    // 机器人到达目标位置后的操作。预制枚举值:COLLECT取货;DELIVERY送货;
    private String operation;
    // 要求调度系统仅在当前指定的范围内选择机器人执行该步骤。固定枚举值:GROUPS机器人资源组编号;ROBOTS机器人编号;
    private String robotType;
    // 与 robotType 匹配的资源类型唯一标识。
    private String robotCode;
}
src/main/java/com/zy/asrs/enums/RcsRetMethodEnum.java
New file
@@ -0,0 +1,38 @@
package com.zy.asrs.enums;
public enum RcsRetMethodEnum {
    TASK_START("start", "任务开始"),
    TASK_END("end", "任务完成"),
    TASK_OUT_BIN("outbin", "走出储位"),
    APPLY_IN_STATION("applyInStation", "入站请求"),
    APPLY_OFF_STATION("applyOutStation", "离站请求"),
    ARRIVE_ON_STATION("arriveOnStation", "到站完成"),
    ARRIVE_OFF_STATION("arriveOffStation", "离站完成");
    private String code;
    private String message;
    RcsRetMethodEnum(String code, String message) {
        this.code = code;
        this.message = message;
    }
    public static RcsRetMethodEnum getEnum(String code) {
        for (RcsRetMethodEnum method : RcsRetMethodEnum.values()) {
            if (method.getCode().equals(code)) {
                return method;
            }
        }
        return null;
    }
    public String getCode() {
        return code;
    }
    public String getMessage() {
        return message;
    }
}
src/main/java/com/zy/asrs/mapper/AgvInfoMapper.java
New file
@@ -0,0 +1,11 @@
package com.zy.asrs.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.AgvInfo;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface AgvInfoMapper extends BaseMapper<AgvInfo> {
}
src/main/java/com/zy/asrs/mapper/BlockStationMapper.java
New file
@@ -0,0 +1,14 @@
package com.zy.asrs.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.BlockStation;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface BlockStationMapper extends BaseMapper<BlockStation> {
    Integer addByBlockNo(@Param("blockNo")String blockNo, @Param("status")int status);
}
src/main/java/com/zy/asrs/mapper/BlockTaskMapper.java
New file
@@ -0,0 +1,16 @@
package com.zy.asrs.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.BlockTask;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface BlockTaskMapper extends BaseMapper<BlockTask> {
    BlockTask findTop();
    BlockTask findByTaskCode(@Param("taskCode")String taskCode);
}
src/main/java/com/zy/asrs/mapper/DigitalTwinMapper.java
New file
@@ -0,0 +1,26 @@
package com.zy.asrs.mapper;
import com.zy.asrs.entity.digitaltwin.DtDetainMatVo;
import com.zy.asrs.entity.digitaltwin.DtInAndOutBoundVo;
import com.zy.asrs.entity.digitaltwin.DtOrderVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface DigitalTwinMapper {
    List<Double> overview(@Param("areaId")String areaId);
    List<DtOrderVo> recentOrder(@Param("startTime")String startTime, @Param("endTime")String endTime);
    List<DtInAndOutBoundVo> recentInBound(@Param("areaId")String areaId, @Param("startTime")String startTime, @Param("endTime")String endTime);
    List<DtInAndOutBoundVo> recentOutBound(@Param("areaId")String areaId, @Param("startTime")String startTime, @Param("endTime")String endTime);
    List<DtDetainMatVo> recentDetainMat(@Param("areaId")String areaId, @Param("startTime")String startTime,
                                        @Param("pageIndex")Integer pageIndex, @Param("pageSize")Integer pageSize);
}
src/main/java/com/zy/asrs/mapper/LocCountMapper.java
New file
@@ -0,0 +1,24 @@
package com.zy.asrs.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.LocCount;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface LocCountMapper extends BaseMapper<LocCount> {
    List<LocCount> getByAreaAndDate(@Param("areaId")String areaId, @Param("startDate")int startDate, @Param("endDate")int endDate);
    List<LocCount> getByDate(@Param("startDate")int startDate, @Param("endDate")int endDate);
    Integer insertOrUpdate(@Param("model")LocCount model);
    List<LocCount> totalLoc();
    List<LocCount> useLoc();
}
src/main/java/com/zy/asrs/service/DigitalTwinService.java
New file
@@ -0,0 +1,70 @@
package com.zy.asrs.service;
import com.zy.asrs.entity.digitaltwin.*;
import java.util.List;
public interface DigitalTwinService {
    /**
     * 总览:总库位、已用库位、剩余库位、今日出库、今日入库、剩余库位
     *
     * @param areaId
     * @return
     */
    DtOverviewVo overview(String areaId);
    /**
     * 近期订单,默认7天
     *
     * @param startDate
     * @param endDate
     * @return
     */
    List<DtOrderVo> order(String startDate, String endDate);
    /**
     * 近期出库、入库数量,默认7天
     *
     * @param areaId
     * @param startDate
     * @param endDate
     * @return
     */
    List<DtInAndOutBoundVo> inAndOutBound(String areaId, String startDate, String endDate);
    /**
     * 近期近期呆滞品信息,默认超过30天为呆滞品
     *
     * @param areaId
     * @param overDayNum
     * @param pageIndex
     * @param pageSize
     * @return
     */
    List<DtDetainMatVo> recentDetainMat(String areaId, Integer overDayNum, Integer pageIndex, Integer pageSize);
    /**
     * 查询库存和库位详细信息
     *
     * @param areaId
     * @return
     */
    List<DtLocDetailVo> warehouseDetail(String areaId);
    /**
     * 近期剩余库位数量,默认7天
     *
     * @param areaId
     * @param startDate
     * @param endDate
     * @return
     */
    List<DtLocVo> recentLoc(String areaId, String startDate, String endDate);
    /**
     * 定期统计剩余库存
     *
     */
    void locNumCount();
}
src/main/java/com/zy/asrs/service/MesService.java
New file
@@ -0,0 +1,154 @@
package com.zy.asrs.service;
import com.alibaba.fastjson.JSONObject;
import com.core.common.R;
import com.zy.asrs.entity.mes.*;
import com.zy.asrs.entity.rcs.RcsReporterTask;
import java.text.ParseException;
public interface MesService {
//    /**
//     * 物料信息同步
//     *
//     * @param matRecvForm
//     * @return
//     */
//    MesReturn matInfoAndInBound(MesMatRecvForm matRecvForm);
    /**
     * 新增、修改物料信息
     *
     * @param mesMatInfo
     * @return 1 成功;-1 保存物料类型失败;-2 保存物料失败;
     * @throws ParseException
     */
    int synMatInfo(MesMatInfo mesMatInfo);
    /**
     * 实际入库反馈
     * 触发条件:针对原料出库检查再入库的情况
     * 推送时机:当所有货物都入库时推送
     *
     * @param orderNo
     * @return
     */
    int recvFeedback(String orderNo);
    /**
     * 出库申请
     *
     * @param mesOutApply
     * @return
     */
    int outBoundOrder(MesInApply mesOutApply);
    /**
     * 出库申请(叫料),齐套性配盘
     *
     * @param mesCallOutApply
     * @return
     */
    int callOutBoundOrder(MesCallOutApply mesCallOutApply);
    /**
     * 出库完成
     *
     * @param orderNo
     * @return
     */
    int outFeedback(String orderNo);
    /**
     * 入库完成
     *
     * @param orderNo
     * @return
     */
    int inFeedback(String orderNo);
    /**
     * 入库申请
     *
     * @param mesInApply
     * @return
     */
    int inBoundOrder(MesInApply mesInApply, int check);
    int transDj(String taskNo,String djNo);
    /**
     * 9.1下发运输任务
     *
     * @param transTask
     * @return
     */
    JSONObject submitTask(TransTask transTask);
    /**
     * 9.2返回任务执行结果
     *
     * @param rcsReporterTask
     * @return
     */
    int reporterTask(RcsReporterTask rcsReporterTask);
    /**
     * 9.8申请华晓AGV进入生产线
     *
     * @param apply
     * @return
     */
    String applyInLine(TransParent apply);
    /**
     * 入站请求:转发AGV->入站请求->给MES
     *
     * @param apply
     * @return
     */
    int applyInStation(TransParent apply);
    /**
     * 入站允许:转发MES->允许入站->给AGV
     *
     * @param allow
     * @return
     */
    MesReturn allowInStation(TransInOutStationAllow allow);
    /**
     * 到站完成:转发AGV->到站完成->给MES
     *
     * @param arrivalStation
     * @return
     */
    int arriveOnStation(TransArrivalStation arrivalStation,String path);
    /**
     * 离站请求:转发AGV->离站请求->给MES
     *
     * @param apply
     * @return
     */
    int applyOutStation(TransParent apply);
    /**
     * 离站允许:转发MES->允许离站->给AGV
     *
     * @param allow
     * @return
     */
    MesReturn allowOutStation(TransInOutStationAllow allow);
    /**
     * 离站完成:转发AGV->离站完成->给MES
     *
     * @param apply
     * @return
     */
    int outStation(TransParent apply);
    R tkt(String taskNo);
}
src/main/java/com/zy/asrs/service/RcsService.java
New file
@@ -0,0 +1,66 @@
package com.zy.asrs.service;
import com.alibaba.fastjson.JSONObject;
import com.zy.asrs.entity.mes.TransInOutStationAllow;
import com.zy.asrs.entity.mes.TransParent;
import com.zy.asrs.entity.rcs.*;
public interface RcsService {
    /**
     * 管理封锁区进入
     *
     */
    void managerBlock();
    /**
     * 2.1.2任务下发接口
     *
     * @param rcsTaskSubmit
     * @param rcsFactory 1 海康;2 华晓;
     * @return
     */
    int submitTask(RcsTaskSubmit rcsTaskSubmit, int rcsFactory);
    /**
     * 2.1.3任务继续执行接口
     *
     * @param rcsTaskContinue
     * @param rcsFactory
     * @return
     */
    int continueTask(RcsTaskContinue rcsTaskContinue, int rcsFactory);
    /**
     * 2.1.4任务取消接口
     *
     * @param rcsTaskCancel
     * @param rcsFactory
     * @return
     */
    int cancelTask(RcsTaskCancel rcsTaskCancel, int rcsFactory);
    /**
     * 2.2.1任务执行回馈
     *
     * @param rcsReporterTask
     * @return
     */
    RcsReturn reporterTask(RcsReporterTask rcsReporterTask);
    /**
     * 2.2.4请求外设接口,请求封锁区
     *
     * @param rcsReporterEqpt
     * @return
     */
    RcsReturn reporterEqpt(RcsReporterEqpt rcsReporterEqpt);
    /**
     * 9.7申请进入生产线
     *
     * @param apply
     * @return
     */
    JSONObject hxApplyInLine(TransParent apply);
}
src/main/java/com/zy/asrs/service/impl/DigitalTwinServiceImpl.java
New file
@@ -0,0 +1,272 @@
package com.zy.asrs.service.impl;
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.service.DigitalTwinService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class DigitalTwinServiceImpl implements DigitalTwinService {
    @Resource
    private DigitalTwinMapper digitalTwinMapper;
    @Resource
    private LocCountMapper locCountMapper;
    /**
     * 总览:总库位、已用库位、剩余库位、今日出库、今日入库、剩余库位
     *
     * @param areaId
     * @return
     */
    public DtOverviewVo overview(String areaId) {
        List<Double> dbOverview = digitalTwinMapper.overview(areaId);
        if (dbOverview != null && !dbOverview.isEmpty()){
            DtOverviewVo dtOverviewVo = DtOverviewVo.builder()
                .totalLoc((int)Math.round(dbOverview.get(0)))
                    .useLoc((int)Math.round(dbOverview.get(1)))
                    .remainingStock((int)Math.round(dbOverview.get(2)))
                    .todayWarehousing((int)Math.round(dbOverview.get(3)))
                    .todayOutbound((int)Math.round(dbOverview.get(4)))
                    .build();
            dtOverviewVo.setIdleLoc(dtOverviewVo.getTotalLoc() - dtOverviewVo.getUseLoc());
            return dtOverviewVo;
        }
        return DtOverviewVo.builder().build();
    }
    /**
     * 近期订单,默认7天
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public List<DtOrderVo> order(String startDate, String endDate) {
        String startTime;
        String endTime;
        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();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            endDate = sdf.format(now);
            startDate = sdf.format(start);
        }
        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);
        // 空日期补全
        return dbOrder;
    }
    /**
     * 近期出库、入库数量,默认7天
     *
     * @param areaId
     * @param startDate
     * @param endDate
     * @return
     */
    public List<DtInAndOutBoundVo> inAndOutBound(String areaId, String startDate, String endDate) {
        List<DtInAndOutBoundVo> dtInAndOutBoundVos = new ArrayList<>();
        String startTime;
        String endTime;
        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();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            endDate = sdf.format(now);
            startDate = sdf.format(start);
        }
        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);
        // 格式整理
        return dtInAndOutBoundVos;
    }
    /**
     * 近期近期呆滞品信息,默认超过30天为呆滞品
     *
     * @param areaId
     * @param overDayNum
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public List<DtDetainMatVo> recentDetainMat(String areaId, Integer overDayNum, Integer pageIndex, Integer pageSize) {
        overDayNum = overDayNum == null ? 30 : overDayNum;
        pageIndex = pageIndex == null ? 1 : pageIndex;
        pageSize = pageSize == null ? 1000000 : pageSize;
        Date now = new Date();
        Calendar calendar = Calendar.getInstance();
        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);
        List<DtDetainMatVo> dbDetainMats = digitalTwinMapper.recentDetainMat(areaId, startTime, pageIndex, pageSize);
        return dbDetainMats;
    }
    /**
     * 查询库存和库位详细信息
     *
     * @param areaId
     * @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;
    }
    /**
     * 近期剩余库位数量,默认7天
     *
     * @param areaId
     * @param startDate
     * @param endDate
     * @return
     */
    public List<DtLocVo> recentLoc(String areaId, String startDate, String endDate) {
        List<DtLocVo> locVos = new ArrayList<>();
        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();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            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));
        }
        for (LocCount locCount : locCounts) {
            String date = locCount.getDate().toString();
            String locDate = date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8);
            DtLocVo dtLocVo = DtLocVo.builder()
                    .locDate(locDate)
                    .idleNum(locCount.getRemainNum())
                    .build();
            locVos.add(dtLocVo);
        }
        return locVos;
    }
    /**
     * 定期统计剩余库存
     *
     */
    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);
        }
    }
    // region 数字孪生
    // 数字孪生整合
    // 机器状态整合
    // endregion
    // region 立库调度
    // 堆垛机存取
    // 输送线拍照、称重
    // endregion
}
src/main/java/com/zy/asrs/service/impl/MatServiceImpl.java
@@ -23,7 +23,8 @@
    }
    @Override
    public Page<Mat> getPage2(Page page, String tagId, Object matnr, Object maktx, Object specs) {
        return page.setRecords(baseMapper.listByPage2(page, tagId, matnr, maktx, specs));
        return page.setRecords(baseMapper.listByPage2(page, "1".equals(tagId) ? "2" : tagId, matnr, maktx, specs));
    }
src/main/java/com/zy/asrs/service/impl/MesServiceImpl.java
New file
@@ -0,0 +1,1090 @@
package com.zy.asrs.service.impl;
import com.alibaba.excel.util.DateUtils;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.R;
import com.core.common.SnowflakeIdWorker;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.mes.*;
import com.zy.asrs.entity.param.CombParam;
import com.zy.asrs.entity.rcs.*;
import com.zy.asrs.mapper.AgvInfoMapper;
import com.zy.asrs.service.*;
import com.zy.common.model.enums.WorkNoType;
import com.zy.common.service.CommonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.text.ParseException;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class MesServiceImpl implements MesService {
    @Value("${mes.url}")
    public String MES_URL;
    @Value("${dj.url}")
    public String DJ_URL;
    @Value("${wms.currentName}")
    public String WMS_CURRENT_NAME;
    @Value("${mes.defaultUserId}")
    public long defaultUserId;
    @Value("${wms.wmsTransStartStation1}")
    public String WMS_TRANS_START_STATION_1;
    @Resource
    private RcsService rcsService;
    @Resource
    private MatService matService;
    @Resource
    private TagService tagService;
    @Resource
    private OrderPakinService orderPakinService;
    @Resource
    private OrderDetlPakinService orderDetlPakinService;
    @Resource
    private OrderPakoutService orderPakoutService;
    @Resource
    private OrderDetlPakoutService orderDetlPakoutService;
    @Resource
    private MobileService mobileService;
    @Resource
    private WaitPakinService waitPakinService;
    @Resource
    private TaskService taskService;
    @Resource
    private TaskDetlService taskDetlService;
    @Resource
    private SnowflakeIdWorker snowflakeIdWorker;
    @Resource
    private CommonService commonService;
    @Resource
    private AgvInfoMapper agvInfoMapper;
    // region MES接口
//    /**
//     * 物料信息同步,MES->WMS
//     * 同步物料信息->入库单
//     *
//     * @param matRecvForm
//     * @return
//     */
//    @Transactional(rollbackFor = Exception.class)
//    public MesReturn matInfoAndInBound(MesMatRecvForm matRecvForm) {
//
//        MesReturn mesReturn = new MesReturn();
//
//        // 1、物料信息同步
//        try {
//            if (synMatInfo(matRecvForm.getItemdata()) == 1) {
//                // 2、生成入库单
//                try {
//                    MesInApply mesInApply = new MesInApply();
//                    mesInApply.setItemno(matRecvForm.getItemdata().getItem_no());
//                    mesInApply.setQty(matRecvForm.getItemdata().getQty());
//                    mesInApply.setOrderNo(matRecvForm.getItemdata().getOrderNo());
//                    if (inBoundOrder(mesInApply, 1) == 1) {
//                        mesReturn.setSuccess("1");
//                    } else {
//                        mesReturn.setSuccess("2");
//                        mesReturn.setMessage("生成入库订单失败");
//                    }
//                } catch (Exception e) {
//                    mesReturn.setSuccess("2");
//                    mesReturn.setMessage("生成入库订单失败");
//                    log.error("MES物料信息同步接口,生成入库订单错误", e);
//                }
//            } else {
//                mesReturn.setSuccess("2");
//                mesReturn.setMessage("同步物料信息失败");
//            }
//        } catch (Exception e) {
//            mesReturn.setSuccess("2");
//            mesReturn.setMessage("同步物料信息失败");
//            log.error("MES物料信息同步接口,同步物料错误", e);
//        }
//
//        return mesReturn;
//    }
    /**
     * 新增、修改物料信息
     *
     * @param mesMatInfo
     * @return 1 成功;-1 保存物料类型失败;-2 保存物料失败;
     * @throws ParseException
     */
    public int synMatInfo(MesMatInfo mesMatInfo)  {
        try {
            // 规则定义:默认第3层为同步的物料类型
            long secondPath = 2;
            String secondParentName = WMS_CURRENT_NAME;
//        long locType = 1;
            long userId = defaultUserId;
//            if (mesMatInfo.getModified_operator1() != null && !mesMatInfo.getModified_operator1().isEmpty()) {
//                userId = Long.parseLong(mesMatInfo.getModified_operator1());
//            }
            Date now = new Date();
            if (mesMatInfo.getModified_date1() != null && !mesMatInfo.getModified_date1().isEmpty()) {
                now = Date.from(OffsetDateTime.parse(mesMatInfo.getModified_date1()).toInstant());
            }
            // 物料类型更新
            EntityWrapper<Tag> wrapper = new EntityWrapper<>();
            wrapper.eq("name", mesMatInfo.getItem_type());
            Tag tag = tagService.selectByName(mesMatInfo.getItem_type(), 3);
            if (tag == null || StringUtils.isEmpty(tag.getName())) {
                Tag newTag = new Tag();
                newTag.setName(mesMatInfo.getItem_type());
                newTag.setParentId(secondPath);
                newTag.setParentName(secondParentName);
                newTag.setPath("2");
                newTag.setPathName(secondParentName);
                newTag.setLevel(3);
                newTag.setStatus(1);
                newTag.setCreateBy(userId);
                newTag.setCreateTime(now);
                newTag.setUpdateBy(userId);
                newTag.setUpdateTime(now);
                if (!tagService.insert(newTag))
                    return -1;
            }
            // 物料更新
            long tagId = tagService.selectByName(mesMatInfo.getItem_type(), 3).getId();
            Mat mat = matService.selectByMatnr(mesMatInfo.getItem_no());
            Mat newMat = new Mat();
            newMat.setMatnr(mesMatInfo.getItem_no());
            newMat.setMaktx(mesMatInfo.getDescription());
            newMat.setTagId(tagId);
            newMat.setLocType(tagId);   //locType
            newMat.setSpecs(mesMatInfo.getSpecification());
            newMat.setUnit("件");   //统一为件,mesMatInfo.getUnit_of_measure()
            newMat.setModel(mesMatInfo.getClassification_code());
            newMat.setMemo(JSONObject.toJSONString(mesMatInfo));
            newMat.setCreateBy(userId);
            newMat.setCreateTime(now);
            newMat.setUpdateBy(userId);
            newMat.setUpdateTime(now);
            newMat.setStatus(1);
            if (mat == null) {
                if (!matService.insert(newMat))
                    return -2;
            } else {
                JSONObject dbMemo = JSONObject.parseObject(mat.getMemo());
//            dbMemo.remove("OrderNo");
//            dbMemo.remove("qty");
            JSONObject newMemo = JSONObject.parseObject(newMat.getMemo());
//            newMemo.remove("OrderNo");
//            newMemo.remove("qty");
                if (!dbMemo.equals(newMemo)) {
                    newMat.setId(mat.getId());
                    if (!matService.updateById(newMat))
                        return -2;
                }
            }
            return 1;
        } catch (Exception e) {
            log.error("同步物料失败", e);
            return -1;
        }
    }
    /**
     * 实际入库反馈
     * 触发条件:针对原料出库检查再入库的情况
     * 推送时机:当订单完成时推送
     *
     * @param orderNo
     * @return
     */
    public int recvFeedback(String orderNo) {
        // 按单号查询
        OrderPakin order = orderPakinService.selectByNo(orderNo);
        if (order != null && order.getSettle() == 4) {   // 校验是否完成
//            List<MesRecvFeedback.MesRecvFeedbackItem> list = new ArrayList<>();
            JSONObject dbMemo = JSONObject.parseObject(order.getMemo());
            List<MesItemDetails> details = new ArrayList<>();
            EntityWrapper<OrderDetlPakin> wrapper = new EntityWrapper<>();
            wrapper.eq("order_no", orderNo);
            List<OrderDetlPakin> orderDetlPakins = orderDetlPakinService.selectList(wrapper);
            if (orderDetlPakins != null && !orderDetlPakins.isEmpty()) {
                for (OrderDetlPakin orderDetl : orderDetlPakins) {
                    int qty = Integer.parseInt(dbMemo.getString("qty"));
                    double real_qty = Double.parseDouble(orderDetl.getQty().toString());
                    MesItemDetails detail = new MesItemDetails();
                    detail.setItemNo(orderDetl.getMatnr());
                    detail.setAnfme(real_qty);
                    details.add(detail);
//                    MesRecvFeedback.MesRecvFeedbackItem item = new MesRecvFeedback.MesRecvFeedbackItem();
//                    item.setItem_no(orderDetl.getMatnr());
//                    item.setOrderNo(orderNo);
//                    item.setQty(qty);
//                    item.setReal_qty(real_qty);
//                    list.add(item);
                }
            }
//            MesRecvFeedback mesRecvFeedback = new MesRecvFeedback();
//            mesRecvFeedback.setSource_no(dbMemo.getString("source_no"));
//            mesRecvFeedback.setOperuser(dbMemo.getString("operuser"));
//            mesRecvFeedback.setItemdata(list);
            MesInApply mesRecvFeedback = new MesInApply();
            mesRecvFeedback.setBillType(dbMemo.getString("billType"));
            mesRecvFeedback.setOrderNo(dbMemo.getString("orderNo"));
            mesRecvFeedback.setCreateTime(dbMemo.getString("createTime"));
            mesRecvFeedback.setDetails(details);
            String url = DJ_URL + "api/InboundOrder/WmsInFinish";
            String response = RcsServiceImpl.sendPost(url, mesRecvFeedback.toString());
            if (!StringUtils.isEmpty(response) && response.contains("Success")){
                MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
                if("1".equals(mesReturn.getSuccess())) {
                    return 1;
                }
            }
        }
        return 0;
    }
    /**
     * 出库申请
     * 加工库、刀具库
     *
     * @param mesOutApply
     * @return 1 成功;-1 订单重复;
     */
    public int outBoundOrder(MesInApply mesOutApply){
        // docType根据库类型确定
        long docType = 7;
        long settle = 1;
        // 校验订单是否重复
        OrderPakout order = orderPakoutService.selectByNo(mesOutApply.getOrderNo());
        if (order != null && !StringUtils.isEmpty(order.getOrderNo())) {
            return -1;
        }
        // 生成订单
        Date now = new Date();
        OrderPakout orderPakout = new OrderPakout();
        orderPakout.setUuid( String.valueOf(snowflakeIdWorker.nextId()));
        orderPakout.setOrderNo(mesOutApply.getOrderNo());
        orderPakout.setOrderTime(com.core.common.DateUtils.convert(now));
        orderPakout.setDocType(docType);
        orderPakout.setSettle(settle);
        orderPakout.setStatus(1);
        orderPakout.setCreateBy(defaultUserId);
        orderPakout.setCreateTime(now);
        orderPakout.setUpdateBy(defaultUserId);
        orderPakout.setUpdateTime(now);
        orderPakout.setMemo(JSONObject.toJSONString(mesOutApply));
        orderPakout.setPakinPakoutStatus(2);
        if (!orderPakoutService.insert(orderPakout)) {
            log.error("MES保存出库订单主档失败");
            throw new CoolException("保存出库订单主档失败");
        }
        // 生成明细
        for (MesItemDetails item : mesOutApply.getDetails()) {
            Mat mat = matService.selectByMatnr(item.getItemNo());
            OrderDetlPakout orderDetlPakout = new OrderDetlPakout();
            orderDetlPakout.setOrderId(orderPakout.getId());
            orderDetlPakout.setOrderNo(orderPakout.getOrderNo());
            orderDetlPakout.setAnfme(Double.valueOf(item.getAnfme()));
            orderDetlPakout.setQty(0.0);
            orderDetlPakout.setMatnr(mat.getMatnr());
            orderDetlPakout.setMaktx(mat.getMaktx());
            orderDetlPakout.setSpecs(mat.getSpecs());
            orderDetlPakout.setModel(mat.getModel());
            orderDetlPakout.setCreateBy(defaultUserId);
            orderDetlPakout.setCreateTime(now);
            orderDetlPakout.setUpdateBy(defaultUserId);
            orderDetlPakout.setUpdateTime(now);
            orderDetlPakout.setStatus(1);
            orderDetlPakout.setPakinPakoutStatus(2);
            if (!orderDetlPakoutService.insert(orderDetlPakout)) {
                log.error("MES保存出库订单明细档失败");
                throw new CoolException("保存出库订单明细档失败");
            }
        }
        // TODO:CTU出库动作
        // todo 呼叫agv产线取空料架
        // TODO:若AGV和输送线没有安全交互,则要保证立库出货完成后再呼叫AGV。
        // 立库生成订单后,自动调度AGV从产线运输空刀架至立库缓存区。
        try {
            if (!StringUtils.isEmpty(mesOutApply.getTaskNo()) && !StringUtils.isEmpty(mesOutApply.getStationId())) {
                TransTask transTask = new TransTask();
                transTask.setTaskno(mesOutApply.getTaskNo());
//                        transTask.setTaskname(mesOutApply.getTaskname());
                transTask.setOrderNo(mesOutApply.getOrderNo());
                transTask.setTransType("02");    //运回刀架时默认02(下空托) mesOutApply.getTransType()
                transTask.setCurProcess(mesOutApply.getProductLineId());
                transTask.setCurStationId(mesOutApply.getStationId());
//                        transTask.setNextProcess();
                transTask.setNextStationId(WMS_TRANS_START_STATION_1);
//                transTask.setItemno(mesOutApply.getItemNo());
                transTask.setQty(0);
                transTask.setProductLineId(mesOutApply.getProductLineId());
//                        transTask.setItemBarcode(codes);
//                        transTask.setTuoPanId(entry.getKey());
                transTask.setOperateType(1);
                transTask.setAgvFactory(1);
                JSONObject sendAgvTask = submitTask(transTask);
                if (!"1".equals(sendAgvTask.getString("Success"))) {
                    log.error("出库下发agv运输任务失败", JSONObject.toJSONString(transTask));
                }
//                // 按零件二维码查询有几个托,多托生成多个任务,每托对应零件二维码
////                String barCode = barCodeListToStr(mesOutApply.getItemBarcode());
//                EntityWrapper<MatItemBarcode> matItemBarcodeEntityWrapper = new EntityWrapper<>();
//                matItemBarcodeEntityWrapper.in("item_barcode", barCode);
//                List<MatItemBarcode> barcodes = matItemBarcodeMapper.selectList(matItemBarcodeEntityWrapper);
//                if (barcodes != null) {
//                    Map<String, List<MatItemBarcode>> map = barcodes.stream().collect(Collectors.groupingBy(MatItemBarcode::getZapplet));
//                    for (Map.Entry<String, List<MatItemBarcode>> entry : map.entrySet()) {
//                        List<MatItemBarcode> list = entry.getValue();
//                        List<String> codes = new ArrayList<>();
//                        for (MatItemBarcode zapllet : list) {
//                            codes.add(zapllet.getItemBarcode());
//                        }
//
//
//                    }
//                }
            }
        } catch (Exception e) {
            log.error("下发AGV运输任务失败", e);
        }
        return 1;
    }
    public int transDj(String taskNo,String djNo) {
        try {
            EntityWrapper<Task> wapper = new EntityWrapper<>();
            wapper.eq("task_no", taskNo).orderBy("wrk_date");
            Task task = taskService.selectOne(wapper);
            if (task != null) {
                JSONObject memo = JSONObject.parseObject(task.getMemo());
                TransTask transTask = new TransTask();
                transTask.setTaskno(taskNo + "_1");
//                        transTask.setTaskname(mesOutApply.getTaskname());
                transTask.setOrderNo(memo.getString("OrderNo"));
                transTask.setTransType("05");    //送刀时默认05(上刀)
                transTask.setCurStationId(WMS_TRANS_START_STATION_1);
                transTask.setNextProcess(memo.getString("ProductLineId"));
                transTask.setNextStationId(memo.getString("CurStationId"));
//                transTask.setItemno(mesOutApply.getItemNo());
//                transTask.setQty(0);
                transTask.setProductLineId(memo.getString("ProductLineId"));
//                        transTask.setItemBarcode(codes);
//                        transTask.setTuoPanId(entry.getKey());
                transTask.setOperateType(1);
                transTask.setAgvFactory(1);
                transTask.setDjNo(djNo);
                JSONObject sendAgvTask = submitTask(transTask);
                if (!"1".equals(sendAgvTask.getString("Success"))) {
                    log.error("上刀下发agv运输任务失败", JSONObject.toJSONString(transTask));
                }
            }
        } catch (Exception e) {
            log.error("上刀下发AGV运输任务失败", e);
        }
        return 1;
    }
    /**
     * 入库申请
     *
     * @param mesInApply
     * @return 1 成功;-1 入库订单重复;0 部分失败;
     */
    public int inBoundOrder(MesInApply mesInApply, int check){
        // docType根据库类型确定
        long docType = 4;
        long settle = 1;
        // 校验订单是否重复
        OrderPakin order = orderPakinService.selectByNo(mesInApply.getOrderNo());
        if (order != null && !StringUtils.isEmpty(order.getOrderNo())) {
            return -1;
        }
        // 生成订单
        Date now = new Date();
        OrderPakin orderPakin = new OrderPakin();
        orderPakin.setUuid(String.valueOf(snowflakeIdWorker.nextId()));
        orderPakin.setOrderNo(mesInApply.getOrderNo());
        orderPakin.setOrderTime(com.core.common.DateUtils.convert(now));
        orderPakin.setDocType(docType);
        orderPakin.setSettle(settle);
        orderPakin.setStatus(1);
        orderPakin.setCreateBy(defaultUserId);
        orderPakin.setCreateTime(now);
        orderPakin.setUpdateBy(defaultUserId);
        orderPakin.setUpdateTime(now);
        orderPakin.setMemo(JSONObject.toJSONString(mesInApply));  //为出库完成反馈保存
        orderPakin.setPakinPakoutStatus(1);
        if (!orderPakinService.insert(orderPakin)) {
            log.error("MES保存入库订单主档失败");
            throw new CoolException("保存入库订单主档失败");
        }
        // 生成明细
        for (MesItemDetails item : mesInApply.getDetails()) {
            Mat mat = matService.selectByMatnr(item.getItemNo());
            OrderDetlPakin orderDetlPakin = new OrderDetlPakin();
            orderDetlPakin.setOrderId(orderPakin.getId());
            orderDetlPakin.setOrderNo(orderPakin.getOrderNo());
            orderDetlPakin.setAnfme(Double.valueOf(item.getAnfme()));
            orderDetlPakin.setQty(0.0);
            orderDetlPakin.setMatnr(mat.getMatnr());
            orderDetlPakin.setMaktx(mat.getMaktx());
            orderDetlPakin.setSpecs(mat.getSpecs());
            orderDetlPakin.setModel(mat.getModel());
//            if (mesInApply.getDetails() != null) {
//                orderDetlPakin.setStandby1(JSONObject.toJSONString(mesInApply.getProductInfo())); //零件详情存在备选1
//            }
            orderDetlPakin.setStandby2(String.valueOf(check));  //保存齐套性检查标识,1 检查;0 不检查;
            orderDetlPakin.setCreateBy(defaultUserId);
            orderDetlPakin.setCreateTime(now);
            orderDetlPakin.setUpdateBy(defaultUserId);
            orderDetlPakin.setUpdateTime(now);
            orderDetlPakin.setStatus(1);
            orderDetlPakin.setPakinPakoutStatus(1);
            if (!orderDetlPakinService.insert(orderDetlPakin)) {
                log.error("MES保存入库订单明细档失败1");
                throw new CoolException("保存入库订单明细档失败1");
            }
        }
//        // TODO:是否绑定货物和托盘?
//        if (!StringUtils.isEmpty(mesInApply.getTuoPanId())) {
//            CombParam combParam = new CombParam();
//            combParam.setOrderNo(mesInApply.getOrderNo());
//            combParam.setBarcode(mesInApply.getTuoPanId());
//            List<CombParam.CombMat> combMats = new ArrayList<>();
//            CombParam.CombMat combMat = new CombParam.CombMat();
//            combMat.setOrderNo(mesInApply.getOrderNo());
//            combMat.setMatnr(mat.getMatnr());
//            combMat.setMaktx(mat.getMaktx());
//            combMat.setSpecs(mat.getSpecs());
//            combMat.setAnfme(Double.valueOf(mesInApply.getQty()));
////            combMat.setBatch("1");
//            combMats.add(combMat);
//            combParam.setCombMats(combMats);
//            // 组托
//            mobileService.comb(combParam, defaultUserId);
//        }
        return 1;
    }
    /**
     * 出库申请(叫料)
     * 装配库、滑块库
     *
     * @param mesCallOutApply
     * @return
     */
    public int callOutBoundOrder(MesCallOutApply mesCallOutApply){
        // docType根据库类型确定
        long docType = 7;
        long settle = 1;
        // 校验订单是否重复
        OrderPakout order = orderPakoutService.selectByNo(mesCallOutApply.getOrderNo());
        if (order != null && !StringUtils.isEmpty(order.getOrderNo())) {
            return -1;
        }
        // 生成订单
        Date now = new Date();
        OrderPakout orderPakout = new OrderPakout();
        orderPakout.setUuid(String.valueOf(snowflakeIdWorker.nextId()));
        orderPakout.setOrderNo(mesCallOutApply.getOrderNo());
        orderPakout.setOrderTime(com.core.common.DateUtils.convert(now));
        orderPakout.setDocType(docType);
        orderPakout.setSettle(settle);
        orderPakout.setStatus(1);
        orderPakout.setCreateBy(defaultUserId);
        orderPakout.setCreateTime(now);
        orderPakout.setUpdateBy(defaultUserId);
        orderPakout.setUpdateTime(now);
        orderPakout.setMemo(JSONObject.toJSONString(mesCallOutApply));
        orderPakout.setPakinPakoutStatus(2);
        if (!orderPakoutService.insert(orderPakout)) {
            log.error("MES保存出库订单(叫料)主档失败");
            throw new CoolException("保存出库订单(叫料)主档失败");
        }
        // 生成明细
        if (mesCallOutApply.getItemdata() != null && !mesCallOutApply.getItemdata().isEmpty()) {
            for (MesCallOutApply.MesOutApplyItem mesOutApplyItem : mesCallOutApply.getItemdata()) {
                Mat mat = matService.selectByMatnr(mesOutApplyItem.getItemno());
                OrderDetlPakout orderDetlPakout = new OrderDetlPakout();
                orderDetlPakout.setOrderId(orderPakout.getId());
                orderDetlPakout.setOrderNo(orderPakout.getOrderNo());
                orderDetlPakout.setAnfme(Double.valueOf(mesOutApplyItem.getQty()));
                orderDetlPakout.setQty(0.0);
                orderDetlPakout.setMatnr(mat.getMatnr());
                orderDetlPakout.setMaktx(mat.getMaktx());
                orderDetlPakout.setSpecs(mat.getSpecs());
                orderDetlPakout.setModel(mat.getModel());
                orderDetlPakout.setThreeCode(mesOutApplyItem.getItemBarcode());
                orderDetlPakout.setStandby1(mesOutApplyItem.getTrayid());   //保存配盘号,非托盘号
                orderDetlPakout.setCreateBy(defaultUserId);
                orderDetlPakout.setCreateTime(now);
                orderDetlPakout.setUpdateBy(defaultUserId);
                orderDetlPakout.setUpdateTime(now);
                orderDetlPakout.setStatus(1);
                orderDetlPakout.setPakinPakoutStatus(2);
                if (!orderDetlPakoutService.insert(orderDetlPakout)) {
                    log.error("MES保存出库订单(叫料)明细档失败");
                    throw new CoolException("保存出库订单(叫料)明细档失败");
                }
            }
        }
        return 1;
    }
    /**
     * 出库完成
     *
     * @param orderNo
     * @return
     */
    public int outFeedback(String orderNo) {
        int success = 0;
        OrderPakout order = orderPakoutService.selectByNo(orderNo);
        if (order != null && order.getSettle() == 4) {   // 校验是否完成
            List<MesItemDetails> details = new ArrayList<>();
            JSONObject dbMemo = JSONObject.parseObject(order.getMemo());
            EntityWrapper<OrderDetlPakout> wrapper = new EntityWrapper<>();
            wrapper.eq("order_no", orderNo);
            List<OrderDetlPakout> orderDetlPakouts = orderDetlPakoutService.selectList(wrapper);
            if (orderDetlPakouts != null && !orderDetlPakouts.isEmpty()) {
                for (OrderDetlPakout orderDetl : orderDetlPakouts) {
                    double real_qty = Double.parseDouble(orderDetl.getQty().toString());
                    MesItemDetails detail = new MesItemDetails();
                    detail.setItemNo(orderDetl.getMatnr());
                    detail.setAnfme(real_qty);
                    details.add(detail);
//                    StringBuilder palletId = new StringBuilder();
//                    EntityWrapper<WaitPakin> wrapper2 = new EntityWrapper<>();
//                    wrapper2.eq("order_no", orderDetl.getOrderNo());
//                    List<WaitPakin> waitPakins = waitPakinService.selectList(wrapper2);
//                    for (WaitPakin waitPakin : waitPakins) {
//                        palletId.append(waitPakin.getZpallet()).append(",");
//                    }
//
//                    MesOutFeedback mesOutFeedback = new MesOutFeedback();
//                    mesOutFeedback.setTaskno(dbMemo.getString("taskno"));
//                    mesOutFeedback.setTaskname(dbMemo.getString("taskname"));
//                    mesOutFeedback.setProductLineId(dbMemo.getString("ProductLineId"));
//                    mesOutFeedback.setStationId(dbMemo.getString("StationID"));
//                    mesOutFeedback.setItemno(orderDetl.getMatnr());
//                    if (!StringUtils.isEmpty(palletId.toString())) {
//                        mesOutFeedback.setTuoPanId(palletId.substring(0, palletId.length() - 1));
//                    }
//                    mesOutFeedback.setQty(Integer.parseInt(orderDetl.getQty().toString()));
//                    mesOutFeedback.setItemBarcode(dbMemo.getString("ItemBarcode"));
//                    mesOutFeedback.setOrderNo(orderNo);
                }
                MesInApply mesOutFeedback = new MesInApply();
                mesOutFeedback.setBillType(dbMemo.getString("billType"));
                mesOutFeedback.setOrderNo(dbMemo.getString("orderNo"));
                mesOutFeedback.setCreateTime(dbMemo.getString("createTime"));
                mesOutFeedback.setDetails(details);
                String url = DJ_URL + "api/OutboundOrder/WmsOutFinish";
                String response = RcsServiceImpl.sendPost(url, mesOutFeedback.toString());
                if (!StringUtils.isEmpty(response) && response.contains("Success")){
                    MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
                    if("1".equals(mesReturn.getSuccess())) {
                        success++;
                    }
                }
                if (success == orderDetlPakouts.size()) {
                    success = 1;
                } else {
                    success = 0;
                }
            }
        }
        return success;
    }
    /**
     * 入库完成
     *
     * @param orderNo
     * @return
     */
    public int inFeedback(String orderNo) {
        int success = 0;
        int recvFeedback = 0;
        OrderPakin order = orderPakinService.selectByNo(orderNo);
        if (order != null && order.getSettle() == 4) {   // 校验是否完成
            EntityWrapper<OrderDetlPakin> wrapper = new EntityWrapper<>();
            wrapper.eq("order_no", orderNo);
            List<OrderDetlPakin> orderDetlPakins = orderDetlPakinService.selectList(wrapper);
            if (orderDetlPakins != null && !orderDetlPakins.isEmpty()) {
                for (OrderDetlPakin orderDetl : orderDetlPakins) {
                    MesInApply result = JSONObject.parseObject(order.getMemo(), MesInApply.class);
//                    result.setAnfme(Float.parseFloat(orderDetl.getAnfme().toString()));
                    String url = MES_URL + "api/order/inComplete";
                    String response = RcsServiceImpl.sendPost(url, result.toString());
                    if (!StringUtils.isEmpty(response) && response.contains("Success")){
                        MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
                        if("1".equals(mesReturn.getSuccess())) {
                            success++;
                        }
                    }
                    if ("1".equals(orderDetl.getStandby2())) {
                        recvFeedback++;
                    }
                }
                // 入库回馈
                if (recvFeedback > 0) {
                    recvFeedback(orderNo);
                }
                if (success == orderDetlPakins.size()) {
                    success = 1;
                } else {
                    success = 0;
                }
            }
        }
        return success;
    }
    // endregion
    // region 搬运任务调度
    // route转发3个WCS任务
    /**
     * 9.1下发运输任务
     * TODO:其他库的任务全部转到滑块库统一调度
     *
     * @param transTask
     * @return
     */
    @Transactional
    public JSONObject submitTask(TransTask transTask) {
        JSONObject result = new JSONObject();
        result.put("taskno", transTask.getTaskno());
        // 重复性校验
        EntityWrapper<Task> wrapper = new EntityWrapper<>();
        wrapper.eq("task_no", transTask.getTaskno());
        List<Task> tasks = taskService.selectList(wrapper);
        if (tasks != null && !tasks.isEmpty()) {
            result.put("Success", "2");
            result.put("Message", "任务重复发送");
            return result;
        }
        try {
            int workNo = commonService.getWorkNo(WorkNoType.OTHER.type);
            Date now = new Date();
            Task task = new Task();
            task.setWrkNo(workNo);
            task.setTaskType("AGV");
            task.setWrkSts(301L);
            task.setIoType(3);
            task.setIoPri(10.00);
            task.setWrkDate(now);
            task.setStaNo(transTask.getNextStationId());
            task.setSourceStaNo(transTask.getCurStationId());
            task.setModiUser(defaultUserId);
            task.setModiTime(now);
            task.setAppeUser(defaultUserId);
            task.setAppeTime(now);
            task.setTaskNo(transTask.getTaskno());
            task.setMemo(JSONObject.toJSONString(transTask));
            if (taskService.insert(task)) {
                Mat mat = matService.selectByMatnr("emptyDj");
                TaskDetl taskDetl = new TaskDetl();
                taskDetl.setWrkNo(task.getWrkNo());
                taskDetl.setIoTime(task.getIoTime());
                taskDetl.setMatnr(mat.getMatnr());
                taskDetl.setAnfme(0.0);
                taskDetl.setStandby1(String.valueOf(transTask.getQty()));
                taskDetl.setMaktx(mat.getMaktx());
                taskDetl.setSpecs(mat.getSpecs());
                taskDetl.setOrderNo(transTask.getOrderNo());
                taskDetl.setModiUser(defaultUserId);
                taskDetl.setModiTime(now);
                taskDetl.setAppeUser(defaultUserId);
                taskDetl.setAppeTime(now);
                taskDetlService.insert(taskDetl);
//                EntityWrapper<WaitPakin> wrapper1 = new EntityWrapper<>();
//                wrapper1.eq("order_no", transTask.getTaskno())
//                        .eq("matnr", mat.getMatnr())
//                        .eq("anfme", transTask.getQty());
//                WaitPakin waitPakin = waitPakinService.selectOne(wrapper1);
//                if (waitPakin != null)
//                {
//                    TaskDetl taskDetl = new TaskDetl();
//                    taskDetl.setWrkNo(task.getWrkNo());
//                    taskDetl.setIoTime(task.getIoTime());
//                    taskDetl.setMatnr(transTask.getItemno());
//                taskDetl.setAnfme(Double.valueOf(transTask.getQty()));
//                    taskDetl.setAnfme(0.0);
//                    taskDetl.setStandby1(String.valueOf(transTask.getQty()));
//                    taskDetl.setZpallet(waitPakin.getZpallet());
//                    taskDetl.setMaktx(mat.getMaktx());
//                    taskDetl.setSpecs(mat.getSpecs());
//                    taskDetl.setOrderNo(transTask.getOrderNo());
//                    taskDetl.setModiUser(defaultUserId);
//                    taskDetl.setModiTime(now);
//                    taskDetl.setAppeUser(defaultUserId);
//                    taskDetl.setAppeTime(now);
//                    taskDetlService.insert(taskDetl);
//                }
//                else {
//                    result.put("Success", "2");
//                    result.put("Message", "接收任务失败");
//                    // Throw
//                }
                // 下发给RCS
                RcsTaskSubmit rcsTaskSubmit = new RcsTaskSubmit();
                rcsTaskSubmit.setRobotTaskCode(transTask.getTaskno());
                rcsTaskSubmit.setInitPriority(10);  //默认10
                List<RcsTaskTargetRoute> targetRouteList = new ArrayList<>();
                RcsTaskTargetRoute startRoute = new RcsTaskTargetRoute();
                startRoute.setSeq(0);
                startRoute.setCode(transTask.getCurStationId());
                startRoute.setOperation("COLLECT");
                targetRouteList.add(startRoute);
                RcsTaskTargetRoute endRoute = new RcsTaskTargetRoute();
                endRoute.setSeq(1);
                endRoute.setCode(transTask.getNextStationId());
                endRoute.setOperation("DELIVERY");
                targetRouteList.add(endRoute);
                rcsTaskSubmit.setTargetRoute(targetRouteList);
                // 转发给海康或华晓RCS
                int success = rcsService.submitTask(rcsTaskSubmit, transTask.getAgvFactory());
                if (success == 1) {
                    result.put("Success", "1");
                    result.put("Message", "任务接收成功");
                } else {
                    result.put("Success", "2");
                    result.put("Message", "任务下发给RCS失败");
                }
            } else {
                result.put("Success", "2");
                result.put("Message", "接收任务失败");
            }
        } catch (Exception e) {
            log.error("下发运输任务错位 - {}", transTask, e);
        }
        return result;
    }
    /**
     * 9.2返回任务执行结果
     *
     * @param rcsReporterTask
     * @return
     */
    public int reporterTask(RcsReporterTask rcsReporterTask) {
        // 结果汇总
        boolean completed = true;
        EntityWrapper<Task> wrapper = new EntityWrapper<>();
        wrapper.eq("task_no", rcsReporterTask.getRobotTaskCode());
        List<Task> tasks = taskService.selectList(wrapper);
        if (tasks != null && !tasks.isEmpty()) {
            for (Task task : tasks) {
                if (task.getWrkSts() != 304) {   // TODO:确认完成,可能存在多盘任务
                    completed = false;
                }
            }
        }
        if (completed) {
            TransTaskFeedback transTaskFeedback = new TransTaskFeedback();
            transTaskFeedback.setTaskno(rcsReporterTask.getRobotTaskCode());
//            transTaskFeedback.setTaskname();
            transTaskFeedback.setResult(1);
            String url = MES_URL + "api/task/reporter";
            String response = RcsServiceImpl.sendPost(url, transTaskFeedback.toString());
            if (!StringUtils.isEmpty(response) && response.contains("Success")){
                MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
                if("1".equals(mesReturn.getSuccess())) {
                    return 1;
                }
            }
        }
        return 0;
    }
    /**
     * 9.8申请华晓AGV进入生产线
     *
     * @param apply
     * @return
     */
    public String applyInLine(TransParent apply) {
        String url = MES_URL + "api/apply/inLine";
        String response = RcsServiceImpl.sendPost(url, apply.toString());
        if (!StringUtils.isEmpty(response) && response.contains("Success")){
            JSONObject jsonObject = JSONObject.parseObject(response);
            if("1".equals(jsonObject.getString("Success"))) {
                return jsonObject.getJSONObject("Data").getString("status");
            }
        }
        return "N";
    }
    /**
     * 入站请求:转发AGV->入站请求->给MES
     *
     * @param apply
     * @return
     */
    public int applyInStation(TransParent apply) {
        String url = MES_URL + (apply.getProductLineId().equals("LL") ? "AGVTransportPalletNotice" : "Aprs/AGVTransportPalletNotice");
        String response = RcsServiceImpl.sendPost(url, JSONObject.toJSONString(apply));
        if (!StringUtils.isEmpty(response) && response.contains("Success")){
            MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
            if("1".equals(mesReturn.getSuccess())) {
                return 1;
            }
        }
        return 0;
    }
    /**
     * 入站允许:转发MES->允许入站->给AGV
     *
     * @param allow
     * @return
     */
    public MesReturn allowInStation(TransInOutStationAllow allow) {
        MesReturn mesReturn = new MesReturn();
        mesReturn.setSuccess("1");
        if ("Y".equals(allow.getStatus())) {
            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, checkRcsFactory(allow.getAgvCode()));
            mesReturn.setSuccess(success == 1 ? "1" : "2");
            mesReturn.setMessage(success == 1 ? "" : "转发给RCS失败");
        }
        return mesReturn;
    }
    /**
     * 到站完成:转发AGV->到站完成->给MES
     *
     * @param arrivalStation
     * @return
     */
    public int arriveOnStation(TransArrivalStation arrivalStation,String path) {
        String url = MES_URL + path;
        String response = RcsServiceImpl.sendPost(url, JSONObject.toJSONString(arrivalStation));
        if (!StringUtils.isEmpty(response) && response.contains("Success")){
            MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
            if("1".equals(mesReturn.getSuccess())) {
                return 1;
            }
        }
        return 0;
    }
    /**
     * 离站请求:转发AGV->离站请求->给MES
     *
     * @param apply
     * @return
     */
    public int applyOutStation(TransParent apply) {
        String url = MES_URL + "api/apply/outStation";
        String response = RcsServiceImpl.sendPost(url, JSONObject.toJSONString(apply));
        if (!StringUtils.isEmpty(response) && response.contains("Success")){
            MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
            if("1".equals(mesReturn.getSuccess())) {
                return 1;
            }
        }
        return 0;
    }
    /**
     * 离站允许:转发MES->允许离站->给AGV
     *
     * @param allow
     * @return
     */
    public MesReturn allowOutStation(TransInOutStationAllow allow) {
        MesReturn mesReturn = new MesReturn();
        mesReturn.setSuccess("1");
        if ("Y".equals(allow.getStatus())) {
            RcsTaskContinue rcsTaskContinue = new RcsTaskContinue();
            rcsTaskContinue.setRobotTaskCode(allow.getTaskno());
            rcsTaskContinue.setTriggerType("TASK");
            rcsTaskContinue.setTriggerCode(allow.getTaskno());
            int success = rcsService.continueTask(rcsTaskContinue, checkRcsFactory(allow.getAgvCode()));
            mesReturn.setSuccess(success == 1 ? "1" : "2");
            mesReturn.setMessage(success == 1 ? "" : "转发给RCS失败");
        }
        return mesReturn;
    }
    /**
     * 离站完成:转发AGV->离站完成->给MES
     *
     * @param apply
     * @return
     */
    public int outStation(TransParent apply) {
        String url = MES_URL + (apply.getProductLineId().equals("LL") ? "AGVDepartureCompleted" : "Aprs/AGVDepartureCompleted");
        String response = RcsServiceImpl.sendPost(url, JSONObject.toJSONString(apply));
        if (!StringUtils.isEmpty(response) && response.contains("Success")){
            MesReturn mesReturn = JSONObject.parseObject(response, MesReturn.class);
            if("1".equals(mesReturn.getSuccess())) {
                return 1;
            }
        }
        return 0;
    }
    @Override
    public R tkt(String taskNo) {
        boolean flag = false;
        try {
            EntityWrapper<Task> wapper = new EntityWrapper<>();
            wapper.eq("task_no", taskNo).orderBy("wrk_date",false);
            Task task = taskService.selectOne(wapper);
            // 下发给RCS
            RcsTaskSubmit rcsTaskSubmit = new RcsTaskSubmit();
            rcsTaskSubmit.setRobotTaskCode(taskNo + "-1");
            rcsTaskSubmit.setInitPriority(10);  //默认10
            List<RcsTaskTargetRoute> targetRouteList = new ArrayList<>();
            RcsTaskTargetRoute startRoute = new RcsTaskTargetRoute();
            startRoute.setSeq(0);
            startRoute.setCode(task.getStaNo());
            startRoute.setOperation("COLLECT");
            targetRouteList.add(startRoute);
            RcsTaskTargetRoute endRoute = new RcsTaskTargetRoute();
            endRoute.setSeq(1);
            endRoute.setCode(task.getSourceStaNo());
            endRoute.setOperation("DELIVERY");
            targetRouteList.add(endRoute);
            rcsTaskSubmit.setTargetRoute(targetRouteList);
            // 更新起点和终点
            String memo = task.getMemo();
            TransTask transTask = JSONObject.parseObject(memo, TransTask.class);
            transTask.setCurStationId(task.getSourceStaNo());
            transTask.setNextStationId(task.getStaNo());
            transTask.setTransType("01"); // 下空托
            // 更新agv任务起点和终点
            task.setTaskNo(taskNo + "-1");
            task.setSourceStaNo(transTask.getCurStationId());
            task.setStaNo(transTask.getNextStationId());
            task.setMemo(JSONObject.toJSONString(transTask));
            taskService.updateById(task);
            // 转发给海康或华晓RCS
            int success = rcsService.submitTask(rcsTaskSubmit, transTask.getAgvFactory());
            if (success == 1) {
                flag = true;
            }
        } catch (Exception e) {
            log.error("空托回产线发AGV运输任务失败", e);
        }
        return flag ?R.ok() : R.parse("空托回产线呼叫agv失败");
    }
    // endregion
    /**
     * 查询Rcs地址
     *
     * @param agvNo
     * @return 1 海康;2 华晓
     */
    private int checkRcsFactory(String agvNo) {
        AgvInfo agvInfo = agvInfoMapper.selectById(agvNo);
        return agvInfo.getAgvFactory();
    }
}
src/main/java/com/zy/asrs/service/impl/RcsServiceImpl.java
New file
@@ -0,0 +1,614 @@
package com.zy.asrs.service.impl;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.mes.TransArrivalStation;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.*;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@Slf4j
@Service
public class RcsServiceImpl implements RcsService {
    // 海康RCS地址
    @Value("${hik.url}")
    private String HIK_URL;
    // 华晓RCS地址
    @Value("${hx.url}")
    private String HX_URL;
    @Value("${mes.defaultUserId}")
    public long defaultUserId;
    @Resource
    private MesService mesService;
    @Resource
    private TaskService taskService;
    @Resource
    private BlockStationMapper blockStationMapper;
    @Resource
    private BlockTaskMapper blockTaskMapper;
    @Resource
    private TaskDetlServiceImpl taskDetlService;
    @Resource
    private WrkMastService wrkMastService;
    // region 封锁区逻辑,目前只有一个大封锁区,任务全部转到滑块库处理,或直接写到滑块库
    /**
     * 申请封锁区请求
     *
     * @param apply
     * @return
     */
    private int applyBlock(RcsReporterEqpt apply) {
        BlockTask blockTask = new BlockTask();
        blockTask.setTaskCode(apply.getTaskCode());
        blockTask.setApplyTime(new Date());
        blockTask.setBlockNo(apply.getEqptCode());
        blockTask.setBlockName(apply.getEqptName());
        blockTask.setMethod(apply.getMethod());
        blockTask.setCompleted(0);
        return blockTaskMapper.insert(blockTask);
    }
    /**
     * 管理封锁区进入
     * TODO:增加锁防冲突,可能为分布式锁,定期5秒循环调用
     *
     */
    public void managerBlock() {
       try {
           BlockTask firstTask = blockTaskMapper.findTop();
           if (firstTask == null) {
               return;
           }
           EntityWrapper<BlockStation> wrapper = new EntityWrapper<>();
           wrapper.eq("block_no", firstTask.getBlockNo());
           List<BlockStation> stations = blockStationMapper.selectList(wrapper);
           if (!stations.isEmpty()) {
               boolean locked = false;
               for (BlockStation station : stations) {
                   // 只允许1个厂家设备进入封锁区,status状态:0 空闲;1 海康封锁中;2 华晓封锁中;-1 异常;
                   if (station.getStatus() > 0 && !station.getStatus().equals(firstTask.getAgvFactory())) {
                       locked = true;
                       break;
                   }
               }
               if (!locked) {
                   // 封锁状态
                   int success = blockStationMapper.addByBlockNo(firstTask.getBlockNo(), firstTask.getAgvFactory());
                   if (success > 0) {
                       // 通知RCS
                       RcsEqptNotify notify = new RcsEqptNotify();
                       notify.setEqptCode(firstTask.getBlockNo());
                       notify.setTaskCode(firstTask.getTaskCode());
                       notify.setActionStatus("1");
                       notifyEqpt(notify, firstTask.getAgvFactory());
                   }
               }
           }
       } catch (Exception e) {
           log.error("管理封锁区异常", e);
       }
    }
    /**
     * 离开释放封锁区请求
     * TODO:增加锁防冲突,可能为分布式锁
     *
     * @param apply
     * @return
     */
    private int releaseBlock(RcsReporterEqpt apply) {
        BlockTask task = blockTaskMapper.findByTaskCode(apply.getTaskCode());
        EntityWrapper<BlockStation> wrapper = new EntityWrapper<>();
        wrapper.eq("block_no", task.getBlockNo());
        List<BlockStation> stations = blockStationMapper.selectList(wrapper);
        if (!stations.isEmpty()) {
            // 先完成任务
            task.setCompleted(1);
            task.setCompletedTime(new Date());
            int updateTask = blockTaskMapper.updateById(task);
            // 再更新封锁区数量
            for (BlockStation station : stations) {
                if (station.getAgvNum() - 1 == 0) {
                    station.setStatus(0);
                }
                station.setAgvNum(station.getAgvNum() - 1);
                int updateBlock = blockStationMapper.updateById(station);
            }
        }
        return 1;
    }
    // endregion
    // region 海康RCS,AGV
    /**
     * 2.1.2任务下发接口
     * 厂家:海量、华晓
     *
     * @param rcsTaskSubmit
     * @param rcsFactory 1 海康;2 华晓;
     * @return
     */
    public int submitTask(RcsTaskSubmit rcsTaskSubmit, int rcsFactory){
        return 1;
//        String url = rcsFactory == 2 ? HX_URL :HIK_URL + "api/robot/controller/task/submit";
//        String response = sendPost(url, rcsTaskSubmit.toString());
//        if (!StringUtils.isEmpty(response) && response.contains("code")){
//            RcsReturn rcsReturn = JSONObject.parseObject(response, RcsReturn.class);
//            if("SUCCESS".equals(rcsReturn.getCode())) {
//                JSONObject data = rcsReturn.getData();
//                String robotTaskCode = data.getString("robotTaskCode");
//                if (robotTaskCode.equals(rcsTaskSubmit.getRobotTaskCode())){
//                    return 1;
//                }
//            }
//        }
//
//        return 0;
    }
    /**
     * 2.1.3任务继续执行接口
     *
     * @param rcsTaskContinue
     * @param rcsFactory
     * @return
     */
    public int continueTask(RcsTaskContinue rcsTaskContinue, int rcsFactory){
        String url = rcsFactory == 2 ? HX_URL :HIK_URL + "api/robot/controller/task/extend/continue";
        String response = sendPost(url, rcsTaskContinue.toString());
        if (!StringUtils.isEmpty(response) && response.contains("code")){
            RcsReturn rcsReturn = JSONObject.parseObject(response, RcsReturn.class);
            if("SUCCESS".equals(rcsReturn.getCode())) {
                JSONObject data = rcsReturn.getData();
                String robotTaskCode = data.getString("robotTaskCode");
                if (robotTaskCode.equals(rcsTaskContinue.getRobotTaskCode())) {
                    return 1;
                }
            }
        }
        return 0;
    }
    /**
     * 2.1.4任务取消接口
     *
     * @param rcsTaskCancel
     * @param rcsFactory
     * @return
     */
    public int cancelTask(RcsTaskCancel rcsTaskCancel, int rcsFactory){
        String url = rcsFactory == 2 ? HX_URL :HIK_URL  + "api/robot/controller/task/cancel";
        String response = sendPost(url, rcsTaskCancel.toString());
        if (!StringUtils.isEmpty(response) && response.contains("code")){
            RcsReturn rcsReturn = JSONObject.parseObject(response, RcsReturn.class);
            if("SUCCESS".equals(rcsReturn.getCode())) {
                JSONObject data = rcsReturn.getData();
                String robotTaskCode = data.getString("robotTaskCode");
                if (robotTaskCode.equals(rcsTaskCancel.getRobotTaskCode())) {
                    return 1;
                }
            }
        }
        return 0;
    }
    /**
     * 2.1.15外设执行通知接口,通知进入封锁区
     *
     * @param rcsEqptNotify
     * @param rcsFactory
     * @return
     */
    private int notifyEqpt(RcsEqptNotify rcsEqptNotify, int rcsFactory){
        String url = rcsFactory == 2 ? HX_URL :HIK_URL + "api/wcs/robot/eqpt/notify";
        String response = sendPost(url, rcsEqptNotify.toString());
        if (!StringUtils.isEmpty(response) && response.contains("code")){
            RcsReturn rcsReturn = JSONObject.parseObject(response, RcsReturn.class);
            if("SUCCESS".equals(rcsReturn.getCode())) {
                JSONObject data = rcsReturn.getData();
                String applyCode = data.getString("taskCode");  //申请请求编号,非任务编号
                if (applyCode.equals(rcsEqptNotify.getTaskCode())) {
                    return 1;
                }
            }
        }
        return 0;
    }
    /**
     * 2.2.1任务执行回馈
     * 厂家:海量、华晓
     *
     * @param rcsReporterTask
     * @return
     */
    public RcsReturn reporterTask(RcsReporterTask rcsReporterTask) {
        RcsReturn rcsReturn = new RcsReturn();
        String robotTaskCode = rcsReporterTask.getRobotTaskCode();
        String singleRobotCode = rcsReporterTask.getSingleRobotCode();
        JSONObject values = rcsReporterTask.getExtra().getJSONObject("values");
        // start : 任务开始;outbin : 走出储位;end : 任务完成
        String method = values.getString("method");
        String carrierType = values.getString("carrierType");
        try {
            if ("Q3".equals(carrierType) || "Q8".equals(carrierType)) {    //AGV
                EntityWrapper<Task> wrapper = new EntityWrapper<>();
                wrapper.eq("task_no", robotTaskCode);
                Task task = taskService.selectOne(wrapper);
                if (task == null || !task.getTaskNo().equals(robotTaskCode)) {
                    rcsReturn.setCode("Err_RobotCodeNotMatch");
                    rcsReturn.setMessage("");
                    JSONObject data = new JSONObject();
                    data.put("robotTaskCode", robotTaskCode);
                    rcsReturn.setData(data);
                    return rcsReturn;
                }
                JSONObject memo = JSONObject.parseObject(task.getMemo());
                switch (Objects.requireNonNull(RcsRetMethodEnum.getEnum(method))) {
                    case TASK_START: {
                        task.setWrkSts(302L);   // 301 任务下发、302 任务执行、303 任务中断、304 任务结束
                        task.setModiTime(new Date());
                        task.setModiUser(defaultUserId);
                        taskService.updateById(task);
                    } break;
//                    case TASK_OUT_BIN: {} break;
                    case TASK_END: {
                        // 更新任务状态等内部逻辑
                        task.setWrkSts(304L);   // 301 任务下发、302 任务执行、303 任务中断、304 任务结束
                        task.setModiTime(new Date());
                        task.setModiUser(defaultUserId);
                        taskService.updateById(task);
                        // 任务完成
                        mesService.reporterTask(rcsReporterTask);
//                    EntityWrapper<TaskDetl> wapper2 = new EntityWrapper<>();
//                    wapper2.eq("wrk_no", task.getWrkNo())
//                            .eq("matnr", memo.getString("ItemNo"))
//                            .eq("order_no", memo.getString("OrderNo"));
//                    TaskDetl taskDetl = taskDetlService.selectOne(wapper2);
//                    taskDetl.setAnfme()
//                    taskDetlService.updateById();
//                    // 301 任务下发、302 任务执行、303 任务中断、304 任务结束
//                    taskService.completeWrkMast();
//                    taskDetlService.
                    } break;
                    case APPLY_IN_STATION:
                    case APPLY_OFF_STATION:
                    case ARRIVE_OFF_STATION: {
                        TransParent apply = new TransParent();
                        apply.setTaskno(robotTaskCode);
                        apply.setTaskname(memo.getString("taskName"));
                        apply.setAgvCode(singleRobotCode);
                        apply.setTransType(memo.getString("TransType"));
                        apply.setProductLineId(memo.getString("ProductLineId"));
//                        apply.setStationId(task.getStaNo());
                        String transType = memo.getString("TransType");
                        if(transType.equals("02") || transType.equals("04") || transType.equals("06")) {
                            apply.setStationId(task.getSourceStaNo());
                        } else {
                            apply.setStationId(task.getStaNo());
                        }
                        if (RcsRetMethodEnum.APPLY_IN_STATION.getCode().equals(method)) {
                            mesService.applyInStation(apply);
                        } else if (RcsRetMethodEnum.APPLY_OFF_STATION.getCode().equals(method)) {
                            mesService.applyOutStation(apply);
                        } else if (RcsRetMethodEnum.ARRIVE_OFF_STATION.getCode().equals(method)) {
                            mesService.outStation(apply);
                        }
                    } break;
                    case ARRIVE_ON_STATION: {
                        EntityWrapper<TaskDetl> wapper2 = new EntityWrapper<>();
                        wapper2.eq("wrk_no", task.getWrkNo())
//                                .eq("matnr", memo.getString("Itemno"))
                                .eq("order_no", memo.getString("OrderNo"));
                        TaskDetl taskDetl = taskDetlService.selectOne(wapper2);
                        TransArrivalStation arrivalStation = new TransArrivalStation();
                        arrivalStation.setTaskno(robotTaskCode);
                        arrivalStation.setTaskname(memo.getString("taskName"));
                        arrivalStation.setTuoPanId(taskDetl == null || taskDetl.getZpallet() == null ? "" : taskDetl.getZpallet());
                        arrivalStation.setDaotype(memo.getString("TransType"));
                        arrivalStation.setProductLineId(memo.getString("ProductLineId"));
//                        arrivalStation.setStationId(task.getStaNo());
                        arrivalStation.setOrderNo(memo.getString("OrderNo"));
                        String transType = memo.getString("TransType");
                        String dJNo = memo.getString("djNo");
                        arrivalStation.setDJNo(dJNo);
                        if(transType.equals("02") || transType.equals("04") || transType.equals("06")) {
                            arrivalStation.setStationID(task.getSourceStaNo());
                        } else {
                            arrivalStation.setStationID(task.getStaNo());
                        }
                        String path;
                        if(transType.equals("05") || transType.equals("06")) {
                            path = "ToolArrivalNotice";
                        } else {
                            path = "AGVArrivalCompleted";
                        }
                        if(transType.equals("01") && arrivalStation.getStationID().contains("XL") || arrivalStation.getStationID().contains("TOOL")) {
                            path = "ToolArrivalNotice";
                        }
                        mesService.arriveOnStation(arrivalStation,path);
                    } break;
                    default: {} break;
                }
            } else if ("CTU".equals(carrierType)) { //CTU
                EntityWrapper<WrkMast> wrapper = new EntityWrapper<>();
                wrapper.eq("task_no", robotTaskCode);
                WrkMast task = wrkMastService.selectOne(wrapper);
                if (task == null || !task.getTaskNo().equals(robotTaskCode)) {
                    rcsReturn.setCode("Err_RobotCodeNotMatch");
                    rcsReturn.setMessage("");
                    JSONObject data = new JSONObject();
                    data.put("robotTaskCode", robotTaskCode);
                    rcsReturn.setData(data);
                    return rcsReturn;
                }
//                JSONObject memo = JSONObject.parseObject(task.getMemo());
                switch (Objects.requireNonNull(RcsRetMethodEnum.getEnum(method))) {
                    case TASK_START: {
//                        task.setWrkSts(302L);   // 301 任务下发、302 任务执行、303 任务中断、304 任务结束
//                        task.setModiTime(new Date());
//                        task.setModiUser(defaultUserId);
//                        taskService.updateById(task);
                    } break;
//                    case TASK_OUT_BIN: {} break;
                    case TASK_END: {
                        // 更新任务状态等内部逻辑
                        long wrkSts = task.getWrkSts(); // 1.入库;101.出库;
                        if (task.getIoType() == 1) {
                            wrkSts = 4L;
                        } else if (task.getIoType() == 101) {
                            wrkSts = 14L;
                        }
                        task.setWrkSts(wrkSts); // 4.入库完成;14.已出库未确认;
                        task.setModiTime(new Date());
                        task.setModiUser(defaultUserId);
                        wrkMastService.updateById(task);
                        // TODO:任务完成触发出入库变更操作
//                        // 入库完成
//                        mesService.inFeedback(memo.getString("OrderNo"));
//                        // 出库完成
//                        mesService.outFeedback(memo.getString("OrderNo"));
                    } break;
                    default: {} break;
                }
            }
            // 返回RCS
            rcsReturn.setCode("SUCCESS");
            rcsReturn.setMessage("");
            JSONObject data = new JSONObject();
            data.put("robotTaskCode", robotTaskCode);
            rcsReturn.setData(data);
        } catch (Exception e) {
            log.error("RCS反馈任务进度处理异常 - {}", rcsReporterTask, e);
            rcsReturn.setCode("Err_Internal");
            rcsReturn.setMessage("内部处理异常");
            JSONObject data = new JSONObject();
            data.put("robotTaskCode", robotTaskCode);
            rcsReturn.setData(data);
        }
        return rcsReturn;
    }
    /**
     * 2.2.4请求外设接口(请求封锁区)
     * 厂家:海量、华晓
     *
     * @param rcsReporterEqpt
     * @return
     */
    public RcsReturn reporterEqpt(RcsReporterEqpt rcsReporterEqpt){
        int success = 0;
        if ("APPLY_LOCK".equals(rcsReporterEqpt.getMethod())) { //申请
            success = applyBlock(rcsReporterEqpt);
        } else if ("RELEASE_EQPT".equals(rcsReporterEqpt.getMethod())) { //释放
            success = releaseBlock(rcsReporterEqpt);
        }
        // 返回RCS
        RcsReturn rcsReturn = new RcsReturn();
        rcsReturn.setCode(success > 0 ? "SUCCESS" : "Err_Internal");
        rcsReturn.setMessage(success > 0 ? "" : "内部错误");
        JSONObject data = new JSONObject();
        data.put("extra", null);
        rcsReturn.setData(data);
        return rcsReturn;
    }
    // endregion
    // region 海康CTU 刀具库
    // TODO: CTU上层组参引用,
    // 2.1.2任务下发接口
    // 2.1.3任务继续执行接口
    // 2.1.4任务取消接口
    // 2.2.1任务执行回馈
////    @Transactional(rollbackFor = Exception.class)
//    public void receiveTaskStatus(RcsReporterTask callbackParam, String method, String stockType, Long hostId) {
//
//        JSONObject values = callbackParam.getExtra().getJSONObject("values");
//        EntityWrapper<Task> wapper = new EntityWrapper<>();
//        wapper.eq("task_no", callbackParam.getRobotTaskCode());
//        Task task = taskService.selectOne(wapper);
//        if (task == null && !StringUtils.isEmpty(task.getWrkNo())) {
//            if (1 == task.getIoType()) {   // 入库
//                // 更新库存
//
//                // 更新任务状态
//            } else if (101 == task.getIoType()) {    // 出库
//                // 更新库存
//
//                // 更新任务状态
//
//                // 货物和托盘解绑
//            }
//        }
//    }
    // endregion
    // region 华晓RCS
    /**
     * 9.7申请进入生产线
     *
     * @param apply
     * @return
     */
    public JSONObject hxApplyInLine(TransParent apply) {
        String status = mesService.applyInLine(apply);
        JSONObject result = new JSONObject();
        result.put("Success", 1);
        result.put("Message", status);
        JSONObject data = new JSONObject();
        data.put("status", status);
        result.put("Data", data);
        return result;
    }
    // endregion
    // region httpUtil
    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url 发送请求的 URL
     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try
        {
            log.info("sendPost - {} - {}", url, param);
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            out = new PrintWriter(conn.getOutputStream());
            out.print(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null)
            {
                result.append(line);
            }
            log.info("recv - {}", result);
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
        }
        finally
        {
            try
            {
                if (out != null)
                {
                    out.close();
                }
                if (in != null)
                {
                    in.close();
                }
            }
            catch (IOException ex)
            {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }
    // endregion
}
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -370,6 +370,12 @@
                wrkDetl.setAppeUser(userId);
                wrkDetl.setModiTime(now);
                wrkDetl.setModiUser(userId);
                wrkDetl.setMatnr(detlDto.getLocDetl().getMatnr());
                wrkDetl.setMaktx(detlDto.getLocDetl().getMaktx());
                wrkDetl.setUnit(detlDto.getLocDetl().getUnit());
                wrkDetl.setSpecs(detlDto.getLocDetl().getSpecs());
                wrkDetl.setUnit(detlDto.getLocDetl().getUnit());
                wrkDetl.setModel(detlDto.getLocDetl().getModel());
                if (!wrkDetlService.insert(wrkDetl)) {
                    throw new CoolException("保存工作档明细失败");
                }
@@ -457,6 +463,11 @@
            wrkDetl.setAppeUser(userId);
            wrkDetl.setModiTime(now);
            wrkDetl.setModiUser(userId);
            wrkDetl.setMatnr(orderDetl.getMatnr());
            wrkDetl.setMaktx(orderDetl.getMaktx());
            wrkDetl.setSpecs(orderDetl.getSpecs());
            wrkDetl.setModel(orderDetl.getModel());
            wrkDetl.setUnit(orderDetl.getUnit());
            if (!wrkDetlService.insert(wrkDetl)) {
                throw new CoolException("保存工作档明细失败");
            }
src/main/java/com/zy/asrs/service/impl/WrkDetlServiceImpl.java
@@ -45,6 +45,11 @@
            wrkDetl.setAppeTime(now);
            wrkDetl.setModiUser(userId);
            wrkDetl.setModiTime(now);
            wrkDetl.setMatnr(mat.getMatnr());
            wrkDetl.setMaktx(mat.getMaktx());
            wrkDetl.setSpecs(mat.getSpecs());
            wrkDetl.setModel(mat.getModel());
            wrkDetl.setUnit(mat.getUnit());
            if (!this.insert(wrkDetl)) {
                throw new CoolException("保存工作明细失败");
            }
src/main/java/com/zy/asrs/task/BlockScheduler.java
New file
@@ -0,0 +1,26 @@
package com.zy.asrs.task;
import com.zy.asrs.service.RcsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Slf4j
@Component
public class BlockScheduler {
    @Resource
    private RcsService rcsService;
    /**
     * 管理封锁区请求
     *
     */
    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute(){
//        rcsService.managerBlock();
    }
}
src/main/java/com/zy/asrs/task/OrderSyncScheduler.java
@@ -2,8 +2,9 @@
import com.core.common.Cools;
import com.zy.asrs.entity.Order;
import com.zy.asrs.service.ApiLogService;
import com.zy.asrs.service.OrderService;
import com.zy.asrs.entity.OrderPakin;
import com.zy.asrs.entity.OrderPakout;
import com.zy.asrs.service.*;
import com.zy.asrs.task.core.ReturnT;
import com.zy.asrs.task.handler.OrderSyncHandler;
import com.zy.asrs.utils.OrderInAndOutUtil;
@@ -15,6 +16,7 @@
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
@@ -30,6 +32,12 @@
    private OrderService orderService;
    @Autowired
    private ApiLogService apiLogService;
    @Resource
    private OrderPakinService orderPakinService;
    @Resource
    private OrderPakoutService orderPakoutService;
    @Resource
    private MesService mesService;
    @Value("${erp.switch.ErpReportOld}")
    private boolean ErpReportOld;
@@ -104,23 +112,43 @@
//    @Scheduled(cron = "0/30 * * * * ? ")
    @Async("orderThreadPool")
    public void completeAndReportOrderReport() {
        if (!ErpReportOld){
            return;
        }
        String erpReport = Parameter.get().getErpReport();
        if (!Cools.isEmpty(erpReport) && erpReport.equals("true")) {
            List<Order> orders = orderService.selectComplete();
            for (Order order : orders) {
        // 入库完成
        List<OrderPakin> pakins = orderPakinService.selectComplete();
        for (OrderPakin orderPakin : pakins) {
                try {
                    ReturnT<String> result = orderSyncHandler.startOrderReport(order);
                    if (!result.isSuccess()) {
                        log.error("单据[orderNo={}]上报erp失败", order.getOrderNo());
                    }
                 mesService.inFeedback(orderPakin.getOrderNo());
                } catch (Exception e) {
                    log.error(e.getMessage());
                    log.error("单据[orderNo={}]上报erp失败", order.getOrderNo());
                log.error("推送入库完成信息错误, order{}", orderPakin, e);
                }
            }
        List<OrderPakout> pakouts = orderPakoutService.selectComplete();
        for (OrderPakout orderPakout : pakouts) {
            try {
                mesService.outFeedback(orderPakout.getOrderNo());
            } catch (Exception e) {
                log.error("推送出库完成信息错误, order{}", orderPakout, e);
        }
    }
//        if (!ErpReportOld){
//            return;
//        }
//        String erpReport = Parameter.get().getErpReport();
//        if (!Cools.isEmpty(erpReport) && erpReport.equals("true")) {
//            List<Order> orders = orderService.selectComplete();
//            for (Order order : orders) {
//                try {
//                    ReturnT<String> result = orderSyncHandler.startOrderReport(order);
//                    if (!result.isSuccess()) {
//                        log.error("单据[orderNo={}]上报erp失败", order.getOrderNo());
//                    }
//                } catch (Exception e) {
//                    log.error(e.getMessage());
//                    log.error("单据[orderNo={}]上报erp失败", order.getOrderNo());
//                }
//            }
//        }
    }
}
src/main/java/com/zy/asrs/task/WorkMastScheduler.java
@@ -2,6 +2,7 @@
import com.zy.asrs.entity.Task;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.MesService;
import com.zy.asrs.service.TaskService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.task.core.ReturnT;
@@ -12,6 +13,7 @@
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@@ -29,6 +31,9 @@
    private WorkMastHandler workMastHandler;
    @Autowired
    private TaskService taskService;
    @Resource
    private MesService mesService;
    // TODO:reporterTask()
    @Scheduled(cron = "0/3 * * * * ? ")
    private void execute(){
src/main/java/com/zy/asrs/task/handler/OrderSyncHandler.java
@@ -8,10 +8,7 @@
import com.zy.asrs.entity.DocType;
import com.zy.asrs.entity.Order;
import com.zy.asrs.entity.OrderDetl;
import com.zy.asrs.service.ApiLogService;
import com.zy.asrs.service.DocTypeService;
import com.zy.asrs.service.OrderDetlService;
import com.zy.asrs.service.OrderService;
import com.zy.asrs.service.*;
import com.zy.asrs.task.AbstractHandler;
import com.zy.asrs.task.core.ReturnT;
import com.zy.asrs.utils.OrderInAndOutUtil;
@@ -26,6 +23,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@@ -46,6 +44,14 @@
    private ApiLogService apiLogService;
    @Autowired
    private DocTypeService docTypeService;
    @Resource
    private MesService mesService;
    //TODO:完成订单时推送MES recvFeedback(orderNo);
    // mesService.inFeedback(memo.getString("OrderNo"));
    //                        // 出库完成
    //                        mesService.outFeedback(memo.getString("OrderNo"));
    @Transactional
    public ReturnT<String> startOrderIssuedOnceMore(Order order) {
src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java
@@ -131,6 +131,11 @@
                            locDetl.setZpallet(wrkDetl.getZpallet()); // 托盘条码
                            locDetl.setModiTime(now);
                            locDetl.setAppeTime(now);
                            locDetl.setMatnr(wrkDetl.getMatnr());
                            locDetl.setMaktx(wrkDetl.getMaktx());
                            locDetl.setSpecs(wrkDetl.getSpecs());
                            locDetl.setUnit(wrkDetl.getUnit());
                            locDetl.setZpallet(wrkDetl.getZpallet());
                            if (!locDetlService.insert(locDetl)) {
//                                exceptionHandle("全板入库 ===>> 添加库存明细失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo());
                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
@@ -202,6 +207,11 @@
                            locDetl.setZpallet(wrkDetl.getZpallet()); // 托盘条码
                            locDetl.setModiTime(now);
                            locDetl.setAppeTime(now);
                            locDetl.setMatnr(wrkDetl.getMatnr());
                            locDetl.setMaktx(wrkDetl.getMaktx());
                            locDetl.setSpecs(wrkDetl.getSpecs());
                            locDetl.setUnit(wrkDetl.getUnit());
                            locDetl.setZpallet(wrkDetl.getZpallet());
                            if (!locDetlService.insert(locDetl)) {
                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                                return FAIL.setMsg("拣料途中并板 ===>> 添加库存明细失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]");
@@ -308,6 +318,11 @@
                            locDetl.setZpallet(wrkDetl.getZpallet()); // 托盘条码
                            locDetl.setModiTime(now);
                            locDetl.setAppeTime(now);
                            locDetl.setMatnr(wrkDetl.getMatnr());
                            locDetl.setMaktx(wrkDetl.getMaktx());
                            locDetl.setSpecs(wrkDetl.getSpecs());
                            locDetl.setUnit(wrkDetl.getUnit());
                            locDetl.setZpallet(wrkDetl.getZpallet());
                            if (!locDetlService.insert(locDetl)) {
                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                                return FAIL.setMsg("并板入库 ===>> 新增库存明细失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]");
src/main/java/com/zy/common/config/LogAspect.java
New file
@@ -0,0 +1,112 @@
package com.zy.common.config;
import com.core.common.R;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.rmi.NoSuchObjectException;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
 * Created by Administrator on 2019-07-09.
 */
@Component
@Aspect
@Slf4j
@Order(2)
public class LogAspect {
    private final List<String> logApiList = Stream.of("digitalTwin", "api/mes", "api/robot")
            .collect(Collectors.toList());
    public LogAspect() {
    }
    /**
     * 切入点
     */
    @Pointcut("execution(* com.zy.asrs.controller.*.*(..))") // && !execution(* com.lg.iac.controller.PictureController.*(..))
    public void controllerPc() {
    }
    /**
     * 环绕通知
     * @param pjp ProceedingJoinPoint
     * @return 方法结果
     */
    @Around("controllerPc()")
    public Object around(ProceedingJoinPoint pjp) {
        try {
            ServletRequestAttributes attributes = Optional.ofNullable((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .orElseThrow(() -> new NoSuchObjectException("前置通知中获取的 ServletRequestAttributes 对象为空"));
            HttpServletRequest request = attributes.getRequest();
            if(urlContain(request.getRequestURL().toString())){
                // 前置通知
                log.info("------【前置通知】------");
                // 记录请求内容
                log.info("浏览器输入的网址:{}", request.getRequestURL().toString());
                log.info("HTTP_METHOD:{}", request.getMethod());
                log.info("IP:{}", request.getRemoteAddr());
                log.info("执行的业务方法名:{}", pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName());
                log.info("业务方法获得的参数:{}", Arrays.toString(pjp.getArgs()));
                Object result = pjp.proceed();
                // 后置通知
                log.info("------【后置通知】------");
                log.info("{}方法的返回值:{}", pjp.getSignature().getName(), result);
                return result;
            } else {
                return pjp.proceed();
            }
        } catch (Throwable e) {
            // 异常通知
            log.error("------【异常通知】------");
            log.error("{}方法异常,参数:{},异常:", pjp.getSignature().getName(), Arrays.toString(pjp.getArgs()), e);
            return R.error("服务器处理数据异常");
        } finally {
            try{
                ServletRequestAttributes attributes = Optional.ofNullable((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                        .orElseThrow(() -> new NoSuchObjectException("前置通知中获取的 ServletRequestAttributes 对象为空"));
                HttpServletRequest request = attributes.getRequest();
                if(urlContain(request.getRequestURL().toString())){
                    // 最终通知
                    log.info("------【最终通知】------");
                    log.info("{}方法执行结束", pjp.getSignature().getName());
                }
            } catch (Exception ignored){
            }
        }
    }
    /**
     * 是否不包含过滤日志接口
     *
     * @param url
     * @return
     */
    private boolean urlContain(String url){
        boolean have = false;
        for(String str : logApiList){
            if(url.contains(str)){
                have = true;
                return have;
            }
        }
        return have;
    }
}
src/main/java/com/zy/common/config/WebConfig.java
@@ -1,7 +1,8 @@
package com.zy.common.config;
import com.zy.common.constant.MesConstant;
import com.zy.common.utils.Http;
//import com.zy.common.constant.MesConstant;
//import com.zy.common.route.RouteFilter;
//import com.zy.common.utils.Http;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
@@ -15,6 +16,7 @@
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -30,11 +32,22 @@
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new RouteFilter())
//                .addPathPatterns("/api/robot") // 拦截路径
//                .excludePathPatterns("/static/**"); // 排除静态资源
        registry.addInterceptor(adminInterceptor)
                .addPathPatterns("/**")
        ;
    }
//    @Bean
//    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
//        RequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping();
//        handlerMapping.setOrder(0);
//        handlerMapping.setInterceptors(new RouteFilter());
//        return handlerMapping;
//    }
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
src/main/java/com/zy/common/route/RouteFilter.java
New file
@@ -0,0 +1,159 @@
package com.zy.common.route;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zy.asrs.entity.AgvInfo;
import com.zy.asrs.entity.rcs.RcsReporterEqpt;
import com.zy.asrs.entity.rcs.RcsReporterTask;
import com.zy.asrs.entity.rcs.RcsReturn;
import com.zy.asrs.mapper.AgvInfoMapper;
import com.zy.asrs.service.RcsService;
import com.zy.asrs.service.impl.RcsServiceImpl;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.apache.tika.utils.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
@Slf4j
@Component
public class RouteFilter implements HandlerInterceptor {
    private static final String[] WAREHOUSE_CODE = {"dj", "jg", "ljq", "hk"};
//    private static final String[] WAREHOUSE = {"刀具库", "加工库", "联结器装配库", "滑块库"};
//    @Value("${mes}")
    private static Integer CURRENT_WMS_ID = 4;  //滑块
    @Resource
    private RcsService rcsService;
    @Resource
    private AgvInfoMapper agvInfoMapper;
    // 请求前
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        if (findIndex(request) != CURRENT_WMS_ID) {
//            // 转发
//            // 获取RequestDispatcher对象
//            RequestDispatcher dispatcher = request.getRequestDispatcher("/SecondServlet");
//
//            // 转发请求到SecondServlet
//            dispatcher.forward(request, response);
//
////            forward(request);
//        }
        forward(request, response);
//        long startTime = System.currentTimeMillis();
//        System.out.println("preHandle,In:" + startTime);
//        request.setAttribute("startTime", startTime);
        return true;
    }
    // TODO:请求转发与响应重定向  //TODO:HttpServletRequest读取一次后不能再使用,需重构下逻辑顺序
    private void forward(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String url = request.getRequestURI();
        StringBuilder body = new StringBuilder();
        BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
        String line;
        while ((line = in.readLine()) != null) {
            body.append(line);
        }
        JSONObject bodyJson = JSONObject.parseObject(body.toString());
        String singleRobotCode = bodyJson.getString("singleRobotCode");
        if (!StringUtils.isBlank(singleRobotCode)) {    //任务回馈接口
            int index = findIndex(singleRobotCode);
            if (index != CURRENT_WMS_ID) {
                String wmsId = WAREHOUSE_CODE[index - 1];  //存储所有AGV所属库区
                url = url.replace(WAREHOUSE_CODE[CURRENT_WMS_ID - 1], wmsId);
                // 转发
                String returns = RcsServiceImpl.sendPost(url, body.toString());
                log.info("转发请求url:{},body:{},返回:{}", url, body, returns);
                response(response, returns);
            } else {
                // 内部逻辑处理
                RcsReporterTask param = JSONObject.toJavaObject(bodyJson, RcsReporterTask.class);
                RcsReturn rcsReturn = rcsService.reporterTask(param);
                response(response, rcsReturn.toString());
            }
        } else {    //请求外设(封锁区),封锁区由当前程序管理不转发
            RcsReporterEqpt param = JSONObject.toJavaObject(bodyJson, RcsReporterEqpt.class);
            RcsReturn rcsReturn = rcsService.reporterEqpt(param);
            response(response, rcsReturn.toString());
        }
    }
    private int findIndex(String agvNo) {
        AgvInfo agvInfo = agvInfoMapper.selectById(agvNo);
        if (agvInfo != null) {
            return Integer.parseInt(agvInfo.getBelongArea());
        }
        return -1;
    }
    public static void response(HttpServletResponse response, String baseRes){
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json; charset=utf-8");
        try (PrintWriter out = response.getWriter()) {
            out.print(JSON.toJSONString(baseRes));
            out.flush();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
//            e.printStackTrace();
        }
    }
//    public static void response(HttpServletResponse response, String baseRes){
//        response.setCharacterEncoding("utf-8");
//        response.setContentType("application/json; charset=utf-8");
//        try (PrintWriter out = response.getWriter()) {
//            R r = R.parse(baseRes);
//            JSONObject jsonObject = new JSONObject();
//            jsonObject.put("total", "0");
//            jsonObject.put("record", "");
//            r.add(jsonObject);
//            out.print(JSON.toJSONString(r));
//            out.flush();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//    /**
//     * 设置webflux模型响应
//     *
//     * @param response ServerHttpResponse
//     * @param contentType content-type
//     * @param status http状态码
//     * @param code 响应状态码
//     * @param value 响应内容
//     * @return Mono<Void>
//     */
//    public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status, Object value, int code)
//    {
//        response.setStatusCode(status);
//        response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
//        RcsReturn<?> result = RcsReturn.fail(code, value.toString());
//        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONString(result).getBytes());
//        return response.writeWith(Mono.just(dataBuffer));
//    }
}
src/main/java/com/zy/common/web/WcsController.java
@@ -51,6 +51,8 @@
    @Autowired
    private WorkService workService;
    // TODO:称重、拍照上报存储,CTU料箱运转
    @PostMapping("/pakin/loc/v1")
    @ResponseBody
    public synchronized R getLocNo(@RequestBody SearchLocParam param) {
src/main/java/com/zy/system/timer/LicenseTimer.java
@@ -26,7 +26,7 @@
    }
    public void setSystemSupport(boolean systemSupport) {
        SYSTEM_SUPPORT = systemSupport;
        SYSTEM_SUPPORT = true; // systemSupport;
    }
    public int getLicenseDays() {
src/main/resources/application-dev.yml
@@ -1,5 +1,5 @@
server:
  port: 8080
  port: 8088
  servlet:
    context-path: /@pom.build.finalName@
@@ -11,8 +11,11 @@
  datasource:
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    username: sa
    password: Skyouc#23
    url: jdbc:sqlserver://127.0.0.1:1433;databasename=jsxswms
    password: sa@123
    url: jdbc:sqlserver://127.0.0.1:1433;databasename=djwms
#    username: sa
#    password: Skyouc#23
#    url: jdbc:sqlserver://192.168.4.24:1433;databasename=jsxswms
  mvc:
    static-path-pattern: /**
  redis:
@@ -110,3 +113,31 @@
    username: "llw"
    password: "666666"
    lcid: 2052
#分库配置
wms:
  #当前是第几库
  currentId: 4
  #当前库名称
  currentName: 滑块装配库
  #立库AGV自动运货出库口编码
  wmsTransStartStation1: 1013
#mes对接
mes:
  url: http://172.26.11.250/dev-api/basicmodel/Api/WMS/
  #默认接口操作人员id
  defaultUserId: 30
#海康对接
hik:
  url: http://127.0.0.1:8089/hik/
#华晓对接
hx:
  url: http://127.0.0.1:8089/hx/
#刀具管理系统对接
dj:
  url: http://172.26.11.2/
src/main/resources/libs/framework-3.2.0.jar
Binary files differ
src/main/resources/logback-spring.xml
@@ -19,6 +19,9 @@
        </encoder>
    </appender>
    <!-- 日志保存路径 -->
    <property name="LOG_PATH" value="D:/wmslogs/dj" />
    <!--info级别-->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/info.log</file>
src/main/resources/mapper/BlockStationMapper.xml
New file
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zy.asrs.mapper.BlockStationMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.BlockStation">
        <result column="task_code" property="taskCode" />
        <result column="apply_time" property="applyTime" />
        <result column="block_no" property="blockNo" />
        <result column="block_name" property="blockName" />
        <result column="method" property="method" />
        <result column="completed" property="completed" />
        <result column="agv_factory" property="agvFactory" />
    </resultMap>
    <update id="addByBlockNo">
        UPDATE agv_block_station SET status = #{status}, agv_num = ISNULL(agv_num, 0) + 1 WHERE block_no = #{blockNo}
    </update>
    <update id="delByBlockNo">
        UPDATE agv_block_station SET status = #{status}, agv_num = ISNULL(agv_num, 0) - 1 WHERE block_no = #{blockNo}
    </update>
</mapper>
src/main/resources/mapper/BlockTaskMapper.xml
New file
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zy.asrs.mapper.BlockTaskMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.BlockTask">
        <result column="task_code" property="taskCode" />
        <result column="apply_time" property="applyTime" />
        <result column="block_no" property="blockNo" />
        <result column="block_name" property="blockName" />
        <result column="method" property="method" />
        <result column="completed" property="completed" />
        <result column="agv_factory" property="agvFactory" />
    </resultMap>
    <select id="findTop" resultType="com.zy.asrs.entity.BlockTask">
        SELECT TOP 1 * FROM agv_block_task WHERE completed = 0 AND method = 'APPLY_LOCK' ORDER BY apply_time ASC
    </select>
    <select id="findByTaskCode" resultType="com.zy.asrs.entity.BlockTask">
        SELECT * FROM agv_block_task WHERE method = 'APPLY_LOCK' AND completed = 0 AND task_code = #{taskCode}
    </select>
</mapper>
src/main/resources/mapper/LocCountMapper.xml
New file
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zy.asrs.mapper.LocCountMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.LocCount">
        <result column="date" property="date" />
        <result column="area_id" property="areaId" />
        <result column="loc_num" property="locNum" />
        <result column="remain_num" property="remainNum" />
    </resultMap>
    <select id="getByAreaAndDate" resultType="com.zy.asrs.entity.LocCount">
        SELECT * FROM asr_loc_count
        WHERE area_id = #{areaId} AND date &gt; #{startDate} AND date &lt; #{endDate}
    </select>
    <select id="getByDate" resultType="com.zy.asrs.entity.LocCount">
        SELECT date, SUM(ISNULL(loc_num, 0)) AS loc_num, SUM(ISNULL(remain_num, 0)) AS remain_num
        FROM asr_loc_count
        GROUP BY date
    </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})
        ELSE
            UPDATE asr_loc_count SET loc_num = #{model.locNum}, remain_num = #{model.remainNum}
    </insert>
    <select id="totalLoc" resultType="com.zy.asrs.entity.LocCount">
        SELECT area_id, COUNT(*) AS loc_num FROM asr_loc_mast WHERE loc_sts != 'Z' GROUP BY area_id
    </select>
    <select id="useLoc" resultType="com.zy.asrs.entity.LocCount">
        SELECT area_id, COUNT(*) AS loc_num 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'
        GROUP BY area_id
    </select>
</mapper>
src/main/resources/mapper/ViewDigitalTwinMapper.xml
New file
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zy.asrs.mapper.DigitalTwinMapper">
    <!--总览:总库位、已用库位、今日库存、今日出库、今日入库-->
    <select id="overview" resultType="Double">
        SELECT COUNT(*) FROM asr_loc_mast WHERE loc_sts != 'Z'
            <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>
        UNION ALL
        SELECT ISNULL(SUM(anfme), 0) FROM asr_loc_detl
        <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>
        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>
    </select>
    <select id="recentOrder" resultType="com.zy.asrs.entity.digitaltwin.DtOrderVo">
        SELECT CONVERT(VARCHAR, order_time, 23) as orderDate, COUNT(*) AS orderNum
        FROM man_order
        WHERE order_time BETWEEN #{startTime} AND #{endTime}
        GROUP BY CONVERT(VARCHAR, order_time, 23)
    </select>
    <select id="recentInBound" resultType="com.zy.asrs.entity.digitaltwin.DtInAndOutBoundVo">
        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>
        GROUP BY CONVERT(VARCHAR, io_time, 23)
    </select>
    <select id="recentOutBound" resultType="com.zy.asrs.entity.digitaltwin.DtInAndOutBoundVo">
        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>
        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>
</mapper>
src/main/webapp/static/js/common.js
@@ -1,4 +1,4 @@
var baseUrl = "/wms";
var baseUrl = "/djwms";
// 详情窗口-高度
var detailHeight = '80%';
src/main/webapp/static/js/mat/mat.js
@@ -211,52 +211,52 @@
                    });
                }
                break;
            case "batchModifties":
                var selected = checkStatus.data;
                if (selected.length === 0) {
                    layer.msg('请选择修改数据');
                } else {
                    let selIds = selected.map(item => {
                       return  item.id
                    });
                    layer.open({
                        type: 1,
                        title: '批量修改',
                        area: ['500px'],
                        shadeClose: true,
                        content: $('#batchModifties'),
                        success: function (layero, index) {
                            layer.iframeAuto(index);
                            form.on('submit(batchModify)', function (data) {
                                let params = {...data?.field}
                                params.id = selIds
                                $.ajax({
                                    url: baseUrl + "/mat/batch/auth",
                                    headers: {'token': localStorage.getItem('token')},
                                    data: JSON.stringify(params),
                                    dataType: 'json',
                                    contentType: 'application/json;charset=UTF-8',
                                    method: 'POST',
                                    success: function (res) {
                                        layer.closeAll();
                                        if (res.code === 200) {
                                        } else if (res.code === 403) {
                                            top.location.href = baseUrl + "/";
                                        } else {
                                            layer.msg(res.msg)
                                        }
                                    }
                                });
                                layer.closeAll();
                            });
                        },
                        end: function () {
                        }
                    });
                }
                break;
            // case "batchModifties":
            //     var selected = checkStatus.data;
            //     if (selected.length === 0) {
            //         layer.msg('请选择修改数据');
            //     } else {
            //         let selIds = selected.map(item => {
            //            return  item.id
            //         });
            //         layer.open({
            //             type: 1,
            //             title: '批量修改',
            //             area: ['500px'],
            //             shadeClose: true,
            //             content: $('#batchModifties'),
            //             success: function (layero, index) {
            //                 layer.iframeAuto(index);
            //                 form.on('submit(batchModify)', function (data) {
            //                     let params = {...data?.field}
            //                     params.id = selIds
            //                     $.ajax({
            //                         url: baseUrl + "/mat/batch/auth",
            //                         headers: {'token': localStorage.getItem('token')},
            //                         data: JSON.stringify(params),
            //                         dataType: 'json',
            //                         contentType: 'application/json;charset=UTF-8',
            //                         method: 'POST',
            //                         success: function (res) {
            //                             layer.closeAll();
            //                             if (res.code === 200) {
            //
            //                             } else if (res.code === 403) {
            //                                 top.location.href = baseUrl + "/";
            //                             } else {
            //                                 layer.msg(res.msg)
            //                             }
            //                         }
            //                     });
            //                     layer.closeAll();
            //                 });
            //             },
            //             end: function () {
            //
            //             }
            //         });
            //     }
            //     break;
            default:
                break;
        }
src/main/webapp/views/basWhs/basWhs.html
@@ -31,7 +31,8 @@
<!-- 表格 -->
<div class="layui-form">
    <table class="layui-hide" id="basWhsType" lay-filter="basWhsType"></table>
<!--    <table class="layui-hide" id="basWhsType" lay-filter="basWhsType"></table>-->
    <table class="layui-hide" id="basWhs" lay-filter="basWhs"></table>
</div>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
@@ -49,7 +50,7 @@
<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/basWhsType/basWhsType.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/basWhs/basWhs.js" charset="utf-8"></script>
<iframe id="detail-iframe" scrolling="auto" style="display:none;"></iframe>
src/main/webapp/views/pda/comb.html
@@ -54,11 +54,11 @@
            limit: 500,
            cellMinWidth: 50,
            cols: [[
                {fixed: 'left', align: 'center', field: 'count', title: '数量', style:'color: blue', width:50},
                {fixed: 'left', align: 'center', field: 'anfme', title: '数量', style:'color: blue', width:50},
                {field: 'matnr', align: 'center', title: '商品编号'},
                {field: 'maktx', align: 'center', title: '商品名称'}
            ]],
            done: function (res, curr, count) {
            done: function (res, curr, anfme) {
            }
        });
@@ -100,7 +100,7 @@
        let toPush = true;
        for (var j=0;j<matData.length;j++){
            if (data.matnr === matData[j].matnr) {
                matData[j].count = Number(matData[j].count) + Number(data.count);
                matData[j].anfme = Number(matData[j].anfme) + Number(data.anfme);
                toPush  = false;
            }
        }
src/main/webapp/views/pda/login.html
@@ -123,7 +123,8 @@
            debugger
            $.ajax({
                url: baseUrl+"/login.action",
                data: user,
                headers: {'Content-Type': 'application/json'},
                data: JSON.stringify(user),
                method: 'POST',
                success: function (res) {
                    if (res.code === 200){
src/main/webapp/views/pda/matQuery.html
@@ -124,9 +124,10 @@
            success: function (res) {
                if (res.code === 200) {
                    if (res.data != null) {
                        $('#matName').val(res.data.matName);
                        $('#str1').val(res.data.str1);
                        $('#str2').val(res.data.str2);
                        console.log(res.data)
                        $('#matName').val(res.data.maktx);
                        $('#str1').val(res.data.unit);
                        $('#str2').val(res.data.specs);
                        countDom.val(initMatCount);
                        $('#count').focus().select();
                    }
@@ -144,9 +145,9 @@
     */
    function confirm(){
        var data = {
            matNo: $('#matNo').val(),
            matName: $('#matName').val(),
            count: countDom.val()
            matnr: $('#matNo').val(),
            maktx: $('#matName').val(),
            anfme: Number(countDom.val())
        };
        parent.addTableData(data);
        parent.layer.close(parent.matCodeLayerIdx);