自动化立体仓库 - WMS系统
AGV出入库作业
库存汇总页面
库存规则
分析页加上AGV数据
AGV库存明细统计
AGV库位地图
28个文件已修改
34个文件已添加
6555 ■■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/AgvBasDevpController.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/AgvIoWorkController.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/AgvLocDetlController.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/AgvMapController.java 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/AgvOpenController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/AllLocDetlController.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/ReportQueryController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/AgvBasMap.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/AllLocDetl.java 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/EmptyPlateOutParam.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/StockOutParam.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/AgvBasDevpMapper.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/AgvBasMapMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/AgvLocDetlMapper.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/AgvLocMastMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/AllLocDetlMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/ReportQueryMapper.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/AgvBasDevpService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/AgvBasMapService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/AgvLocDetlService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/AgvLocMastService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/AgvWorkService.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/AllLocDetlService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/AgvBasDevpServiceImpl.java 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/AgvBasMapServiceImpl.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/AgvLocDetlServiceImpl.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/AgvLocMastServiceImpl.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/AgvWorkServiceImpl.java 159 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/AllLocDetlServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/AgvWrkMastScheduler.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/AgvWrkMastHandler.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/utils/Utils.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/AgvBasDevpDto.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/service/AgvCommonService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/ViewStayTimeMapper.xml 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/agvLocDetlStatis/locDetlStatis.js 256 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/agvPakStore/emptyIn.js 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/agvPakStore/emptyOut.js 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/agvPakStore/locCheckOut.js 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/agvPakStore/locMove.js 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/agvPakStore/pakStore.js 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/agvPakStore/stockAdjust.js 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/agvPakStore/stockOut.js 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/allLocDetl/locDetl.js 601 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/common.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvBasDevp/basDevpWaitPakinDetail.html 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvBasDevpVisualized/basDevp.html 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvLocDetlStatis/locDetlStatis.html 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvPakStore/emptyIn.html 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvPakStore/emptyOut.html 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvPakStore/locCheckOut.html 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvPakStore/locDetlCheckQuery.html 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvPakStore/locDetlQuery.html 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvPakStore/locMove.html 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvPakStore/matQuery.html 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvPakStore/pakStore.html 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvPakStore/stockAdjust.html 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/agvPakStore/stockOut.html 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/allLocDetl/locDetl.html 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/allLocDetl/locDetl_detail.html 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/home/agvMap.html 1069 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/home/console.html 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/AgvBasDevpController.java
@@ -158,6 +158,9 @@
        return R.ok();
    }
    /*
    站点明细
     */
    @RequestMapping(value = "/basDevp/detail/list/auth")
    public R basDevpDetailList(@RequestParam(defaultValue = "1")Integer curr,
                               @RequestParam(defaultValue = "10")Integer limit,
@@ -185,14 +188,13 @@
            }
        }
        return R.error("数据异常");
        return R.ok();
    }
    @RequestMapping(value = "/basDevp/visualized/list/auth")
    public R visualizedList(@RequestBody JSONObject param){
        String stationCode = param.get("stationCode").toString();
        Map<String, Object> result = agvBasDevpService.getAgvBasDevpDtoByStationCode(stationCode);
@@ -208,8 +210,8 @@
        List<String> devNos = (List<String>) map.get("devNo");
        List<AgvWrkMast> agvWrkMastList = devNos.stream().map(devNo -> {
            AgvWrkMast agvWrkMast = agvWrkMastService.selectOne(new EntityWrapper<AgvWrkMast>().eq("loc_no", devNo));
            if(agvWrkMast.getIoType() == 103){
                throw new CoolException("工作号为" + agvWrkMast.getWrkNo() + "类型为103.拣料入库,无法执行容器离场任务,请重新选择站点。");
            if(agvWrkMast.getIoType() != 101 && agvWrkMast.getIoType() != 110){
                throw new CoolException("工作号为" + agvWrkMast.getWrkNo() + "类型不为101.出库,无法执行容器离场任务,请重新选择站点。");
            }
            return agvWrkMast;
        }).collect(Collectors.toList());
@@ -219,7 +221,7 @@
           if(code == 0){
               //将工作党状态改为容器离场
               agvWrkMastList.forEach(agvWrkMast -> {
                   agvWrkMast.setWrkSts(207L);
                   agvWrkMast.setWrkSts(206L);
                   agvWrkMastService.updateById(agvWrkMast);
               });
               //修改站点状态
@@ -239,7 +241,7 @@
    }
    /*
    拣料入库
    拣料/盘点入库
     */
    @RequestMapping(value = "/basDevp/visualized/container/pickIn")
    public R visualiZedPickIn(@RequestBody Map<String,Object> map){
@@ -247,7 +249,7 @@
        List<AgvWrkMast> agvWrkMastList = devNos.stream().map(devNo -> {
            AgvWrkMast agvWrkMast = agvWrkMastService.selectOne(new EntityWrapper<AgvWrkMast>().eq("loc_no", devNo));
            if(agvWrkMast.getIoType() == 101){
                throw new CoolException("工作号为" + agvWrkMast.getWrkNo() + "类型为101.入库,无法执行拣料入库任务,请重新选择站点。");
                throw new CoolException("工作号为" + agvWrkMast.getWrkNo() + "类型为101.出库,无法执行拣料入库任务,请重新选择站点。");
            }
            return agvWrkMast;
        }).collect(Collectors.toList());
src/main/java/com/zy/asrs/controller/AgvIoWorkController.java
New file
@@ -0,0 +1,173 @@
package com.zy.asrs.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.core.annotations.ManagerAuth;
import com.core.common.BaseRes;
import com.core.common.Cools;
import com.core.common.DateUtils;
import com.core.common.R;
import com.zy.asrs.entity.AgvLocDetl;
import com.zy.asrs.entity.AgvLocMast;
import com.zy.asrs.entity.param.EmptyPlateOutParam;
import com.zy.asrs.entity.param.StockOutParam;
import com.zy.asrs.service.AgvBasDevpService;
import com.zy.asrs.service.AgvLocDetlService;
import com.zy.asrs.service.AgvLocMastService;
import com.zy.asrs.service.AgvWorkService;
import com.zy.common.web.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/agv")
public class AgvIoWorkController extends BaseController {
    @Autowired
    AgvLocDetlService agvLocDetlService;
    @Autowired
    AgvLocMastService agvLocMastService;
    @Autowired
    AgvWorkService agvWorkService;
    @Autowired
    AgvBasDevpService agvBasDevpService;
    @RequestMapping(value = "/stock/out/list/auth")
    @ManagerAuth
    public R list(@RequestParam(defaultValue = "1")Integer curr,
                  @RequestParam(defaultValue = "10")Integer limit,
                  @RequestParam(required = false)String orderByField,
                  @RequestParam(required = false)String orderByType,
                  @RequestParam(required = false)String condition,
                  @RequestParam Map<String, Object> param,
                  @RequestParam(required = false)Boolean unreason){
        if (!Cools.isEmpty(unreason) && unreason) {
            return R.ok(agvLocDetlService.selectPage(new Page<>(curr, limit), new EntityWrapper<AgvLocDetl>()
                    .where(" DATALENGTH( batch ) != 11 or\n" +
                            "            batch LIKE '%[a-z]%'")));
        }
        param.remove("unreason");
        String row = "";
        EntityWrapper<AgvLocDetl> wrapper = new EntityWrapper<>();
        if (param.get("row") != null) {
            String chooseRow = (String) param.get("row");
            if (chooseRow.length() == 1) {
                row = "0" + chooseRow;
                param.remove("row");
            }else {
                row = chooseRow;
                param.remove("row");
            }
        }
        excludeTrash(param);
        convert(param, wrapper);
        allLike(AgvLocDetl.class, param.keySet(), wrapper, condition);
        if (!Cools.isEmpty(orderByField)){wrapper.orderBy(humpToLine(orderByField), "asc".equals(orderByType));}
        if (!row.equals("")){
            wrapper.and()
                    .where("loc_no like '" +row +"%'");
        }
        Page<AgvLocDetl> agvLocDetlPage = agvLocDetlService.selectPage(new Page<>(curr, limit), wrapper);
        List<AgvLocDetl> collect = agvLocDetlPage.getRecords().stream().filter(agvLocDetl -> {
            AgvLocMast agvLocMast = agvLocMastService.selectById(agvLocDetl.getLocNo());
            return agvLocMast.getLocSts().equals("F");
        }).collect(Collectors.toList());
        agvLocDetlPage.setRecords(collect);
        return R.ok(agvLocDetlPage);
    }
    @RequestMapping(value = "/locDetl/auth")
    @ManagerAuth
    public R stockOutList(@RequestParam(value = "locNos[]") List<String> locNos){
        if (!locNos.isEmpty()) {
            List<AgvLocDetl> res = new ArrayList<>();
            for (String locNo : new HashSet<>(locNos)) {
                List<AgvLocDetl> locDetls = agvLocDetlService.selectList(new EntityWrapper<AgvLocDetl>().eq("loc_no", locNo));
                if (!locDetls.isEmpty()) {
                    res.addAll(locDetls);
                }
            }
            return R.ok().add(res);
        }
        return R.parse(BaseRes.EMPTY);
    }
    @RequestMapping("/locCheck/out/start")
    @ManagerAuth(memo = "AGV盘点出库")
    public R locCheckOutStart(@RequestBody StockOutParam param) {
        agvWorkService.locCheckOut(param, getUserId());
        return R.ok("出库启动成功");
    }
    @PostMapping(value = "/group/empty/stock")
    @ManagerAuth(memo = "获取同一楼层的空库位")
    public R getGroupEmptyStock(@RequestParam(required = false) String sourceLocNo) {
        if(Cools.isEmpty(sourceLocNo)){
            return null;
        }
        AgvLocMast agvLocMast = agvLocMastService.selectById(sourceLocNo);
        if(Cools.isEmpty(agvLocMast)){
            return null;
        }
        int floor =  Integer.parseInt(sourceLocNo.split("@")[1]);
        List<String> locNoList = agvLocMastService.queryGroupEmptyStock(floor);
        return R.ok().add(locNoList);
    }
    @RequestMapping("/loc/move/start")
    @ManagerAuth(memo = "库位移转")
    public R locMoveStart(@RequestParam String sourceLocNo,
                          @RequestParam String targetLocNo) {
        agvWorkService.locMove(sourceLocNo, targetLocNo, getUserId());
        return R.ok("移库启动成功");
    }
    @RequestMapping("/available/empty/put/site")
    @ManagerAuth(memo = "可用站点选择")
    public R availableEmptyPutSite(){
        return R.ok().add(agvBasDevpService.getAvailableEmptyInSite());
    }
    @RequestMapping("/empty/plate/in/start")
    @ManagerAuth(memo = "空板入库")
    public R emptyPlateInStart(@RequestParam String sourceStaNo) {
        return R.ok("入库启动成功").add(agvWorkService.emptyPlateIn(sourceStaNo, getUserId()));
    }
    @RequestMapping("/empty/plate/out/start")
    @ManagerAuth(memo = "空板出库")
    public R emptyPlateOutStart(EmptyPlateOutParam param) {
        agvWorkService.emptyPlateOut(param, getUserId());
        return R.ok("出库启动成功");
    }
    private <T> void convert(Map<String, Object> map, EntityWrapper<T> wrapper){
        for (Map.Entry<String, Object> entry : map.entrySet()){
            String val = String.valueOf(entry.getValue());
            if (val.contains(RANGE_TIME_LINK)){
                String[] dates = val.split(RANGE_TIME_LINK);
                wrapper.ge(entry.getKey(), DateUtils.convert(dates[0]));
                wrapper.le(entry.getKey(), DateUtils.convert(dates[1]));
            } else {
                if (entry.getKey().equals("locNo")) {
                    wrapper.eq("loc_no", String.valueOf(entry.getValue()));
                } else {
                    wrapper.like(entry.getKey(), String.valueOf(entry.getValue()));
                }
            }
        }
    }
}
src/main/java/com/zy/asrs/controller/AgvLocDetlController.java
@@ -1,5 +1,8 @@
package com.zy.asrs.controller;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.core.annotations.ManagerAuth;
@@ -7,13 +10,21 @@
import com.core.common.DateUtils;
import com.core.common.R;
import com.zy.asrs.entity.AgvLocDetl;
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.Mat;
import com.zy.asrs.service.AgvLocDetlService;
import com.zy.asrs.service.MatService;
import com.zy.common.web.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
@RestController
@@ -22,6 +33,8 @@
    @Autowired
    private AgvLocDetlService agvLocDetlService;
    @Autowired
    private MatService matService;
    @RequestMapping(value = "/locDetl/list/auth")
    @ManagerAuth
@@ -63,6 +76,75 @@
        return R.ok(agvLocDetlService.selectPage(new Page<>(curr, limit), wrapper));
    }
    @RequestMapping(value = "/locDetl/statis/auth")
    @ManagerAuth(memo = "AGV库存明细统计")
    public R statis(@RequestParam(defaultValue = "1")Integer curr,
                    @RequestParam(defaultValue = "10")Integer limit,
                    @RequestParam Map<String, Object> param) {
        Page<AgvLocDetl> stockStatis = agvLocDetlService.getStockStatis(toPage(curr, limit, param, AgvLocDetl.class));
        for (AgvLocDetl locDetl : stockStatis.getRecords()) {
            Mat mat = matService.selectByMatnr(locDetl.getMatnr());
            if (mat != null) {
                locDetl.sync(mat);
            }
        }
        return R.ok().add(stockStatis);
    }
    /*
    获取库存总数
     */
    @RequestMapping("/locDetl/count")
    public R getAllCount(){
        Integer sum = agvLocDetlService.sum();
        return R.ok(sum);
    }
    @RequestMapping(value = "/locDetl/statis/export")
    public void statisExport(HttpServletResponse response) throws IOException {
        List<AgvLocDetl> excel = agvLocDetlService.getStockStatisExcel();
        for (AgvLocDetl locDetl : excel) {
            Mat mat = matService.selectByMatnr(locDetl.getMatnr());
            if (mat != null) {
                locDetl.sync(mat);
            }
        }
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("库存明细统计报表", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), LocDetl.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("表1")
                .doWrite(excel);
    }
    @RequestMapping(value = "/locDetl/export/auth")
    @ManagerAuth(memo = "库位明细导出")
    public synchronized R export(@RequestBody JSONObject param){
        List<String> fields = JSONObject.parseArray(param.getJSONArray("fields").toJSONString(), String.class);
        EntityWrapper<AgvLocDetl> wrapper = new EntityWrapper<>();
        Map<String, Object> map = excludeTrash(param.getJSONObject("locDetl"));
        String row = "";
        if (map.get("row") != null) {
            String chooseRow = (String) map.get("row");
            if (chooseRow.length() == 1) {
                row = "0" + chooseRow;
                map.remove("row");
            }else {
                row = chooseRow;
                map.remove("row");
            }
        }
        convert(map, wrapper);
        if (!row.equals("")){
            wrapper.and()
                    .where("loc_no like '" +row +"%'");
        }
        List<AgvLocDetl> list = agvLocDetlService.selectList(wrapper);
        return R.ok(exportSupport(list, fields));
    }
    private <T> void convert(Map<String, Object> map, EntityWrapper<T> wrapper){
        for (Map.Entry<String, Object> entry : map.entrySet()){
            String val = String.valueOf(entry.getValue());
src/main/java/com/zy/asrs/controller/AgvMapController.java
New file
@@ -0,0 +1,258 @@
package com.zy.asrs.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.core.annotations.ManagerAuth;
import com.core.common.R;
import com.zy.asrs.entity.AgvLocDetl;
import com.zy.asrs.entity.AgvLocMast;
import com.zy.asrs.entity.BasMap;
import com.zy.asrs.service.AgvBasMapService;
import com.zy.asrs.service.AgvLocDetlService;
import com.zy.asrs.service.AgvLocMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.utils.RedisUtil;
import com.zy.common.web.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/agv")
public class AgvMapController extends BaseController {
    @Autowired
    private AgvLocMastService agvLocMastService;
    @Autowired
    private AgvLocDetlService agvLocDetlService;
    @Autowired
    private AgvBasMapService agvBasMapService;
    @Autowired
    private RedisUtil redisUtil;
    private static final List<String> DISABLE_LOC_NO = new ArrayList<String>() {{
//        add("0200101");
//        add("0300101");
//        add("0400101");
//        add("0500101");
//        add("0600101");
//        add("0700101");
//        add("0800101");
//        add("0900101");
//        add("1000101");
//        add("1100101");
//        add("1200101");
    }};
    @GetMapping("/map/getData/{floor}/{lev}/auth")
    @ManagerAuth
    public String getMapData(@PathVariable("floor") Integer floor, @PathVariable("lev") Integer lev) {
        BasMap basMap = agvBasMapService.selectLatestMap(lev,floor);
        //解析json地图数据
        List<ArrayList> arrayLists = JSON.parseArray(basMap.getData(), ArrayList.class);
        //获取当前楼层库位数据
        List<AgvLocMast> locMasts = agvLocMastService.selectLocByLevAndFloor(lev,floor);
        for (AgvLocMast locMast : locMasts) {
            Integer row = locMast.getRow1();
            Integer bay = locMast.getBay1();
            int x = bay;
            int y = row;
            //1楼
            if(floor == 1){
                x = generateMap1Row(row);
                y = generateMap1Bay(bay);
            }
            //3楼
            if(floor == 3){
                y = generateMap3Row(row);
                x = generateMap3Bay(bay);
            }
            ArrayList rowData = arrayLists.get(x);
            Object o = rowData.get(y);
            JSONObject jsonObject = JSON.parseObject(o.toString());
            if (DISABLE_LOC_NO.contains(locMast.getLocNo())) {
                //禁止库位
                jsonObject.put("value", 10);//将禁用库位进行设置
            }
            jsonObject.put("locNo", locMast.getLocNo());//设置库位号
            jsonObject.put("locSts", locMast.getLocSts());//库位状态
            //更新list
            rowData.set(y, jsonObject);
            arrayLists.set(x, rowData);
        }
        return JSONObject.toJSONString(arrayLists);
    }
    private Integer generateMap1Row(int row){
        int x = 21-row;
        if(row > 1){
            x --;
        }
        if(row > 3){
            x --;
        }
        if(row > 4){
            x --;
        }
        if(row > 6){
            x --;
        }
        if(row > 8){
            x --;
        }
        if(row > 10){
            x --;
        }
        if(row > 12){
            x --;
        }
        return x;
    }
    private Integer generateMap1Bay(int bay){
        int y = bay;
        if(y > 28){
            y ++;
        }
        if(y > 57){
            y ++;
        }
        return y;
    }
    private Integer generateMap3Row(int row){
        int x = row;
        Integer[] rowAdd = {2,4,6,8,9,11,12,14,16,18,19,21,23,25,27,29,31,33};
        for(int i=0; i<rowAdd.length; i++){
            if(row >= rowAdd[i]){
                x ++;
            }
        }
        return x;
    }
    private Integer generateMap3Bay(int bay){
        int y = 73-bay;
        if(bay >= 15) y --;
        if(bay >= 47) y --;
        return y;
    }
    @RequestMapping("/map/searchData/auth")
    @ManagerAuth
    public R searchLoc(@RequestParam("lev") Integer lev,
                       @RequestParam("locNo") String locNo,
                       @RequestParam("orderNo") String orderNo,
                       @RequestParam("specs") String specs,
                       @RequestParam("matnr") String matnr,
                       @RequestParam("maktx") String maktx
                       ) {
        List<AgvLocDetl> locDetls = agvLocDetlService.searchByLike(orderNo, matnr, maktx, specs, locNo);
        ArrayList<AgvLocDetl> lists = new ArrayList<>();
        for (AgvLocDetl locDetl : locDetls) {//过滤掉不是当前楼层的数据
            int lev1 = Utils.getAgvLev(locDetl.getLocNo());
            if (lev1 == lev) {
                lists.add(locDetl);
            }
        }
        //搜索指定库位号,即使库位为空,也可以返回数据
        AgvLocMast locMast = agvLocMastService.selectById(locNo);
        if (locMast != null) {
            AgvLocDetl locDetl = new AgvLocDetl();
            locDetl.setLocNo(locMast.getLocNo());
            lists.add(locDetl);
        }
        return R.ok().add(lists);
    }
    /*
    @GetMapping("/map/realtime/getData/{lev}/auth")
    @ManagerAuth
    public String getRealtimeMapData(@PathVariable("lev") Integer lev) {
        BasMap basMap = basMapService.selectLatestMap(lev);
        //解析json地图数据
        List<ArrayList> arrayLists = JSON.parseArray(basMap.getData(), ArrayList.class);
//        ArrayList<HashMap<String, Integer>> lineRows = new ArrayList<>();
//        int dataRow = 0;
//        int dataRowCount = 0;
//        for (int i = 1; i < arrayLists.size(); i++) {
//            boolean flag = true;
//            ArrayList rows = arrayLists.get(i);
//            for (int j = 1; j < rows.size() - 1; j++) {
//                Object o = rows.get(j);
//                JSONObject jsonObject = JSON.parseObject(o.toString());
//                int value = Integer.parseInt(jsonObject.get("value").toString());
//                if (value >= 0 && value != 3) {
//                    //只有该行中的任一一列有数据,则不需要创建空白行
//                    flag = false;
//                }
//            }
//
//            if (flag) {
//                //空白行需要跳过
//                HashMap<String, Integer> map = new HashMap<>();
//                map.put("start", dataRow);
//                int end = i - 1 - dataRowCount;
//                map.put("end", end);
//                map.put("count", dataRowCount);
//                dataRow = end;
//                dataRowCount++;
//                lineRows.add(map);
//            }
//        }
        //获取当前楼层库位数据
        List<LocMast> locMasts = locMastService.selectLocByLev(lev);
        for (LocMast locMast : locMasts) {
            Integer row = locMast.getRow1();
            Integer bay = locMast.getBay1();
//            for (HashMap<String, Integer> lineRow : lineRows) {
//                if (row > lineRow.get("start") && row <= lineRow.get("end")) {
//                    row += lineRow.get("count");
//                    break;
//                }
//            }
            ArrayList rowData = arrayLists.get(row);
            Object o = rowData.get(bay);
            JSONObject jsonObject = JSON.parseObject(o.toString());
            if (DISABLE_LOC_NO.contains(locMast.getLocNo())) {
                //禁止库位
                jsonObject.put("value", 10);//将禁用库位进行设置
            }
            jsonObject.put("locNo", locMast.getLocNo());//设置库位号
            jsonObject.put("locSts", locMast.getLocSts());//库位状态
            //更新list
            rowData.set(bay, jsonObject);
            arrayLists.set(row, rowData);
        }
        return JSONObject.toJSONString(arrayLists);
    } */
//    @GetMapping("/map/resetMap/{lev}/auth")
//    @ManagerAuth
//    public R resetMap(@PathVariable("lev") Integer lev) {
//        Object o = redisUtil.get("realtimeBasMap_" + lev);
//        if (o == null) {
//            return R.error();
//        }
//        redisUtil.del("realtimeBasMap_" + lev);
//        basMapService.deleteByLev(lev);
//        return R.ok();
//    }
}
src/main/java/com/zy/asrs/controller/AgvOpenController.java
@@ -107,10 +107,14 @@
            //修改AGV工作档的工作状态为205.工作完成
            agvWrkMastService.updateWrkStsByWrkNo(agvWrkMast.getWrkNo(),205);
            //出库任务 101.出库 || 103.拣料出库
            if(agvWrkMast.getIoType() == 101 || agvWrkMast.getIoType() == 103){
            //出库任务 101.出库 || 103.拣料出库 || 107.盘点出库
            if(agvWrkMast.getIoType() == 101 || agvWrkMast.getIoType() == 103 || agvWrkMast.getIoType() == 107){
                //修改出库站点状态
                agvBasDevpService.updateLocStsAndBarcodeByDevNo(agvWrkMast.getLocNo(),"F",agvWrkMast.getBarcode());
            }
            //出库任务 110.空板出库
            if(agvWrkMast.getIoType() == 110){
                agvBasDevpService.updateLocStsAndBarcodeByDevNo(agvWrkMast.getLocNo(),"D",agvWrkMast.getBarcode());
            }
        }
@@ -154,16 +158,10 @@
        @Transactional
        public void success(AgvWrkMast agvWrkMast, AgvTaskCallBackParam param) {
            //入库任务 || 拣料入库任务
            if(agvWrkMast.getIoType() == 1 || agvWrkMast.getIoType() == 53){
            //入库任务 || 拣料入库任务 ||盘点再入库 ||空板入库
            if(agvWrkMast.getIoType() == 1 || agvWrkMast.getIoType() == 53 || agvWrkMast.getIoType() == 57 || agvWrkMast.getIoType() == 10){
                //修改源站点状态为O.空,以及解绑托盘条码
                agvBasDevpService.updateLocStsAndBarcodeByDevNo(agvWrkMast.getSourceLocNo(),"O","");
            }
            //出库任务 101.出库 || 103.拣料出库
            if(agvWrkMast.getIoType() == 101 || agvWrkMast.getIoType() == 103){
                //修改源库位状态
            }
            //修改AGV工作档的工作状态为203.RCS放货中
src/main/java/com/zy/asrs/controller/AllLocDetlController.java
New file
@@ -0,0 +1,84 @@
package com.zy.asrs.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.core.annotations.ManagerAuth;
import com.core.common.Cools;
import com.core.common.DateUtils;
import com.core.common.R;
import com.zy.asrs.entity.AllLocDetl;
import com.zy.asrs.service.AllLocDetlService;
import com.zy.common.web.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("/all")
public class AllLocDetlController extends BaseController {
    @Autowired
    private AllLocDetlService allLocDetlService;
    @RequestMapping(value = "/locDetl/list/auth")
    @ManagerAuth
    public R list(@RequestParam(defaultValue = "1")Integer curr,
                  @RequestParam(defaultValue = "10")Integer limit,
                  @RequestParam(required = false)String orderByField,
                  @RequestParam(required = false)String orderByType,
                  @RequestParam(required = false)String condition,
                  @RequestParam Map<String, Object> param,
                  @RequestParam(required = false)Boolean unreason){
        if (!Cools.isEmpty(unreason) && unreason) {
            return R.ok(allLocDetlService.selectPage(new Page<>(curr, limit), new EntityWrapper<AllLocDetl>()
                    .where(" DATALENGTH( batch ) != 11 or\n" +
                            "            batch LIKE '%[a-z]%'")));
        }
        param.remove("unreason");
        String row = "";
        EntityWrapper<AllLocDetl> wrapper = new EntityWrapper<>();
        if (param.get("row") != null) {
            String chooseRow = (String) param.get("row");
            if (chooseRow.length() == 1) {
                row = "0" + chooseRow;
                param.remove("row");
            }else {
                row = chooseRow;
                param.remove("row");
            }
        }
        excludeTrash(param);
        convert(param, wrapper);
        allLike(AllLocDetl.class, param.keySet(), wrapper, condition);
        if (!Cools.isEmpty(orderByField)){wrapper.orderBy(humpToLine(orderByField), "asc".equals(orderByType));}
        if (!row.equals("")){
            wrapper.and()
                    .where("loc_no like '" +row +"%'");
        }
        return R.ok(allLocDetlService.selectPage(new Page<>(curr, limit), wrapper));
    }
    private <T> void convert(Map<String, Object> map, EntityWrapper<T> wrapper){
        for (Map.Entry<String, Object> entry : map.entrySet()){
            String val = String.valueOf(entry.getValue());
            if (val.contains(RANGE_TIME_LINK)){
                String[] dates = val.split(RANGE_TIME_LINK);
                wrapper.ge(entry.getKey(), DateUtils.convert(dates[0]));
                wrapper.le(entry.getKey(), DateUtils.convert(dates[1]));
            } else {
                if (entry.getKey().equals("locNo")) {
                    wrapper.eq("loc_no", String.valueOf(entry.getValue()));
                } else {
                    wrapper.like(entry.getKey(), String.valueOf(entry.getValue()));
                }
            }
        }
    }
}
src/main/java/com/zy/asrs/controller/ReportQueryController.java
@@ -71,8 +71,10 @@
        if (!Cools.isEmpty(locNo) && !locNo.equals("null")) {
            bean.setLoc_no(locNo);
        }
        List<ViewStayTimeBean> list = reportQueryMapper.queryViewStayTimeList(bean);
        int count = reportQueryMapper.getViewStayTimeCount(bean);
//        List<ViewStayTimeBean> list = reportQueryMapper.queryViewStayTimeList(bean);
//        int count = reportQueryMapper.getViewStayTimeCount(bean);
        List<ViewStayTimeBean> list = reportQueryMapper.queryAllViewStayTimeList(bean);
        int count = reportQueryMapper.getAllViewStayTimeCount(bean);
        Page<ViewStayTimeBean> page = new Page<>();
        page.setRecords(list);
        page.setTotal(count);
src/main/java/com/zy/asrs/entity/AgvBasMap.java
New file
@@ -0,0 +1,100 @@
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 com.core.common.Cools;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
@Data
@TableName("agv_bas_map")
public class AgvBasMap implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value= "")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 地图数据
     */
    @ApiModelProperty(value= "地图数据")
    private String data;
    /**
     * 创建时间
     */
    @ApiModelProperty(value= "创建时间")
    @TableField("create_time")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /**
     * 更新时间
     */
    @ApiModelProperty(value= "更新时间")
    @TableField("update_time")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /**
     * 更新前地图数据
     */
    @ApiModelProperty(value= "更新前地图数据")
    @TableField("last_data")
    private String lastData;
    /**
     * 层
     */
    @ApiModelProperty(value= "层")
    private Integer lev;
    /**
     * 楼
     */
    @ApiModelProperty(value= "楼")
    private Integer floor;
    public AgvBasMap() {}
    public AgvBasMap(String data, Date createTime, Date updateTime, String lastData, Integer lev) {
        this.data = data;
        this.createTime = createTime;
        this.updateTime = updateTime;
        this.lastData = lastData;
        this.lev = lev;
    }
//    BasMap basMap = new BasMap(
//            null,    // 地图数据
//            null,    // 创建时间
//            null,    // 更新时间
//            null,    // 更新前地图数据
//            null    // 楼层
//    );
    public String getCreateTime$(){
        if (Cools.isEmpty(this.createTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
    }
    public String getUpdateTime$(){
        if (Cools.isEmpty(this.updateTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
    }
}
src/main/java/com/zy/asrs/entity/AllLocDetl.java
New file
@@ -0,0 +1,266 @@
package com.zy.asrs.entity;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import com.core.common.Cools;
import com.core.common.SpringUtils;
import com.zy.asrs.service.LocMastService;
import com.zy.common.utils.Synchro;
import com.zy.system.entity.User;
import com.zy.system.service.UserService;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
@Data
@TableName("all_loc_detl")
@ExcelIgnoreUnannotated
public class AllLocDetl implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value= "库位号")
    @TableField("loc_no")
    private String locNo;
    @ApiModelProperty(value= "托盘条码")
    private String zpallet;
    @ApiModelProperty(value= "数量")
    @ExcelProperty("数量")
    private Double anfme;
    @ApiModelProperty(value= "物料号")
    @ExcelProperty("物料号")
    private String matnr;
    @ApiModelProperty(value= "物料号")
    @ExcelProperty("物料号")
    private String maktx;
    @ApiModelProperty(value= "序列码")
    @ExcelProperty("序列码")
    private String batch;
    @ApiModelProperty(value= "单据编号")
    @ExcelProperty("单据编号")
    @TableField("order_no")
    private String orderNo;
    @ApiModelProperty(value= "规格")
    private String specs;
    @ApiModelProperty(value= "批次")
    private String model;
    @ApiModelProperty(value= "颜色")
    private String color;
    @ApiModelProperty(value= "品牌")
    private String brand;
    @ApiModelProperty(value= "单位")
    private String unit;
    @ApiModelProperty(value= "单价")
    private Double price;
    @ApiModelProperty(value= "sku")
    private String sku;
    @ApiModelProperty(value= "包数")
    private Double units;
    @ApiModelProperty(value= "条码")
    private String barcode;
    @ApiModelProperty(value= "物料状态")
    private String origin;
    @ApiModelProperty(value= "厂家")
    private String manu;
    @ApiModelProperty(value= "单据时间")
    @TableField("manu_date")
    private String manuDate;
    @ApiModelProperty(value= "品项数")
    @TableField("item_num")
    private String itemNum;
    @ApiModelProperty(value= "安全库存量")
    @TableField("safe_qty")
    private Double safeQty;
    @ApiModelProperty(value= "重量")
    private Double weight;
    @ApiModelProperty(value= "长度")
    private Double length;
    @ApiModelProperty(value= "体积")
    private Double volume;
    @ApiModelProperty(value= "三方编码")
    @TableField("three_code")
    private String threeCode;
    @ApiModelProperty(value= "供应商")
    private String supp;
    @ApiModelProperty(value= "供应商编码")
    @TableField("supp_code")
    private String suppCode;
    @ApiModelProperty(value= "是否批次 1: 是  0: 否  ")
    @TableField("be_batch")
    private Integer beBatch;
    @ApiModelProperty(value= "保质期")
    @TableField("dead_time")
    private String deadTime;
    @ApiModelProperty(value= "预警天数")
    @TableField("dead_warn")
    private Integer deadWarn;
    @ApiModelProperty(value= "制购 1: 制造  2: 采购  3: 外协  ")
    private Integer source;
    @ApiModelProperty(value= "要求检验 1: 是  0: 否  ")
    private Integer inspect;
    @ApiModelProperty(value= "危险品 1: 是  0: 否  ")
    private Integer danger;
    @ApiModelProperty(value= "修改人员")
    @TableField("modi_user")
    private Long modiUser;
    @ApiModelProperty(value= "修改时间")
    @TableField("modi_time")
    private Date modiTime;
    @ApiModelProperty(value= "创建者")
    @TableField("appe_user")
    private Long appeUser;
    @ApiModelProperty(value= "添加时间")
    @TableField("appe_time")
    private Date appeTime;
    @ApiModelProperty(value= "备注")
    private String memo;
    @TableField("stock_freeze")
    @ApiModelProperty(value= "库存冻结{1:正常,0:冻结}")
    private Integer stockFreeze;
    public String getLocNo$(){
        LocMastService service = SpringUtils.getBean(LocMastService.class);
        LocMast locMast = service.selectById(this.locNo);
        if (!Cools.isEmpty(locMast)){
            return String.valueOf(locMast.getLocNo());
        }
        return null;
    }
    public String getBeBatch$(){
        if (null == this.beBatch){ return null; }
        switch (this.beBatch){
            case 1:
                return "是";
            case 0:
                return "否";
            default:
                return String.valueOf(this.beBatch);
        }
    }
    public String getSource$(){
        if (null == this.source){ return null; }
        switch (this.source){
            case 1:
                return "制造";
            case 2:
                return "采购";
            case 3:
                return "外协";
            default:
                return String.valueOf(this.source);
        }
    }
    public String getInspect$(){
        if (null == this.inspect){ return null; }
        switch (this.inspect){
            case 1:
                return "是";
            case 0:
                return "否";
            default:
                return String.valueOf(this.inspect);
        }
    }
    public String getDanger$(){
        if (null == this.danger){ return null; }
        switch (this.danger){
            case 1:
                return "是";
            case 0:
                return "否";
            default:
                return String.valueOf(this.danger);
        }
    }
    public String getModiUser$(){
        UserService service = SpringUtils.getBean(UserService.class);
        User user = service.selectById(this.modiUser);
        if (!Cools.isEmpty(user)){
            return String.valueOf(user.getUsername());
        }
        return null;
    }
    public String getModiTime$(){
        if (Cools.isEmpty(this.modiTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.modiTime);
    }
    public String getAppeUser$(){
        UserService service = SpringUtils.getBean(UserService.class);
        User user = service.selectById(this.appeUser);
        if (!Cools.isEmpty(user)){
            return String.valueOf(user.getUsername());
        }
        return null;
    }
    public String getAppeTime$(){
        if (Cools.isEmpty(this.appeTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.appeTime);
    }
    public void sync(Object source) {
        Synchro.Copy(source, this);
    }
    public String getStockFreeze$() {
        if (Cools.isEmpty(this.stockFreeze)){
            return "";
        }
        return this.stockFreeze == 1 ? "正常" : "冻结";
    }
}
src/main/java/com/zy/asrs/entity/param/EmptyPlateOutParam.java
@@ -1,14 +1,19 @@
package com.zy.asrs.entity.param;
import lombok.Data;
import java.util.List;
/**
 * Created by vincent on 2020/6/13
 */
@Data
public class EmptyPlateOutParam {
    // 出站口
    private Integer outSite;
    // AGV出站口
    private String stationCode;
    // 库位号集合
    private List<String> locNos;
src/main/java/com/zy/asrs/entity/param/StockOutParam.java
@@ -13,6 +13,9 @@
    // 出站口
    private Integer outSite;
    // AGV出战口
    private String station;
    // 物料编号集合
    private List<LocDetl> locDetls;
src/main/java/com/zy/asrs/mapper/AgvBasDevpMapper.java
@@ -4,12 +4,18 @@
import com.zy.asrs.entity.AgvBasDevp;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface AgvBasDevpMapper extends BaseMapper<AgvBasDevp> {
    @Delete("delete from agv_bas_devp")
    public void deleteAll();
    void deleteAll();
    @Select("select dev_no from agv_bas_devp where loc_sts = 'O'")
    List<String> getAvailableEmptyInSite();
}
src/main/java/com/zy/asrs/mapper/AgvBasMapMapper.java
New file
@@ -0,0 +1,20 @@
package com.zy.asrs.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.AgvBasMap;
import com.zy.asrs.entity.BasMap;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface AgvBasMapMapper extends BaseMapper<AgvBasMap> {
    @Select("select top 1 * from agv_bas_map where lev = #{lev} and floor = #{floor} order by id desc")
    BasMap selectLatestMap(@Param("lev")Integer lev, @Param("floor")Integer floor);//获取最新地图数据
    boolean deleteByLev(Integer lev);//删除指定楼层地图
}
src/main/java/com/zy/asrs/mapper/AgvLocDetlMapper.java
@@ -2,9 +2,6 @@
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.AgvLocDetl;
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.result.StockVo;
import com.zy.common.model.QueryStockPreDo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@@ -18,4 +15,42 @@
@Repository
public interface AgvLocDetlMapper extends BaseMapper<AgvLocDetl> {
    @Update("update agv_loc_detl set loc_no = '${targetLoc}' where loc_no = '${sourceLoc}' ")
    void updateStock(@Param("sourceLoc")String sourceLoc, @Param("targetLoc")String targetLoc);
    @Select("select * from\n" +
            "(\n" +
            "\t\tselect\n" +
            "\t\tROW_NUMBER() over (order by sum(a.anfme) desc) as row\n" +
            "\t\t, a.matnr\n" +
            "\t\t, sum(a.anfme) as anfme\n" +
            "\t\tfrom agv_loc_detl a\n" +
            "\t\twhere 1=1\n" +
            "\t\tgroup by a.matnr\n" +
            " ) t where t.row between ((#{pageNumber}-1)*#{pageSize}+1) and (#{pageNumber}*#{pageSize})")
    List<AgvLocDetl> getStockStatis(Map<String, Object> map);
    @Select("select count(1) as count from\n" +
            "        (\n" +
            "        select\n" +
            "        a.matnr\n" +
            "        from agv_loc_detl a\n" +
            "        where 1=1\n" +
            "        \n" +
            "        group by a.matnr\n" +
            "     ) b")
    Integer getStockStatisCount(Map<String, Object> map);
    @Select("SELECT SUM(anfme) FROM agv_loc_detl")
    Integer sum();
    @Select("select\n" +
            "        ROW_NUMBER() over (order by sum(a.anfme) desc) as row\n" +
            "        , a.matnr\n" +
            "        , sum(a.anfme) as anfme\n" +
            "        from agv_loc_detl a\n" +
            "        where 1=1\n" +
            "        group by a.matnr")
    List<AgvLocDetl> getStockStatisExcel();
}
src/main/java/com/zy/asrs/mapper/AgvLocMastMapper.java
@@ -2,10 +2,7 @@
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.AgvLocMast;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.*;
import java.util.List;
@@ -24,4 +21,12 @@
    List<AgvLocMast> queryFreeLocMast2(Short locType1, Integer rowBeg, Integer rowEnd, Integer bayBeg, Integer bayEnd, Integer levBeg, Integer levEnd);
    @Select("select loc_no " +
            "from agv_loc_mast " +
            "where loc_sts = 'O' and floor = ${floor}")
    List<String> queryGroupEmptyStock(@Param("floor")int floor);
    @Select("SELECT * FROM agv_loc_mast WHERE lev1 = #{lev} And floor = #{floor}")
    List<AgvLocMast> selectLocByLevAndFloor(@Param("lev")int lev, @Param("floor")int floor);
}
src/main/java/com/zy/asrs/mapper/AllLocDetlMapper.java
New file
@@ -0,0 +1,12 @@
package com.zy.asrs.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.zy.asrs.entity.AllLocDetl;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface AllLocDetlMapper extends BaseMapper<AllLocDetl> {
}
src/main/java/com/zy/asrs/mapper/ReportQueryMapper.java
@@ -23,6 +23,12 @@
    //不分页查询所有信息,用于excel导出
    public List<ViewStayTimeBean> getViewStayTimeAll(ViewStayTimeBean viewStayTime);
    //分页查询AGV和四项库库存滞留时间
    public List<ViewStayTimeBean> queryAllViewStayTimeList(ViewStayTimeBean viewStayTime);
    public int getAllViewStayTimeCount(ViewStayTimeBean viewStayTime);
    //不分页查询AGV和四项库所有信息,用于excel导出
    public List<ViewStayTimeBean> getAllViewStayTimeAll(ViewStayTimeBean viewStayTime);
//    // 库位Map
    @Select("select distinct row1 from asr_loc_mast order by row1 asc")
    List<Integer> getViewLocRowTotal();
src/main/java/com/zy/asrs/service/AgvBasDevpService.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.service.IService;
import com.zy.asrs.entity.AgvBasDevp;
import java.util.List;
import java.util.Map;
public interface AgvBasDevpService extends IService<AgvBasDevp> {
@@ -14,4 +15,6 @@
    public void updateLocStsAndBarcodeByDevNo(String devNo, String locSts, String barcode);
    public Map<String, Object> getAgvBasDevpDtoByStationCode(String stationCode);
    public List<String> getAvailableEmptyInSite();
}
src/main/java/com/zy/asrs/service/AgvBasMapService.java
New file
@@ -0,0 +1,13 @@
package com.zy.asrs.service;
import com.baomidou.mybatisplus.service.IService;
import com.zy.asrs.entity.AgvBasMap;
import com.zy.asrs.entity.BasMap;
public interface AgvBasMapService extends IService<AgvBasMap> {
    BasMap selectLatestMap(Integer lev, Integer floor);//获取最新地图数据
    boolean deleteByLev(Integer lev);//删除指定楼层地图
}
src/main/java/com/zy/asrs/service/AgvLocDetlService.java
@@ -1,5 +1,6 @@
package com.zy.asrs.service;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.IService;
import com.zy.asrs.entity.AgvLocDetl;
import com.zy.common.model.LocDto;
@@ -12,4 +13,14 @@
    public double queryStockAndSetLocDto(String matnr, String batch, String orderNo, List<LocDto> locDtoList, double issued);
    public void updateStock(String sourceLoc, String targetLoc);
    Page<AgvLocDetl> getStockStatis(Page<AgvLocDetl> page);
    Integer sum();
    List<AgvLocDetl> getStockStatisExcel();
    List<AgvLocDetl> searchByLike(String orderNo, String matnr, String maktx, String specs, String locNo);
}
src/main/java/com/zy/asrs/service/AgvLocMastService.java
@@ -19,4 +19,9 @@
    void updateLocType2ByRBL(Integer locType2, AgvLocRule locRule);
    public void updateLocStsByLocNo(String locNo, String locSts);
    public List<String> queryGroupEmptyStock(int floor);
    List<AgvLocMast> selectLocByLevAndFloor(int lev, int floor);
}
src/main/java/com/zy/asrs/service/AgvWorkService.java
@@ -2,6 +2,8 @@
import com.zy.asrs.entity.AgvBasDevp;
import com.zy.asrs.entity.AgvWrkMast;
import com.zy.asrs.entity.param.EmptyPlateOutParam;
import com.zy.asrs.entity.param.StockOutParam;
import com.zy.common.model.StartupDto;
import com.zy.common.model.TaskDto;
@@ -24,5 +26,21 @@
     */
    void pickIn(List<AgvWrkMast> agvWrkMastList);
    /*
    盘点出库
     */
    void locCheckOut(StockOutParam param, Long userId);
    /*
    库位移转
     */
    void locMove(String sourceLocNo, String targetLocNo, Long userId);
    /*
    空板入库
     */
    String emptyPlateIn(String sourceStaion, Long userId);
    void emptyPlateOut(EmptyPlateOutParam param, Long userId);
}
src/main/java/com/zy/asrs/service/AllLocDetlService.java
New file
@@ -0,0 +1,8 @@
package com.zy.asrs.service;
import com.baomidou.mybatisplus.service.IService;
import com.zy.asrs.entity.AllLocDetl;
public interface AllLocDetlService extends IService<AllLocDetl> {
}
src/main/java/com/zy/asrs/service/impl/AgvBasDevpServiceImpl.java
@@ -109,16 +109,11 @@
                AgvBasDevpDto agvBasDevpDto = new AgvBasDevpDto();
                BeanUtils.copyProperties(agvBasDevp, agvBasDevpDto);
//                if (Cools.isEmpty(agvBasDevpDto.getBarcode())) {
//                    return agvBasDevpDto;
//                }
                //如果工作位状态为0.空库位,则直接返回
                if("O".equals(agvBasDevpDto.getLocSts())){
                    return agvBasDevpDto;
                }
//              AgvWrkMast agvWrkMast = agvWrkMastService.selectOne(new EntityWrapper<AgvWrkMast>()
//                        .eq("barcode", agvBasDevpDto.getBarcode()));
                AgvWrkMast agvWrkMast = agvWrkMastService.selectOne(new EntityWrapper<AgvWrkMast>()
                        .eq("loc_no", agvBasDevpDto.getDevNo())
                        .or().eq("source_loc_no",agvBasDevpDto.getDevNo()));
@@ -139,6 +134,8 @@
                    }
                }
                setFlagForAgvBasDevpDto(agvWrkMast,agvBasDevpDto);
                return agvBasDevpDto;
            }).collect(Collectors.toList());
@@ -153,4 +150,29 @@
        return result;
    }
    private void setFlagForAgvBasDevpDto(AgvWrkMast agvWrkMast, AgvBasDevpDto agvBasDevpDto){
        //当工作档类型为101.出库 并且 工作位状态为F.在库时,显示容器离场按钮
        if(agvWrkMast.getIoType() == 101 && "F".equals(agvBasDevpDto.getLocSts())){
            agvBasDevpDto.setContainerMoveOutFlag(true);
        }
        //当工作档类型为101.出库 并且 工作位状态为F.在库时,显示容器离场按钮
        if(agvWrkMast.getIoType() == 110 && "D".equals(agvBasDevpDto.getLocSts())){
            agvBasDevpDto.setContainerMoveOutFlag(true);
        }
        //当工作档类型为103.拣料出库 并且 工作位状态为F.在库时,显示拣料/盘点入库按钮
        if(agvWrkMast.getIoType() == 103 && "F".equals(agvBasDevpDto.getLocSts())){
            agvBasDevpDto.setPickInFlag(true);
        }
        //当工作档类型为107.盘点出库 并且 工作位状态为F.在库时,显示拣料/盘点入库按钮
        if(agvWrkMast.getIoType() == 107 && "F".equals(agvBasDevpDto.getLocSts())){
            agvBasDevpDto.setPickInFlag(true);
        }
    }
    public List<String> getAvailableEmptyInSite() {
        return this.baseMapper.getAvailableEmptyInSite();
    }
}
src/main/java/com/zy/asrs/service/impl/AgvBasMapServiceImpl.java
New file
@@ -0,0 +1,23 @@
package com.zy.asrs.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zy.asrs.entity.AgvBasMap;
import com.zy.asrs.entity.BasMap;
import com.zy.asrs.mapper.AgvBasMapMapper;
import com.zy.asrs.service.AgvBasMapService;
import org.springframework.stereotype.Service;
@Service
public class AgvBasMapServiceImpl extends ServiceImpl<AgvBasMapMapper, AgvBasMap> implements AgvBasMapService {
    @Override
    public BasMap selectLatestMap(Integer lev, Integer floor) {
        return this.baseMapper.selectLatestMap(lev,floor);
    }
    @Override
    public boolean deleteByLev(Integer lev) {
        return this.baseMapper.deleteByLev(lev);
    }
}
src/main/java/com/zy/asrs/service/impl/AgvLocDetlServiceImpl.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.core.common.Cools;
import com.zy.asrs.entity.AgvLocDetl;
@@ -80,6 +81,53 @@
    }
    /*
    更新库存明细
     */
    public void updateStock(String sourceLoc, String targetLoc) {
        this.baseMapper.updateStock(sourceLoc,targetLoc);
    }
    public Page<AgvLocDetl> getStockStatis(Page<AgvLocDetl> page) {
        page.setRecords(baseMapper.getStockStatis(page.getCondition()));
        page.setTotal(baseMapper.getStockStatisCount(page.getCondition()));
        return page;
    }
    /*
    获取库存总数
     */
    public Integer sum() {
        return this.baseMapper.sum();
    }
    public List<AgvLocDetl> getStockStatisExcel(){
        return this.baseMapper.getStockStatisExcel();
    }
    public List<AgvLocDetl> searchByLike(String orderNo, String matnr, String maktx, String specs, String locNo) {
        if (Cools.isEmpty(orderNo) && Cools.isEmpty(matnr) && Cools.isEmpty(maktx) && Cools.isEmpty(specs) && Cools.isEmpty(locNo)) {
            return new ArrayList<AgvLocDetl>();
        }
        EntityWrapper<AgvLocDetl> wrapper = new EntityWrapper<>();
        if(Cools.isEmpty(orderNo)){
            wrapper.like("order_no",orderNo);
        }
        if(Cools.isEmpty(matnr)){
            wrapper.like("matnr",matnr);
        }
        if(Cools.isEmpty(maktx)){
            wrapper.like("maktx",maktx);
        }
        if(Cools.isEmpty(specs)){
            wrapper.like("specs",specs);
        }
        if(Cools.isEmpty()){
            wrapper.like("loc_no",locNo);
        }
        return this.selectList(wrapper);
    }
    private List<String> queryAgvStaNosByFloor(int floor){
        List<String> agvStaNos = new ArrayList<>();
        if(floor == 1){
src/main/java/com/zy/asrs/service/impl/AgvLocMastServiceImpl.java
@@ -1,5 +1,6 @@
package com.zy.asrs.service.impl;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zy.asrs.entity.AgvLocMast;
import com.zy.asrs.entity.AgvLocRule;
@@ -18,10 +19,10 @@
public class AgvLocMastServiceImpl extends ServiceImpl<AgvLocMastMapper, AgvLocMast> implements AgvLocMastService {
    @Autowired
    AgvLocMastMapper agvLockMastMapper;
    AgvLocMastMapper agvLocMastMapper;
    public void clearLoc(){
        agvLockMastMapper.deleteAll();
        agvLocMastMapper.deleteAll();
    }
    public void initLocFloor1() {
@@ -94,4 +95,15 @@
        this.updateById(agvLocMast);
    }
    public List<String> queryGroupEmptyStock(int floor) {
        return this.baseMapper.queryGroupEmptyStock(floor);
    }
    public List<AgvLocMast> selectLocByLevAndFloor(int lev, int floor) {
        List<AgvLocMast> agvLocMastList = this.selectList(new EntityWrapper<AgvLocMast>().eq("lev1", lev).eq("floor", floor));
        return agvLocMastList;
        //return this.agvLocMastMapper.selectLocByLevAndFloor(lev,floor);
    }
}
src/main/java/com/zy/asrs/service/impl/AgvWorkServiceImpl.java
@@ -5,6 +5,8 @@
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.EmptyPlateOutParam;
import com.zy.asrs.entity.param.StockOutParam;
import com.zy.asrs.service.*;
import com.zy.common.model.LocDto;
import com.zy.common.model.OrderDto;
@@ -38,7 +40,7 @@
    @Autowired
    private AgvBasDevpService agvBasDevpService;
    @Autowired
    private AgvLocMastService agvLockMastService;
    private AgvLocMastService agvLocMastService;
    @Autowired
    private AgvLocDetlService agvLocDetlService;
    @Autowired
@@ -104,7 +106,7 @@
        agvTaskDtos.forEach(taskDto -> {
            AgvLocMast agvLocMast = agvLockMastService.selectById(taskDto.getLocNo());
            AgvLocMast agvLocMast = agvLocMastService.selectById(taskDto.getLocNo());
            AgvLocDetl agvLocDetl = agvLocDetlService.selectOne(new EntityWrapper<AgvLocDetl>().eq("loc_no", taskDto.getLocNo()));
            //工作档所需参数
@@ -128,7 +130,7 @@
            modifyOrderDetl(taskDto.getLocDtos().get(0), userId);
            //更新源站点信息
            String locSts = ioType == 101 ? "R" : "P";
            updateAgvLocMast(agvLockMastService.selectById(sourceLocNo),locSts);
            updateAgvLocMast(agvLocMastService.selectById(sourceLocNo),locSts);
            //更新目标站点状态
            //locSts = ioType == 101 ? "S" : "Q";
            updateAgvBasDevp(agvBasDevpService.selectById(targetLocNo),"S");
@@ -143,7 +145,11 @@
        agvWrkMastList.forEach(agvWrkMast -> {
            //修改工作党
            agvWrkMast.setWrkSts(201L);
            agvWrkMast.setIoType(53);
            //根据出库类型 设置入库类型 53拣料入库 57盘点入库
            int ioType = agvWrkMast.getIoType() == 103 ? 53 : 57;
            agvWrkMast.setIoType(ioType);
            String locNo = agvWrkMast.getLocNo();
            agvWrkMast.setLocNo(agvWrkMast.getSourceLocNo());
            agvWrkMast.setSourceLocNo(locNo);
@@ -151,22 +157,139 @@
            agvWrkMastService.updateById(agvWrkMast);
            AgvWrkDetl agvWrkDetl = agvWrkDetlService.selectOne(new EntityWrapper<AgvWrkDetl>().eq("wrk_no", agvWrkMast.getWrkNo()));
            AgvLocMast agvLocMast = agvLockMastService.selectById(agvWrkMast.getLocNo());
            AgvLocMast agvLocMast = agvLocMastService.selectById(agvWrkMast.getLocNo());
            AgvLocDetl agvLocDetl = agvLocDetlService.selectOne(new EntityWrapper<AgvLocDetl>().eq("loc_no",agvLocMast.getLocNo()));
            AgvBasDevp agvBasDevp = agvBasDevpService.selectById(agvWrkMast.getSourceLocNo());
            //修改工作党明细
            agvWrkDetl.setAnfme(agvLocDetl.getAnfme() - agvWrkDetl.getAnfme());
            agvWrkDetlService.update(agvWrkDetl,new EntityWrapper<AgvWrkDetl>().eq("wrk_no",agvWrkDetl.getWrkNo()));
            //修改库存信息
            agvLocDetl.setAnfme(agvWrkDetl.getAnfme());
            agvLocDetlService.update(agvLocDetl,new EntityWrapper<AgvLocDetl>().eq("loc_no",agvLocDetl.getLocNo()));
            //修改库位信息
            agvLocMast.setLocSts("Q");
            agvLockMastService.selectById(agvLocMast);
            //修改站点信息
            agvBasDevp.setLocSts("R");
            agvBasDevpService.updateById(agvBasDevp);
            //拣料入库
            if(ioType == 53){
                //修改工作党明细
                agvWrkDetl.setAnfme(agvLocDetl.getAnfme() - agvWrkDetl.getAnfme());
                agvWrkDetlService.update(agvWrkDetl,new EntityWrapper<AgvWrkDetl>().eq("wrk_no",agvWrkDetl.getWrkNo()));
                //修改库存信息
                agvLocDetl.setAnfme(agvWrkDetl.getAnfme());
                agvLocDetlService.update(agvLocDetl,new EntityWrapper<AgvLocDetl>().eq("loc_no",agvLocDetl.getLocNo()));
            }
            //修改库位信息
            updateAgvLocMast(agvLocMast,"Q");
            //修改站点信息
            updateAgvBasDevp(agvBasDevp,"R");
        });
    }
    /*
    盘点出库
     */
    @Transactional
    public void locCheckOut(StockOutParam param, Long userId) {
        String station = param.getStation();
        List<AgvBasDevp> agvBasDevpList = agvBasDevpService.selectList(new EntityWrapper<AgvBasDevp>()
                .eq("station_code", station)
                .eq("loc_sts","O"));
        if(param.getLocDetls().size() > agvBasDevpList.size()){
            throw new CoolException("当前站点可用缓存货架数量为" + agvBasDevpList.size() + ",少于需要盘点出库库位数量,请重新选择盘点库位");
        }
        param.getLocDetls().forEach(locDetl -> {
            AgvLocMast agvLocMast = agvLocMastService.selectById(locDetl.getLocNo());
            AgvLocDetl agvLocDetl = agvLocDetlService.selectOne(new EntityWrapper<AgvLocDetl>().eq("loc_no", locDetl.getLocNo()));
            AgvBasDevp agvBasDevp = agvBasDevpService.selectOne(new EntityWrapper<AgvBasDevp>()
                    .eq("station_code", station)
                    .eq("loc_sts","O"));
            Date now = new Date();
            //生成工作党
            AgvWrkMast wrkMast = createWrkMast(107, 21L, locDetl.getLocNo(), agvBasDevp.getDevNo(), agvLocDetl.getZpallet(), now, userId);
            //生成工作明细档
            createWrkDetlReWrite(locDetl.getMatnr(),wrkMast.getWrkNo(),null,locDetl.getBatch(),locDetl.getCount(),wrkMast.getBarcode(),now,userId);
            //修改库位信息
            updateAgvLocMast(agvLocMast,"P");
            //修改站点信息
            updateAgvBasDevp(agvBasDevp,"S");
        });
    }
    /*
    库位移转
     */
    @Transactional
    public void locMove(String sourceLocNo, String targetLocNo, Long userId) {
        AgvLocMast sourceLocMast = agvLocMastService.selectById(sourceLocNo);
        AgvLocMast targetLocMast = agvLocMastService.selectById(targetLocNo);
        AgvLocDetl sourceLocDetl = agvLocDetlService.selectOne(new EntityWrapper<AgvLocDetl>().eq("loc_no", sourceLocMast.getLocNo()));
        if(!sourceLocMast.getLocSts().equals("F")){
            throw new CoolException(sourceLocMast.getLocNo() + "源库位出库失败,状态:"+sourceLocMast.getLocSts$());
        }
        if(!targetLocMast.getLocSts().equals("O")){
            throw new CoolException("移转失败,目标库位状态:"+targetLocMast.getLocSts$());
        }
        Date now = new Date();
        //生成移库工作档
        AgvWrkMast wrkMast = createWrkMast(11, 21L, sourceLocNo, targetLocNo, sourceLocDetl.getZpallet(), now, userId);
        //生成工作党明细
        createWrkDetlReWrite(sourceLocDetl.getMatnr(),wrkMast.getWrkNo(),null,sourceLocDetl.getBatch(),sourceLocDetl.getAnfme(),sourceLocDetl.getZpallet(),now,userId);
        //修改目标库位状态
        updateAgvLocMast(targetLocMast,"S");
        //修改原库位状态
        updateAgvLocMast(sourceLocMast,"R");
    }
    /*
    空板入库
     */
    @Transactional
    public String emptyPlateIn(String sourceStaion, Long userId) {
        Date now = new Date();
        // 源站点状态检测
        AgvBasDevp agvBasDevp = agvBasDevpService.selectById(sourceStaion);
        if(!agvBasDevp.getLocSts().equals("O")){
            throw new CoolException("当前工作位状态为" + agvBasDevp.getLocSts()+",无法进行空板入库");
        }
        // 检索库位
        AgvLocMast locMast = agvCommonService.getLocNo(null, agvBasDevp.getFloor());
        // 生成工作档 10.空板入库
        createWrkMast(10,201L,agvBasDevp.getDevNo(),locMast.getLocNo(),null,now,userId);
        //更新源站点状态
        updateAgvBasDevp(agvBasDevp,"R");
        //更新目标库位状态
        updateAgvLocMast(locMast,"S");
        return locMast.getLocNo();
    }
    /*
    空板出库
     */
    @Transactional
    public void emptyPlateOut(EmptyPlateOutParam param, Long userId) {
        Date now = new Date();
        //判断所选工作站空余工作位数量是否满足出库数量
        List<AgvBasDevp> agvBasDevpList = agvBasDevpService.selectList(new EntityWrapper<AgvBasDevp>()
                .eq("station_code", param.getStationCode())
                .eq("loc_sts","O"));
        if(agvBasDevpList.size() < param.getLocNos().size()){
            throw new CoolException("当前工作站可出库工作位数量为"+ agvBasDevpList.size() + ",小于要出库的库位数量,请重新选择出库库位");
        }
        param.getLocNos().forEach(locNo -> {
            AgvLocMast agvLocMast = agvLocMastService.selectById(locNo);
            if(!agvLocMast.getLocSts().equals("D")){
                throw new CoolException(agvLocMast.getLocNo() + "库位状态已经不为D.空桶/空栈板,请重新选择库位进行空板出库");
            }
            //检索工作位
            AgvBasDevp agvBasDevp = agvBasDevpService.selectOne(new EntityWrapper<AgvBasDevp>()
                    .eq("station_code", param.getStationCode())
                    .eq("loc_sts", "O"));
            //生成工作档
            createWrkMast(110,21L,locNo,agvBasDevp.getDevNo(),null,now,userId);
            //修改源库位状态
            updateAgvLocMast(agvLocMast,"R");
            //修改目标工作位状态
            updateAgvBasDevp(agvBasDevp,"S");
        });
    }
@@ -175,7 +298,7 @@
     */
    private void updateAgvLocMast(AgvLocMast locMast, String locSts){
        locMast.setLocSts(locSts);
        agvLockMastService.updateById(locMast);
        agvLocMastService.updateById(locMast);
    }
    /*
src/main/java/com/zy/asrs/service/impl/AllLocDetlServiceImpl.java
New file
@@ -0,0 +1,11 @@
package com.zy.asrs.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zy.asrs.entity.AllLocDetl;
import com.zy.asrs.mapper.AllLocDetlMapper;
import com.zy.asrs.service.AllLocDetlService;
import org.springframework.stereotype.Service;
@Service
public class AllLocDetlServiceImpl extends ServiceImpl<AllLocDetlMapper, AllLocDetl> implements AllLocDetlService {
}
src/main/java/com/zy/asrs/task/AgvWrkMastScheduler.java
@@ -34,14 +34,17 @@
    /*
    定时处理AGV工作档中工作状态为205.工作完成 且 (1.入库 || 53,拣料入库)的数据
    定时处理AGV工作档中工作状态为205.工作完成 且 (1.入库 || 53,拣料入库 || 57.盘点入库 || 10.空板入库 || 11.库格移载)的数据
     */
    @Scheduled(cron = "0/5 * * * * ? ")
    public void excutePutwayWrk(){
        List<AgvWrkMast> agvWrkMastList = agvWrkMastService.selectList(new EntityWrapper<AgvWrkMast>()
                .eq("wrk_sts", 205)
                .andNew().eq("io_type",53)
                .or().eq("io_type",1));
                .or().eq("io_type",1)
                .or().eq("io_type",57)
                .or().eq("io_type",10)
                .or().eq("io_type",11));
        if(!Cools.isEmpty(agvWrkMastList)){
            agvWrkMastList.stream().forEach(agvWrkMast -> {
                ReturnT<String> returnT = agvWrkMastHandler.completedPutWayWrk(agvWrkMast);
@@ -50,13 +53,14 @@
    }
    /*
    定时处理AGV工作档中工作状态为205.工作完成 且 101出库类型的数据
    定时处理AGV工作档中工作状态为206.容器离场完成 且 (101.出库 || 110.空板出库)
     */
    @Scheduled(cron = "0/5 * * * * ? ")
    public void excuteCarryWrk(){
        List<AgvWrkMast> agvWrkMastList = agvWrkMastService.selectList(new EntityWrapper<AgvWrkMast>()
                .eq("wrk_sts", 207)
                .eq("io_type",101));
                .eq("wrk_sts", 206)
                .andNew().eq("io_type",110)
                .or().eq("io_type",101));
        if(!Cools.isEmpty(agvWrkMastList)){
            agvWrkMastList.stream().forEach(agvWrkMast -> {
                ReturnT<String> returnT = agvWrkMastHandler.completedCarryWrk(agvWrkMast);
@@ -66,15 +70,17 @@
    /*
    putaway:上架
    定时处理AGV工作档中工作状态为201.生成入库任务ID 且(出库类型为 53.拣料再入库 || 1.入库 || 10.空板入库栽 || 57.盘点再入库)的数据
     */
    @Scheduled(cron = "0/5 * * * * ? ")
    public void startPutwayWrk(){
        List<AgvWrkMast> agvWrkMastList = agvWrkMastService.selectPage(new Page<>(1, 50)
                ,new EntityWrapper<AgvWrkMast>()
                .eq("wrk_sts", 201)   //201.生成入库任务ID
                .andNew().eq("io_type", 53).or() //53.拣料再入库
                .eq("io_type", 1)).getRecords();
                .eq("wrk_sts", 201)
                .andNew().eq("io_type", 53)
                .or().eq("io_type", 1)
                .or().eq("io_type", 10)
                .or().eq("io_type", 57)).getRecords();
        if(!Cools.isEmpty(agvWrkMastList)){
            try {
@@ -87,15 +93,18 @@
    /*
    carry:搬运,统指出库、移库、点到点搬运等
    定时处理AGV工作档中工作状态为21.生成出库任务 且(出库类型为 101.出库 || 103.拣料出库 || 11.库格移栽 || 110.空板出库 || 107.盘点出库)的数据
     */
    @Scheduled(cron = "0/5 * * * * ? ")
    public void startCarryWrk(){
        List<AgvWrkMast> agvWrkMastList = agvWrkMastService.selectPage(new Page<>(1, 50)
                ,new EntityWrapper<AgvWrkMast>()
                        .eq("wrk_sts", 21)   //21.生成出库任务
                        .andNew().eq("io_type", 101).or()
                        .eq("io_type", 103)).getRecords();
                        .eq("wrk_sts", 21)
                        .andNew().eq("io_type", 101)
                        .or().eq("io_type", 103)
                        .or().eq("io_type", 11)
                        .or().eq("io_type", 110)
                        .or().eq("io_type", 107)).getRecords();
        if(!Cools.isEmpty(agvWrkMastList)){
            try {
src/main/java/com/zy/asrs/task/handler/AgvWrkMastHandler.java
@@ -46,11 +46,16 @@
        String barcode = agvWrkMast.getBarcode();
        String orderNo = getOrderNoByWrkNo(wrkNo);
        //修改工作档状态为206.库存更新完成
        agvWrkMast.setWrkSts(206L);
        //修改工作档状态为207.库存更新完成
        agvWrkMast.setWrkSts(207L);
        agvWrkMastService.updateById(agvWrkMast);
        //修改目标库位状态为F.在库
        agvLocMastService.updateLocStsByLocNo(agvWrkMast.getLocNo(),"F");
        if(agvWrkMast.getIoType() == 10){
            // 空板入库 设置库位状态为D.空桶/空栈板
            agvLocMastService.updateLocStsByLocNo(agvWrkMast.getLocNo(),"D");
        }else{
            //修改目标库位状态为F.在库
            agvLocMastService.updateLocStsByLocNo(agvWrkMast.getLocNo(),"F");
        }
        //生成AGV工作历史档
        agvWrkMastLogService.save(wrkNo);
        //生成AGV工作明细历史档
@@ -59,6 +64,7 @@
        agvWrkMastService.deleteById(wrkNo);
        //删除AGV工作明细档
        agvWrkDetlService.delete(new EntityWrapper<AgvWrkDetl>().eq("wrk_no",wrkNo));
        //类型为出库时
        if(agvWrkMast.getIoType() == 1){
            //更新目标库位明细
            agvLocDetlService.addLocDetlInfo(agvWrkMast.getLocNo(),wrkNo);
@@ -66,7 +72,13 @@
            agvWaitPakinLogService.save(barcode);
            //删除入库通知档
            agvWaitPakinService.delete(new EntityWrapper<AgvWaitPakin>().eq("zpallet",barcode));
        }
        //类型为库位移转时
        if(agvWrkMast.getIoType() == 11){
            //更新库存明细
            agvLocDetlService.updateStock(agvWrkMast.getSourceLocNo(),agvWrkMast.getLocNo());
            //修改源库位状态为O
            agvLocMastService.updateLocStsByLocNo(agvWrkMast.getSourceLocNo(),"O");
        }
        if(!isJSON(orderNo)){
            //检查订单是否已完成
@@ -82,17 +94,21 @@
        return SUCCESS;
    }
    @Transactional
    public ReturnT<String> completedCarryWrk(AgvWrkMast agvWrkMast) {
        int wrkNo = agvWrkMast.getWrkNo();
        String orderNo = getOrderNoByWrkNo(wrkNo);
        //修改工作档状态为206.库存更新完成
        agvWrkMast.setWrkSts(206L);
        //修改工作档状态为207.库存更新完成
        agvWrkMast.setWrkSts(207L);
        agvWrkMastService.updateById(agvWrkMast);
        //修改源库位状态为O
        agvLocMastService.updateLocStsByLocNo(agvWrkMast.getSourceLocNo(),"O");
        //更新目标库位明细
        agvLocDetlService.delete(new EntityWrapper<AgvLocDetl>().eq("loc_no",agvWrkMast.getSourceLocNo()));
        if(agvWrkMast.getIoType() == 101){
            //更新目标库位明细 101.出库 删除源库位库存明细
            agvLocDetlService.delete(new EntityWrapper<AgvLocDetl>().eq("loc_no",agvWrkMast.getSourceLocNo()));
        }
        //生成AGV工作历史档
        agvWrkMastLogService.save(wrkNo);
        //生成AGV工作明细历史档
@@ -124,7 +140,7 @@
        if(code == 0){
            agvWrkMastList.forEach(agvWrkMast -> {
                //202.RCS取货中
                agvWrkMast.setWrkSts((long)202);
                agvWrkMast.setWrkSts(202L);
                agvWrkMastService.updateById(agvWrkMast);
                if(agvWrkMast.getIoType() == 1){
                    //修改AGV入库通知档状态入出状态为Y
@@ -146,7 +162,7 @@
        if(code == 0){
            agvWrkMastList.forEach(agvWrkMast -> {
                //202.RCS取货中
                agvWrkMast.setWrkSts((long)202);
                agvWrkMast.setWrkSts(202L);
                agvWrkMastService.updateById(agvWrkMast);
            });
            //agvWrkMastService.updateBatchById(agvWrkMastList);
@@ -159,16 +175,10 @@
    private String getOrderNoByWrkNo(int wrkNo){
        AgvWrkDetl agvWrkDetl = agvWrkDetlService.selectOne(new EntityWrapper<AgvWrkDetl>().eq("wrk_no", wrkNo));
        if(Cools.isEmpty(agvWrkDetl)){
            return null;
        }
        return agvWrkDetl.getOrderNo();
    }
    public static void main(String[] args) {
        String order = "[{\"anfme\":50.0,\"orderNo\":\"CS110011001111\"},{\"anfme\":50.0,\"orderNo\":\"CS110011001110\"}]";
        List<Map> maps = JSONArray.parseArray(order, Map.class);
        maps.forEach(map -> {
            Object orderNo = map.get("orderNo");
            System.out.println(orderNo );
        });
    }
    private boolean isJSON(String str) {
src/main/java/com/zy/asrs/utils/Utils.java
@@ -168,6 +168,16 @@
    }
    /**
     * 通过库位号获取 层
     */
    public static int getAgvLev(String locNo) {
        if (!Cools.isEmpty(locNo)) {
            return Integer.parseInt(locNo.substring(11, 13));
        }
        throw new RuntimeException("库位解析异常");
    }
    /**
     * 当检索到双深库位的浅库位时,如果深库位无货,则放入对应的深库位
     */
    public static void toDeepIfEmptyByShallow(String shallowLoc) {
src/main/java/com/zy/common/model/AgvBasDevpDto.java
@@ -18,4 +18,8 @@
    private AgvWrkDetl agvWrkDetl;
    private boolean containerMoveOutFlag;
    private boolean pickInFlag;
}
src/main/java/com/zy/common/service/AgvCommonService.java
@@ -72,9 +72,11 @@
        AgvLocMast locMast = null;
        //库位规则
        locMast = getLocByLocRule(agvWaitPakinList.get(0),floor);
        if(!Cools.isEmpty(locMast)){
            return locMast;
        if(!Cools.isEmpty(agvWaitPakinList)){
            locMast = getLocByLocRule(agvWaitPakinList.get(0),floor);
            if(!Cools.isEmpty(locMast)){
                return locMast;
            }
        }
        // 靠近摆放规则 --- 相同订单号, 同天同规格物料
src/main/resources/mapper/ViewStayTimeMapper.xml
@@ -90,6 +90,51 @@
    ) a
</select>
<!-- 分页查询AGV和四项库所有信息 -->
<select id="queryAllViewStayTimeList" parameterType="com.zy.asrs.entity.ViewStayTimeBean" resultType="com.zy.asrs.entity.ViewStayTimeBean">
    select
        *
    from (
             select
                 ROW_NUMBER() over (order by stay_time desc) as row
        , *
             from
                 (
                     SELECT
                         GETDATE() AS today
                          , CONVERT(decimal, DATEDIFF(second,all_loc_detl.appe_time, GETDATE()) / 86400.0, 9) AS stay_time
                          , all_loc_detl.*
                     FROM all_loc_detl
                     where 1=1
                     <include refid="viewStayTimeConditionSql"></include>
                 ) t
                     left join (select matnr as c ,store_max_date,store_max,store_min from man_mat) b
                               on t.matnr = b.c
                     left join (select matnr as f,sum(asr_loc_detl.anfme) as sum_qty from asr_loc_detl group by asr_loc_detl.matnr ) as z
                               on z.f= b.c
         ) a  where a.row between ((#{pageNumber}-1)*#{pageSize}+1) and (#{pageNumber}*#{pageSize})
</select>
<select id="getAllViewStayTimeCount" parameterType="com.zy.asrs.entity.ViewStayTimeBean" resultType="Integer">
    select
        count(1)
    from (
             select
                 ROW_NUMBER() over (order by stay_time desc) as row
        , *
             from
                 (
                     SELECT
                         GETDATE() AS today
                          , CONVERT(decimal, DATEDIFF(second,all_loc_detl.appe_time, GETDATE()) / 86400.0, 9) AS stay_time
                          , all_loc_detl.*
                     FROM all_loc_detl
                     where 1=1
                     <include refid="viewStayTimeConditionSql"></include>
                 ) t
         ) a
</select>
<!-- 不分页查询所有信息,用于excel导出 -->
<select id="getViewStayTimeAll" parameterType="com.zy.asrs.entity.ViewStayTimeBean" resultType="com.zy.asrs.entity.ViewStayTimeBean">
    select
@@ -112,4 +157,26 @@
    ) a
</select>
<!-- 不分页查询AGV和四项库所有信息,用于excel导出 -->
<select id="getAllViewStayTimeAll" parameterType="com.zy.asrs.entity.ViewStayTimeBean" resultType="com.zy.asrs.entity.ViewStayTimeBean">
    SELECT
        *
    FROM
        (
            SELECT
                ROW_NUMBER ( ) OVER ( ORDER BY stay_time DESC ) AS row, *
            FROM
                (
                    SELECT
                        GETDATE( ) AS today,
                        CONVERT ( DECIMAL, DATEDIFF( SECOND, all_loc_detl.appe_time, GETDATE( ) ) / 86400.0, 9 ) AS stay_time,
                        dbo.all_loc_detl.*
                    FROM
                        all_loc_detl
                    where 1=1
                    <include refid="viewStayTimeConditionSql"></include>
                ) t
        ) a
</select>
</mapper>
src/main/webapp/static/js/agvLocDetlStatis/locDetlStatis.js
New file
@@ -0,0 +1,256 @@
var pageCurr;
function getCol() {
    var cols = [
        {field: 'anfme', align: 'center',title: '库存数量', style: 'font-weight: bold'}
    ];
    arrRemove(detlCols, "field", "anfme")
    arrRemove(detlCols, "field", "zpallet")
    cols.push.apply(cols, detlCols);
    // cols.push({field: 'anfme', align: 'center',title: '数量', style: 'font-weight: bold'}
    // )
    return cols;
}
layui.use(['table','laydate', 'form'], function(){
    var table = layui.table;
    var $ = layui.jquery;
    var layer = layui.layer;
    var layDate = layui.laydate;
    var form = layui.form;
    // 数据渲染
    tableIns = table.render({
        elem: '#locDetlStatis',
        headers: {token: localStorage.getItem('token')},
        url: baseUrl+'/agv/locDetl/statis/auth',
        page: true,
        limit: 20,
        limits: [20, 30, 50, 100, 200, 500],
        even: true,
        toolbar: '#toolbar',
        cellMinWidth: 50,
        cols: [getCol()],
        request: {
            pageName: 'curr',
            pageSize: 'limit'
        },
        parseData: function (res) {
            return {
                'code': res.code,
                'msg': res.msg,
                'count': res.data.total,
                'data': res.data.records
            }
        },
        response: {
            statusCode: 200
        },
        done: function(res, curr, count) {
            if (res.code === 403) {
                top.location.href = baseUrl+"/";
            }
            pageCurr=curr;
            limit();
            form.on('checkbox(tableCheckbox)', function (data) {
                var _index = $(data.elem).attr('table-index')||0;
                if(data.elem.checked){
                    res.data[_index][data.value] = 'Y';
                }else{
                    res.data[_index][data.value] = 'N';
                }
            });
            /**
             * 显示库存总数量
             */
            $.ajax({
                url: baseUrl+"/agv/locDetl/count",
                headers: {'token': localStorage.getItem('token')},
                contentType:'application/json;charset=UTF-8',
                method: 'POST',
                success: function (res) {
                    $("#countNum").text(res.data + '个');
                }
            });
        }
    });
    // 监听排序事件
    table.on('sort(locDetlStatis)', function (obj) {
        var searchData = {};
        $.each($('#search-box [name]').serializeArray(), function() {
            searchData[this.name] = this.value;
        });
        searchData['orderByField'] = obj.field;
        searchData['orderByType'] = obj.type;
        tableIns.reload({
            where: searchData,
            page: {
                curr: 1
            },
            done: function (res, curr, count) {
                if (res.code === 403) {
                    top.location.href = baseUrl+"/";
                }
                pageCurr=curr;
                limit();
            }
        });
    });
    // 监听头工具栏事件
    table.on('toolbar(locDetlStatis)', function (obj) {
        var checkStatus = table.checkStatus(obj.config.id);
        switch(obj.event) {
            case 'exportAll':
                layer.closeAll();
                layer.load(1, {shade: [0.1,'#fff']});
                location.href = baseUrl + "/agv/locDetl/statis/export";
                layer.closeAll('loading');
                break;
            case 'exportData':
                layer.confirm('确定导出Excel吗', {shadeClose: true}, function(){
                    var titles=[];
                    var fields=[];
                    obj.config.cols[0].map(function (col) {
                        if (col.type === 'normal' && col.hide === false && col.toolbar == null) {
                            titles.push(col.title);
                            fields.push(col.field);
                        }
                    });
                    var exportData = {};
                    $.each($('#search-box [name]').serializeArray(), function() {
                        exportData[this.name] = this.value;
                    });
                    var param = {
                        'locDetl': exportData,
                        'fields': fields
                    };
                    $.ajax({
                        url: baseUrl+"/agv/locDetl/export/auth",
                        headers: {'token': localStorage.getItem('token')},
                        data: JSON.stringify(param),
                        dataType:'json',
                        contentType:'application/json;charset=UTF-8',
                        method: 'POST',
                        success: function (res) {
                            layer.closeAll();
                            if (res.code === 200) {
                                table.exportFile(titles,res.data,'xls');
                            } else if (res.code === 403) {
                                top.location.href = baseUrl+"/";
                            } else {
                                layer.msg(res.msg)
                            }
                        }
                    });
                });
                break;
        }
    });
    // 监听行工具事件
    table.on('tool(locDetlStatis)', function(obj){
        var data = obj.data;
        switch (obj.event) {
            // 详情
            case 'detail':
                layer.open({
                    type: 2,
                    title: '详情',
                    maxmin: true,
                    area: [top.detailWidth, top.detailHeight],
                    shadeClose: false,
                    content: 'locDetl_detail.html',
                    success: function(layero, index){
                        setFormVal(layer.getChildFrame('#detail', index), data, true);
                        top.convertDisabled(layer.getChildFrame('#data-detail :input', index), true);
                        layer.getChildFrame('#data-detail-submit-save,#data-detail-submit-edit,#prompt', index).hide();
                        layer.iframeAuto(index);layer.style(index, {top: (($(window).height()-layer.getChildFrame('#data-detail', index).height())/3)+"px"});
                        layero.find('iframe')[0].contentWindow.layui.form.render('select');
                        layero.find('iframe')[0].contentWindow.layui.form.render('checkbox');
                    }
                });
                break;
        }
    });
    // 搜索栏搜索事件
    form.on('submit(search)', function (data) {
        pageCurr = 1;
        tableReload(false);
    });
    // 搜索栏重置事件
    form.on('submit(reset)', function (data) {
        pageCurr = 1;
        clearFormVal($('#search-box'));
        tableReload(false);
    });
    // 时间选择器
    layDate.render({
        elem: '#modiTime\\$',
        type: 'datetime'
    });
    layDate.render({
        elem: '#appeTime\\$',
        type: 'datetime'
    });
});
// 关闭动作
$(document).on('click','#data-detail-close', function () {
    parent.layer.closeAll();
});
function tableReload(child) {
    var searchData = {};
    $.each($('#search-box [name]').serializeArray(), function() {
        searchData[this.name] = this.value;
    });
    (child ? parent.tableIns : tableIns).reload({
        where: searchData,
        page: {
            curr: pageCurr
        },
        done: function (res, curr, count) {
            if (res.code === 403) {
                top.location.href = baseUrl+"/";
            }
            pageCurr=curr;
            if (res.data.length === 0 && count !== 0) {
                tableIns.reload({
                    where: searchData,
                    page: {
                        curr: pageCurr-1
                    }
                });
                pageCurr -= 1;
            }
            limit(child);
        }
    });
}
function detailScreen(index) {
    var detail = layer.getChildFrame('#data-detail', index);
    var height = detail.height()+60;
    if (height > ($(window).height()*0.9)) {
        height = ($(window).height()*0.8);
    }
    layer.style(index, {
//        top: (($(window).height()-height)/3)+"px",
        height: height+'px'
    });
}
$('body').keydown(function () {
    if (event.keyCode === 13) {
        $("#search").click();
    }
});
src/main/webapp/static/js/agvPakStore/emptyIn.js
New file
@@ -0,0 +1,62 @@
var pageCurr;
layui.use(['table','laydate', 'form'], function() {
    var table = layui.table;
    var $ = layui.jquery;
    var layer = layui.layer;
    var layDate = layui.laydate;
    var form = layui.form;
    getInBound();
    limit();
    // 获取入库口
    function getInBound(){
        $.ajax({
            url: baseUrl+"/agv/available/empty/put/site",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            async: false,
            success: function (res) {
                if (res.code === 200){
                    var tpl = $("#putSiteSelectTemplate").html();
                    var template = Handlebars.compile(tpl);
                    var html = template(res);
                    $('#inSiteSelect').append(html);
                    form.render('select');
                } else if (res.code === 403){
                    top.location.href = baseUrl+"/";
                }else {
                    layer.msg(res.msg)
                }
            }
        })
    }
    // 空板入库
    form.on('submit(inbound)', function (data) {
        var inSite = $('#inSiteSelect').val();
        layer.confirm('请确保该工作位上已放有空板', function(){
            $.ajax({
                url: baseUrl+"/agv/empty/plate/in/start",
                headers: {'token': localStorage.getItem('token')},
                method: 'POST',
                data: {sourceStaNo: inSite},
                async: false,
                success: function (res) {
                    if (res.code === 200){
                        layer.msg("入库启动成功,目标库位:" + res.data);
                    } else if (res.code === 403){
                        top.location.href = baseUrl+"/";
                    }else {
                        layer.msg(res.msg)
                    }
                }
            })
        });
    });
})
src/main/webapp/static/js/agvPakStore/emptyOut.js
New file
@@ -0,0 +1,204 @@
var pageCurr;
layui.config({
    base: baseUrl + "/static/layui/lay/modules/"
}).use(['table','laydate', 'form', 'admin'], function() {
    var table = layui.table;
    var $ = layui.jquery;
    var layer = layui.layer;
    var layDate = layui.laydate;
    var form = layui.form;
    var admin = layui.admin;
    // 获取出库口
    function getOutBound(){
        // $.ajax({
        //     url: baseUrl+"/agv/available/empty/put/site",
        //     headers: {'token': localStorage.getItem('token')},
        //     method: 'POST',
        //     async: false,
        //     success: function (res) {
        //         if (res.code === 200){
        //             var tpl = $("#takeSiteSelectTemplate").html();
        //             var template = Handlebars.compile(tpl);
        //             var html = template(res);
        //             $('#staNoSelect').append(html);
        //             form.render('select');
        //         } else if (res.code === 403){
        //             top.location.href = baseUrl+"/";
        //         }else {
        //             layer.msg(res.msg)
        //         }
        //     }
        // })
    }
    // 数据渲染
    tableIns = table.render({
        elem: '#locMast',
        headers: {token: localStorage.getItem('token')},
        url: baseUrl+'/agv/locMast/list/auth',
        page: true,
        limit: 16,
        limits: [16, 30, 50, 100, 200, 500],
        where: {loc_sts: "D",floor:$('#floorSelect option:selected').val()},
        even: true,
        toolbar: '#toolbar',
        defaultToolbar: ['filter'],
        cellMinWidth: 50,
        cols: [[
            {type: 'checkbox', fixed: 'left'}
            ,{field: 'locNo', align: 'center',title: '库位号',sort:true}
            ,{field: 'locSts$', align: 'center',title: '库位状态',width:200}
            // ,{field: 'whsType$', align: 'center',title: '库位类型'}
            ,{field: 'row1', align: 'center',title: '排'}
            ,{field: 'bay1', align: 'center',title: '列'}
            ,{field: 'lev1', align: 'center',title: '层'}
            // ,{field: 'fullPlt', align: 'center',title: '满板', templet:function(row){
            //         var html = "<input value='fullPlt' type='checkbox' disabled=‘disabled’ lay-skin='primary' lay-filter='tableCheckbox' table-index='"+row.LAY_TABLE_INDEX+"'";
            //         if(row.fullPlt === 'Y'){html += " checked ";}
            //         html += ">";
            //         return html;
            //     },width:80}
            ,{field: 'modiUser$', align: 'center',title: '修改人员',event: 'modiUser'}
            ,{field: 'modiTime$', align: 'center',title: '修改时间'}
        ]],
        request: {
            pageName: 'curr',
            pageSize: 'limit'
        },
        parseData: function (res) {
            return {
                'code': res.code,
                'msg': res.msg,
                'count': res.data.total,
                'data': res.data.records
            }
        },
        response: {
            statusCode: 200
        },
        done: function(res, curr, count) {
            if (res.code === 403) {
                top.location.href = baseUrl+"/";
            }
            pageCurr=curr;
            getOutBound();
            limit();
            form.on('checkbox(tableCheckbox)', function (data) {
                var _index = $(data.elem).attr('table-index')||0;
                if(data.elem.checked){
                    res.data[_index][data.value] = 'Y';
                }else{
                    res.data[_index][data.value] = 'N';
                }
            });
        }
    });
    // 监听头工具栏事件
    table.on('toolbar(locMast)', function (obj) {
        var data = table.checkStatus(obj.config.id).data;
        switch (obj.event) {
            case 'outbound':
                var staNo = $("#staNoSelect").val();
                if (staNo === "" || staNo === null){
                    layer.msg("请选择出库口");
                    return;
                }
                var locNos = [];
                data.forEach(function(elem) {
                    locNos.push(elem.locNo);
                });
                if (data.length === 0){
                    layer.msg('请至少选中一行数据');
                } else {
                    $.ajax({
                        url: baseUrl+"/agv/empty/plate/out/start",
                        headers: {'token': localStorage.getItem('token')},
                        data: {
                            stationCode: staNo,
                            locNos: locNos
                        },
                        method: 'POST',
                        traditional:true,
                        success: function (res) {
                            if (res.code === 200){
                                tableReload(); // 重载表格
                                getOutBound(); // 重载出库口
                                layer.msg(res.msg);
                            } else if (res.code === 403){
                                top.location.href = baseUrl+"/";
                            } else {
                                layer.msg(res.msg)
                            }
                        }
                    });
                }
                break;
        }
    });
    function changeStation(){
        var floor = $('#floorSelect option:selected').val();
        $('#staNoSelect').empty();
        if(floor == 1){
            $('#staNoSelect').append("<option value=CS-101>CS-101</option>");
            $('#staNoSelect').append("<option value=CS-102>CS-102</option>")
        }
        if(floor == 3){
            $('#staNoSelect').append("<option value=CS-305>CS-305</option>");
            $('#staNoSelect').append("<option value=CS-306>CS-306</option>")
            $('#staNoSelect').append("<option value=CS-307>CS-307</option>")
        }
        form.render();
    }
    // 搜索栏搜索事件
    form.on('submit(search)', function (data) {
        pageCurr = 1;
        $('#detlTable').css("display", 'none');
        tableReload(false);
        getOutBound();
        changeStation();
    });
    // 搜索栏重置事件
    form.on('submit(reset)', function (data) {
        pageCurr = 1;
        clearFormVal($('#search-box'));
        $('#detlTable').css("display", 'none');
        tableReload(false);
        getOutBound();
    });
})
function tableReload(child) {
    var searchData = {};
    $.each($('#search-box [name]').serializeArray(), function() {
        searchData[this.name] = this.value;
    });
    (child ? parent.tableIns : tableIns).reload({
        where: searchData,
        page: {
            curr: pageCurr
        },
        done: function (res, curr, count) {
            if (res.code === 403) {
                top.location.href = baseUrl+"/";
            }
            pageCurr=curr;
            if (res.data.length === 0 && count !== 0) {
                tableIns.reload({
                    where: searchData,
                    page: {
                        curr: pageCurr-1
                    }
                });
                pageCurr -= 1;
            }
            limit(child);
        }
    });
}
src/main/webapp/static/js/agvPakStore/locCheckOut.js
New file
@@ -0,0 +1,161 @@
var locDetlLayerIdx;
var tableIns;
var form;
var locDetlData = [];
function getCol() {
    var cols = [
        {field: 'locNo', align: 'center',title: '库位号', merge: true, style: 'font-weight: bold'}
    ];
    cols.push.apply(cols, detlCols);
    return cols;
}
layui.config({
    base: baseUrl + "/static/layui/lay/modules/"
}).use(['table','laydate', 'form', 'admin', 'tableMerge'], function() {
    var table = layui.table;
    var $ = layui.jquery;
    var layer = layui.layer;
    var layDate = layui.laydate;
    form = layui.form;
    var admin = layui.admin;
    var tableMerge = layui.tableMerge;
    tableIns = table.render({
        elem: '#chooseData',
        headers: {token: localStorage.getItem('token')},
        data: [],
        even: true,
        toolbar: '#toolbar',
        cellMinWidth: 50,
        cols: [getCol()],
        done: function(res, curr, count) {
            tableMerge.render(this);
            limit();
            getOutBound();
        }
    });
    // 监听头工具栏事件
    table.on('toolbar(chooseData)', function (obj) {
        switch (obj.event) {
            case 'outbound':
                if (locDetlData.length === 0){
                    layer.msg('请先添加盘点库存', {icon: 2});
                } else {
                    var staNo = $("#staNoSelect").val();
                    if (staNo === "" || staNo === null){
                        layer.msg("请选择盘点站", {icon: 2});
                        return;
                    }
                    let param = {
                        station: staNo,
                        locDetls: locDetlData
                    }
                    $.ajax({
                        url: baseUrl+"/agv/locCheck/out/start",
                        headers: {'token': localStorage.getItem('token')},
                        data: JSON.stringify(param),
                        contentType:'application/json;charset=UTF-8',
                        method: 'POST',
                        success: function (res) {
                            if (res.code === 200){
                                locDetlData = [];
                                tableIns.reload({data: locDetlData});
                                layer.msg(res.msg, {icon: 1});
                            } else if (res.code === 403){
                                top.location.href = baseUrl+"/";
                            } else {
                                layer.msg(res.msg, {icon: 2})
                            }
                        }
                    });
                }
                break;
        }
    });
    // 获取出库口
    function getOutBound(){
        $.ajax({
            url: baseUrl+"/available/take/check/site",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            async: false,
            success: function (res) {
                if (res.code === 200){
                    var tpl = $("#takeSiteSelectTemplate").html();
                    var template = Handlebars.compile(tpl);
                    var html = template(res);
                    $('#staNoSelect').append(html);
                    form.render('select');
                } else if (res.code === 403){
                    top.location.href = baseUrl+"/";
                }else {
                    layer.msg(res.msg)
                }
            }
        })
    }
    $(document).on('click','#mat-query', function () {
        let loadIndex = layer.msg('请求中...', {icon: 16, shade: 0.01, time: false});
        locDetlLayerIdx = layer.open({
            type: 2,
            title: false,
            closeBtn: false,
            maxmin: false,
            area: ['90%', '85%'],
            shadeClose: true,
            content: 'locDetlCheckQuery.html',
            success: function(layero, index){
                layer.close(loadIndex);
            }
        });
    })
})
// 添加表格数据
function addTableData(data,floor) {
    if(locDetlData[0]){
        if(floor != locDetlData[0].locNo.split('@')[1]){
            return false;
        }
    }
    for (let i=0;i<data.length;i++){
        let pass = false;
        for (let j=0;j<locDetlData.length;j++){
            if (data[i].matnr === locDetlData[j].matnr && data[i].batch === locDetlData[j].batch && data[i].locNo === locDetlData[j].locNo) {
                pass = true;
                break;
            }
        }
        if (pass) {
            data.splice(i--, 1);
        } else {
            data[i]["count"] = data[i]["anfme"];
        }
    }
    locDetlData.push.apply(locDetlData, data);
    tableIns.reload({data: locDetlData});
    layer.close(locDetlLayerIdx);
    return true;
}
// 添加盘点站选择
function addStationData(data) {
    $('#staNoSelect').empty();
    if(data == 1){
        $('#staNoSelect').append("<option value=CS-101>CS-101</option>");
        $('#staNoSelect').append("<option value=CS-102>CS-102</option>")
    }
    if(data == 3){
        $('#staNoSelect').append("<option value=CS-305>CS-305</option>");
        $('#staNoSelect').append("<option value=CS-306>CS-306</option>")
        $('#staNoSelect').append("<option value=CS-307>CS-307</option>")
    }
    form.render();
}
src/main/webapp/static/js/agvPakStore/locMove.js
New file
@@ -0,0 +1,135 @@
var pageCurr = 0;
var tableIns;
function getCol() {
    var cols = [
        {field: 'locNo', align: 'center',title: '库位号', merge: true, style: 'font-weight: bold'}
    ];
    cols.push.apply(cols, detlCols);
    return cols;
}
layui.config({
    base: baseUrl + "/static/layui/lay/modules/"
}).use(['table','laydate', 'form', 'tableMerge'], function() {
    var table = layui.table;
    var $ = layui.jquery;
    var form = layui.form;
    var tableMerge = layui.tableMerge;
    // 数据渲染
    tableIns = table.render({
        elem: '#locMatCode',
        headers: {token: localStorage.getItem('token')},
        // url: baseUrl+'/locDetl/list/auth',
        data:[],
        page: true,
        limit: 16,
        limits: [16, 50, 100, 200, 500],
        even: true,
        cellMinWidth: 50,
        cols: [getCol()],
        request: {
            pageName: 'curr',
            pageSize: 'limit'
        },
        parseData: function (res) {
            return {
                'code': res.code,
                'msg': res.msg,
                'count': res.data.total,
                'data': res.data.records
            }
        },
        response: {
            statusCode: 200
        },
        done: function(res, curr, count) {
            tableMerge.render(this);
            if (res.code === 403) {
                top.location.href = baseUrl+"/";
            }
            pageCurr=curr;
            limit();
            clearSelect();
        }
    });
});
// 搜索库位物料
function getLoc(el) {
    tableIns.reload({
        url: baseUrl+'/agv/locDetl/list/auth'
        , where: {loc_no: el.value}
        , done:function (res) {
            limit();
            clearSelect();
            // 获取同一堆垛机的空库位
            http.post(baseUrl + "/agv/group/empty/stock", {sourceLocNo: el.value}, function (res) {
                if (res.data != null) {
                    var tpl = $("#emptyLocStock").html();
                    var template = Handlebars.compile(tpl);
                    var html = template(res);
                    $('#targetLocNo').append(html);
                    layui.form.render('select');
                }
            });
        }
    });
}
// 移库启动
function locMove() {
    var sourceLocNo = $("#sourceLocNo").val();
    var targetLocNo = $("#targetLocNo").val();
    if (sourceLocNo === null || sourceLocNo === ""){
        $("#sourceLocNo").css("border-color", "red");
        setTimeout(function () {
            $("#sourceLocNo").css("border-color", "#b8b8b8");
        }, 1000);
        layer.msg("请输入源库位");
        return;
    }
    if (targetLocNo === null || targetLocNo === "") {
        $(".layui-select-title .layui-input").css("border-color", "red");
        setTimeout(function () {
            $(".layui-select-title .layui-input").css("border-color", "#b8b8b8");
        }, 1000);
        layer.msg("请输入目标库位");
        return;
    }
    $.ajax({
        url: baseUrl + "/agv/loc/move/start",
        headers: {'token': localStorage.getItem('token')},
        dataType: 'json',
        data: {
            sourceLocNo: sourceLocNo,
            targetLocNo: targetLocNo
        },
        method: 'POST',
        success: function (res) {
            if (res.code === 200) {
                $("#sourceLocNo").val("");
                $("#targetLocNo").empty();
                layui.form.render('select');
                tableIns.reload({
                    data: [],
                    url: '',
                    done:function (res) {
                        limit();clearSelect();
                    }
                });
                layer.msg(res.msg);
            } else if (res.code === 403) {
                top.location.href = baseUrl + "/";
            } else {
                layer.msg(res.msg);
            }
        }
    })
}
function clearSelect() {
    $("#targetLocNo").empty();
    layui.form.render('select');
}
src/main/webapp/static/js/agvPakStore/pakStore.js
New file
@@ -0,0 +1,202 @@
var matCodeLayerIdx;
var initCountVal = 0;
var matCodeData = [];
function getCol() {
    var cols = [
        {fixed: 'left', field: 'anfme', title: '数量(必填)', align: 'center', edit:'text', width: 120,  style:'color: blue;font-weight: bold'},
        {field: 'batch', title: '序列码(选填)', align: 'center', edit:'text', width: 200,  style:'color: block;font-weight: bold'}
    ];
    cols.push.apply(cols, matCols);
    cols.push({fixed: 'right', title:'操作', align: 'center', toolbar: '#operate', width: 80})
    return cols;
}
layui.config({
    base: baseUrl + "/static/layui/lay/modules/"
}).use(['admin', 'table','laydate', 'form'], function() {
    var table = layui.table;
    var $ = layui.jquery;
    var layer = layui.layer;
    var form = layui.form;
    var admin = layui.admin;
    tableIns = table.render({
        elem: '#chooseData',
        data: [],
        even: true,
        limit: 500,
        cellMinWidth: 50,
        toolbar: '#toolbar',
        cols: [getCol()],
        done: function (res, curr, count) {
            limit();
            getInBound();
        }
    });
    // 页面修改
    table.on('edit(chooseData)', function (obj) {
        let index = obj.tr.attr("data-index");
        let data = matCodeData[index];
        let modify = true;
        if (obj.field === 'anfme'){
            let vle = Number(obj.value);
            if (isNaN(vle)) {
                layer.msg("请输入数字", {icon: 2});
                modify = false;
            } else {
                if (vle <= 0) {
                    layer.msg("数量必须大于零", {icon: 2});
                    modify = false;
                }
            }
        }
        if (modify) {
            data[obj.field] = obj.value;
        }
        tableIns.reload({data: matCodeData});
    });
    // 监听头工具栏事件
    table.on('toolbar(chooseData)', function (obj) {
        var checkStatus = table.checkStatus(obj.config.id);
        var data = checkStatus.data;
        switch(obj.event) {
            case 'comb':
                // 判断是否存在物料
                if (matCodeData.length === 0) {
                    layer.msg("请先提取商品", {icon: 2});
                    return;
                }
                // 判断物料数量是否存在异常
                for (var i=0;i<matCodeData.length;i++){
                    if (isNaN(matCodeData[i].anfme)) {
                        layer.msg("请输入数字", {icon: 2});
                        return;
                    }
                    if (matCodeData[i].anfme <= 0){
                        layer.msg("数量必须大于零", {icon: 2});
                        return;
                    }
                }
                let devpNo = $('#putSiteSelect').val();
                if (isEmpty(devpNo)) {
                    layer.msg("请选择入库站", {icon: 2});
                    return;
                }
                $.ajax({
                    url: baseUrl+"/full/store/put/start",
                    headers: {'token': localStorage.getItem('token')},
                    data: JSON.stringify({
                        devpNo: Number(devpNo),
                        list: matCodeData
                    }),
                    contentType:'application/json;charset=UTF-8',
                    method: 'POST',
                    async: false,
                    success: function (res) {
                        if (res.code === 200){
                            layer.msg("入库启动成功,目标库位:" + res.data, {icon: 1});
                            matCodeData = [];
                            $('#focusMatByMat').val("");
                            tableIns.reload({data: matCodeData,done:function (res) { limit(); getInBound();}});
                        } else if (res.code === 403){
                            top.location.href = baseUrl+"/";
                        }else {
                            layer.msg(res.msg, {icon: 2})
                        }
                    }
                })
                break;
            default:
                break;
        }
    });
    // 监听行工具事件
    table.on('tool(chooseData)', function(obj){
        switch (obj.event) {
            case 'remove':
                let index = obj.tr.attr("data-index");
                matCodeData.splice(index, 1);
                tableIns.reload({data: matCodeData});
                break;
        }
    });
    // 获取可用入库站点
    function getInBound() {
        $.ajax({
            url: baseUrl + "/available/put/site",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
                if (res.code === 200) {
                    var tpl = $("#putSiteSelectTemplate").html();
                    var template = Handlebars.compile(tpl);
                    var html = template(res);
                    $('#putSiteSelect').append(html);
                    form.render('select');
                } else if (res.code === 403) {
                    top.location.href = baseUrl + "/";
                } else {
                    layer.msg(res.msg, {icon: 2})
                }
            }
        })
    }
    // 提取物料
    $(document).on('click','#mat-query', function () {
        let loadIndex = layer.msg('请求中...', {icon: 16, shade: 0.01, time: false});
        matCodeLayerIdx = admin.open({
            type: 2,
            title: false,
            closeBtn: false,
            maxmin: false,
            area: ['90%', '85%'],
            shadeClose: true,
            content: 'matQuery.html',
            success: function(layero, index){
                layer.close(loadIndex);
            }
        });
    })
});
// 扫码
function focusMat(el) {
    if (isEmpty(el.value)) {
        return
    }
    $.ajax({
        url: baseUrl + "/mat/" + el.value + "/auth",
        headers: {'token': localStorage.getItem('token')},
        method: 'GET',
        success: function (res) {
            if (res.code === 200) {
                matCodeData = [];
                var param = new Array();
                param[0] = res.data;
                addTableData(param);
            } else if (res.code === 403) {
                top.location.href = baseUrl + "/";
            } else {
                layer.msg(res.msg, {icon: 2})
            }
        }
    })
}
// 添加表格数据
function addTableData(list) {
    list.map(function (d) {
        d['anfme'] = initCountVal;
    })
    matCodeData.push.apply(matCodeData, list);
    tableIns.reload({data: matCodeData});
    layer.close(matCodeLayerIdx);
}
src/main/webapp/static/js/agvPakStore/stockAdjust.js
New file
@@ -0,0 +1,241 @@
var initCountVal = 0;
var initAnfmeVal = "-";
var matCodeData = [];
var currLocNo;
var matCodeLayerIdx;
function getCol() {
    var cols = [
        {fixed: 'left', field: 'count', title: '实际数量', align: 'center', edit:'text', width: 120,  style:'color: blue;font-weight: bold'}
        ,{field: 'anfme', align: 'center',title: '数量'}
        ,{field: 'batch', align: 'center',title: '序列码(编辑)', edit: true, style: 'font-weight:bold'}
    ];
    arrRemove(detlCols, "field", "anfme");
    arrRemove(detlCols, "field", "batch");
    cols.push.apply(cols, detlCols);
    cols.push({fixed: 'right', title:'操作', align: 'center', toolbar: '#operate', width:80})
    return cols;
}
layui.config({
    base: baseUrl + "/static/layui/lay/modules/"
}).use(['table','laydate', 'form', 'admin'], function() {
    var table = layui.table;
    var $ = layui.jquery;
    var layer = layui.layer;
    var layDate = layui.laydate;
    var form = layui.form;
    var admin = layui.admin;
    tableIns = table.render({
        elem: '#chooseData',
        data: [],
        even: true,
        limit: 500,
        cellMinWidth: 50,
        toolbar: '#toolbar',
        cols: [getCol()],
        done: function (res, curr, count) {
            limit();
        }
    });
    // 页面修改
    table.on('edit(chooseData)', function (obj) {
        let index = obj.tr.attr("data-index");
        let data = matCodeData[index];
        let modify = true;
        if (obj.field === 'count'){
            let vle = Number(obj.value);
            if (isNaN(vle)) {
                layer.msg("请输入数字", {icon: 2});
                modify = false;
            } else {
                if (vle <= 0) {
                    layer.msg("数量必须大于零", {icon: 2});
                    modify = false;
                }
            }
        }
        if (modify) {
            data[obj.field] = obj.value;
        }
        tableIns.reload({data: matCodeData});
    });
    // 监听头工具栏事件
    table.on('toolbar(chooseData)', function (obj) {
        switch(obj.event) {
            case 'adjust':
                if (isEmpty(currLocNo)) {
                    layer.msg("请先检索库位", {icon: 2})
                    inputTip($("#searchLocNo"));
                    return;
                }
                if (matCodeData.length === 0) {
                    layer.msg("请先添加明细", {icon: 2});
                    return;
                }
                for (var i=0;i<matCodeData.length;i++){
                    if (isNaN(matCodeData[i].count)) {
                        layer.msg("请输入数字", {icon: 2});
                        return;
                    }
                    if (matCodeData[i].count < 0){
                        layer.msg("数量不能小于零", {icon: 2});
                        return;
                    }
                }
                layer.confirm('确定调整'+currLocNo+'库位的明细吗?', {shadeClose: true}, function(){
                    $.ajax({
                        url: baseUrl+"/locDdetl/adjust/start",
                        headers: {'token': localStorage.getItem('token')},
                        data: JSON.stringify({
                            locNo: currLocNo,
                            list: matCodeData
                        }),
                        contentType:'application/json;charset=UTF-8',
                        method: 'POST',
                        async: false,
                        success: function (res) {
                            if (res.code === 200){
                                layer.msg(currLocNo + res.msg, {icon: 1});
                                init(currLocNo)
                            } else if (res.code === 403){
                                top.location.href = baseUrl+"/";
                            }else {
                                layer.msg(res.msg, {icon: 2})
                            }
                        }
                    })
                });
                break;
        }
    });
    // 监听行工具事件
    table.on('tool(chooseData)', function(obj){
        var data = obj.data;
        switch (obj.event) {
            case 'remove':
                let index = obj.tr.attr("data-index");
                matCodeData.splice(index, 1);
                tableIns.reload({data: matCodeData});
                break;
        }
    });
    // 检索事件
    form.on('submit(search)', function (data) {
        let locNo = data.field.loc_no;
        if (locNo === "") {
            inputTip($("#searchLocNo"));
            layer.msg("请输入库位号");
            return;
        }
        init(locNo);
    });
    // 重置事件
    form.on('submit(reset)', function (data) {
        reset();
    });
    function init(locNo) {
        http.post(baseUrl + "/locDetl/list/auth", {locNo: locNo,limit: 1000}, function (res) {
            matCodeData = [];
            matCodeData = res.data.records;
            for (var i = 0; i<matCodeData.length; i++) {
                matCodeData[i]["count"] = matCodeData[i]["anfme"];
            }
            locTips(true, locNo);
            tableReload();
        })
    }
    function reset() {
        clearFormVal($('#search-box'));
        matCodeData = [];
        tableReload();
        locTips(false);
    }
    // 重载表格
    function tableReload() {
        tableIns.reload({data: matCodeData});
    }
    // 库位提示框
    function locTips(retrieve, locNo) {
        if (retrieve) {
            http.post(baseUrl+"/locMast/"+locNo+"/auth", null, function (res) {
                let data = res.data;
                if (data != null) {
                    $(".retrieve").show();
                    $("#locMsg").html(locNo + "&nbsp;,库位状态:" + data.locSts$);
                    $('.not-retrieve').hide();
                    currLocNo = locNo;
                } else {
                    layer.msg("请输入有效库位号", {icon: 2});
                    $('.not-retrieve').show();
                    $("#locMsg").html("");
                    $(".retrieve").hide();
                    currLocNo = null;
                    inputTip($("#searchLocNo"));
                }
            })
        } else {
            $('.not-retrieve').show();
            $("#locMsg").html("");
            $(".retrieve").hide();
            currLocNo = null;
        }
    }
    $(document).on('click','#mat-query', function () {
        if (isEmpty(currLocNo)) {
            layer.msg("请先检索库位")
            inputTip($("#searchLocNo"));
            return;
        }
        let loadIndex = layer.msg('请求中...', {icon: 16, shade: 0.01, time: false});
        matCodeLayerIdx = admin.open({
            type: 2,
            title: false,
            closeBtn: false,
            maxmin: false,
            area: ['90%', '85%'],
            shadeClose: true,
            content: 'matQuery.html',
            success: function(layero, index){
                layer.close(loadIndex);
            }
        });
    })
})
// 搜索框空值提示
function inputTip(el) {
    el.css("border-color", "red");
    setTimeout(function () {
        el.css("border-color", "#b8b8b8");
    }, 1000);
}
// 添加表格数据
function addTableData(data) {
    for (let i=0;i<data.length;i++){
        for (let j=0;j<matCodeData.length;j++){
            if (data[i].matnr === matCodeData[j].matnr && data[i].batch === matCodeData[j].batch) {
                data.splice(i, 1);
                break;
            } else {
                data[i]['anfme'] = initAnfmeVal;
                data[i]['count'] = initCountVal;
            }
        }
    }
    matCodeData.push.apply(matCodeData, data);
    tableIns.reload({data: matCodeData});
    layer.close(matCodeLayerIdx);
}
src/main/webapp/static/js/agvPakStore/stockOut.js
New file
@@ -0,0 +1,177 @@
var locDetlLayerIdx;
var locDetlData = [];
function getCol() {
    var cols = [
        {field: 'count', align: 'center',title: '出库数量', edit:'text', width: 130,  style:'color: blue;font-weight: bold'}
        ,{field: 'anfme', align: 'center',title: '库存数量'}
        ,{field: 'locNo$', align: 'center',title: '库位号'}
    ];
    arrRemove(detlCols,  'field', 'anfme');
    cols.push.apply(cols, detlCols);
    cols.push({fixed: 'right', title:'操作', align: 'center', toolbar: '#operate', width: 80})
    return cols;
}
layui.config({
    base: baseUrl + "/static/layui/lay/modules/"
}).use(['table','laydate', 'form', 'admin'], function() {
    var table = layui.table;
    var $ = layui.jquery;
    var layer = layui.layer;
    var form = layui.form;
    var admin = layui.admin;
    tableIns = table.render({
        elem: '#chooseData',
        headers: {token: localStorage.getItem('token')},
        data: [],
        even: true,
        toolbar: '#toolbar',
        cellMinWidth: 50,
        limit: 500,
        cols: [getCol()],
        done: function(res, curr, count) {
            limit();
            getOutBound();
        }
    });
    // 页面修改
    table.on('edit(chooseData)', function (obj) {
        let index = obj.tr.attr("data-index");
        let data = locDetlData[index];
        let modify = true;
        if (obj.field === 'count'){
            let vle = Number(obj.value);
            if (isNaN(vle)) {
                layer.msg("请输入数字", {icon: 2});
                modify = false;
            } else {
                if (vle <= 0) {
                    layer.msg("数量必须大于零", {icon: 2});
                    modify = false;
                }
                if (vle > Number(data.anfme)) {
                    layer.msg("出库数量不得大于库存数量", {icon: 2});
                    modify = false;
                }
            }
        }
        if (modify) {
            data[obj.field] = obj.value;
        }
        tableIns.reload({data: locDetlData});
    });
    // 监听头工具栏事件
    table.on('toolbar(chooseData)', function (obj) {
        switch (obj.event) {
            case 'outbound':
                if (locDetlData.length === 0){
                    layer.msg('请先提取商品库存', {icon: 2});
                } else {
                    var staNo = $("#staNoSelect").val();
                    if (staNo === "" || staNo === null){
                        layer.msg("请选择出库口", {icon: 2});
                        return;
                    }
                    let param = {
                        outSite: staNo,
                        locDetls: locDetlData
                    }
                    $.ajax({
                        url: baseUrl+"/plate/out/start",
                        headers: {'token': localStorage.getItem('token')},
                        data: JSON.stringify(param),
                        contentType:'application/json;charset=UTF-8',
                        method: 'POST',
                        success: function (res) {
                            if (res.code === 200){
                                locDetlData = [];
                                tableIns.reload({data: locDetlData,done:function (res) {limit();getOutBound();}});
                                layer.msg(res.msg, {icon: 1});
                            } else if (res.code === 403){
                                top.location.href = baseUrl+"/";
                            } else {
                                layer.msg(res.msg, {icon: 2})
                            }
                        }
                    });
                }
                break;
        }
    });
    // 监听行工具事件
    table.on('tool(chooseData)', function(obj){
        switch (obj.event) {
            case 'remove':
                let index = obj.tr.attr("data-index");
                locDetlData.splice(index, 1);
                tableIns.reload({data: locDetlData});
                break;
        }
    });
    // 获取出库口
    function getOutBound(){
        $.ajax({
            url: baseUrl+"/available/take/site",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            async: false,
            success: function (res) {
                if (res.code === 200){
                    var tpl = $("#takeSiteSelectTemplate").html();
                    var template = Handlebars.compile(tpl);
                    var html = template(res);
                    $('#staNoSelect').append(html);
                    form.render('select');
                } else if (res.code === 403){
                    top.location.href = baseUrl+"/";
                }else {
                    layer.msg(res.msg)
                }
            }
        })
    }
    $(document).on('click','#mat-query', function () {
        let loadIndex = layer.msg('请求中...', {icon: 16, shade: 0.01, time: false});
        locDetlLayerIdx = layer.open({
            type: 2,
            title: false,
            closeBtn: false,
            maxmin: false,
            area: ['90%', '85%'],
            shadeClose: true,
            content: 'locDetlQuery.html',
            success: function(layero, index){
                layer.close(loadIndex);
            }
        });
    })
})
// 添加表格数据
function addTableData(data) {
    for (var i=0;i<data.length;i++){
        let pass = false;
        for (var j=0;j<locDetlData.length;j++){
            if (data[i].matnr === locDetlData[j].matnr && data[i].batch === locDetlData[j].batch && data[i].locNo$ === locDetlData[j].locNo$) {
                pass = true;
                break;
            }
        }
        if (pass) {
            data.splice(i--, 1);
        } else {
            data[i]["count"] = data[i]["anfme"];
        }
    }
    locDetlData.push.apply(locDetlData, data);
    tableIns.reload({data: locDetlData});
    layer.close(locDetlLayerIdx);
}
src/main/webapp/static/js/allLocDetl/locDetl.js
New file
@@ -0,0 +1,601 @@
var pageCurr;
var tableData;
function getCol() {
    var cols = [
        {field: 'locNo', align: 'center',title: '库位号'},
        {field: 'matnr', align: 'center',title: '物料号', sort:true}
        ,{field: 'maktx', align: 'center',title: '物料名称', sort:true}
        ,{field: 'orderNo', align: 'center',title: '单据编号', hide: false}
        ,{field: 'batch', align: 'center',title: '序列码', width: 300, sort:true}
        ,{field: 'anfme', align: 'center',title: '数量'}
        ,{field: 'zpallet', align: 'center',title: '托盘条码'}
        ,{field: 'specs', align: 'center',title: '规格'}
        ,{field: 'model', align: 'center',title: '通用型号', hide: true}
        ,{field: 'color', align: 'center',title: '颜色', hide: true}
        ,{field: 'brand', align: 'center',title: '品牌', hide: true}
        ,{field: 'unit', align: 'center',title: '单位', hide: true}
        ,{field: 'price', align: 'center',title: '单价', hide: true}
        ,{field: 'sku', align: 'center',title: 'sku', hide: true}
        ,{field: 'units', align: 'center',title: '包数', hide: true}
        ,{field: 'barcode', align: 'center',title: '条码', hide: true}
        ,{field: 'origin', align: 'center',title: '物料状态', hide: true}
        ,{field: 'manu', align: 'center',title: '厂家', hide: true}
        ,{field: 'manuDate', align: 'center',title: '单据时间', hide: true}
        ,{field: 'itemNum', align: 'center',title: '品项数', hide: true}
        ,{field: 'safeQty', align: 'center',title: '安全库存量', hide: true}
        ,{field: 'weight', align: 'center',title: '单箱净重', hide: true}
        ,{field: 'length', align: 'center',title: '单箱毛重', hide: true}
        ,{field: 'volume', align: 'center',title: '单箱体积', hide: true}
        ,{field: 'threeCode', align: 'center',title: '箱子尺寸', hide: true}
        ,{field: 'supp', align: 'center',title: '供应商', hide: true}
        ,{field: 'suppCode', align: 'center',title: '供应商编码', hide: true}
        ,{field: 'beBatch$', align: 'center',title: '是否批次', hide: true}
        ,{field: 'deadTime', align: 'center',title: '保质期', hide: true}
        ,{field: 'deadWarn', align: 'center',title: '预警天数', hide: true}
        ,{field: 'source$', align: 'center',title: '制购', hide: true}
        ,{field: 'check$', align: 'center',title: '要求检验', hide: true}
        ,{field: 'danger$', align: 'center',title: '危险品', hide: true}
    ];
    // cols.push.apply(cols, detlCols);
    cols.push({field: 'modiUser$', align: 'center',title: '修改人员',hide: true}
        ,{field: 'modiTime$', align: 'center',title: '修改时间'}
        ,{field: 'stockFreeze', align: 'center',title: '库存冻结', templet: '#stockFreezeTpl'}
    )
    return cols;
}
layui.use(['table','laydate', 'form'], function(){
    var table = layui.table;
    var $ = layui.jquery;
    var layer = layui.layer;
    var layDate = layui.laydate;
    var form = layui.form;
    // 数据渲染
    tableIns = table.render({
        elem: '#locDetl',
        headers: {token: localStorage.getItem('token')},
        url: baseUrl+'/all/locDetl/list/auth',
        page: true,
        limit: 20,
        where:{
          unreason: false
        },
        limits: [20, 30, 50, 100, 200, 500],
        even: true,
        toolbar: '#toolbar',
        cellMinWidth: 50,
        cols: [getCol()],
        request: {
            pageName: 'curr',
            pageSize: 'limit'
        },
        parseData: function (res) {
            return {
                'code': res.code,
                'msg': res.msg,
                'count': res.data.total,
                'data': res.data.records
            }
        },
        response: {
            statusCode: 200
        },
        done: function(res, curr, count) {
            if (res.code === 403) {
                top.location.href = baseUrl+"/";
            }
            tableData = table.cache.locDetl;
            pageCurr=curr;
            limit();
            form.on('checkbox(tableCheckbox)', function (data) {
                var _index = $(data.elem).attr('table-index')||0;
                if(data.elem.checked){
                    res.data[_index][data.value] = 'Y';
                }else{
                    res.data[_index][data.value] = 'N';
                }
            });
        }
    });
    // 监听排序事件
    table.on('sort(locDetl)', function (obj) {
        var searchData = {};
        $.each($('#search-box [name]').serializeArray(), function() {
            searchData[this.name] = this.value;
        });
        searchData['orderByField'] = obj.field;
        searchData['orderByType'] = obj.type;
        tableIns.reload({
            where: searchData,
            page: {
                curr: 1
            },
            done: function (res, curr, count) {
                if (res.code === 403) {
                    top.location.href = baseUrl+"/";
                }
                pageCurr=curr;
                limit();
            }
        });
    });
    // 监听头工具栏事件
    table.on('toolbar(locDetl)', function (obj) {
        var checkStatus = table.checkStatus(obj.config.id);
        switch(obj.event) {
            case 'addData':
                layer.open({
                    type: 2,
                    title: '新增',
                    maxmin: true,
                    area: [top.detailWidth, top.detailHeight],
                    shadeClose: false,
                    content: 'locDetl_detail.html',
                    success: function(layero, index){
                        layer.getChildFrame('#data-detail-submit-edit', index).hide();
                        clearFormVal(layer.getChildFrame('#detail', index));
                        layer.iframeAuto(index);layer.style(index, {top: (($(window).height()-layer.getChildFrame('#data-detail', index).height())/3)+"px"});
                    }
                });
                break;
            case 'refreshData':
                tableIns.reload({
                    page: {
                        curr: pageCurr
                    }
                });
                limit();
                break;
            case 'deleteData':
                var data = checkStatus.data;
                if (data.length === 0){
                    layer.msg('请选择数据');
                } else {
                    layer.confirm('确定删除'+(data.length===1?'此':data.length)+'条数据吗', function(){
                        $.ajax({
                            url: baseUrl+"/all/locDetl/delete/auth",
                            headers: {'token': localStorage.getItem('token')},
                            data: {param: JSON.stringify(data)},
                            method: 'POST',
                            traditional:true,
                            success: function (res) {
                                if (res.code === 200){
                                    layer.closeAll();
                                    tableReload(false);
                                } else if (res.code === 403){
                                    top.location.href = baseUrl+"/";
                                } else {
                                    layer.msg(res.msg)
                                }
                            }
                        })
                    });
                }
                break;
            case 'exportData':
                layer.confirm('确定导出Excel吗', {shadeClose: true}, function(){
                    var titles=[];
                    var fields=[];
                    obj.config.cols[0].map(function (col) {
                        if (col.type === 'normal' && col.hide === false && col.toolbar == null) {
                            titles.push(col.title);
                            fields.push(col.field);
                        }
                    });
                    var exportData = {};
                    $.each($('#search-box [name]').serializeArray(), function() {
                        exportData[this.name] = this.value;
                    });
                    var param = {
                        'locDetl': exportData,
                        'fields': fields
                    };
                    var loadIndex = layer.msg('正在导出...', {icon: 16, shade: 0.01, time: false});
                    $.ajax({
                        url: baseUrl+"/all/locDetl/export/auth",
                        headers: {'token': localStorage.getItem('token')},
                        data: JSON.stringify(param),
                        dataType:'json',
                        contentType:'application/json;charset=UTF-8',
                        method: 'POST',
                        success: function (res) {
                            layer.close(loadIndex);
                            layer.closeAll();
                            if (res.code === 200) {
                                table.exportFile(titles,res.data,'xls');
                            } else if (res.code === 403) {
                                top.location.href = baseUrl+"/";
                            } else {
                                layer.msg(res.msg)
                            }
                        }
                    });
                });
                break;
        }
    });
    // 监听行工具事件
    table.on('tool(locDetl)', function(obj){
        var data = obj.data;
        switch (obj.event) {
            // 详情
            case 'detail':
                layer.open({
                    type: 2,
                    title: '详情',
                    maxmin: true,
                    area: [top.detailWidth, top.detailHeight],
                    shadeClose: false,
                    content: 'locDetl_detail.html',
                    success: function(layero, index){
                        setFormVal(layer.getChildFrame('#detail', index), data, true);
                        top.convertDisabled(layer.getChildFrame('#data-detail :input', index), true);
                        layer.getChildFrame('#data-detail-submit-save,#data-detail-submit-edit,#prompt', index).hide();
                        layer.iframeAuto(index);layer.style(index, {top: (($(window).height()-layer.getChildFrame('#data-detail', index).height())/3)+"px"});
                        layero.find('iframe')[0].contentWindow.layui.form.render('select');
                        layero.find('iframe')[0].contentWindow.layui.form.render('checkbox');
                    }
                });
                break;
            // 编辑
            case 'edit':
                layer.open({
                    type: 2,
                    title: '修改',
                    maxmin: true,
                    area: [top.detailWidth, top.detailHeight],
                    shadeClose: false,
                    content: 'locDetl_detail.html',
                    success: function(layero, index){
                        layer.getChildFrame('#data-detail-submit-save', index).hide();
                        setFormVal(layer.getChildFrame('#detail', index), data, false);
                        top.convertDisabled(layer.getChildFrame('#data-detail :input', index), false);
                        top.convertDisabled(layer.getChildFrame('#locNo,#matnr', index), true);
                        layer.iframeAuto(index);layer.style(index, {top: (($(window).height()-layer.getChildFrame('#data-detail', index).height())/3)+"px"});
                        layero.find('iframe')[0].contentWindow.layui.form.render('select');
                        layero.find('iframe')[0].contentWindow.layui.form.render('checkbox');
                    }
                });
                break;
            case 'locNo':
                var param = top.reObject(data).locNo;
                if (param === undefined) {
                    layer.msg("无数据");
                } else {
                   layer.open({
                       type: 2,
                       title: '库位号详情',
                       maxmin: true,
                       area: [top.detailWidth, top.detailHeight],
                       shadeClose: false,
                       content: '../locMast/locMast_detail.html',
                       success: function(layero, index){
                           $.ajax({
                               url: baseUrl+"/all/locMast/"+ param +"/auth",
                               headers: {'token': localStorage.getItem('token')},
                               method: 'GET',
                               success: function (res) {
                                   if (res.code === 200){
                                       setFormVal(layer.getChildFrame('#detail', index), res.data, true);
                                       top.convertDisabled(layer.getChildFrame('#data-detail :input', index), true);
                                       layer.getChildFrame('#data-detail-submit-save,#data-detail-submit-edit,#prompt', index).hide();
                                       layer.iframeAuto(index);layer.style(index, {top: (($(window).height()-layer.getChildFrame('#data-detail', index).height())/3)+"px"});
                                       layero.find('iframe')[0].contentWindow.layui.form.render('select');
                                       layero.find('iframe')[0].contentWindow.layui.form.render('checkbox');
                                   } else if (res.code === 403){
                                       parent.location.href = "/";
                                   }else {
                                       layer.msg(res.msg)
                                   }
                               }
                           })
                       }
                   });
                }
                break;
            case 'modiUser':
                var param = top.reObject(data).modiUser;
                if (param === undefined) {
                    layer.msg("无数据");
                } else {
                   layer.open({
                       type: 2,
                       title: '修改人员详情',
                       maxmin: true,
                       area: [top.detailWidth, top.detailHeight],
                       shadeClose: false,
                       content: '../user/user_detail.html',
                       success: function(layero, index){
                           $.ajax({
                               url: baseUrl+"/user/"+ param +"/auth",
                               headers: {'token': localStorage.getItem('token')},
                               method: 'GET',
                               success: function (res) {
                                   if (res.code === 200){
                                       setFormVal(layer.getChildFrame('#detail', index), res.data, true);
                                       top.convertDisabled(layer.getChildFrame('#data-detail :input', index), true);
                                       layer.getChildFrame('#data-detail-submit-save,#data-detail-submit-edit,#prompt', index).hide();
                                       layer.iframeAuto(index);layer.style(index, {top: (($(window).height()-layer.getChildFrame('#data-detail', index).height())/3)+"px"});
                                       layero.find('iframe')[0].contentWindow.layui.form.render('select');
                                       layero.find('iframe')[0].contentWindow.layui.form.render('checkbox');
                                   } else if (res.code === 403){
                                       parent.location.href = "/";
                                   }else {
                                       layer.msg(res.msg)
                                   }
                               }
                           })
                       }
                   });
                }
                break;
            case 'appeUser':
                var param = top.reObject(data).appeUser;
                if (param === undefined) {
                    layer.msg("无数据");
                } else {
                   layer.open({
                       type: 2,
                       title: '创建者详情',
                       maxmin: true,
                       area: [top.detailWidth, top.detailHeight],
                       shadeClose: false,
                       content: '../user/user_detail.html',
                       success: function(layero, index){
                           $.ajax({
                               url: baseUrl+"/user/"+ param +"/auth",
                               headers: {'token': localStorage.getItem('token')},
                               method: 'GET',
                               success: function (res) {
                                   if (res.code === 200){
                                       setFormVal(layer.getChildFrame('#detail', index), res.data, true);
                                       top.convertDisabled(layer.getChildFrame('#data-detail :input', index), true);
                                       layer.getChildFrame('#data-detail-submit-save,#data-detail-submit-edit,#prompt', index).hide();
                                       layer.iframeAuto(index);layer.style(index, {top: (($(window).height()-layer.getChildFrame('#data-detail', index).height())/3)+"px"});
                                       layero.find('iframe')[0].contentWindow.layui.form.render('select');
                                       layero.find('iframe')[0].contentWindow.layui.form.render('checkbox');
                                   } else if (res.code === 403){
                                       parent.location.href = "/";
                                   }else {
                                       layer.msg(res.msg)
                                   }
                               }
                           })
                       }
                   });
                }
                break;
        }
    });
    // 数据保存动作
    form.on('submit(save)', function () {
        if (banMsg != null){
            layer.msg(banMsg);
            return;
        }
        method("add");
    });
    // 数据修改动作
    form.on('submit(edit)', function () {
        method("update")
    });
    function method(name){
        var index = layer.load(1, {
            shade: [0.5,'#000'] //0.1透明度的背景
        });
        var data = {
//            id: $('#id').val(),
            locNo: $('#locNo').val(),
            matnr: $('#matnr').val(),
            lgnum: $('#lgnum').val(),
            tbnum: $('#tbnum').val(),
            tbpos: $('#tbpos').val(),
            zmatid: $('#zmatid').val(),
            maktx: $('#maktx').val(),
            werks: $('#werks').val(),
            anfme: $('#anfme').val(),
            altme: $('#altme').val(),
            zpallet: $('#zpallet').val(),
            bname: $('#bname').val(),
            memo: $('#memo').val(),
            modiUser: $('#modiUser').val(),
            modiTime: top.strToDate($('#modiTime\\$').val()),
            appeUser: $('#appeUser').val(),
            appeTime: top.strToDate($('#appeTime\\$').val()),
        };
        $.ajax({
            url: baseUrl+"/all/locDetl/"+name+"/auth",
            headers: {'token': localStorage.getItem('token')},
            data: top.reObject(data),
            method: 'POST',
            success: function (res) {
                if (res.code === 200){
                    parent.layer.closeAll();
                    parent.$(".layui-laypage-btn")[0].click();
                    $("#data-detail :input").each(function () {
                        $(this).val("");
                    });
                } else if (res.code === 403){
                    top.location.href = baseUrl+"/";
                }else {
                    layer.msg(res.msg)
                }
                layer.close(index);
            }
        })
    }
    // 复选框事件
    form.on('checkbox(detailCheckbox)', function (data) {
        var el = data.elem;
        if (el.checked) {
            $(el).val('Y');
        } else {
            $(el).val('N');
        }
    });
    // 搜索栏搜索事件
    form.on('submit(search)', function (data) {
        pageCurr = 1;
        tableReload(false);
    });
    // 搜索栏重置事件
    form.on('submit(reset)', function (data) {
        pageCurr = 1;
        clearFormVal($('#search-box'));
        tableReload(false);
    });
    //查看异常数据
    form.on('submit(unreason)', function (data) {
        pageCurr = 1;
        tableIns.reload({
            where: {
                unreason: true
            },
            page: {
                curr: pageCurr
            },
            done: function (res, curr, count) {
                if (res.code === 403) {
                    top.location.href = baseUrl+"/";
                }
                pageCurr=curr;
                limit(child);
            }
        });
    });
    // 时间选择器
    layDate.render({
        elem: '#modiTime\\$',
        type: 'datetime'
    });
    layDate.render({
        elem: '#appeTime\\$',
        type: 'datetime'
    });
    form.on('switch(stockFreezeSwitch)', function (obj) {
        let index  = obj.othis.parents('tr').attr("data-index");
        let data = tableData[index];
        data[this.stockFreeze] = obj.elem.checked?1:0;
        http.post(baseUrl + "/all/locDetl/updateStockFreeze/auth", {
            locNo: data.locNo,
            matnr: data.matnr,
            stockFreeze: data[this.stockFreeze]
        }, function (res) {
            layer.msg(res.msg, {icon: 1});
        });
    })
});
// 关闭动作
$(document).on('click','#data-detail-close', function () {
    parent.layer.closeAll();
});
function tableReload(child) {
    var searchData = {
        unreason: false
    };
    $.each($('#search-box [name]').serializeArray(), function() {
        searchData[this.name] = this.value;
    });
    (child ? parent.tableIns : tableIns).reload({
        where: searchData,
        page: {
            curr: pageCurr
        },
        done: function (res, curr, count) {
            if (res.code === 403) {
                top.location.href = baseUrl+"/";
            }
            pageCurr=curr;
            if (res.data.length === 0 && count !== 0) {
                tableIns.reload({
                    where: searchData,
                    page: {
                        curr: pageCurr-1
                    }
                });
                pageCurr -= 1;
            }
            limit(child);
        }
    });
}
function setFormVal(el, data, showImg) {
    for (var val in data) {
        var find = el.find(":input[id='" + val + "']");
        if (find[0]!=null){
            if (find[0].type === 'checkbox'){
                if (data[val]==='Y'){
                    find.attr("checked","checked");
                    find.val('Y');
                } else {
                    find.remove("checked");
                    find.val('N');
                }
                continue;
            }
        }
        find.val(data[val]);
        if (showImg){
            var next = find.next();
            if (next.get(0)){
                if (next.get(0).localName === "img") {
                    find.hide();
                    next.attr("src", data[val]);
                    next.show();
                }
            }
        }
    }
}
function clearFormVal(el) {
    $(':input', el)
        .val('')
        .removeAttr('checked')
        .removeAttr('selected');
}
function detailScreen(index) {
    var detail = layer.getChildFrame('#data-detail', index);
    var height = detail.height()+60;
    if (height > ($(window).height()*0.9)) {
        height = ($(window).height()*0.8);
    }
    layer.style(index, {
//        top: (($(window).height()-height)/3)+"px",
        height: height+'px'
    });
}
$('body').keydown(function () {
    if (event.keyCode === 13) {
        $("#search").click();
    }
});
src/main/webapp/static/js/common.js
@@ -222,6 +222,7 @@
var detlCols = [
    ,{field: 'zpallet', align: 'center',title: '托盘条码', hide: true}
    ,{field: 'zpallet', align: 'center',title: '托盘条码', hide: false}
    ,{field: 'matnr', align: 'center',title: '物料号',hide: true}
    ,{field: 'matnr', align: 'center',title: '物料号'}
    ,{field: 'batch', align: 'center',title: '序列码', width: 300, sort:true, hide: false}
    ,{field: 'maktx', align: 'center',title: '物料名称'}
src/main/webapp/views/agvBasDevp/basDevpWaitPakinDetail.html
@@ -70,6 +70,12 @@
                pageSize: 'limit'
            },
            parseData: function (res) {
                if(!res.data){
                    return {
                        'code': res.code,
                        'msg': res.msg,
                    }
                }
                return {
                    'code': res.code,
                    'msg': res.msg,
src/main/webapp/views/agvBasDevpVisualized/basDevp.html
@@ -61,15 +61,16 @@
<!--                        <button type="button" class="layui-btn layui-btn-normal" value="{{devNo}}">拣料入库</button>-->
<!--                    </div>-->
                    {{#if agvWrkDetl}}
                    {{#if containerMoveOutFlag}}
                    <div style=" padding-bottom: 20px">
                        <button type="button" class="layui-btn layui-btn-normal" value="{{devNo}}" lay-submit lay-filter="containerMoveOut">容器离场</button>
                        <button type="button" class="layui-btn layui-btn-normal" value="{{devNo}}" lay-submit lay-filter="pickIn">拣料入库</button>
                    </div>
                    {{/if}}
                    {{#if pickInFlag}}
                    <div style=" padding-bottom: 20px">
                        <button type="button" class="layui-btn layui-btn-normal" value="{{devNo}}" lay-submit lay-filter="pickIn">拣料/盘点入库</button>
                    </div>
                    {{/if}}
                    <div>
                        工作站编码:{{devNo}} </br>
                        站点状态:{{locSts$}}
@@ -204,7 +205,7 @@
        });
        //拣料入库
        //拣料/盘点入库
        form.on('submit(pickIn)', function () {
            var devNoList = [];
            devNoList.push(this.value);
src/main/webapp/views/agvLocDetlStatis/locDetlStatis.html
New file
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
</head>
<body>
<!-- 搜索栏 -->
<div id="search-box" class="layui-form layui-card-header">
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="matnr" placeholder="物料号" autocomplete="off">
        </div>
    </div>
    <!-- 待添加 -->
    <div id="data-search-btn" class="layui-btn-container layui-form-item" style="display: inline-block">
        <button id="search" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="search">搜索
        </button>
        <button id="reset" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="reset">重置
        </button>
    </div>
    <div class="layui-inline">
        <fieldset class="layui-elem-field">
            <legend>总计数量</legend>
            <div class="layui-field-box" id="countNum">
                请稍等
            </div>
        </fieldset>
    </div>
</div>
<!-- 表格 -->
<div class="layui-form">
    <table class="layui-hide" id="locDetlStatis" lay-filter="locDetlStatis"></table>
</div>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container layui-col-md1">
        <button class="layui-btn" lay-event="exportAll" style="margin-top: -0px">导出全部</button>
    </div>
</script>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/agvLocDetlStatis/locDetlStatis.js" charset="utf-8"></script>
</body>
</html>
src/main/webapp/views/agvPakStore/emptyIn.html
New file
@@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        html {
            height: 100%;
            padding: 10px;
            background-color: #f1f1f1;
            box-sizing: border-box;
        }
        body {
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 0 3px rgba(0,0,0,.3);
        }
        .function-area {
            padding: 50px 80px;
        }
        .layui-form-label {
            width: 120px;
        }
        .function-area .layui-form {
            width: 300px;
        }
        #btn-inbound {
            display: none;
        }
    </style>
</head>
<body>
<!-- 功能区 -->
<div class="function-area">
    <div class="layui-form layui-form-pane">
        <div class="layui-form-item" style="margin-bottom: 30px">
            <label class="layui-form-label" style="">空板入库口</label>
            <div class="layui-input-block">
                <select id="inSiteSelect" lay-verify="required" lay-search="">
                    <option value="">请选择站点</option>
                </select>
            </div>
        </div>
        <hr style="margin-top: 10px">
        <div style="text-align: left; margin-top: 30px">
            <button class="layui-btn layui-btn-lg layui-btn-radius layui-btn-normal" id="btn-inbound" lay-submit lay-filter="inbound">启动入库</button>
        </div>
    </div>
</div>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
<script type="text/javascript" src="../../static/js/agvPakStore/emptyIn.js" charset="utf-8"></script>
<script type="text/template" id="putSiteSelectTemplate">
    {{#each data}}
    <option value="{{this}}">{{this}}</option>
    {{/each}}
</script>
</body>
</html>
src/main/webapp/views/agvPakStore/emptyOut.html
New file
@@ -0,0 +1,150 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        html {
            height: 100%;
            padding: 10px;
            background-color: #f1f1f1;
            box-sizing: border-box;
        }
        body {
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 0 3px rgba(0,0,0,.3);
            padding-bottom: 20px;
        }
        #search-box {
            padding: 30px 0 20px 0;
        }
        #search-box .layui-inline:first-child {
            margin-left: 30px;
        }
        #search-box .layui-inline {
            margin-right: 5px;
        }
        #data-search-btn {
            margin-left: 10px;
            display: inline-block;
        }
        #data-search-btn.layui-btn-container .layui-btn {
            margin-right: 20px;
        }
        #staNoSpan {
            text-align: center;
            display: inline-block;
            width: 100px;
            font-size: 13px;
        }
        .layui-btn-container .layui-form-select {
            display: inline-block;
            width: 150px;
            height: 30px;
        }
        .layui-btn-container .layui-form-select.layui-form-selected {
            display: inline-block;
            width: 150px;
        }
        .layui-btn-container .layui-select-title input {
            font-size: 13px;
        }
        .layui-btn-container .layui-anim.layui-anim-upbit dd {
            font-size: 13px;
        }
        #btn-outbound {
            margin-left: 60px;
            display: none;
        }
    </style>
</head>
<body>
<!-- 搜索栏 -->
<div id="search-box" class="layui-form layui-card-header">
    <div class="layui-inline">
        <div class="layui-input-inline">
            <select id="floorSelect" name="floor" lay-filter="floorSelect">
                <option value="1">1楼</option>
                <option value="3">3楼</option>
            </select>
        </div>
    </div>
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="loc_no" placeholder="库位号" autocomplete="off">
        </div>
    </div>
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="row1" placeholder="排" lay-verify="number"  autocomplete="off">
        </div>
    </div>
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="bay1" placeholder="列" lay-verify="number" autocomplete="off">
        </div>
    </div>
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="lev1" placeholder="层" lay-verify="number" autocomplete="off">
        </div>
    </div>
    <!-- 待添加 -->
    <div id="data-search-btn" class="layui-btn-container layui-form-item" style="display: inline-block">
        <button id="search" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="search">搜索</button>
        <button id="reset" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="reset">重置</button>
    </div>
</div>
<script type="text/html" id="toolbar">
    <div class="layui-form">
        <div class="layui-btn-container">
            <!-- 1.选择出库口 -->
            <span id="staNoSpan">空板出库口:</span>
            <select id="staNoSelect" lay-verify="required">
                <option value="CS-101">CS-101</option>
                <option value="CS-102">CS-102</option>
            </select>
            <!-- 2.启动出库 -->
            <button class="layui-btn layui-btn-lg" id="btn-outbound" lay-event="outbound">启动出库</button>
        </div>
    </div>
</script>
<!-- 空板库位表 -->
<table class="layui-hide" id="locMast" lay-filter="locMast"></table>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
<script type="text/javascript" src="../../static/js/agvPakStore/emptyOut.js" charset="utf-8"></script>
<!--启动出库-->
<div id="outboundDiv">
</div>
<script type="text/template" id="takeSiteSelectTemplate">
    {{#each data}}
    <option value="{{this}}">{{this}}</option>
    {{/each}}
</script>
</body>
</html>
src/main/webapp/views/agvPakStore/locCheckOut.html
New file
@@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        html {
            height: 100%;
            padding: 10px;
            background-color: #f1f1f1;
            box-sizing: border-box;
        }
        body {
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 0 3px rgba(0,0,0,.3);
        }
        #staNoSpan {
            text-align: center;
            display: inline-block;
            width: 100px;
            font-size: 13px;
        }
        .layui-btn-container .layui-form-select {
            display: inline-block;
            width: 150px;
            height: 30px;
        }
        .layui-btn-container .layui-form-select.layui-form-selected {
            display: inline-block;
            width: 150px;
        }
        .layui-btn-container .layui-select-title input {
            font-size: 13px;
        }
        .layui-btn-container .layui-anim.layui-anim-upbit dd {
            font-size: 13px;
        }
        #btn-outbound {
            margin-left: 60px;
        }
        /*----------------------------------*/
        .function-area {
            padding: 20px 50px;
        }
        .function-btn {
            font-size: 16px;
            padding: 1px 2px;
            width: 100px;
            height: 50px;
            border-color: #2b425b;
            border-radius: 4px;
            border-width: 2px;
            background: none;
            border-style: solid;
            transition: 0.4s;
            cursor: pointer;
            letter-spacing: 1.5px;
        }
        .function-btn:hover {
            background-color: #2b425b;
            color: #fff;
        }
        #mat-query {
            display: none;
        }
        #btn-outbound {
            display: none;
        }
    </style>
</head>
<body style="padding-bottom: 30px">
<!-- 功能区 -->
<div class="function-area">
    <button id="mat-query" class="function-btn">提取库存</button>
</div>
<hr>
<!-- 表格 -->
<div style="padding-bottom: 5px; margin-bottom: 45px">
    <!-- 头部 -->
    <script type="text/html" id="toolbar">
        <div class="layui-form">
            <div class="layui-btn-container">
                <!-- 1.选择出库口 -->
                <span id="staNoSpan">盘点站:</span>
                <select id="staNoSelect" lay-verify="required">
                    <option value="">请选择站点</option>
                </select>
                <!-- 2.启动出库 -->
                <button class="layui-btn layui-btn-lg" id="btn-outbound" lay-event="outbound">盘点出库</button>
            </div>
        </div>
    </script>
    <!-- 行 -->
    <script type="text/html" id="operate">
        <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="remove">移除</a>
    </script>
    <table class="layui-table" id="chooseData" lay-filter="chooseData"></table>
</div>
<script type="text/template" id="takeSiteSelectTemplate">
    {{#each data}}
    <option value="{{this}}">{{this}}</option>
    {{/each}}
</script>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
<script type="text/javascript" src="../../static/js/agvPakStore/locCheckOut.js" charset="utf-8"></script>
</body>
</html>
src/main/webapp/views/agvPakStore/locDetlCheckQuery.html
New file
@@ -0,0 +1,230 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        body {
            padding: 0 20px;
        }
        .layui-table-box {
            border-right: 1px solid #9F9F9F;
            border-left: 1px solid #9F9F9F;
        }
        #search-box {
            padding: 30px 0 20px 0;
        }
        #search-box .layui-inline:first-child {
            margin-left: 30px;
        }
        #search-box .layui-inline {
            margin-right: 5px;
        }
        #data-search-btn {
            margin-left: 10px;
            display: inline-block;
        }
        #data-search-btn.layui-btn-container .layui-btn {
            margin-right: 20px;
        }
    </style>
</head>
<body>
<!-- 搜索栏 -->
<fieldset class="layui-elem-field site-demo-button" style="margin: 20px;">
    <legend>搜索栏</legend>
    <!-- 搜索栏 -->
    <div id="search-box" class="layui-form layui-card-header">
        <div class="layui-inline">
            <div class="layui-input-inline">
                <input class="layui-input" type="text" name="loc_no" placeholder="库位号" autocomplete="off">
            </div>
        </div>
        <div class="layui-inline">
            <div class="layui-input-inline">
                <input class="layui-input" type="text" name="matnr" placeholder="物料号"  autocomplete="off">
            </div>
        </div>
        <div class="layui-inline">
            <div class="layui-input-inline">
                <input class="layui-input" type="text" name="maktx" placeholder="物料描述" autocomplete="off">
            </div>
        </div>
        <!-- 日期范围 -->
        <div class="layui-inline" style="width: 300px">
            <div class="layui-input-inline">
                <input class="layui-input layui-laydate-range" name="modi_time" type="text" placeholder="起始时间 - 终止时间" autocomplete="off" style="width: 300px">
            </div>
        </div>
        <!-- 待添加 -->
        <div id="data-search-btn" class="layui-btn-container layui-form-item" style="display: inline-block">
            <button id="search" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="search">搜索</button>
            <button id="reset" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="reset">重置</button>
        </div>
    </div>
</fieldset>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
        <button class="layui-btn" id="btn-confirm" lay-event="confirm" style="">提取</button>
    </div>
</script>
<div class="layui-form">
    <table class="layui-hide" id="stockOut" lay-filter="stockOut"></table>
</div>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
</body>
<script>
    function getCol() {
        let cols = [
            {type: 'checkbox', merge: ['locNo']}
            ,{field: 'locNo', align: 'center',title: '库位号', merge: true, width:150, style: 'font-weight: bold'}
        ];
        cols.push.apply(cols, detlCols);
        cols.push({field: 'modiUser$', align: 'center',title: '修改人员', hide: true}
            ,{field: 'modiTime$', align: 'center',title: '修改时间'})
        return cols;
    }
    layui.config({
        base: baseUrl + "/static/layui/lay/modules/"
    }).use(['table','laydate', 'form', 'admin', 'tableMerge'], function() {
        var table = layui.table;
        var $ = layui.jquery;
        var layer = layui.layer;
        var layDate = layui.laydate;
        var form = layui.form;
        var admin = layui.admin;
        var tableMerge = layui.tableMerge;
        // 数据渲染
        locDetlTableIns = table.render({
            elem: '#stockOut',
            headers: {token: localStorage.getItem('token')},
            url: baseUrl+'/agv/stock/out/list/auth',
            page: true,
            limit: 20,
            limits: [20, 50, 100, 200, 500],
            even: true,
            toolbar: '#toolbar',
            cellMinWidth: 50,
            cols: [getCol()],
            request: {
                pageName: 'curr',
                pageSize: 'limit'
            },
            parseData: function (res) {
                return {
                    'code': res.code,
                    'msg': res.msg,
                    'count': res.data.total,
                    'data': res.data.records
                }
            },
            response: {
                statusCode: 200
            },
            done: function(res, curr, count) {
                tableMerge.render(this);
                if (res.code === 403) {
                    top.location.href = baseUrl+"/";
                }
            }
        });
        // 监听头工具栏事件
        table.on('toolbar(stockOut)', function (obj) {
            var checkStatus = table.checkStatus(obj.config.id);
            var data = checkStatus.data;
            switch(obj.event) {
                case 'confirm':
                    if (data.length === 0){
                        layer.msg("请选择数据", {icon: 2});
                        return;
                    }
                    //判断是否1楼和3楼库位同时被勾选
                    var floor = data[0].locNo.split('@')[1];
                    var flag = true;
                    let locNos = [];
                    data.forEach(function(elem) {
                        if(floor != elem.locNo.split('@')[1]){
                            flag = false;
                        }
                        locNos.push(elem.locNo);
                    });
                    if(!flag){
                        layer.msg("当前选择的库位号存在不同楼层,请选择同一楼层下的库位", {icon: 2});
                        return;
                    }
                    $.ajax({
                        url: baseUrl+"/agv/locDetl/auth",
                        headers: {'token': localStorage.getItem('token')},
                        data: {locNos:locNos},
                        method: 'POST',
                        async: false,
                        success: function (res) {
                            if (res.code === 200) {
                                data = res.data;
                            } else if (res.code === 403) {
                                top.location.href = baseUrl + "/";
                            } else {
                                layer.msg(res.msg)
                            }
                        }
                    })
                    flag = parent.addTableData(data,floor);
                    if(flag){
                        parent.addStationData(floor);
                    }else{
                        layer.msg("当前选择的库位号存在不同楼层,请选择同一楼层下的库位", {icon: 2});
                        return;
                    }
                    break;
            }
        });
        // 搜索栏搜索事件
        form.on('submit(search)', function (data) {
            tableReload();
        });
        layDate.render({
            elem: '.layui-laydate-range'
            ,type: 'datetime'
            ,range: true
        });
    })
    function tableReload() {
        var searchData = {};
        $.each($('#search-box [name]').serializeArray(), function() {
            searchData[this.name] = this.value;
        });
        locDetlTableIns.reload({
            where: searchData
        });
    }
</script>
</html>
src/main/webapp/views/agvPakStore/locDetlQuery.html
New file
@@ -0,0 +1,189 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        body {
        }
        .layui-table-box {
            border-right: 1px solid #9F9F9F;
            border-left: 1px solid #9F9F9F;
        }
        #search-box {
            padding: 30px 0 20px 0;
        }
        #search-box .layui-inline:first-child {
            margin-left: 30px;
        }
        #search-box .layui-inline {
            margin-right: 5px;
        }
        #data-search-btn {
            margin-left: 10px;
            display: inline-block;
        }
        #data-search-btn.layui-btn-container .layui-btn {
            margin-right: 20px;
        }
    </style>
</head>
<body>
<div style="padding: 25px; line-height: 22px; background-color: #393D49; color: #fff; font-weight: 300;">
    <span style="font-size: large; font-weight: bold">提取库存商品</span>
</div>
<!-- 搜索栏 -->
<fieldset class="layui-elem-field site-demo-button" style="margin: 20px;">
    <legend>搜索栏</legend>
    <!-- 搜索栏 -->
    <div id="search-box" class="layui-form layui-card-header">
        <div class="layui-inline">
            <div class="layui-input-inline">
                <input class="layui-input" type="text" name="loc_no" placeholder="库位号" autocomplete="off">
            </div>
        </div>
        <div class="layui-inline">
            <div class="layui-input-inline">
                <input class="layui-input" type="text" name="matnr" placeholder="物料号"  autocomplete="off">
            </div>
        </div>
        <div class="layui-inline">
            <div class="layui-input-inline">
                <input class="layui-input" type="text" name="maktx" placeholder="物料描述" autocomplete="off">
            </div>
        </div>
        <!-- 日期范围 -->
        <div class="layui-inline" style="width: 300px">
            <div class="layui-input-inline">
                <input class="layui-input layui-laydate-range" name="modi_time" type="text" placeholder="起始时间 - 终止时间" autocomplete="off" style="width: 300px">
            </div>
        </div>
        <!-- 待添加 -->
        <div id="data-search-btn" class="layui-btn-container layui-form-item" style="display: inline-block">
            <button id="search" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="search">搜索</button>
        </div>
    </div>
</fieldset>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
        <button class="layui-btn" id="btn-confirm" lay-event="confirm" style="">提取</button>
    </div>
</script>
<div class="layui-form">
    <table class="layui-hide" id="stockOut" lay-filter="stockOut"></table>
</div>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
</body>
<script>
    function getCol() {
        var cols = [
            {type: 'checkbox'}
            ,{field: 'locNo$', align: 'center',title: '库位号'}
        ];
        cols.push.apply(cols, detlCols);
        cols.push({field: 'modiUser$', align: 'center',title: '修改人员', hide: true}
            ,{field: 'modiTime$', align: 'center',title: '修改时间'})
        return cols;
    }
    layui.config({
        base: baseUrl + "/static/layui/lay/modules/"
    }).use(['table','laydate', 'form', 'admin'], function() {
        var table = layui.table;
        var $ = layui.jquery;
        var layer = layui.layer;
        var layDate = layui.laydate;
        var form = layui.form;
        var admin = layui.admin;
        // 数据渲染
        locDetlTableIns = table.render({
            elem: '#stockOut',
            headers: {token: localStorage.getItem('token')},
            url: baseUrl+'/stock/out/list/auth',
            page: true,
            limits: [16, 30, 50, 100, 200, 500],
            limit: 16,
            even: true,
            toolbar: '#toolbar',
            cellMinWidth: 50,
            cols: [getCol()],
            request: {
                pageName: 'curr',
                pageSize: 'limit'
            },
            parseData: function (res) {
                return {
                    'code': res.code,
                    'msg': res.msg,
                    'count': res.data.total,
                    'data': res.data.records
                }
            },
            response: {
                statusCode: 200
            },
            done: function(res, curr, count) {
                if (res.code === 403) {
                    top.location.href = baseUrl+"/";
                }
            }
        });
        // 监听头工具栏事件
        table.on('toolbar(stockOut)', function (obj) {
            var checkStatus = table.checkStatus(obj.config.id);
            var data = checkStatus.data;
            switch(obj.event) {
                case 'confirm':
                    if (data.length === 0){
                        layer.msg("请选择数据");
                        return;
                    }
                    parent.addTableData(data);
                    break;
            }
        });
        // 搜索栏搜索事件
        form.on('submit(search)', function (data) {
            tableReload();
        });
        layDate.render({
            elem: '.layui-laydate-range'
            ,type: 'datetime'
            ,range: true
        });
    })
    function tableReload() {
        var searchData = {};
        $.each($('#search-box [name]').serializeArray(), function() {
            searchData[this.name] = this.value;
        });
        locDetlTableIns.reload({
            where: searchData,
        });
    }
</script>
</html>
src/main/webapp/views/agvPakStore/locMove.html
New file
@@ -0,0 +1,130 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        html {
            height: 100%;
            padding: 10px;
            background-color: #f1f1f1;
            box-sizing: border-box;
        }
        body {
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 0 3px rgba(0,0,0,.3);
            padding-bottom: 20px;
        }
        .function-area {
            padding: 50px 80px 50px 70px;
            display: inline-block;
        }
        .cool-auto-complete-div {
            height: 40px;
            border-radius: 5px;
            border: 1px solid #b8b8b8;
            color: #888;
            box-shadow: inset 0 1px 2px #ECECEC;
            -moz-box-shadow: inset 0 1px 2px #ECECEC;
            -webkit-box-shadow: inset 0 1px 2px #ECECEC;
        }
        .function-btn {
            margin-left: 15px;
            background: #E27575;
            border: none;
            padding: 10px 25px 10px 25px;
            color: #FFF;
            box-shadow: 1px 1px 5px #B6B6B6;
            border-radius: 3px;
            text-shadow: 1px 1px 1px #9E3F3F;
            cursor: pointer;
        }
        .function-btn:hover {
            opacity: 0.8
        }
        .layui-layer-lan .layui-layer-btn a {
            background: #4476A7;
            border-color: #4476A7;
            color: #fff;
        }
        .layui-layer-lan .layui-layer-btn .layui-layer-btn1 {
            background: #fff;
            color: #333;
            border-color: #E9E7E7;
        }
        .layui-layer-lan .layui-layer-btn .layui-layer-btn1:hover {
            background-color: #f7f7f7;
        }
        #loc-move-btn {
            display: none;
        }
    </style>
</head>
<body>
<div class="function-area layui-form">
    <!-- 源库位 -->
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input id="sourceLocNo" class="layui-input" onkeyup="getLoc(this)" type="text" placeholder="源库位" autocomplete="off">
        </div>
    </div>
    <div class="layui-form-mid" style="float: none; display: inline-block; margin-left: 10px">-</div>
    <div class="layui-input-inline">
        <select id="targetLocNo" name="modules" lay-verify="required" lay-search="">
            <option value="">目标空库位</option>
        </select>
    </div>
    <button id="loc-move-btn" class="function-btn" onclick="locMove()" style="background: #4476A7;text-shadow: inherit;height: 45px;font-size: 15px;margin-left: 20px">库位移转</button>
</div>
<hr>
<table class="layui-table" id="locMatCode" lay-filter="locMatCode"></table>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
<script type="text/javascript" src="../../static/js/agvPakStore/locMove.js" charset="utf-8"></script>
<script type="text/template" id="emptyLocStock">
    <option value="">请输入并选择</option>
    {{#each data}}
    <option value="{{this}}">{{this}}</option>
    {{/each}}
</script>
<div id="locMoveWindow" style="height: 100%;display: none">
    <div style="float: left;width: 35%;height: 100%">
        <div>
            <span style="display: block">源库位</span>
            <input type="text">
        </div>
    </div>
    <div style="float: left;width: 30%;height: 100%;position: relative;">
        <span style="position:absolute;top: 45%;left: 50%;color: #666;transform: translateX(-50%);;display: block">移转至</span>
        <hr style="position: absolute; top: 50%;width: 100%;border: none;height: 1px;background-color: #666">
    </div>
    <div style="float: right;width: 35%;height: 100%">
        <div>
            <span style="display: block">目标库位</span>
            <input type="text">
        </div>
    </div>
</div>
</body>
</html>
src/main/webapp/views/agvPakStore/matQuery.html
New file
@@ -0,0 +1,173 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        body {
            /*overflow: hidden;*/
        }
        .layui-table-box {
            border-right: 1px solid #9F9F9F;
            border-left: 1px solid #9F9F9F;
        }
    </style>
</head>
<body>
<div style="padding: 25px; line-height: 22px; background-color: #393D49; color: #fff; font-weight: 300;">
    <span style="font-size: large; font-weight: bold">选择商品</span>
</div>
<div class="layui-card" style="padding: 0 20px; overflow: scroll;">
    <fieldset class="layui-elem-field site-demo-button" style="margin: 20px;">
        <legend>搜索栏</legend>
        <div id="search-box" class="layui-form layui-card-header">
            <div class="layui-inline">
                <div class="layui-input-inline">
                    <input class="layui-input" type="text" name="matnr" placeholder="物料号" autocomplete="off">
                </div>
            </div>
            <div class="layui-inline">
                <div class="layui-input-inline">
                    <input class="layui-input" type="text" name="maktx" placeholder="物料号" autocomplete="off">
                </div>
            </div>
            <!-- 日期范围 -->
            <div class="layui-inline" style="width: 300px">
                <div class="layui-input-inline">
                    <input class="layui-input layui-laydate-range" name="modi_time" type="text" placeholder="起始时间 - 终止时间" autocomplete="off" style="width: 300px">
                </div>
            </div>
            <div class="layui-inline">
                <div class="layui-input-inline">
                    <input class="layui-input" type="text" name="condition" placeholder="请输入" autocomplete="off">
                </div>
            </div>
            <!-- 待添加 -->
            <div id="data-search-btn" class="layui-btn-container layui-form-item" style="display: inline-block">
                <button id="search" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="search">搜索</button>
            </div>
        </div>
    </fieldset>
    <div class="layui-form">
        <table class="layui-hide" id="mat" lay-filter="mat"></table>
    </div>
</div>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
        <button class="layui-btn" id="btn-confirm" lay-event="confirm" style="">提取</button>
    </div>
</script>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
</body>
<script>
    function getCol() {
        let cols = [
            {type: 'checkbox', fixed: 'left'}
        ];
        cols.push.apply(cols, matCols);
        cols.push(
            {field: 'modiUser$', align: 'center',title: '修改人员', hide: true},
            {field: 'modiTime$', align: 'center',title: '修改时间'}
        )
        return cols;
    }
    layui.config({
        base: baseUrl + "/static/layui/lay/modules/"
    }).use(['table','laydate', 'form', 'admin'], function() {
        var table = layui.table;
        var $ = layui.jquery;
        var layer = layui.layer;
        var layDate = layui.laydate;
        var form = layui.form;
        var admin = layui.admin;
        // 物料查询数据表
        matQueryTable = table.render({
            elem: '#mat',
            headers: {token: localStorage.getItem('token')},
            url: baseUrl + '/mat/list/auth',
            page: true,
            limit: 7,
            limits: [7, 10, 30,50,100],
            even: true,
            cellMinWidth: 50,
            toolbar: '#toolbar',
            cols: [getCol()],
            request: {
                pageName: 'curr',
                pageSize: 'limit'
            },
            parseData: function (res) {
                return {
                    'code': res.code,
                    'msg': res.msg,
                    'count': res.data.total,
                    'data': res.data.records
                }
            },
            response: {
                statusCode: 200
            },
            done: function (res, curr, count) {
                if (res.code === 403) {
                    top.location.href = baseUrl + "/";
                }
            }
        });
        // 监听头工具栏事件
        table.on('toolbar(mat)', function (obj) {
            let checkStatus = table.checkStatus(obj.config.id);
            let data = checkStatus.data;
            switch(obj.event) {
                case 'confirm':
                    if (data.length === 0){
                        layer.msg("请选择数据", {icon: 2});
                        return;
                    }
                    parent.addTableData(data);
                    break;
            }
        });
        // 搜索栏搜索事件
        form.on('submit(search)', function (data) {
            tableReload();
        });
        layDate.render({
            elem: '.layui-laydate-range'
            ,type: 'datetime'
            ,range: true
        });
    })
    function tableReload() {
        var searchData = {};
        $.each($('#search-box [name]').serializeArray(), function() {
            searchData[this.name] = this.value;
        });
        matQueryTable.reload({
            where: searchData
        });
    }
</script>
</html>
src/main/webapp/views/agvPakStore/pakStore.html
New file
@@ -0,0 +1,133 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        html {
            height: 100%;
            padding: 10px;
            background-color: #f1f1f1;
            box-sizing: border-box;
        }
        body {
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 0 3px rgba(0,0,0,.3);
        }
        .function-area {
            padding: 20px 50px;
        }
        .function-btn {
            font-size: 16px;
            padding: 1px 2px;
            width: 100px;
            height: 50px;
            border-color: #2b425b;
            border-radius: 4px;
            border-width: 2px;
            background: none;
            border-style: solid;
            transition: 0.4s;
            cursor: pointer;
            letter-spacing: 1.5px;
        }
        .function-btn:hover {
            background-color: #2b425b;
            color: #fff;
        }
        .layui-layer-page .layui-layer-content {
            position: relative;
            overflow: visible !important;
        }
        #mat-query {
            display: none;
        }
        #staNoSpan {
            text-align: center;
            display: inline-block;
            width: 100px;
            font-size: 13px;
        }
        .layui-btn-container .layui-form-select {
            display: inline-block;
            width: 150px;
            height: 30px;
        }
        .layui-btn-container .layui-form-select.layui-form-selected {
            display: inline-block;
            width: 150px;
        }
        .layui-btn-container .layui-select-title input {
            font-size: 13px;
        }
        .layui-btn-container .layui-anim.layui-anim-upbit dd {
            font-size: 13px;
        }
        #btn-comb {
            margin-left: 60px;
            display: none;
        }
    </style>
</head>
<body>
<!-- 功能区 -->
<div class="function-area">
    <button id="mat-query" class="function-btn">提取商品</button>
</div>
<hr>
<!-- 表格 -->
<div style="padding-bottom: 5px; margin-bottom: 45px">
    <!-- 头部 -->
    <script type="text/html" id="toolbar">
        <div class="layui-form">
            <div class="layui-btn-container">
                <!-- 1.选择入库口 -->
                <span id="staNoSpan">入库口:</span>
                <select id="putSiteSelect" lay-verify="required">
                    <option value="">请选择站点</option>
                </select>
                <!-- 2.启动出库 -->
                <button class="layui-btn layui-btn-normal layui-btn-lg" id="btn-comb" lay-event="comb" style="">启动入库</button>
            </div>
        </div>
    </script>
    <!-- 行 -->
    <script type="text/html" id="operate">
        <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="remove">移除</a>
    </script>
    <table class="layui-table" id="chooseData" lay-filter="chooseData"></table>
</div>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
<script type="text/javascript" src="../../static/js/pakStore/pakStore.js" charset="utf-8"></script>
<script type="text/template" id="putSiteSelectTemplate">
    {{#each data}}
        <option value="{{this}}">{{this}}</option>
    {{/each}}
</script>
</body>
</html>
src/main/webapp/views/agvPakStore/stockAdjust.html
New file
@@ -0,0 +1,133 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        html {
            height: 100%;
            padding: 10px;
            background-color: #f1f1f1;
            box-sizing: border-box;
        }
        body {
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 0 3px rgba(0,0,0,.3);
        }
        /* search */
        .layui-card-header {
            border-bottom: none;
        }
        #search-box {
            padding: 30px 0 10px 0;
        }
        #search-box .layui-inline:first-child {
            margin-left: 30px;
        }
        #search-box .layui-inline {
            margin-right: 5px;
        }
        #data-search-btn {
            margin-left: 10px;
            display: inline-block;
        }
        #data-search-btn.layui-btn-container .layui-btn {
            margin-right: 20px;
        }
        /* add */
        .function-area {
            padding: 15px 0 20px 40px;
        }
        .function-btn {
            font-size: 16px;
            padding: 1px 1px 1px 1px;
            width: 120px;
            height: 40px;
            border-color: #2b425b;
            border-radius: 4px;
            border-width: 1px;
            background: none;
            border-style: solid;
            transition: 0.4s;
            cursor: pointer;
        }
        .function-btn:hover {
            background-color: #2b425b;
            color: #fff;
        }
        #mat-query {
            display: none;
        }
        #btn-adjust {
            display: none;
        }
    </style>
</head>
<body style="padding-bottom: 30px">
<!-- 搜索栏 -->
<div id="search-box" class="layui-form layui-card-header">
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input id="searchLocNo" class="layui-input" type="text" name="loc_no" placeholder="库位号" autocomplete="off"  style="height: 45px;border-color: #b8b8b8">
        </div>
    </div>
    <!-- 待添加 -->
    <div id="data-search-btn" class="layui-btn-container layui-form-item" style="display: inline-block">
        <button id="search" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="search">检索</button>
        <button id="reset" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="reset">重置</button>
    </div>
    <!-- 库位提示 -->
    <div style="display: inline-block; font-size: 20px;font-weight: 300">
        <div class="not-retrieve" style="color: #ff0000;font-family: '黑体';">
            请先检索库位
        </div>
        <div class="retrieve" style="display: none;color: #0097ff;font-family: '黑体';">
            当前检索库位:&nbsp; <span id="locMsg" style=""></span>
        </div>
    </div>
</div>
<hr>
<!-- 功能区 -->
<div class="function-area">
    <button id="mat-query" class="function-btn">新增库存</button>
</div>
<!-- 头部 -->
<script type="text/html" id="toolbar">
    <button class="layui-btn layui-btn-lg" id="btn-adjust" lay-event="adjust" style="">调整库存</button>
</script>
<!-- 行 -->
<script type="text/html" id="operate">
    <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="remove">移除</a>
</script>
<!-- 表格 -->
<table class="layui-table" id="chooseData" lay-filter="chooseData"></table>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
<script type="text/javascript" src="../../static/js/pakStore/stockAdjust.js" charset="utf-8"></script>
</body>
</html>
src/main/webapp/views/agvPakStore/stockOut.html
New file
@@ -0,0 +1,131 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
    <style>
        html {
            height: 100%;
            padding: 10px;
            background-color: #f1f1f1;
            box-sizing: border-box;
        }
        body {
            background-color: #fff;
            border-radius: 5px;
            box-shadow: 0 0 3px rgba(0,0,0,.3);
            padding-bottom: 20px;
        }
        #staNoSpan {
            text-align: center;
            display: inline-block;
            width: 100px;
            font-size: 13px;
        }
        .layui-btn-container .layui-form-select {
            display: inline-block;
            width: 150px;
            height: 30px;
        }
        .layui-btn-container .layui-form-select.layui-form-selected {
            display: inline-block;
            width: 150px;
        }
        .layui-btn-container .layui-select-title input {
            font-size: 13px;
        }
        .layui-btn-container .layui-anim.layui-anim-upbit dd {
            font-size: 13px;
        }
        #btn-outbound {
            margin-left: 60px;
            display: none;
        }
        /*----------------------------------*/
        .function-area {
            padding: 20px 50px;
        }
        .function-btn {
            font-size: 16px;
            padding: 1px 2px;
            width: 100px;
            height: 50px;
            border-color: #2b425b;
            border-radius: 4px;
            border-width: 2px;
            background: none;
            border-style: solid;
            transition: 0.4s;
            cursor: pointer;
            letter-spacing: 1.5px;
        }
        .function-btn:hover {
            background-color: #2b425b;
            color: #fff;
        }
        #mat-query {
            display: none;
        }
    </style>
