自动化立体仓库 - WMS系统
zhou zhou
2025-09-27 33bdd9772bf8bc4a4dbd02b690b57921f7606e18
#websocket
5个文件已添加
5个文件已修改
561 ■■■■■ 已修改文件
pom.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/MatDto.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/WrkDetlMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/WrkDetlService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WrkDetlServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/webSocketConfig/LedCommand.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/webSocketConfig/LedWebsocket.java 272 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/webSocketConfig/WebSocketConfig.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/webSocketConfig/WebSocketServer.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkDetlMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -116,6 +116,17 @@
            <artifactId>truelicense-core</artifactId>
            <version>1.33</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.26</version>
        </dependency>
    </dependencies>
    <build>
src/main/java/com/zy/asrs/entity/param/MatDto.java
New file
@@ -0,0 +1,80 @@
package com.zy.asrs.entity.param;
import lombok.Data;
/**
 * Created by vincent on 2020/8/6
 */
@Data
public class MatDto {
    // 物料编号
    private String matnr;
    // 物料名称
    private String maknx;
    private String batch;
    private String specs;
    // 客户信息
    private String manu;
    // 备注
    private String memo;
    // 物料数量
    private Double count;
    private Double total;
    private String orderNo;
    private String customer;
    public MatDto() {
    }
    public MatDto(String matnr, String maknx, String batch, String specs, String manu, String memo, Double count, Double total) {
        this.matnr = matnr;
        this.maknx = maknx;
        this.batch = batch;
        this.specs = specs;
        this.manu = manu;
        this.memo = memo;
        this.count = count;
        this.total = total;
    }
    public MatDto(String matnr, String maknx, String batch, String specs, String manu, String memo, Double count, Double total, String orderNo, String customer) {
        this.matnr = matnr;
        this.maknx = maknx;
        this.batch = batch;
        this.specs = specs;
        this.manu = manu;
        this.memo = memo;
        this.count = count;
        this.total = total;
        this.orderNo = orderNo;
        this.customer = customer;
    }
    public MatDto(String matNo, String maknx, Double count) {
        this.matnr = matNo;
        this.maknx = maknx;
        this.count = count;
    }
    public MatDto(String matNo, String maknx, Double count, String specs) {
        this.specs = specs;
        this.matnr = matNo;
        this.maknx = maknx;
        this.count = count;
    }
    public MatDto(String matNo, String maknx, Double count, Double total, String specs) {
        this.specs = specs;
        this.matnr = matNo;
        this.maknx = maknx;
        this.count = count;
        this.total = total;
    }
}
src/main/java/com/zy/asrs/mapper/WrkDetlMapper.java
@@ -23,4 +23,6 @@
    int updateInspect( @Param("wrkNo")Integer wrkNo, @Param("matnr")String matnr, @Param("batch")String batch);
    List<WrkDetl> selectPakoutQuery(@Param("staNo")Integer staNo, @Param("matnr")String matnr);
    List<WrkDetl> findByWorkNo(Integer workNo);
}
src/main/java/com/zy/asrs/service/WrkDetlService.java
@@ -21,4 +21,5 @@
    List<WrkDetl> selectPakoutQuery(Integer staNo, String matnr);
    List<WrkDetl> findByWorkNo(Integer wrkNo);
}
src/main/java/com/zy/asrs/service/impl/WrkDetlServiceImpl.java
@@ -13,6 +13,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -79,4 +80,9 @@
    public List<WrkDetl> selectPakoutQuery(Integer staNo, String matnr) {
        return this.baseMapper.selectPakoutQuery(staNo, matnr);
    }
    @Override
    public List<WrkDetl> findByWorkNo(Integer workNo) {
        return this.baseMapper.findByWorkNo(workNo);
    }
}
src/main/java/com/zy/asrs/webSocketConfig/LedCommand.java
New file
@@ -0,0 +1,53 @@
package com.zy.asrs.webSocketConfig;
import com.core.common.Cools;
import com.zy.asrs.entity.param.MatDto;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
 * led命令报文
 * Created by vincent on 2020/8/11
 */
