2 小时以前 6d910029b6c81db0a2b66caa66952781397b153a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package cn.iocoder.yudao.module.mes.framework.qrcode;
 
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.pallet.MesProPalletDO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 
import java.nio.charset.StandardCharsets;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;
 
/**
 * MES 二维码标签构建器:统一"二维码编码内容 + 图片叠加可读文本"的文本组装规则,
 * 保证批次、托盘、袋码三种标签的关键信息保留一致。
 * <p>
 * 配置了 {@code mes.trace-base-url} 时,二维码内容为 H5 溯源地址(带 code 参数),否则回退为纯码值(兼容旧码)
 */
public final class MesProQrLabelBuilder {
 
    private MesProQrLabelBuilder() {
    }
 
    /**
     * H5 溯源页面基础地址,由 {@code MesQrCodeConfig} 启动时注入;为空时二维码编码纯码值
     */
    private static volatile String traceBaseUrl = "";
 
    public static void setTraceBaseUrl(String traceBaseUrl) {
        MesProQrLabelBuilder.traceBaseUrl = StrUtil.blankToDefault(traceBaseUrl, "");
    }
 
    /**
     * 组装二维码内容:配置了溯源地址则拼 URL,否则返回纯码值
     */
    private static String buildQrCodeContent(String code) {
        if (StrUtil.isEmpty(traceBaseUrl)) {
            return code;
        }
        return traceBaseUrl + "?code=" + URLEncoder.encode(code, StandardCharsets.UTF_8);
    }
 
    /**
     * 批次二维码标签
     */
    public static QrLabelInfo buildBatchLabel(MesProBatchDO batch,
                                              Map<Long, MesMdmItemDO> itemMap,
                                              Map<Long, AdminUserRespDTO> userMap) {
        // 未补录业务信息时用临时批次码作为二维码内容,并明确提示状态;品种/产线等信息缺失时不拼接空文本
        String code = StrUtil.blankToDefault(batch.getCode(), batch.getTempCode());
        LinkedHashMap<String, String> keyValues = new LinkedHashMap<>();
        keyValues.put("批次号", code);
        if (StrUtil.isEmpty(batch.getCode())) {
            keyValues.put("状态", "待补录");
        }
        MesMdmItemDO item = itemMap.get(batch.getItemId());
        if (item != null) {
            keyValues.put("品种", item.getName());
            keyValues.put("规格", item.getSpecification());
        }
        if (StrUtil.isNotEmpty(batch.getLineName()) || StrUtil.isNotEmpty(batch.getLineCode())) {
            keyValues.put("产线", StrUtil.join(" / ", batch.getLineName(), batch.getLineCode()));
        }
        if (batch.getProduceDate() != null) {
            keyValues.put("生产日期", LocalDateTimeUtil.format(batch.getProduceDate(), "yyyy-MM-dd HH:mm"));
        }
        if (batch.getPlanQuantity() != null) {
            keyValues.put("计划数量", String.valueOf(batch.getPlanQuantity()));
        }
        AdminUserRespDTO user = userMap.get(batch.getOwnerUserId());
        if (user != null) {
            keyValues.put("责任人", user.getNickname());
        }
        return QrLabelInfo.builder().fileName(code).code(buildQrCodeContent(code)).keyValues(keyValues).build();
    }
 
    /**
     * 托盘二维码标签
     */
    public static QrLabelInfo buildPalletLabel(MesProPalletDO pallet,
                                               MesProBatchDO batch,
                                               Map<Long, MesMdmItemDO> itemMap,
                                               Map<Long, AdminUserRespDTO> userMap) {
        // 未绑定批次(临时托盘码)时用临时码作为二维码内容并明确提示状态
        String code = StrUtil.blankToDefault(pallet.getCode(), pallet.getTempCode());
        LinkedHashMap<String, String> keyValues = new LinkedHashMap<>();
        keyValues.put("托盘码", code);
        if (StrUtil.isEmpty(pallet.getCode())) {
            keyValues.put("状态", "未绑定批次");
        }
        keyValues.put("托盘序号", pallet.getPalletNo() == null ? "" : String.valueOf(pallet.getPalletNo()));
        if (StrUtil.isNotEmpty(pallet.getBatchCode())) {
            keyValues.put("批次号", pallet.getBatchCode());
        }
        if (pallet.getBagCount() != null) {
            keyValues.put("已装袋数", String.valueOf(pallet.getBagCount()));
        }
        if (batch != null) {
            fillBatchKeyValues(keyValues, batch, itemMap, userMap);
        }
        return QrLabelInfo.builder().fileName(code).code(buildQrCodeContent(code)).keyValues(keyValues).build();
    }
 
    /**
     * 袋码二维码标签
     */
    public static QrLabelInfo buildBagCodeLabel(MesProBagCodeDO bagCode,
                                                MesProBatchDO batch,
                                                Map<Long, MesMdmItemDO> itemMap,
                                                Map<Long, AdminUserRespDTO> userMap) {
        LinkedHashMap<String, String> keyValues = new LinkedHashMap<>();
        keyValues.put("袋码", bagCode.getCode());
        keyValues.put("袋序号", bagCode.getBagNo() == null ? "" : String.valueOf(bagCode.getBagNo()));
        keyValues.put("批次号", bagCode.getBatchCode());
        if (StrUtil.isNotEmpty(bagCode.getPalletCode())) {
            keyValues.put("绑定托盘", bagCode.getPalletCode());
        }
        if (batch != null) {
            fillBatchKeyValues(keyValues, batch, itemMap, userMap);
        }
        return QrLabelInfo.builder().fileName(bagCode.getCode()).code(buildQrCodeContent(bagCode.getCode())).keyValues(keyValues).build();
    }
 
    /**
     * 填充批次公共可读文本(品种、规格、产线、生产日期、责任人)
     */
    private static void fillBatchKeyValues(LinkedHashMap<String, String> keyValues, MesProBatchDO batch,
                                           Map<Long, MesMdmItemDO> itemMap, Map<Long, AdminUserRespDTO> userMap) {
        MesMdmItemDO item = itemMap.get(batch.getItemId());
        if (item != null) {
            keyValues.put("品种", item.getName());
            keyValues.put("规格", item.getSpecification());
        }
        keyValues.put("产线", StrUtil.join(" / ", batch.getLineName(), batch.getLineCode()));
        keyValues.put("生产日期", batch.getProduceDate() == null ? ""
                : LocalDateTimeUtil.format(batch.getProduceDate(), "yyyy-MM-dd HH:mm"));
        AdminUserRespDTO user = userMap.get(batch.getOwnerUserId());
        if (user != null) {
            keyValues.put("责任人", user.getNickname());
        }
    }
 
}