diff --git a/src/main/java/com/xujie/sys/modules/longchuang/controller/ProductionPlanController.java b/src/main/java/com/xujie/sys/modules/longchuang/controller/ProductionPlanController.java index 799c3c5..fb1ec53 100644 --- a/src/main/java/com/xujie/sys/modules/longchuang/controller/ProductionPlanController.java +++ b/src/main/java/com/xujie/sys/modules/longchuang/controller/ProductionPlanController.java @@ -169,10 +169,12 @@ public class ProductionPlanController { @PostMapping("/workReport/reportNodeWithMedia") public R reportNodeWithMedia(@ModelAttribute ProductionPlanNodeReportData data, - @RequestParam("file") MultipartFile[] files) { + @RequestParam(value = "file", required = false) MultipartFile[] files) { String logNo = productionPlanService.reportNodeWithMedia(data, files); boolean reportNode = data == null || !Boolean.FALSE.equals(data.getReportNode()); - return R.ok().put("msg", reportNode ? "报工并上传成功" : "影像上传成功").put("logNo", logNo); + boolean homeLiftStockingStepOnly = !reportNode && isHomeLiftStockingNode(data); + String successMsg = reportNode ? "报工并上传成功" : (homeLiftStockingStepOnly ? "步骤记录成功" : "影像上传成功"); + return R.ok().put("msg", successMsg).put("logNo", logNo); } @PostMapping("/machiningTask/delete") @@ -240,4 +242,15 @@ public class ProductionPlanController { public R getNodeAssigneeUsers(@RequestBody(required = false) ProductionPlanRoleQueryData data) { return R.ok().put("rows", productionPlanService.queryNodeAssigneeUsers(data)); } + + private boolean isHomeLiftStockingNode(ProductionPlanNodeReportData data) { + if (data == null) { + return false; + } + String orderType = data.getOrderType() == null ? "" : data.getOrderType().trim(); + String nodeCode = data.getNodeCode() == null ? "" : data.getNodeCode().trim(); + String nodeName = data.getNodeName() == null ? "" : data.getNodeName().replaceAll("\\s+", ""); + return "HOME_LIFT".equalsIgnoreCase(orderType) + && ("stocking".equalsIgnoreCase(nodeCode) || "仓库配料".equals(nodeName)); + } } diff --git a/src/main/java/com/xujie/sys/modules/longchuang/service/impl/ProductionPlanServiceImpl.java b/src/main/java/com/xujie/sys/modules/longchuang/service/impl/ProductionPlanServiceImpl.java index 01764cc..c3bf13b 100644 --- a/src/main/java/com/xujie/sys/modules/longchuang/service/impl/ProductionPlanServiceImpl.java +++ b/src/main/java/com/xujie/sys/modules/longchuang/service/impl/ProductionPlanServiceImpl.java @@ -103,6 +103,7 @@ public class ProductionPlanServiceImpl implements ProductionPlanService { private static final String NODE_MEDIA_REF_TYPE = "LONGCHUANG_NODE_REPORT_MEDIA"; private static final String MEDIA_INFO_VIDEO_STANDARD = "VIDEO_STD_MP4_H264_AAC"; private static final String MEDIA_INFO_VIDEO_RAW = "VIDEO_RAW"; + private static final String MEDIA_INFO_STEP_ONLY = "STEP_ONLY"; private static final List PACK_MEDIA_STEP_LIST = Arrays.asList( "1平台箱", "2门箱", @@ -111,6 +112,12 @@ public class ProductionPlanServiceImpl implements ProductionPlanService { "5钣金箱", "6铝型材箱" ); + private static final List HOME_LIFT_STOCKING_MEDIA_STEP_LIST = Arrays.asList( + "1平台组装配料", + "2门组装配料", + "3背景墙/吊顶配料", + "4打包配料" + ); @Autowired private ProductionPlanMapper productionPlanMapper; @@ -260,14 +267,16 @@ public class ProductionPlanServiceImpl implements ProductionPlanService { if (data == null || !StringUtils.hasText(data.getOrderType())) { throw new I18nException("lc.production.report.param.incomplete"); } - if (files == null || files.length <= 0) { - throw new XJException("请先拍照或录制视频"); - } String orderType = normalizeOrderType(data.getOrderType()); if (ORDER_TYPE_MACHINING.equals(orderType) && !isMachiningInspectionNode(orderType, data.getNodeCode())) { throw new XJException("机加工仅检验节点支持上传影像"); } boolean reportNode = !Boolean.FALSE.equals(data.getReportNode()); + boolean allowNoFileUpload = !reportNode + && isHomeLiftStockingNode(orderType, data.getNodeCode(), data.getNodeName()); + if ((files == null || files.length <= 0) && !allowNoFileUpload) { + throw new XJException("请先拍照或录制视频"); + } String logNo = reportNode ? reportOrderNode(data, orderType) : validateMediaUploadOnly(data, orderType); saveNodeReportMedia(data, orderType, logNo, files); return logNo; @@ -1317,6 +1326,16 @@ public class ProductionPlanServiceImpl implements ProductionPlanService { checkNodeAssigneePermission(data.getOrderNo(), orderType, data.getNodeCode()); Long userId = getCurrentUserId(); String userName = getCurrentUserName(); + String stockingStep = resolveReportStepForHomeLiftStocking(data, node, orderType); + if (StringUtils.hasText(stockingStep)) { + String stepRemark = "仓库配料步骤:" + stockingStep; + String remark = StringUtils.hasText(data.getRemark()) ? data.getRemark().trim() : ""; + if (!StringUtils.hasText(remark)) { + data.setRemark(stepRemark); + } else if (!remark.contains(stepRemark)) { + data.setRemark(remark + ";" + stepRemark); + } + } productionPlanMapper.updateOrderNodeToDone(data.getOrderNo(), data.getNodeCode(), data.getRemark(), userId); BigDecimal reportQty = data.getReportQty(); boolean qtyRequired = ORDER_TYPE_CABLE_COP.equals(orderType) @@ -1359,6 +1378,10 @@ public class ProductionPlanServiceImpl implements ProductionPlanService { data.setRemark("报工数量:" + data.getReportQty()); } productionPlanMapper.insertNodeReportLog(data); + if (StringUtils.hasText(stockingStep) && !Boolean.TRUE.equals(data.getReportNode())) { + // HOME_LIFT 仓库配料在“确认报工”时也落一条步骤记录,便于日志留痕 + saveStepOnlyMediaRecord(data, orderType, logNo, stockingStep, node, userId, userName); + } return logNo; } @@ -1368,6 +1391,16 @@ public class ProductionPlanServiceImpl implements ProductionPlanService { throw new I18nException("lc.production.report.node.not.exists"); } String mediaStep = resolveMediaStep(data, node, orderType); + Long userId = getCurrentUserId(); + String userName = getCurrentUserName(); + if (files == null || files.length <= 0) { + if (Boolean.FALSE.equals(data.getReportNode()) + && isHomeLiftStockingNode(orderType, node.getNodeCode(), node.getNodeName())) { + saveStepOnlyMediaRecord(data, orderType, logNo, mediaStep, node, userId, userName); + return; + } + throw new XJException("请先拍照或录制视频"); + } String rootPath = StringUtils.hasText(workReportMediaRootPath) ? workReportMediaRootPath : "D:\\longchuang"; File rootDir = new File(rootPath); if (!rootDir.exists() && !rootDir.mkdirs()) { @@ -1390,8 +1423,6 @@ public class ProductionPlanServiceImpl implements ProductionPlanService { throw new XJException("节点影像日期目录创建失败"); } - Long userId = getCurrentUserId(); - String userName = getCurrentUserName(); List savedFileList = new ArrayList<>(); int uploadCount = 0; try { @@ -1473,6 +1504,37 @@ public class ProductionPlanServiceImpl implements ProductionPlanService { } } + private void saveStepOnlyMediaRecord(ProductionPlanNodeReportData data, + String orderType, + String logNo, + String mediaStep, + ProductionPlanOrderNodeData node, + Long userId, + String userName) { + String stepLabel = StringUtils.hasText(mediaStep) ? mediaStep : "步骤记录"; + String placeholderFileName = "仓库配料步骤记录_" + stepLabel + ".txt"; + String placeholderNewFileName = "STEP_ONLY_" + UUID.randomUUID().toString().replace("-", "") + ".txt"; + + SysOssEntity ossEntity = new SysOssEntity(); + ossEntity.setUrl(placeholderNewFileName); + ossEntity.setCreateDate(new Date()); + ossEntity.setFileName(placeholderFileName); + ossEntity.setNewFileName(placeholderNewFileName); + ossEntity.setFileType("txt"); + ossEntity.setFileSuffix("txt"); + ossEntity.setCreatedBy(userName); + ossEntity.setOrderRef1(data.getOrderNo()); + ossEntity.setOrderRef2(node.getNodeCode()); + ossEntity.setOrderRef3(logNo); + ossEntity.setOrderRef4(orderType); + ossEntity.setOrderRef5(String.valueOf(userId)); + ossEntity.setOrderRef6(stepLabel); + ossEntity.setOrderReftype(NODE_MEDIA_REF_TYPE); + ossEntity.setCAdditionalInfo(MEDIA_INFO_STEP_ONLY); + ossEntity.setConclusion(userName); + sysOssService.save(ossEntity); + } + private String resolveMediaStep(ProductionPlanNodeReportData data, ProductionPlanOrderNodeData node, String orderType) { if (node == null) { return ""; @@ -1480,23 +1542,67 @@ public class ProductionPlanServiceImpl implements ProductionPlanService { String nodeCode = StringUtils.hasText(node.getNodeCode()) ? node.getNodeCode().trim() : ""; String nodeName = StringUtils.hasText(node.getNodeName()) ? node.getNodeName().replaceAll("\\s+", "") : ""; boolean packNode = "pack".equals(nodeCode) || "打包".equals(nodeName); - if (!packNode) { + boolean homeLiftStockingNode = isHomeLiftStockingNode(orderType, nodeCode, nodeName); + if (!packNode && !homeLiftStockingNode) { return ""; } - if (ORDER_TYPE_RENOVATION.equals(orderType)) { + if (packNode && ORDER_TYPE_RENOVATION.equals(orderType)) { return ""; } String mediaStep = data == null ? "" : data.getMediaStep(); + String stepLabel = homeLiftStockingNode ? "仓库配料步骤" : "打包步骤"; + List stepList = homeLiftStockingNode ? HOME_LIFT_STOCKING_MEDIA_STEP_LIST : PACK_MEDIA_STEP_LIST; if (!StringUtils.hasText(mediaStep)) { - throw new XJException("请先选择打包步骤"); + throw new XJException("请先选择" + stepLabel); + } + String matchedStep = resolveMediaStepFromList(mediaStep, stepList); + if (StringUtils.hasText(matchedStep)) { + return matchedStep; + } + throw new XJException(stepLabel + "不正确,请重新选择"); + } + + private String resolveReportStepForHomeLiftStocking(ProductionPlanNodeReportData data, ProductionPlanOrderNodeData node, String orderType) { + if (node == null || !ORDER_TYPE_HOME_LIFT.equals(orderType)) { + return ""; + } + String nodeCode = StringUtils.hasText(node.getNodeCode()) ? node.getNodeCode().trim() : ""; + String nodeName = StringUtils.hasText(node.getNodeName()) ? node.getNodeName().replaceAll("\\s+", "") : ""; + boolean stockingNode = isHomeLiftStockingNode(orderType, nodeCode, nodeName); + if (!stockingNode) { + return ""; + } + String mediaStep = data == null ? "" : data.getMediaStep(); + if (!StringUtils.hasText(mediaStep)) { + throw new XJException("请先选择仓库配料步骤"); + } + String matchedStep = resolveMediaStepFromList(mediaStep, HOME_LIFT_STOCKING_MEDIA_STEP_LIST); + if (StringUtils.hasText(matchedStep)) { + return matchedStep; + } + throw new XJException("仓库配料步骤不正确,请重新选择"); + } + + private String resolveMediaStepFromList(String mediaStep, List stepList) { + if (!StringUtils.hasText(mediaStep) || stepList == null || stepList.isEmpty()) { + return ""; } String normalizedStep = mediaStep.replaceAll("\\s+", ""); - for (String step : PACK_MEDIA_STEP_LIST) { - if (step.replaceAll("\\s+", "").equals(normalizedStep)) { + for (String step : stepList) { + if (StringUtils.hasText(step) && step.replaceAll("\\s+", "").equals(normalizedStep)) { return step; } } - throw new XJException("打包步骤不正确,请重新选择"); + return ""; + } + + private boolean isHomeLiftStockingNode(String orderType, String nodeCode, String nodeName) { + if (!ORDER_TYPE_HOME_LIFT.equals(orderType)) { + return false; + } + String normalizedCode = StringUtils.hasText(nodeCode) ? nodeCode.trim() : ""; + String normalizedName = StringUtils.hasText(nodeName) ? nodeName.replaceAll("\\s+", "") : ""; + return "stocking".equals(normalizedCode) || "仓库配料".equals(normalizedName); } private void removeNodeReportMedia(String orderNo, String nodeCode, String logNo, String orderType) {