@Data
public class LedCommand extends Object {
    private String title;
    private Integer workNo;
    private Integer staNo;
    private Integer sourceStaNo;
    private String locNo;
    private String sourceLocNo;
    private List<MatDto> matDtos = new ArrayList<>();
    private boolean emptyMk = false;
    private Integer ioType;
    private String barcode;
    @Override
    public String toString() {
        StringBuffer s = new StringBuffer();
        s.append("工作号[" + this.workNo + "]\n");
        s.append("工作类型[" + this.title + "]\n");
        if (!Cools.isEmpty(this.barcode)) {
            s.append("托盘码[" + this.barcode + "]\n");
        }
        if (!this.emptyMk){
            for (MatDto matDto : matDtos) {
                s.append("[商品编码:" + matDto.getMatnr() + ", 数量:" + matDto.getCount() + "]\n");
            }
        }
        return s.toString();
    }
}
src/main/java/com/zy/asrs/webSocketConfig/LedWebsocket.java
New file
@@ -0,0 +1,272 @@
package com.zy.asrs.webSocketConfig;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Arith;
import com.core.common.Cools;
import com.core.common.R;
import com.core.exception.CoolException;
import com.zy.asrs.domain.vo.LocChartPie;
import com.zy.asrs.entity.*;
import com.zy.asrs.domain.dto.WorkChartAxis;
import com.zy.asrs.entity.param.MatDto;
import com.zy.asrs.mapper.ReportQueryMapper;
import com.zy.asrs.service.*;
import com.zy.common.service.CommonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@Component
@Slf4j
public class LedWebsocket {
    private static final String[] WEEK = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
    @Autowired
    private ReportQueryMapper reportQueryMapper;
    @Autowired
    private WebSocketServer webSocketServer;
    @Autowired
    private LocDetlService locDetlService;
    @Autowired
    private BasDevpService basDevpService;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private WrkDetlService wrkDetlService;
    @Autowired
    private OrderDetlService orderDetlService;
    @Scheduled(cron = "0/2 * * * * ? ")
    private void send() {
        //饼图
        List<Map<String, Object>> pie = new ArrayList<>();
        LocChartPie locUseRate = reportQueryMapper.getLocUseRate();
        if(locUseRate!=null) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "在库");
            map.put("value", locUseRate.getFqty());
            pie.add(map);
            Map<String, Object> map1 = new HashMap<>();
            map1.put("name", "空");
            map1.put("value", locUseRate.getOqty());
            pie.add(map1);
            Map<String, Object> map2 = new HashMap<>();
            map2.put("name", "使用");
            map2.put("value", locUseRate.getUqty());
            pie.add(map2);
            Map<String, Object> map3 = new HashMap<>();
            map3.put("name", "禁用");
            map3.put("value", locUseRate.getXqty());
            pie.add(map3);
        }
        // 总库位数
        Integer total = (int) Arith.add(0, locUseRate.getFqty(), locUseRate.getOqty(), locUseRate.getUqty(), locUseRate.getXqty());
        // 使用中
        Integer used = locUseRate.getFqty() + locUseRate.getUqty();
        // 库位使用率
        double usedDivides = Arith.divides(3, used, total);
        double usedPr = Arith.multiplys(1, usedDivides, 100);
        //折线图
        Map<String,Object> map=new HashMap<String, Object>();
        List<AxisBean> list = new ArrayList<AxisBean>();
        List<WorkChartAxis> listChart = reportQueryMapper.getChartAxis();
        if(listChart!=null) {
            ArrayList<Integer> data1 = new ArrayList<Integer>();
            ArrayList<Integer> data2 = new ArrayList<Integer>();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DATE, -12);
            for(int i=0;i<12;i++) {
                boolean flag = true;
                calendar.add(Calendar.DATE, 1);
                String str = sf.format(calendar.getTime());
                for(WorkChartAxis workChart : listChart) {
                    if(str.equals(workChart.getYmd())) {
                        data1.add(workChart.getInqty());
                        data2.add(workChart.getOutqty());
                        flag = false;
                        break;
                    }
                }
                if(flag) {
                    data1.add(0);
                    data2.add(0);
                }
            }
            AxisBean inqty = new AxisBean();
            inqty.setName("入库数量");
            Integer[] array1 = new Integer[data1.size()];
            inqty.setData(data1.toArray(array1));
            list.add(inqty);
            AxisBean outqty = new AxisBean();
            outqty.setName("出库数量");
            Integer[] array2 = new Integer[data2.size()];
            outqty.setData(data2.toArray(array2));
            list.add(outqty);
        }
        //仓库数据
        EntityWrapper<LocDetl> locDetlEntityWrapper = new EntityWrapper<>();
        locDetlEntityWrapper.setSqlSelect("TOP 5 matnr,SUM(anfme) as matnrCount").groupBy("matnr").orderBy("matnrCount",false);
        List<Map<String, Object>>  selectMap = locDetlService.selectMaps(locDetlEntityWrapper);
        Date now = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
