自动化立体仓库 - WMS系统
pang.jiabao
2025-04-29 25e2f9601aed6d23923f3200ef248036b7787e7c
产品合格校验手动excel导入
5个文件已修改
2个文件已添加
191 ■■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/LocDetlController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/ProductCalibrationExcelParam.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/importexcle/ProductCalibrationImportListener.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/LocDetlMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/LocDetlMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/locDetl/locDetl.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/locDetl/locDetl.html 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/LocDetlController.java
@@ -14,13 +14,16 @@
import com.core.common.R;
import com.zy.asrs.entity.LocDetl;
import com.zy.asrs.entity.Mat;
import com.zy.asrs.entity.param.ProductCalibrationExcelParam;
import com.zy.asrs.importexcle.LocMat;
import com.zy.asrs.importexcle.LocMatListener;
import com.zy.asrs.importexcle.ProductCalibrationImportListener;
import com.zy.asrs.mapper.LocDetlMapper;
import com.zy.asrs.service.LocDetlService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.MatService;
import com.zy.common.web.BaseController;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
@@ -46,11 +49,26 @@
    @Resource
    private LocMastService locMastService;
    @Resource
    private SqlSessionFactory sqlSessionFactory;
    @PostMapping("/importLocData")
    @ManagerAuth(memo = "导入立库已有库存")
    public R importLocData(@RequestParam("file") MultipartFile multipartFile) {
        try {
            importLocData1(multipartFile);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
        return R.ok("导入成功");
    }
    @PostMapping("/productCalibration")
    @ManagerAuth(memo = "产品校验导入excel方式")
    public R productCalibration(@RequestParam("file") MultipartFile multipartFile) {
        try {
            productCalibrationExcel(multipartFile);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(e.getMessage());
@@ -73,6 +91,12 @@
                new LocMatListener(locMastService,locDetlMapper,getUserId())).sheet().doReadSync();
    }
    @Transactional(rollbackFor = Exception.class)
    public void productCalibrationExcel(MultipartFile multipartFile) throws IOException {
        EasyExcel.read(multipartFile.getInputStream(), ProductCalibrationExcelParam.class,
                new ProductCalibrationImportListener(sqlSessionFactory)).sheet().doReadSync();
    }
    @RequestMapping(value = "/locDetl/update")
    public R update1() {
        if (!locDetlService.updateLocNo("0402805", "0402804")) {
src/main/java/com/zy/asrs/entity/param/ProductCalibrationExcelParam.java
New file
@@ -0,0 +1,21 @@
package com.zy.asrs.entity.param;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
 * @author pang.jiabao
 * @description 产品校验excel导入param
 * @createDate 2025/4/29 9:19
 */
@Data
public class ProductCalibrationExcelParam {
    // index从0开始
    @ExcelProperty(value = "卷号",index = 0)
    private String rollNo;
    @ExcelProperty(value = "校验结果 合格/不合格",index = 1)
    private String qualified;
}
src/main/java/com/zy/asrs/importexcle/ProductCalibrationImportListener.java
New file
@@ -0,0 +1,103 @@
package com.zy.asrs.importexcle;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.core.exception.CoolException;
import com.zy.asrs.entity.param.ProductCalibrationExcelParam;
import com.zy.asrs.mapper.LocDetlMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.ArrayList;
import java.util.List;
/**
 * @author pang.jiabao
 * @description 监听立库已有物料excel数据导入
 * @createDate 2023/10/9 11:13
 */
@Slf4j
public class ProductCalibrationImportListener extends AnalysisEventListener<ProductCalibrationExcelParam> {
    /**
     * 每隔1000条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    private int count = 0;
    List<ProductCalibrationExcelParam> list = new ArrayList<>();
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private final SqlSessionFactory sqlSessionFactory;
    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     */
    public ProductCalibrationImportListener(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }
    /**
     * 这个每一条数据解析都会来调用
     */
    @SneakyThrows
    @Override
    public void invoke(ProductCalibrationExcelParam data, AnalysisContext context) {
        log.info("成品校验解析到第 {} 条数据:{}", ++count, JSON.toJSONString(data));
        if ("合格".equals(data.getQualified()) || "不合格".equals(data.getQualified())) {
            list.add(data);
        } else {
            throw new CoolException("成品校验校验结果异常:" + data);
        }
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }
    /**
     * 所有数据解析完成了 都会来调用
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        if (list.size() > 0) {
            saveData();
        }
        log.info("成品校验所有数据解析完成!");
    }
    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", list.size());
        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
            LocDetlMapper mapper = sqlSession.getMapper(LocDetlMapper.class);
            list.forEach(productCalibrationExcelParam -> {
                mapper.updateQualifiedByRollNo(productCalibrationExcelParam.getRollNo(), productCalibrationExcelParam.getQualified());
            });
            sqlSession.commit();
        }
        log.info("成品校验存储数据库成功!");
    }
    /**
     * 解析出现错误会进入该方法 具体看源代码或文档
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        log.error("成品校验处理异常:" + exception.getMessage());
        throw exception;
    }
}
src/main/java/com/zy/asrs/mapper/LocDetlMapper.java
@@ -105,4 +105,11 @@
     * @param status 状态
     */
    void updateLhStsByLocNo(@Param("locNo") String locNo,@Param("status") int status);
    /**
     * 更新成品校验结果
     * @param rollNo 卷号
     * @param qualified 校验结果 合格/不合格
     */
    void updateQualifiedByRollNo(@Param("rollNo") String rollNo, @Param("qualified") String qualified);
}
src/main/resources/mapper/LocDetlMapper.xml
@@ -443,6 +443,9 @@
    <update id="updateLhStsByLocNo">
        update asr_loc_detl set dead_warn = #{status},modi_time = getdate() where loc_no = #{locNo}
    </update>
    <update id="updateQualifiedByRollNo">
        update asr_loc_detl set three_code = #{qualified} where model = #{rollNo}
    </update>
</mapper>
src/main/webapp/static/js/locDetl/locDetl.js
@@ -46,12 +46,13 @@
    return cols;
}
layui.use(['table','laydate', 'form'], function(){
layui.use(['table','laydate', 'form','upload','layer'], function(){
    var table = layui.table;
    var $ = layui.jquery;
    var layer = layui.layer;
    var layDate = layui.laydate;
    var form = layui.form;
    var upload = layui.upload;
    // 数据渲染
    tableIns = table.render({
@@ -97,6 +98,28 @@
        }
    });
    upload.render({
        elem: '#uploadExcel', // 绑定元素
        url: baseUrl+'/productCalibration', // 上传接口,替换为你的后端接口
        headers:{'token': localStorage.getItem('token')},
        accept: 'file', // 允许上传的文件类型
        exts: 'xls|xlsx', // 允许上传的文件后缀
        done: function(res){
            // 上传完毕回调
            if(res.code === 200){
                layer.msg(res.msg);
                console.log('文件数据:', res.data);
            } else {
                layer.msg(res.msg || '上传失败');
            }
        },
        error: function(){
            // 请求异常回调
            layer.msg('上传失败,请重试');
        }
    });
    // 监听排序事件
    table.on('sort(locDetl)', function (obj) {
        var searchData = {};
src/main/webapp/views/locDetl/locDetl.html
@@ -9,6 +9,11 @@
    <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">
    <style>
    #uploadExcel{
        display: none;
    }
    </style>
</head>
<body>
@@ -71,7 +76,8 @@
</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>
        <button id="uploadExcel" class="layui-btn layui-btn-primary layui-btn-sm" >产品校验</button>
        <button class="layui-btn layui-btn-primary layui-btn-sm" id="btn-export" lay-event="exportData" style="margin-top: 1px">导出</button>
    </div>
<!--    <input type="file" id="fileInput" accept=".xlsx, .xls">-->
<!--    <button class="layui-btn layui-btn-primary layui-btn-sm" id="btn-import" onclick="exportExc()" style="margin-top: 10px">导入</button>-->