liu
10 小时以前 66517edf1de22c8203daa256abffddae43bae704
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java
@@ -22,12 +22,12 @@
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.framework.qrcode.MesProQrLabelBuilder;
import cn.iocoder.yudao.module.mes.framework.qrcode.QrCodeImageUtils;
import cn.iocoder.yudao.module.mes.framework.qrcode.QrLabelInfo;
import cn.iocoder.yudao.module.mes.framework.qrexport.MesProQrExportProperties;
import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
import cn.iocoder.yudao.module.mes.service.pro.bagcode.MesProBagCodeService;
import cn.iocoder.yudao.module.mes.service.pro.batch.MesProBatchService;
import cn.iocoder.yudao.module.mes.service.pro.qrexport.MesProQrLabelAssembler;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
@@ -42,11 +42,9 @@
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -56,7 +54,7 @@
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_BAG_CODE_NOT_EXISTS;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_QR_EXPORT_PARAMS_INVALID;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_QR_EXPORT_TOO_MANY;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_QR_EXPORT_TOO_MANY_FOR_SYNC;
@Tag(name = "管理后台 - MES 袋码赋码(一袋一码)")
@RestController
@@ -72,6 +70,10 @@
    private AdminUserApi adminUserApi;
    @Resource
    private MesMdmItemService mdmItemService;
    @Resource
    private MesProQrLabelAssembler labelAssembler;
    @Resource
    private MesProQrExportProperties qrExportProperties;
    @PostMapping("/generate")
    @Operation(summary = "生成袋码数据包(一袋一码),累计达到阈值时自动生成托盘码")
@@ -142,12 +144,12 @@
    }
    @GetMapping("/get-by-code")
    @Operation(summary = "扫码追溯:根据袋码(二维码内容)反查批次、产线、责任人等信息")
    @Operation(summary = "内部扫码查询:根据追溯码或业务码反查袋、批次、产线信息")
    @Parameter(name = "code", description = "单元识别代码(国标:不超过 20 个字符,数字或字母数字组合)",
            required = true, example = "0286267849370923")
    @PreAuthorize("@ss.hasPermission('mes:pro-bag-code:query')")
    public CommonResult<MesProBagCodeTraceRespVO> getBagCodeByCode(@RequestParam("code") String code) {
        MesProBagCodeDO bagCode = bagCodeService.getBagCodeByCode(code);
        MesProBagCodeDO bagCode = bagCodeService.getBagCodeByScanCode(code);
        if (bagCode == null) {
            throw exception(PRO_BAG_CODE_NOT_EXISTS);
        }
@@ -211,13 +213,36 @@
        if (CollUtil.isEmpty(list)) {
            throw exception(PRO_BAG_CODE_NOT_EXISTS);
        }
        if (list.size() > QrCodeImageUtils.MAX_QR_EXPORT) {
            throw exception(PRO_QR_EXPORT_TOO_MANY);
        }
        QrCodeImageUtils.writeZip(response, zipName, buildBagCodeQrLabels(list));
        assertSyncExportAllowed(list.size());
        QrCodeImageUtils.writeZip(response, zipName, labelAssembler.buildBagCodeLabels(list));
    }
    // ==================== 拼接 VO ====================
    @PostMapping("/generate-business-code")
    @Operation(summary = "补生成已有袋码的出入库业务码(已有码值不变)")
    @PreAuthorize("@ss.hasPermission('mes:pro-bag-code:create')")
    public CommonResult<Integer> generateBusinessCodes(@Valid @RequestBody
            cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagBusinessCodeGenerateReqVO reqVO) {
        return success(bagCodeService.generateBusinessCodes(reqVO.getIds()));
    }
    @GetMapping("/export-business-qr")
    @Operation(summary = "导出出入库业务码二维码 ZIP(二维码仅编码业务码值)")
    @PreAuthorize("@ss.hasPermission('mes:pro-bag-code:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportBusinessQr(@RequestParam(value = "uuid", required = false) String uuid,
                                 @RequestParam(value = "batchId", required = false) Long batchId,
                                 HttpServletResponse response) throws IOException {
        List<MesProBagCodeDO> list;
        if (StrUtil.isNotBlank(uuid)) list = bagCodeService.getPrintableBagCodeListByUuid(uuid);
        else if (batchId != null) list = bagCodeService.getPrintableBagCodeListByBatchId(batchId);
        else throw exception(PRO_QR_EXPORT_PARAMS_INVALID);
        if (CollUtil.isEmpty(list)) throw exception(PRO_BAG_CODE_NOT_EXISTS);
        assertSyncExportAllowed(list.size());
        QrCodeImageUtils.writeZip(response, "袋码业务二维码-" + (StrUtil.isNotBlank(uuid) ? uuid : batchId),
                labelAssembler.buildBagBusinessLabels(list));
    }
    private List<MesProBagCodeRespVO> buildBagCodeRespVOList(List<MesProBagCodeDO> list) {
        if (CollUtil.isEmpty(list)) {
@@ -278,24 +303,15 @@
    }
    /**
     * 构建袋码二维码标签列表(二维码编码纯码值,图片叠加关键信息文字)
     * 同步导出只承接小批量
     * <p>
     * 数量超过分界线时必须走后台导出任务:同步响应会随张数线性变长(上万张可达数分钟、响应体上 GB),
     * 必然被网关或浏览器截断,用户看到的将是「下载失败」而不是可操作的提示。
     */
    private List<QrLabelInfo> buildBagCodeQrLabels(List<MesProBagCodeDO> list) {
        // 1. 获得关联数据(批次、品种、责任人);品种集合含袋码自身品种与历史批次品种
        Map<Long, MesProBatchDO> batchMap = convertMap(
                batchService.getBatchList(convertSet(list, MesProBagCodeDO::getBatchId)), MesProBatchDO::getId);
        Set<Long> itemIds = convertSet(list, MesProBagCodeDO::getItemId);
        itemIds.addAll(convertSet(batchMap.values(), MesProBatchDO::getItemId));
        Map<Long, MesMdmItemDO> itemMap = mdmItemService.getItemMap(itemIds);
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
                convertSet(batchMap.values(), MesProBatchDO::getOwnerUserId));
        // 2. 构建标签
        List<QrLabelInfo> labels = new ArrayList<>(list.size());
        for (MesProBagCodeDO bagCode : list) {
            labels.add(MesProQrLabelBuilder.buildBagCodeLabel(
                    bagCode, batchMap.get(bagCode.getBatchId()), itemMap, userMap));
    private void assertSyncExportAllowed(int count) {
        if (count > qrExportProperties.getSyncThreshold()) {
            throw exception(PRO_QR_EXPORT_TOO_MANY_FOR_SYNC, count, qrExportProperties.getSyncThreshold());
        }
        return labels;
    }
}