//         Map<String, Object> map = new HashMap<>();
         map.put("to","all");
         map.put("message", Cools.add("type", "default").add("pie", pie)
                 .add("stockCunt", locUseRate.getFqty())
                 .add("emptyCount", locUseRate.getOqty())
                 .add("noneCount", locUseRate.getXqty())
                 .add("total", total)
                 .add("used", used)
                 .add("usedPr", usedPr)
                 .add("rows",list)
                 .add("year", calendar.get(Calendar.YEAR))
                 .add("month", CommonService.zerofill(String.valueOf(calendar.get(Calendar.MONTH)+1), 2))
                 .add("day", CommonService.zerofill(String.valueOf(calendar.get(Calendar.DATE)), 2))
                 .add("hour", CommonService.zerofill(String.valueOf(calendar.get(Calendar.HOUR_OF_DAY)), 2))
                 .add("minute", CommonService.zerofill(String.valueOf(calendar.get(Calendar.MINUTE)), 2))
                 .add("second", CommonService.zerofill(String.valueOf(calendar.get(Calendar.SECOND)) , 2))
                 .add("week", WEEK[calendar.get(Calendar.DAY_OF_WEEK)-1])
                 .add("inventoryData",selectMap));
        webSocketServer.onMessage(JSONObject.toJSONString(map),null,"all");
    }
    @Scheduled(cron = "0/2 * * * * ? ")
    private void TaskOrErrorSend(){
        Map<String,Object> map=new HashMap<>();
        BasDevp basDevp = basDevpService.selectOne(new EntityWrapper<BasDevp>().eq("dev_no", 1002));
        if (basDevp == null || Cools.isEmpty(basDevp.getDecDesc()) || basDevp.getWrkNo() == 0){
            return;
        }
        if (!Cools.isEmpty(basDevp.getDecDesc())){
            map.put("to","1002");
            map.put("message",Cools.add("type", "error").add("errMsg",basDevp.getDecDesc()));
            webSocketServer.onMessage(JSONObject.toJSONString(map),null,"1002");
        }else if (basDevp.getWrkNo() != 0){
            WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", basDevp.getWrkNo()));
            if (null == wrkMast){
                return;
            }
            List<LedCommand> commandList = getCommandList(basDevp.getWrkNo().toString());
            map.put("to","1002");
            map.put("message",Cools.add("type", "task").add("taskList",commandList));
            webSocketServer.onMessage(JSONObject.toJSONString(map),null,"1002");
        }
    }
    public List<LedCommand> getCommandList(String taskNo){
        List<LedCommand> commands = new ArrayList<>();
        // 工作档集合
        List<WrkMast> wrkMasts = new ArrayList<>();
        // 获取工作档数据
        WrkMast wrkMast = wrkMastService.selectById(taskNo);
        if (null == wrkMast) { return null; }
        wrkMasts.add(wrkMast);
        // 组装命令
        LedCommand ledCommand = new LedCommand();
        ledCommand.setWorkNo(wrkMast.getWrkNo());
        ledCommand.setIoType(wrkMast.getIoType());
        wrkMasts.add(wrkMast);
        // 出库模式
        switch (wrkMast.getIoType()) {
            case 1:
                ledCommand.setTitle("全板入库");
                break;
            case 10:
                ledCommand.setTitle("空板入库");
                break;
            case 101:
                ledCommand.setTitle("全板出库");
                break;
            case 103:
                ledCommand.setTitle("拣料出库");
                break;
            case 104:
                ledCommand.setTitle("并板出库");
                break;
            case 107:
                ledCommand.setTitle("盘点出库");
                break;
            case 110:
                ledCommand.setTitle("空板出库");
                ledCommand.setEmptyMk(true);
                break;
            default:
                break;
        }
        ledCommand.setSourceLocNo(wrkMast.getSourceLocNo());
        ledCommand.setStaNo(wrkMast.getStaNo());
        ledCommand.setBarcode(wrkMast.getBarcode());
        if (wrkMast.getIoType() != 110 && wrkMast.getIoType() != 10) {
            List<WrkDetl> wrkDetls = wrkDetlService.findByWorkNo(wrkMast.getWrkNo());
            wrkDetls.forEach(wrkDetl -> {
                Double total = 0.0;
                EntityWrapper<LocDetl> wrapper = new EntityWrapper<>();
                LocDetl locDetl = locDetlService.selectOne(wrapper.eq("zpallet", wrkDetl.getZpallet()).eq("matnr", wrkDetl.getMatnr()));
                if (Cools.isEmpty(locDetl)) {
                    total = wrkDetl.getAnfme();
                } else {
                    total = locDetl.getAnfme();
                }
                if (!Cools.isEmpty(wrkDetl.getOrderNo())){
                    OrderDetl orderDetl = orderDetlService.selectOne(new EntityWrapper<OrderDetl>().eq("order_no", wrkDetl.getOrderNo())
                            .eq("matnr", wrkDetl.getMatnr()).eq("batch", wrkDetl.getBatch()));
                    if (wrkMast.getIoType() == 101 || wrkMast.getIoType() == 1) {
                        ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(),total,orderDetl.getSuppCode(),orderDetl.getSku()));
                    }
                    if (wrkMast.getIoType() == 103 && (null == wrkDetl.getInspect() || 0 == wrkDetl.getInspect())) {
                        ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(),total,orderDetl.getSuppCode(),orderDetl.getSku()));
                    }
                    if (wrkMast.getIoType() == 107 || wrkMast.getIoType() == 104) {
                        ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(),total,orderDetl.getSuppCode(),orderDetl.getSku()));
                    }
                }else {
                    if (wrkMast.getIoType() == 101 || wrkMast.getIoType() == 1) {
                        ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(),total));
                    }
                    if (wrkMast.getIoType() == 103 && (null == wrkDetl.getInspect() || 0 == wrkDetl.getInspect())) {
                        ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(),total));
                    }
                    if (wrkMast.getIoType() == 107 || wrkMast.getIoType() == 104) {
                        ledCommand.getMatDtos().add(new MatDto(wrkDetl.getMatnr(), wrkDetl.getMaktx(), wrkDetl.getBatch(), wrkDetl.getSpecs(), wrkDetl.getManu(), wrkDetl.getMemo(), wrkDetl.getAnfme(),total));
                    }
                }
            });
        }
        commands.add(ledCommand);
        Set<Integer> workNos = wrkMasts.stream().map(WrkMast::getWrkNo).collect(Collectors.toSet());
        // 修改主档led标记
        for (WrkMast wrkMast1 : wrkMasts) {
            wrkMast1.setOveMk("Y");
            wrkMast1.setModiTime(new Date());
            if (!wrkMastService.update(wrkMast1,new EntityWrapper<WrkMast>().eq("wrk_No",wrkMast1.getWrkNo()))) {
                throw new CoolException("更新工作档失败");
            }
        }
        return commands;
    }
}
src/main/java/com/zy/asrs/webSocketConfig/WebSocketConfig.java
New file
@@ -0,0 +1,17 @@
package com.zy.asrs.webSocketConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
    /**
     * 注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
src/main/java/com/zy/asrs/webSocketConfig/WebSocketServer.java
New file
@@ -0,0 +1,116 @@
package com.zy.asrs.webSocketConfig;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ServerEndpoint(value = "/led/{username}")
@Component
@Service
public class WebSocketServer {
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    /**
     * 记录当前在线连接数
     */
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        sessionMap.put(username, session);
        log.info("有新用户加入,username={}, 当前在线人数为:{}", username, sessionMap.size());
        JSONObject result = new JSONObject();
        JSONArray array = new JSONArray();
        result.set("users", array);
        for (Object key : sessionMap.keySet()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.set("username", key);
            // {"username", "zhang", "username": "admin"}
            array.add(jsonObject);
        }