</head>
<body>
<!-- 功能区 -->
<div class="function-area">
    <button id="mat-query" class="function-btn">提取库存</button>
</div>
<hr>
<!-- 表格 -->
<div style="padding-bottom: 5px; margin-bottom: 45px">
    <!-- 头部 -->
    <script type="text/html" id="toolbar">
        <div class="layui-form">
            <div class="layui-btn-container">
                <!-- 1.选择出库口 -->
                <span id="staNoSpan">出库口:</span>
                <select id="staNoSelect" lay-verify="required">
                    <option value="">请选择站点</option>
                </select>
                <!-- 2.启动出库 -->
                <button class="layui-btn layui-btn-lg" id="btn-outbound" lay-event="outbound">启动出库</button>
            </div>
        </div>
    </script>
    <!-- 行 -->
    <script type="text/html" id="operate">
        <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="remove">移除</a>
    </script>
    <table class="layui-table" id="chooseData" lay-filter="chooseData"></table>
</div>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
<script type="text/javascript" src="../../static/js/pakStore/stockOut.js" charset="utf-8"></script>
<script type="text/template" id="takeSiteSelectTemplate">
    {{#each data}}
    <option value="{{siteId}}">{{desc}}</option>
    {{/each}}
</script>
</body>
</html>
src/main/webapp/views/allLocDetl/locDetl.html
New file
@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
</head>
<body>
<!-- 搜索栏 -->
<div id="search-box" class="layui-form layui-card-header">
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="loc_no" placeholder="库位号" autocomplete="off">
        </div>
    </div>
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="zpallet" placeholder="托盘码" autocomplete="off">
        </div>
    </div>
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="matnr" placeholder="物料号" autocomplete="off">
        </div>
    </div>
<!--    <div class="layui-inline">-->
<!--        <div class="layui-input-inline">-->
<!--            <input class="layui-input" type="text" name="row" placeholder="排数" autocomplete="off">-->
<!--        </div>-->
<!--    </div>-->
    <div class="layui-inline">
        <div class="layui-input-inline">
            <input class="layui-input" type="text" name="condition" placeholder="请输入" autocomplete="off">
        </div>
    </div>
    <!-- 待添加 -->
    <div id="data-search-btn" class="layui-btn-container layui-form-item" style="display: inline-block">
        <button id="search" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="search">搜索</button>
        <button id="reset" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="reset">重置</button>
<!--        <button id="unreason" class="layui-btn layui-btn-primary layui-btn-radius" lay-submit lay-filter="unreason">查看异常数据</button>-->
    </div>
</div>
<!-- 表格 -->
<div class="layui-form">
    <table class="layui-hide" id="locDetl" lay-filter="locDetl"></table>
</div>
<script type="text/html" id="toolbar">
    <div class="layui-btn-container">
        <button class="layui-btn layui-btn-primary layui-btn-sm" id="btn-export" lay-event="exportData" style="margin-top: 10px">导出</button>
    </div>
</script>
<script type="text/html" id="operate">
    <a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="detail">详情</a>
</script>
<script type="text/html" id="stockFreezeTpl">
    <input type="checkbox" name="stockFreeze" value="{{d.stockFreeze}}" lay-skin="switch" lay-text="正常|冻结" lay-filter="stockFreezeSwitch" {{ d.stockFreeze === 1 ? 'checked' : '' }}>
</script>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/allLocDetl/locDetl.js" charset="utf-8"></script>
<iframe id="detail-iframe" scrolling="auto" style="display:none;"></iframe>
</body>
</html>
src/main/webapp/views/allLocDetl/locDetl_detail.html
New file
@@ -0,0 +1,168 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/common.css" media="all">
</head>
<body>
<!-- 详情 -->
<div id="data-detail" class="layer_self_wrap">
    <form id="detail" class="layui-form">
    <!--
        <div class="layui-inline"  style="display: none">
            <label class="layui-form-label"><span class="not-null">*</span>编  号:</label>
            <div class="layui-input-inline">
                <input id="id" class="layui-input" type="text" placeholder="编号">
            </div>
        </div>
    -->
        <div class="layui-inline"  style="width:31%;">
            <label class="layui-form-label"><span class="not-null">*</span>库 位 号:</label>
            <div class="layui-input-inline cool-auto-complete">
                <input id="locNo" class="layui-input" type="text" onkeyup="check(this.id, 'locDetl')" lay-verify="required"  style="display: none">
                <input id="locNo$" class="layui-input cool-auto-complete-div" onclick="autoShow(this.id)" type="text" placeholder="请输入..." onfocus=this.blur()>
                <div class="cool-auto-complete-window">
                    <input class="cool-auto-complete-window-input" data-key="locMastQueryBylocNo" onkeyup="autoLoad(this.getAttribute('data-key'))">
                    <select class="cool-auto-complete-window-select" data-key="locMastQueryBylocNoSelect" onchange="confirmed(this.getAttribute('data-key'))" multiple="multiple">
                    </select>
                </div>
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;">
            <label class="layui-form-label"><span class="not-null">*</span>物  料:</label>
            <div class="layui-input-inline">
                <input id="matnr" class="layui-input" type="text" onkeyup="check(this.id, 'locDetl')" lay-verify="required" >
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;display: none">
            <label class="layui-form-label">仓 库 号:</label>
            <div class="layui-input-inline">
                <input id="lgnum" class="layui-input" type="text" >
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;display: none">
            <label class="layui-form-label" style="font-size: x-small">转储请求编号:</label>
            <div class="layui-input-inline">
                <input id="tbnum" class="layui-input" type="text" lay-verify="number" >
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;display: none">
            <label class="layui-form-label">行 项 目:</label>
            <div class="layui-input-inline">
                <input id="tbpos" class="layui-input" type="text" lay-verify="number" >
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;display: none">
            <label class="layui-form-label" style="font-size: x-small">物料标签ID:</label>
            <div class="layui-input-inline">
                <input id="zmatid" class="layui-input" type="text" >
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;">
            <label class="layui-form-label">物料描述:</label>
            <div class="layui-input-inline">
                <input id="maktx" class="layui-input" type="text">
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;display: none">
            <label class="layui-form-label">工  厂:</label>
            <div class="layui-input-inline">
                <input id="werks" class="layui-input" type="text">
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;">
            <label class="layui-form-label">数  量:</label>
            <div class="layui-input-inline">
                <input id="anfme" class="layui-input" type="text" lay-verify="number" >
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;">
            <label class="layui-form-label">单  位:</label>
            <div class="layui-input-inline">
                <input id="altme" class="layui-input" type="text">
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;">
            <label class="layui-form-label">托盘条码:</label>
            <div class="layui-input-inline">
                <input id="zpallet" class="layui-input" type="text">
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;display: none">
            <label class="layui-form-label">用户ID:</label>
            <div class="layui-input-inline">
                <input id="bname" class="layui-input" type="text">
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;">
            <label class="layui-form-label">备  注:</label>
            <div class="layui-input-inline">
                <input id="memo" class="layui-input" type="text">
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;display: none">
            <label class="layui-form-label">修改人员:</label>
            <div class="layui-input-inline cool-auto-complete">
                <input id="modiUser" class="layui-input" type="text" lay-verify="number"  style="display: none">
                <input id="modiUser$" class="layui-input cool-auto-complete-div" onclick="autoShow(this.id)" type="text" placeholder="请输入..." onfocus=this.blur()>
                <div class="cool-auto-complete-window">
                    <input class="cool-auto-complete-window-input" data-key="userQueryBymodiUser" onkeyup="autoLoad(this.getAttribute('data-key'))">
                    <select class="cool-auto-complete-window-select" data-key="userQueryBymodiUserSelect" onchange="confirmed(this.getAttribute('data-key'))" multiple="multiple">
                    </select>
                </div>
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;display: none">
            <label class="layui-form-label">修改时间:</label>
            <div class="layui-input-inline">
                <input id="modiTime$" class="layui-input" type="text" autocomplete="off">
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;display: none">
            <label class="layui-form-label">创 建 者:</label>
            <div class="layui-input-inline cool-auto-complete">
                <input id="appeUser" class="layui-input" type="text" lay-verify="number"  style="display: none">
                <input id="appeUser$" class="layui-input cool-auto-complete-div" onclick="autoShow(this.id)" type="text" placeholder="请输入..." onfocus=this.blur()>
                <div class="cool-auto-complete-window">
                    <input class="cool-auto-complete-window-input" data-key="userQueryByappeUser" onkeyup="autoLoad(this.getAttribute('data-key'))">
                    <select class="cool-auto-complete-window-select" data-key="userQueryByappeUserSelect" onchange="confirmed(this.getAttribute('data-key'))" multiple="multiple">
                    </select>
                </div>
            </div>
        </div>
        <div class="layui-inline"  style="width:31%;display: none">
            <label class="layui-form-label">添加时间:</label>
            <div class="layui-input-inline">
                <input id="appeTime$" class="layui-input" type="text" autocomplete="off">
            </div>
        </div>
        <hr class="layui-bg-gray">
        <div id="data-detail-btn" class="layui-btn-container layui-form-item">
            <div id="data-detail-submit-save" type="button" class="layui-btn layui-btn-normal" lay-submit lay-filter="save">保存</div>
            <div id="data-detail-submit-edit" type="button" class="layui-btn layui-btn-normal" lay-submit lay-filter="edit">修改</div>
            <div id="data-detail-close" type="button" class="layui-btn" lay-submit lay-filter="close">关闭</div>
        </div>
        <div id="prompt">
            温馨提示:请仔细填写相关信息,<span class="extrude"><span class="not-null">*</span> 为必填选项。</span>
        </div>
    </form>
</div>
</body>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/locDetl/locDetl.js" charset="utf-8"></script>
</html>
src/main/webapp/views/home/agvMap.html
New file
@@ -0,0 +1,1069 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>库位地图</title>
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/element.css">
    <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
    <script type="text/javascript" src="../../static/layui/layui.js"></script>
    <script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
    <script type="text/javascript" src="../../static/js/common.js"></script>
    <script type="text/javascript" src="../../static/js/vue.min.js"></script>
    <script type="text/javascript" src="../../static/js/element.js"></script>
    <style>
        .pointContainer {
            display: flex;
            justify-content: center;
            margin-top: 1px;
        }
        .pointBox {
            background: #bababa;
            width: 40px;
            height: 40px;
            margin-right: 1px;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 14px;
            user-select: none;
            color: #fff;
        }
        .pointBox:hover{
            background: #00ff7f;
        }
        .pointBoxEmpty {
            background: #c2c934;
        }
        .pointBoxOut {
            background: #f1aa19;
        }
        .pointBoxOutYy {
            background: #618593;
        }
        .pointBoxInYy {
            background: #fa736f;
        }
        .pointBoxGreen {
            background: #00ff7f;
        }
        .pointBoxBlue {
            background: #55aaff;
        }
        .pointBoxRed {
            background: #ff0000;
        }
        .pointBoxStart {
            background: #ffaa00;
        }
        .pointBoxEnd {
            background: #ff55ff;
        }
        .pointBoxStation {
            background: #ffff00;
        }
        .chargeStation {
            background: #ffaa7f;
        }
        .pointBoxDefault {
            background: #86779d;
        }
        .pointBoxSelected {
            background: #00ff7f !important;
        }
        .pointBoxSearch {
            background: #9900ff;
        }
        .crnLine{
            width: auto;
            height: 2px;
            margin: 10px 0;
            background: #000;
            position: relative;
        }
        .popBox {
            position: absolute;
        }
        /*卡片样式start*/
        .apple-card {
            width: 190px;
            height: 254px;
            margin: 0 auto;
            background-color: #011522;
            border-radius: 8px;
            z-index: 1;
            animation:fadeInOut 0.5s 1;
        }
        .apple-card .tools {
            display: flex;
            align-items: center;
            padding: 9px;
        }
        .apple-card .circle {
            padding: 0 4px;
        }
        .apple-card .box {
            display: inline-block;
            align-items: center;
            width: 10px;
            height: 10px;
            padding: 1px;
            border-radius: 50%;
        }
        .apple-card .red {
            background-color: #ff605c;
            position: relative;
        }
        .apple-card .red:hover{
            background-color: #ff0300;
        }
        .apple-card .red:hover::before {
            content: "x";
            font-size: 11px;
            color: #fff;
            width: 10px;
            height: 10px;
            display: flex;
            justify-content: center;
            align-items: center;
            position: absolute;
            animation:fadeInOut 0.5s 1;
        }
        .apple-card .yellow {
            background-color: #ffbd44;
        }
        .apple-card .green {
            background-color: #00ca4e;
        }
        .apple-card .card-content{
            color: #fff;
            padding: 10px;
        }
        /*卡片样式end*/
        /*滑动卡片start*/
        .hoverCard {
            width: 150px;
            height: 224px;
            border-radius: 20px;
            background: #f5f5f5;
            position: relative;
            padding: 1.8rem;
            border: 2px solid #c3c6ce;
            transition: 0.5s ease-out;
            overflow: visible;
            margin-top: 30px;
        }
        .hoverCard .card-details {
            color: black;
            height: 100%;
            gap: .5em;
            display: grid;
            place-content: center;
        }
        .hoverCard .card-button {
            transform: translate(-50%, 125%);
            width: 60%;
            border-radius: 1rem;
            border: none;
            background-color: #008bf8;
            color: #fff;
            font-size: 1rem;
            padding: .5rem 1rem;
            position: absolute;
            left: 50%;
            bottom: 0;
            opacity: 0;
            transition: 0.3s ease-out;
        }
        .hoverCard .text-body {
            color: rgb(134, 134, 134);
        }
        /*Text*/
        .hoverCard .text-title {
            font-size: 1.5em;
            font-weight: bold;
        }
        /*Hover*/
        .hoverCard:hover {
            border-color: #008bf8;
            box-shadow: 0 4px 18px 0 rgba(0, 0, 0, 0.25);
        }
        .hoverCard:hover .card-button {
            transform: translate(-50%, 50%);
            opacity: 1;
        }
        /*滑动卡片end*/
        /*楼层控制start*/
        .floorSelect {
            --text: #414856;
            --radio: #7C96B2;
            --radio-checked: #4F29F0;
            --radio-size: 20px;
            --width: 150px;
            --height: 200px;
            --border-radius: 10px;
            width: var(--width);
            height: var(--height);
            border-radius: var(--border-radius);
            color: var(--text);
            position: relative;
            box-shadow: 0 10px 30px rgba(65, 72, 86, 0.05);
            display: grid;
            grid-template-columns: auto var(--radio-size);
            align-items: center;
        }
        .floorSelect label {
            cursor: pointer;
        }
        .floorSelect input[type="radio"] {
            -webkit-appearance: none;
            -moz-appearance: none;
            position: relative;
            height: var(--radio-size);
            width: var(--radio-size);
            outline: none;
            margin: 0;
            cursor: pointer;
            border: 2px solid var(--radio);
            background: transparent;
            border-radius: 50%;
            display: grid;
            justify-self: end;
            justify-items: center;
            align-items: center;
            overflow: hidden;
            transition: border .5s ease;
        }
        .floorSelect input[type="radio"]::before, .floorSelect input[type="radio"]::after {
            content: "";
            display: flex;
            justify-self: center;
            border-radius: 50%;
        }
        .floorSelect input[type="radio"]::before {
            position: absolute;
            width: 100%;
            height: 100%;
            z-index: 1;
            opacity: var(--opacity, 1);
        }
        .floorSelect input[type="radio"]::after {
            position: relative;
            width: calc(100% /2);
            height: calc(100% /2);
            background: var(--radio-checked);
            top: var(--y, 100%);
            transition: top 0.5s cubic-bezier(0.48, 1.97, 0.5, 0.63);
        }
        .floorSelect input[type="radio"]:checked {
            --radio: var(--radio-checked);
        }
        .floorSelect input[type="radio"]:checked::after {
            --y: 0%;
            animation: stretch-animate .3s ease-out .17s;
        }
        .floorSelect input[type="radio"]:checked::before {
            --opacity: 0;
        }
        .floorSelect input[type="radio"]:checked ~ input[type="radio"]::after {
            --y: -100%;
        }
        .floorSelect input[type="radio"]:not(:checked)::before {
            --opacity: 1;
            transition: opacity 0s linear .5s;
        }
        @keyframes stretch-animate {
            0% {
                transform: scale(1, 1);
            }
            28% {
                transform: scale(1.15, 0.85);
            }
            50% {
                transform: scale(0.9, 1.1);
            }
            100% {
                transform: scale(1, 1);
            }
        }
        /*楼层控制end*/
        /*搜索start*/
        .search-input {
            line-height: 28px;
            border: 2px solid transparent;
            border-bottom-color: #777;
            padding: .2rem 0;
            outline: none;
            background-color: transparent;
            color: #0d0c22;
            transition: .3s cubic-bezier(0.645, 0.045, 0.355, 1);
        }
        .search-input:focus, .search-input:hover {
            outline: none;
            padding: .2rem 1rem;
            border-radius: 1rem;
            border-color: #7a9cc6;
        }
        .search-input::placeholder {
            color: #777;
        }
        .search-input:focus::placeholder {
            opacity: 0;
            transition: opacity .3s;
        }
        /*搜索end*/
        @keyframes fadeInOut {
            0%{
                opacity: 0;
            }
            100%{
                opacity: 1;
            }
        }
    </style>
</head>
<body>
<div id="app" style="display: flex;justify-content: space-around;margin-top: 50px;flex-wrap: wrap;" @click="bgClick()">
    <div style="margin-top: 20px;"><button class="layui-btn" @click="currentFloor = 1" :style="{background: currentFloor==1?'red':''}">1楼</button></div>
    <div style="margin-top: 20px;"><button class="layui-btn" @click="currentFloor = 3" :style="{background: currentFloor==3?'red':''}">3楼</button></div>
    <div style="flex: 18;display: flex;justify-content: center;" :style="{zoom:showScale/100.0,marginTop:(showScale)*4 + 'px'}">
        <div style="margin-top: -110px;">
            <div class="pointContainer" v-for="(x,index) in map" :key="index">
                <div v-if="index != 0 && (index != map.length-1)" v-for="(y,idx) in x" :key="idx">
                    <div v-if="idx != 0 && (idx != map[index].length-1)">
                        <div v-if="map[index][idx].value < 0" style="visibility: hidden;" class="pointBox"></div>
                        <!--库位-->
                        <div v-else-if="map[index][idx].value  == 0" @contextmenu.prevent="rightEvent(index,idx,$event)">
                            <div v-if="map[index][idx].locSts == 'O'" :class="{'pointBoxSearch':map[index][idx].searchStatus}" class="pointBox pointBoxBlue">{{ map[index][idx].locSts }}</div>
                            <div v-else-if="map[index][idx].locSts == 'F'" @click.left="selectLoc(index,idx)" :class="{'pointBoxSelected':map[index][idx].locOutSelected,'pointBoxSearch':map[index][idx].searchStatus}" class="pointBox pointBoxRed">{{ map[index][idx].locSts }}</div>
                            <div v-else-if="map[index][idx].locSts == 'D'" :class="{'pointBoxSearch':map[index][idx].searchStatus}" class="pointBox pointBoxEmpty">{{ map[index][idx].locSts }}</div>
                            <div v-else-if="map[index][idx].locSts == 'P'" :class="{'pointBoxSearch':map[index][idx].searchStatus}" class="pointBox pointBoxOut">{{ map[index][idx].locSts }}</div>
                            <div v-else-if="map[index][idx].locSts == 'R'" :class="{'pointBoxSearch':map[index][idx].searchStatus}" class="pointBox pointBoxOutYy">{{ map[index][idx].locSts }}</div>
                            <div v-else-if="map[index][idx].locSts == 'S'" class="pointBox pointBoxInYy">{{ map[index][idx].locSts }}</div>
                            <div v-else class="pointBox pointBoxDefault" :class="{'pointBoxSearch':map[index][idx].searchStatus}">{{ map[index][idx].locSts }}</div>
                        </div>
                        <!--母轨道-->
                        <div v-else-if="map[index][idx].value  == 3">
                            <div class="pointBox" style="visibility: hidden;"></div>
                        </div>
                        <!--站点-->
                        <div v-else-if="map[index][idx].value  == 4" class="pointBox pointBoxStation" style="visibility: hidden;"></div>
                        <div v-else-if="map[index][idx].value  == 5" class="pointBox chargeStation"
                             @contextmenu.prevent="rightEvent(index,idx,$event)"></div>
                        <div v-else-if="map[index][idx].value  == 9" class="pointBox pointBoxRed"
                             @contextmenu.prevent="rightEvent(index,idx,$event)"></div>
                    </div>
                </div>
                <div style="width: 40px;display: flex;justify-content: center;align-items: center;">
                    {{ getRealRowByX(index) }}
                </div>
            </div>
        </div>
        <div>
            <div style="margin-top: 20px;"><button class="layui-btn" @click="currentLev = 1" :style="{background: currentLev==1?'red':''}">1F</button></div>
            <div style="margin-top: 20px;"><button class="layui-btn" @click="currentLev = 2" :style="{background: currentLev==2?'red':''}">2F</button></div>
            <div style="margin-top: 20px;"><button class="layui-btn" @click="currentLev = 3" :style="{background: currentLev==3?'red':''}">3F</button></div>
            <div style="margin-top: 20px;"><button class="layui-btn" @click="currentLev = 4" :style="{background: currentLev==4?'red':''}">4F</button></div>
            <div style="margin-top: 20px;"><button class="layui-btn" @click="currentLev = 5" :style="{background: currentLev==5?'red':''}">5F</button></div>
            <div style="margin-top: 20px;"><button class="layui-btn" @click="currentLev = 6" :style="{background: currentLev==6?'red':''}">6F</button></div>
            <div style="margin-top: 20px;"><button class="layui-btn" @click="currentLev = 7" :style="{background: currentLev==7?'red':''}">7F</button></div>
            <div style="margin-top: 20px;"><button class="layui-btn" @click="currentLev = 8" :style="{background: currentLev==8?'red':''}">8F</button></div>
            <div class="lev-for-floor3" style="margin-top: 20px; display: none;"><button class="layui-btn" @click="currentLev = 8" :style="{background: currentLev==8?'red':''}">9F</button></div>
            <div class="lev-for-floor3" style="margin-top: 20px; display: none;"><button class="layui-btn" @click="currentLev = 8" :style="{background: currentLev==8?'red':''}">10F</button></div>
            <div class="lev-for-floor3" style="margin-top: 20px; display: none;"><button class="layui-btn" @click="currentLev = 8" :style="{background: currentLev==8?'red':''}">11F</button></div>
            <div class="lev-for-floor3" style="margin-top: 20px; display: none;"><button class="layui-btn" @click="currentLev = 8" :style="{background: currentLev==8?'red':''}">12F</button></div>
        </div>
    </div>
    <div style="padding: 40px 20px 10px 10px;" :style="window.innerWidth < 2000 ? 'margin-top: 0px;' : 'flex: 5;margin-top: -70px;'">
        <el-slider v-model="showScale" :marks="showScaleMarks"></el-slider>
        <div style="display: flex;justify-content: space-between;flex-wrap: wrap;">
            <div class="hoverCard" style="width: 100%;">
                <div class="card-details" style="place-content: normal;height: auto;">
                    <div class="text-body" style="display: flex;flex-wrap: wrap;">
                        <div style="width: 100%;margin-bottom: 20px;">
                            <div style="display: flex;justify-content: space-between;">
                                <div><input v-model="searchMatnr" placeholder="物料号" type="text" class="search-input"></div>
                                <div><input v-model="searchOrderNo" placeholder="订单号" type="text" class="search-input"></div>
                            </div>
                            <div style="display: flex;justify-content: space-between;margin-top: 10px;">
                                <div><input style="width: 110px;" v-model="searchMaktx" placeholder="物料名称" type="text" class="search-input"></div>
                                <div><input style="width: 110px;" v-model="searchSpecs" placeholder="规格" type="text" class="search-input"></div>
                                <div><input style="width: 110px;" v-model="searchLocNo" placeholder="库位号" type="text" class="search-input"></div>
                            </div>
                            <button style="width: 100%;margin-top: 10px;" @click="searchLoc" class="layui-btn layui-btn-sm">搜索</button>
                        </div>
<!--                        <div>-->
<!--                            <button @click="locToLoc2" class="layui-btn layui-btn-sm">侧边移库</button>-->
<!--                        </div>-->
                        <div>
                            <button @click="init" class="layui-btn layui-btn-sm">刷新</button>
                        </div>
                        <div style="margin-left: 10px;">
                            <button @click="resetSearch" class="layui-btn layui-btn-sm">重置</button>
                        </div>
                        <div v-if="!locOutStatus" style="margin-left: 10px;">
                            <button @click="locOutStatus = true" class="layui-btn layui-btn-sm">出库选择</button>
                        </div>
                        <div v-else style="margin-left: 10px;border: 1px red solid;display: flex;">
                            <div>
                                <button @click="cancelSelectLoc" class="layui-btn layui-btn-sm">取消选择</button>
                            </div>
                            <div style="display: flex;justify-content: center;align-items: center;">
                                <select v-model="outSite">
                                    <option v-for="(item,index) in outSites" :key="index" :value="item.siteId">{{ item.desc }}</option>
                                </select>
                            </div>
                            <div>
                                <button @click="locOut" class="layui-btn layui-btn-sm">出库</button>
                            </div>
                        </div>
                    </div>
                </div>
                <button class="card-button">功能区</button>
            </div>
            <div class="hoverCard">
                <div class="card-details">
                    <div class="text-body" style="display: flex;justify-content: space-around;flex-wrap: wrap;">
                        <div style="flex: 1;margin-top: 10px;">
                            <div style="font-size: 10px;">空库位</div><div class="pointBox pointBoxBlue">O</div>
                        </div>
                        <div style="flex: 1;margin-top: 10px;">
                            <div style="font-size: 10px;">在库</div><div class="pointBox pointBoxRed">F</div>
                        </div>
                        <div style="flex: 1;margin-top: 10px;">
                            <div style="font-size: 10px;">空板</div><div class="pointBox pointBoxEmpty">D</div>
                        </div>
                        <div style="flex: 1;margin-top: 10px;">
                            <div style="font-size: 10px;">出库中</div><div class="pointBox pointBoxOut">P</div>
                        </div>
                        <div style="flex: 1;margin-top: 10px;">
                            <div style="font-size: 10px;">出库预约</div><div class="pointBox pointBoxOutYy">R</div>
                        </div>
                        <div style="flex: 1;margin-top: 10px;">
                            <div style="font-size: 10px;">入库预约</div><div class="pointBox pointBoxInYy">S</div>
                        </div>
                        <div style="flex: 1;margin-top: 10px;">
                            <div style="font-size: 10px;">搜索结果</div><div class="pointBox pointBoxSearch"></div>
                        </div>
                        <div style="flex: 1;margin-top: 10px;">
                            <div style="font-size: 10px;">选择结果</div><div class="pointBox pointBoxSelected"></div>
                        </div>
                        <div style="flex: 1;margin-top: 10px;">
                            <div style="font-size: 10px;">其他</div><div class="pointBox pointBoxDefault">其他</div>
                        </div>
                    </div>
                </div>
                <button class="card-button">库位状态</button>
            </div>
<!--            <div class="hoverCard">-->
<!--                <div class="card-details">-->
<!--                    <p class="text-title" style="text-align: center;">楼层 {{currentLev}}F</p>-->
<!--                    <div class="text-body" style="display: flex;">-->
<!--                        <div class="floorSelect">-->
<!--                            <label for="01">1F</label>-->
<!--                            <input id="01" type="radio" name="r" v-model="currentLev" value="1" checked="">-->
<!--                            <label for="02">2F</label>-->
<!--                            <input id="02" type="radio" v-model="currentLev" name="r" value="2">-->
<!--                            <label for="03">3F</label>-->
<!--                            <input id="03" type="radio" v-model="currentLev" name="r" value="3">-->
<!--                            <label for="04">4F</label>-->
<!--                            <input id="04" type="radio" v-model="currentLev" name="r" value="4">-->
<!--                        </div>-->
<!--                    </div>-->
<!--                </div>-->
<!--                <button class="card-button">楼层 {{currentLev}}F</button>-->
<!--            </div>-->
        </div>
    </div>
    <div v-if="rightBox" @click.stop="" :style="{left: rightBoxLeft,top: rightBoxTop}" class="popBox">
        <div class="apple-card">
            <div class="tools">
                <div class="circle" @click.stop="rightBox = false">
                    <span class="red box"></span>
                </div>
                <div class="circle">
                    <span class="yellow box"></span>
                </div>
                <div class="circle">
                    <span class="green box"></span>
                </div>
            </div>
            <div class="card-content">
                <div>
                    库位号: {{ map[mapI][mapJ].locNo }}
                </div>
                <div style="margin-top: 10px;">
                    库位状态: {{ getLocSts(map[mapI][mapJ].locSts) }}
                </div>
                <div style="margin-top: 10px;display: flex;justify-content: space-between;flex-wrap: wrap;">
                    <div style="margin-top: 5px;">
                        <button class="layui-btn layui-btn-sm" @click="openLocDetail(map[mapI][mapJ].locNo)">库位详情</button>
                    </div>
<!--                    <div style="margin-top: 5px;">-->
<!--                        <button v-if="map[mapI][mapJ].locSts == 'F'" class="layui-btn layui-btn-sm" @click="locMove(map[mapI][mapJ].locNo)">库位移转</button>-->
<!--                        <button v-else-if="map[mapI][mapJ].locSts == 'D'" class="layui-btn layui-btn-sm" @click="locMove(map[mapI][mapJ].locNo)">库位移转</button>-->
<!--                        <button v-else class="layui-btn layui-btn-sm layui-btn-disabled" disabled>库位移转</button>-->
<!--                    </div>-->
                </div>
            </div>
        </div>
    </div>
    <div v-if="crnBox" @click.stop="" :style="{left: crnBoxLeft,top: crnBoxTop}" class="popBox">
        <div class="apple-card">
            <div class="tools">
                <div class="circle" @click.stop="crnBox = false">
                    <span class="red box"></span>
                </div>
                <div class="circle">
                    <span class="yellow box"></span>
                </div>
                <div class="circle">
                    <span class="green box"></span>
                </div>
            </div>
            <div class="card-content">
                <div>堆垛机号:{{crnList[crnBox - 1].crnNo}}</div>
                <div>工作号:{{crnList[crnBox - 1].wrkNo}}</div>
                <div>源库位:{{crnList[crnBox - 1].frmLocno}}</div>
                <div>目标库位:{{crnList[crnBox - 1].toLocno}}</div>
                <div>可入:{{crnList[crnBox - 1].inEnable}}</div>
                <div>可出:{{crnList[crnBox - 1].outEnable}}</div>
                <div>状态:{{crnList[crnBox - 1].crnSts$}}</div>
                <div>异常:{{crnList[crnBox - 1].crnErr$}}</div>
            </div>
        </div>
    </div>
</div>
<script>
    var $layui = layui.config({
        base: baseUrl + "/static/layui/lay/modules/"
    }).use(['layer','form'], function () {})
    var app = new Vue({
        el: '#app',
        data: {
            map: [],
            mapData: "",
            importData: null,
            startPosition: "0500501",
            endPosition: "0802501",
            mapI: 0,
            mapJ: 0,
            rightBox: false,
            rightBoxTop: "0px",
            rightBoxLeft: "0px",
            pointContainerWidth: 0,
            currentLev: 1,
            currentFloor: 1,
            crnList: null,
            crnBox: false,
            crnBoxTop: "0px",
            crnBoxLeft: "0px",
            locOutStatus: false,
            locOutLocNo: [],
            searchMatnr: "",
            searchOrderNo: "",
            searchSpecs: "",
            searchMaktx: "",
            searchLocNo: "",
            outSite: null,
            outSites: null,
            showScale: 65, //控制地图显示大小比例
            showScaleMarks: {//比例滑动条显示标记
                0: "0%",
                50: {
                    style: {
                        color: '#1989FA'
                    },
                    label: "50%"
                },
                100: "100%",
            },
            locStsList: [],//库位状态列表
        },
        created(){
            this.init()
            this.getOutSite()
        },
        watch: {
            map: {
                deep: true,
                handler(val) {
                    this.printData()
                }
            },
            currentLev: {
                deep: true,
                handler(val) {
                    this.init()
                    if (this.searchMatnr != ""
                        || this.searchOrderNo != ""
                        || this.searchSpecs != ""
                        || this.searchMaktx != ""
                        || this.searchLocNo != "") {
                        this.searchLoc()
                    }
                }
            },
            currentFloor: {
                deep: true,
                handler(val) {
                    if(this.currentFloor == 3){
                        $(".lev-for-floor3").show();
                    }else{
                        $(".lev-for-floor3").hide();
                    }
                    this.init()
                    if (this.searchMatnr != ""
                        || this.searchOrderNo != ""
                        || this.searchSpecs != ""
                        || this.searchMaktx != ""
                        || this.searchLocNo != "") {
                        this.searchLoc()
                    }
                }
            }
        },
        methods: {
            init(){
                let that = this
                var floor = $('#floorSelect option:selected').val();
                $.ajax({
                    url: baseUrl + "/agv/map/getData/" + this.currentFloor + "/" +this.currentLev + "/auth",
                    headers: {'token': localStorage.getItem('token')},
                    method: "get",
                    success: (data) => {
                        that.importDataClick(data)
                    }
                })
                this.locOutStatus = false
                this.locOutLocNo = []
                this.getLocStsList();//获取库位状态列表
            },
            resetSearch(){
                this.searchMatnr = ""
                this.searchOrderNo = ""
                this.searchSpecs = ""
                this.searchMaktx = ""
                this.searchLocNo = ""
                this.searchLoc()
            },
            printData() {
                this.mapData = JSON.stringify(this.map)
            },
            importDataClick(mapData) {
                let tmp = JSON.parse(mapData);
                let data = []
                tmp.forEach((item, index) => {
                    let data2 = []
                    item.forEach((val, idx) => {
                        val.searchStatus = false//搜索标记
                        data2.push(val)
                    })
                    this.pointContainerWidth = item.length * (40+1)
                    data.push(data2)
                })
                this.map = data
                this.printData()
            },
            getRealRowByX(x) {
                //获取真实库位行号,通过坐标x
                let data = this.map
                let rowData = data[x]
                for (var i = 1; i < rowData.length; i++) {
                    if (rowData[i].locNo != undefined) {
                        let locNo = rowData[i].locNo;
                        return "#" + parseInt(locNo.substr(0, 2));
                    }
                }
                return "";
            },
            rightEvent(x, y, e) {
                this.rightBox = true
                this.mapI = x
                this.mapJ = y
                this.rightBoxTop = e.y + "px"
                this.rightBoxLeft = e.x + "px"
            },
            bgClick() {
                this.rightBox = false
                this.crnBox = false
            },
            openLocDetail(locNo) {
                url = '/agv/locDetl/list/auth';
                $layui.layer.open({
                    type: 2,
                    title: '库位物料',
                    maxmin: true,
                    area: [top.detailWidth, top.detailHeight],
                    shadeClose: true,
                    content: '../report/locDetl.html?locNo=' + locNo,
                    success: function(layero, index){
                    }
                });
            },
            getLocStsList() {
                //获取库位状态列表
                let that = this
                $.ajax({
                    url: baseUrl + "/basLocSts/list/auth",
                    headers: {'token': localStorage.getItem('token')},
                    method: "get",
                    success: (res) => {
                        that.locStsList = res.data.records
                    }
                })
            },
            getLocSts(locSts) {
                //获取库位状态
                let locStsList = this.locStsList
                let locDesc = ""
                locStsList.forEach((item,index) => {
                    if (item.locSts == locSts) {
                        locDesc = item.locDesc
                    }
                })
                return locDesc
            },
            locMove(locNo) {
                //库位移转
                let that = this
                $.ajax({
                    url: baseUrl + "/loc/move/start",
                    headers: {'token': localStorage.getItem('token')},
                    dataType: 'json',
                    data: {
                        sourceLocNo: locNo
                    },
                    method: 'POST',
                    success: function (res) {
                        if (res.code === 200) {
                            $layui.layer.msg(res.msg);
                            that.init()
                        } else if (res.code === 403) {
                            top.location.href = baseUrl + "/";
                        } else {
                            $layui.layer.msg(res.msg);
                        }
                    }
                })
            },
            clickCrnBox(e,crnNo) {
                this.crnBox = crnNo
                this.crnBoxTop = e.y + "px"
                this.crnBoxLeft = e.x + "px"
            },
            locOut() {
                //出库
                let that = this
                let locOutLocNo = this.locOutLocNo
                if (locOutLocNo.length == 0) {
                    $layui.layer.msg("请先选择库位");
                    return;
                }
                let map = this.map
                //巷道list
                let bayList = []
                // 将用户选定的库位通过巷道进行分组
                locOutLocNo.forEach((item,index) => {
                    let obj = {
                        x: item.x,
                        y: item.y,
                        locNo: map[item.x][item.y].locNo
                    }
                    if (bayList[item.y] == undefined) {
                        bayList[item.y] = [obj]
                    }else {
                        bayList[item.y].push(obj)
                    }
                })
                //进行排序
                bayList.forEach((item,index) => {
                    for (var i = 0; i < item.length; i++) {
                        for (var j = i+1; j < item.length; j++) {
                            if (item[i].x > item[j].x) {
                                //交换
                                let tmp = item[j];
                                item[j] = item[i]
                                item[i] = tmp
                            }
                        }
                    }
                })
                //准备出库
                if (this.outSite == null) {
                    $layui.layer.msg("请选择出库站点");
                    return;
                }
                let locNos = []
                bayList.forEach((item,index) => {
                    item.forEach((val,idx) => {
                        locNos.push(val.locNo)
                    })
                })
                let locDetls = []
                $.ajax({
                    url: baseUrl+"/agv/locDetl/auth",
                    headers: {'token': localStorage.getItem('token')},
                    data: {locNos:locNos},
                    method: 'POST',
                    async: false,
                    success: function (res) {
                        if (res.code === 200) {
                            locDetls = res.data
                        } else if (res.code === 403) {
                            top.location.href = baseUrl + "/";
                        } else {
                            layer.msg(res.msg)
                        }
                    }
                })
                locDetls.forEach((item,index) => {
                    item.count = item.anfme
                })
                $.ajax({
                    url: baseUrl + "/plate/out/start",
                    headers: {'token': localStorage.getItem('token')},
                    data: JSON.stringify({
                        outSite: this.outSite,
                        locDetls: locDetls
                    }),
                    contentType:'application/json;charset=UTF-8',
                    method: 'POST',
                    success: function (res) {
                        if (res.code === 200){
                            $layui.layer.msg(res.msg);
                            that.init()
                        } else if (res.code === 403){
                            top.location.href = baseUrl+"/";
                        } else {
                            $layui.layer.msg(res.msg)
                        }
                    }
                });
            },
            searchDataIndex(data,dist) {
                //搜索起始点
                let searchStartPoint = -1;
                dist.forEach((val,idx) => {
                    if (val.x == data.x && val.y == data.y) {
                        //找到点位
                        searchStartPoint = idx
                    }
                })
                return searchStartPoint;
            },
            selectLoc(x, y) {
                //选择库位
                if (this.locOutStatus) {
                    let tmp = this.map
                    let selected = tmp[x][y].locOutSelected ? 0 : 1
                    tmp[x][y].locOutSelected = selected
                    if (selected) {
                        this.locOutLocNo.push({
                            x: x,
                            y: y
                        });
                    }else {
                        //剔除掉不选择元素
                        let locOutLocNo = this.locOutLocNo
                        let tmp = []
                        locOutLocNo.forEach((item,index) => {
                            if (item.x !== x || item.y !== y) {
                                tmp.push(item)
                            }
                        })
                        this.locOutLocNo = tmp
                    }
                    this.map = tmp
                    this.$forceUpdate()
                }
            },
            cancelSelectLoc() {
                //取消选择库位
                let data = this.locOutLocNo
                let tmp = this.map
                data.forEach((item,index) => {
                    tmp[item.x][item.y].locOutSelected = 0;
                })
                this.locOutLocNo = []
                this.map = tmp
                this.locOutStatus = false
            },
            searchLoc() {
                //通过物料编号搜索库位号
                // if (this.searchValue == "") {
                //     $layui.layer.msg("请输入物料编号或订单号");
                //     return;
                // }
                let that = this;
                $.ajax({
                    url: baseUrl + "/agv/map/searchData/auth",
                    headers: {'token': localStorage.getItem('token')},
                    dataType: 'json',
                    data: {
                        lev: this.currentLev,
                        locNo: this.searchLocNo,
                        orderNo: this.searchOrderNo,
                        specs: this.searchSpecs,
                        matnr: this.searchMatnr,
                        maktx: this.searchMaktx
                    },
                    method: 'POST',
                    success: function (res) {
                        if (res.code === 200) {
                            let tmp = that.map
                            let data = res.data
                            tmp.forEach((item,index) => {//清空之前的搜索结果
                                item.forEach((val,idx) => {
                                    if (tmp[index][idx].searchStatus != undefined) {
                                        tmp[index][idx].searchStatus = false;//搜索标记
                                    }
                                })
                            })
                            tmp.forEach((item,index) => {//清空之前的搜索结果
                                item.forEach((val,idx) => {
                                    if (tmp[index][idx].searchStatus != undefined) {
                                        tmp[index][idx].searchStatus = false;//搜索标记
                                    }
                                })
                            })
                            data.forEach((item,i) => {
                                let locNo = item.locNo
                                tmp.forEach((item,index) => {
                                    item.forEach((val,idx) => {
                                        if (tmp[index][idx].locNo == locNo) {
                                            tmp[index][idx].searchStatus = true//搜索标记
                                        }
                                    })
                                })
                            })
                            that.map = tmp
                            $layui.layer.msg("搜索成功");
                        } else if (res.code === 403) {
                            top.location.href = baseUrl + "/";
                        } else {
                            $layui.layer.msg(res.msg);
                        }
                    }
                })
            },
            getOutSite() {
                let that = this
                $.ajax({
                    url: baseUrl + "/agv/available/take/site",
                    headers: {'token': localStorage.getItem('token')},
                    dataType: 'json',
                    data: {},
                    method: 'POST',
                    success: function (res) {
                        if (res.code === 200) {
                            that.outSites = res.data
                            that.outSite = res.data[0].siteId
                        } else if (res.code === 403) {
                            top.location.href = baseUrl + "/";
                        } else {
                            $layui.layer.msg(res.msg);
                        }
                    }
                })
            },
        }
    })
</script>
</body>
</html>
src/main/webapp/views/home/console.html
@@ -266,11 +266,11 @@
        var cols = [
            //{field: 'appeTime$', title: '入库时间', align: 'center', width: 165}
            {field: 'stay_time', align: 'center',title: '滞留天数',width: 90}
            ,{field: 'store_max_date', align: 'center',title: '库龄上限',width: 90}
            ,{field: 'store_min', title: '库存下限', align: 'center'}
            //,{field: 'store_max_date', align: 'center',title: '库龄上限',width: 90}
            //,{field: 'store_min', title: '库存下限', align: 'center'}
            ,{field: 'sum_qty', title: '库存总数', align: 'center'}
            ,{field: 'store_max', title: '库存上限', align: 'center'}
            ,{field: 'loc_no', align: 'center',title: '库位号',width: 90}
            //,{field: 'store_max', title: '库存上限', align: 'center'}
            ,{field: 'loc_no', align: 'center',title: '库位号'}
        ];
        cols.push.apply(cols, detlCols);