From 02a1ae81eba7b48223052fb833859f0a65dd7d21 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 19 十月 2026 17:31:08 +0800
Subject: [PATCH] feat(mes): 实现袋码大批量生成异步任务功能
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java | 118 +++++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 91 insertions(+), 27 deletions(-)
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java
index 46b6160..c5523de 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/bagcode/MesProBagCodeController.java
@@ -13,6 +13,7 @@
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeBindReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeGenerateRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeGenerateReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeGenerateTaskRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodePageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeRawGenerateReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeReplaceReqVO;
@@ -21,13 +22,16 @@
import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeTraceRespVO;
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.bagcode.MesProBagCodeGenerateTaskDO;
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.enums.pro.MesProBagCodeGenerateTaskStatusEnum;
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.MesProBagCodeGenerateTaskService;
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 +46,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 +58,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
@@ -67,11 +69,17 @@
@Resource
private MesProBagCodeService bagCodeService;
@Resource
+ private MesProBagCodeGenerateTaskService generateTaskService;
+ @Resource
private MesProBatchService batchService;
@Resource
private AdminUserApi adminUserApi;
@Resource
private MesMdmItemService mdmItemService;
+ @Resource
+ private MesProQrLabelAssembler labelAssembler;
+ @Resource
+ private MesProQrExportProperties qrExportProperties;
@PostMapping("/generate")
@Operation(summary = "鐢熸垚琚嬬爜鏁版嵁鍖咃紙涓�琚嬩竴鐮侊級锛岀疮璁¤揪鍒伴槇鍊兼椂鑷姩鐢熸垚鎵樼洏鐮�")
@@ -86,6 +94,23 @@
public CommonResult<MesProBagCodeGenerateRespVO> generateRawBagCodes(
@Valid @RequestBody MesProBagCodeRawGenerateReqVO rawGenerateReqVO) {
return success(bagCodeService.generateRawBagCodes(rawGenerateReqVO));
+ }
+
+ @GetMapping("/generate-task/get")
+ @Operation(summary = "鑾峰緱琚嬬爜鐢熸垚浠诲姟锛堝ぇ鎵归噺鐢熸垚鐨勮繘搴﹁疆璇級")
+ @Parameter(name = "id", description = "浠诲姟缂栧彿", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:pro-bag-code:query')")
+ public CommonResult<MesProBagCodeGenerateTaskRespVO> getGenerateTask(@RequestParam("id") Long id) {
+ return success(buildGenerateTaskRespVO(generateTaskService.getTask(id)));
+ }
+
+ @PostMapping("/generate-task/cancel")
+ @Operation(summary = "鍙栨秷琚嬬爜鐢熸垚浠诲姟锛堝仠姝㈢敓鎴愬苟娓呯悊鍗婃垚鍝侊級")
+ @Parameter(name = "id", description = "浠诲姟缂栧彿", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:pro-bag-code:create')")
+ public CommonResult<Boolean> cancelGenerateTask(@RequestParam("id") Long id) {
+ generateTaskService.cancel(id);
+ return success(true);
}
@PostMapping("/replace")
@@ -142,12 +167,12 @@
}
@GetMapping("/get-by-code")
- @Operation(summary = "鎵爜杩芥函锛氭牴鎹鐮侊紙浜岀淮鐮佸唴瀹癸級鍙嶆煡鎵规銆佷骇绾裤�佽矗浠讳汉绛変俊鎭�")
+ @Operation(summary = "鍐呴儴鎵爜鏌ヨ锛氭牴鎹拷婧爜鎴栦笟鍔$爜鍙嶆煡琚嬨�佹壒娆°�佷骇绾夸俊鎭�")
@Parameter(name = "code", description = "鍗曞厓璇嗗埆浠g爜锛堝浗鏍囷細涓嶈秴杩� 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);
}
@@ -160,6 +185,13 @@
public CommonResult<PageResult<MesProBagCodeRespVO>> getBagCodePage(@Valid MesProBagCodePageReqVO pageReqVO) {
PageResult<MesProBagCodeDO> pageResult = bagCodeService.getBagCodePage(pageReqVO);
return success(new PageResult<>(buildBagCodeRespVOList(pageResult.getList()), pageResult.getTotal()));
+ }
+
+ @GetMapping("/unbound-ton-bags")
+ @Operation(summary = "鑾峰緱鍙粦瀹氱敓浜ф壒娆$殑鍚ㄨ")
+ @PreAuthorize("@ss.hasAnyPermissions('mes:pro-batch:create', 'mes:pro-batch:update', 'mes:pro-bag-code:query')")
+ public CommonResult<List<MesProBagCodeRespVO>> getUnboundTonBags() {
+ return success(buildBagCodeRespVOList(bagCodeService.getUnboundTonBags()));
}
@GetMapping("/list-by-uuid")
@@ -211,13 +243,54 @@
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 MesProBagCodeGenerateTaskRespVO buildGenerateTaskRespVO(MesProBagCodeGenerateTaskDO task) {
+ MesProBagCodeGenerateTaskRespVO respVO = BeanUtils.toBean(task, MesProBagCodeGenerateTaskRespVO.class);
+ for (MesProBagCodeGenerateTaskStatusEnum value : MesProBagCodeGenerateTaskStatusEnum.values()) {
+ if (value.getStatus().equals(task.getStatus())) {
+ respVO.setStatusName(value.getName());
+ break;
+ }
+ }
+ Integer total = task.getTotalCount();
+ if (total == null || total <= 0) {
+ respVO.setProgress(0);
+ } else {
+ int finished = task.getFinishedCount() == null ? 0 : task.getFinishedCount();
+ respVO.setProgress((int) Math.min(100L, (long) finished * 100 / total));
+ }
+ return respVO;
+ }
private List<MesProBagCodeRespVO> buildBagCodeRespVOList(List<MesProBagCodeDO> list) {
if (CollUtil.isEmpty(list)) {
@@ -278,24 +351,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;
}
}
--
Gitblit v1.9.3