//        {"users": [{"username": "zhang"},{ "username": "admin"}]}
        sendAllMessage(JSONUtil.toJsonStr(result));  // 后台发送消息给所有的客户端
    }
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("username") String username) {
        sessionMap.remove(username);
        log.info("有一连接关闭,移除username={}的用户session, 当前在线人数为:{}", username, sessionMap.size());
    }
    /**
     * 收到客户端消息后调用的方法
     * 后台收到客户端发送过来的消息
     * onMessage 是一个消息的中转站
     * 接受 浏览器端 socket.send 发送过来的 json数据
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("username") String username) {
//        log.info("服务端收到用户username={}的消息:{}", username, message);
        JSONObject obj = JSONUtil.parseObj(message);
        String toUsername = obj.getStr("to"); // to表示发送给哪个用户,比如 admin
        String text = obj.getStr("message"); // 发送的消息文本  hello
        // {"to": "admin", "text": "聊天文本"}
        if ("heartBeat".equals(toUsername)) {
            log.info("心跳");
        }else if ("all".equals(toUsername)) {
            sendAllMessage(text);
        }else {
            Session toSession = sessionMap.get(toUsername); // 根据 to用户名来获取 session,再通过session发送消息文本
            if (toSession != null) {
                // 服务器端 再把消息组装一下,组装后的消息包含发送人和发送的文本内容
                // {"from": "zhang", "text": "hello"}
                JSONObject jsonObject = new JSONObject();
                jsonObject.set("from", username);  // from 是 zhang
                jsonObject.set("text", text);  // text 同上面的text
                this.sendMessage(text, toSession);
//            log.info("发送给用户username={},消息:{}", toUsername, jsonObject.toString());
            } else {
//                log.info("发送失败,未找到用户username={}的session", toUsername);
            }
        }
    }
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }
    /**
     * 服务端发送消息给客户端
     */
    private void sendMessage(String message, Session toSession) {
        try {
//            log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
            toSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }
    /**
     * 服务端发送消息给所有客户端
     */
    private void sendAllMessage(String message) {
        try {
            for (Session session : sessionMap.values()) {
//                log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }
}
src/main/resources/mapper/WrkDetlMapper.xml
@@ -107,5 +107,8 @@
        and awm.sta_no = #{staNo}
        and awd.matnr + '-' + awd.batch = #{matnr}
    </select>
    <select id="findByWorkNo" resultMap="BaseResultMap">
        select wrk_no, matnr, maktx, anfme ,specs,batch from asr_wrk_detl where 1=1 and wrk_no = #{workNo}
    </select>
</mapper>