From f13ba9e05f653bc3083c4d17fe8658e67054131e Mon Sep 17 00:00:00 2001
From: huang <1532065656@qq.com>
Date: 星期一, 08 十二月 2025 17:06:23 +0800
Subject: [PATCH] 添加导入Excel表数据功能
---
/dev/null | 426 ---------------------
mes-processes/mes-plcSend/src/main/java/com/mes/device/service/GlassInfoService.java | 9
mes-web/src/api/engineering.js | 17
mes-processes/mes-plcSend/src/main/java/com/mes/device/service/impl/GlassInfoServiceImpl.java | 309 +++++++++++++++
mes-processes/mes-plcSend/src/main/java/com/mes/device/controller/GlassInfoImportController.java | 67 +++
mes-processes/mes-plcSend/src/main/resources/application-dev.yml | 3
mes-web/src/views/plcTest/components/MultiDeviceTest/TaskOrchestration.vue | 322 +++++++++++++++-
7 files changed, 702 insertions(+), 451 deletions(-)
diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/device/controller/GlassInfoImportController.java b/mes-processes/mes-plcSend/src/main/java/com/mes/device/controller/GlassInfoImportController.java
new file mode 100644
index 0000000..cee3a46
--- /dev/null
+++ b/mes-processes/mes-plcSend/src/main/java/com/mes/device/controller/GlassInfoImportController.java
@@ -0,0 +1,67 @@
+package com.mes.device.controller;
+
+import com.mes.device.service.GlassInfoService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author :huang
+ * @date :2025-12-08
+ * 宸ョ▼瀵煎叆杞彂鎺ュ彛锛堟帴鏀跺墠绔� Excel 琛屾暟鎹紝鍚庣缁勮鍚庤浆鍙� MES锛�
+ */
+@Slf4j
+@RestController
+@RequestMapping("excel")
+@RequiredArgsConstructor
+public class GlassInfoImportController {
+
+ private final GlassInfoService glassInfoService;
+ private final RestTemplate restTemplate = new RestTemplate();
+
+ @Value("${mes.engineering.import-url}")
+ private String mesEngineeringImportUrl;
+
+ /**
+ * 瀵煎叆宸ョ▼
+ * 鍓嶇鍏ュ弬绀轰緥锛�
+ * {
+ * "excelRows": [
+ * {"glassId":"GL001","width":"1000","height":"2000","thickness":"5","quantity":"2","orderNumber":"NG25082101","filmsId":"鐧界幓"}
+ * ]
+ * }
+ */
+ @PostMapping("/importExcel")
+ public ResponseEntity<?> importEngineer(@RequestBody Map<String, Object> body) {
+ Object rowsObj = body.get("excelRows");
+ if (!(rowsObj instanceof List)) {
+ return ResponseEntity.badRequest().body("excelRows 蹇呴』鏄暟缁�");
+ }
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> excelRows = (List<Map<String, Object>>) rowsObj;
+ if (CollectionUtils.isEmpty(excelRows)) {
+ return ResponseEntity.badRequest().body("excelRows 涓嶈兘涓虹┖");
+ }
+
+ Map<String, Object> payload = glassInfoService.buildEngineerImportPayload(excelRows);
+ log.info("鏋勫缓鐨� MES 瀵煎叆鏁版嵁: {}", payload);
+
+ try {
+ ResponseEntity<Map> mesResp = restTemplate.postForEntity(mesEngineeringImportUrl, payload, Map.class);
+ return ResponseEntity.status(mesResp.getStatusCode()).body(mesResp.getBody());
+ } catch (Exception e) {
+ log.error("杞彂 MES 瀵煎叆鎺ュ彛澶辫触 url={}, error={}", mesEngineeringImportUrl, e.getMessage(), e);
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("杞彂 MES 澶辫触: " + e.getMessage());
+ }
+ }
+}
+
+
diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/device/entity/request/LoadVehicleRequest.java b/mes-processes/mes-plcSend/src/main/java/com/mes/device/entity/request/LoadVehicleRequest.java
deleted file mode 100644
index 5db1499..0000000
--- a/mes-processes/mes-plcSend/src/main/java/com/mes/device/entity/request/LoadVehicleRequest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.mes.device.entity.request;
-
-import com.github.xingshuangs.iot.common.enums.EDataType;
-import com.github.xingshuangs.iot.protocol.s7.serializer.S7Variable;
-import lombok.Data;
-
-/**
- * 涓婂ぇ杞﹁澶囪姹傚疄浣�
- * 鐢ㄤ簬瀹氫箟涓婂ぇ杞﹁澶囧悜PLC鍐欏叆鐨勫瓧娈电粨鏋�
- * 瀛楁鍦板潃鏄犲皠閫氳繃DeviceConfig.configJson涓殑addressMapping閰嶇疆
- *
- * @author mes
- * @since 2025-11-19
- */
-@Data
-public class LoadVehicleRequest {
-
- /**
- * 璇锋眰瀛� 0鏃犺姹� 1鏈夎姹傦紙涓婂ぇ杞︽竻0锛�
- */
- @S7Variable(address = "plcRequest", type = EDataType.UINT16)
- private Integer plcRequest;
-
- /**
- * 杩涚墖浣嶇疆
- */
- @S7Variable(address = "inPosition", type = EDataType.UINT16)
- private Integer inPosition;
-
- /**
- * 鐜荤拑ID1
- */
- @S7Variable(address = "plcGlassId1", type = EDataType.STRING, count = 20)
- private String plcGlassId1;
-
- /**
- * 鐜荤拑ID2
- */
- @S7Variable(address = "plcGlassId2", type = EDataType.STRING, count = 20)
- private String plcGlassId2;
-
- /**
- * 鐜荤拑ID3
- */
- @S7Variable(address = "plcGlassId3", type = EDataType.STRING, count = 20)
- private String plcGlassId3;
-
- /**
- * 鐜荤拑ID4
- */
- @S7Variable(address = "plcGlassId4", type = EDataType.STRING, count = 20)
- private String plcGlassId4;
-
- /**
- * 鐜荤拑ID5
- */
- @S7Variable(address = "plcGlassId5", type = EDataType.STRING, count = 20)
- private String plcGlassId5;
-
- /**
- * 鐜荤拑ID6
- */
- @S7Variable(address = "plcGlassId6", type = EDataType.STRING, count = 20)
- private String plcGlassId6;
-
- /**
- * 鐜荤拑鏁伴噺
- */
- @S7Variable(address = "plcGlassCount", type = EDataType.UINT16)
- private Integer plcGlassCount;
-}
-
diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/device/entity/request/VerticalCarData.java b/mes-processes/mes-plcSend/src/main/java/com/mes/device/entity/request/VerticalCarData.java
deleted file mode 100644
index 6c3edc8..0000000
--- a/mes-processes/mes-plcSend/src/main/java/com/mes/device/entity/request/VerticalCarData.java
+++ /dev/null
@@ -1,426 +0,0 @@
-package com.mes.device.entity.request;
-
-import cn.hutool.core.collection.CollectionUtil;
-import com.github.xingshuangs.iot.common.enums.EDataType;
-import com.github.xingshuangs.iot.protocol.s7.serializer.S7Variable;
-import com.mes.vertical.history.VerticalSheetCageHistoryTask;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @Author : zhoush
- * @Date: 2025/6/15 15:15
- * @Description:
- */
-@ApiModel(description = ":")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-@Builder
-public class VerticalCarData {
-
- @ApiModelProperty(value = "鑱旀満鐘舵��", position = 1)
- @S7Variable(address = "verticalCar.onlineState", type = EDataType.BOOL)
- private Boolean onlineState;
-
- @ApiModelProperty(value = "璇锋眰瀛�", position = 2)
- @S7Variable(address = "verticalCar.plcRequest", type = EDataType.UINT16)
- private Integer plcRequest;
-
- @ApiModelProperty(value = "姹囨姤瀛�", position = 3)
- @S7Variable(address = "verticalCar.reportWord", type = EDataType.UINT16)
- private Integer reportWord;
-
- @ApiModelProperty(value = "1鐘舵��", position = 4)
- @S7Variable(address = "verticalCar.state1", type = EDataType.UINT16)
- private Integer state1;
-
- @ApiModelProperty(value = "2鐘舵��", position = 5)
- @S7Variable(address = "verticalCar.state2", type = EDataType.UINT16)
- private Integer state2;
-
- @ApiModelProperty(value = "3鐘舵��", position = 6)
- @S7Variable(address = "verticalCar.state3", type = EDataType.UINT16)
- private Integer state3;
-
- @ApiModelProperty(value = "4鐘舵��", position = 7)
- @S7Variable(address = "verticalCar.state4", type = EDataType.UINT16)
- private Integer state4;
-
- @ApiModelProperty(value = "5鐘舵��", position = 8)
- @S7Variable(address = "verticalCar.state5", type = EDataType.UINT16)
- private Integer state5;
-
- @ApiModelProperty(value = "6鐘舵��", position = 9)
- @S7Variable(address = "verticalCar.state6", type = EDataType.UINT16)
- private Integer state6;
-
- @ApiModelProperty(value = "鍙戦�佸瓧", position = 10)
- @S7Variable(address = "verticalCar.mesSend", type = EDataType.UINT16)
- private Integer mesSend;
-
- @ApiModelProperty(value = "纭瀛�", position = 11)
- @S7Variable(address = "verticalCar.confirmWord", type = EDataType.UINT16)
- private Integer confirmWord;
-
- @ApiModelProperty(value = "杞︽淇℃伅", position = 12)
- @S7Variable(address = "verticalCar.trainInfo", type = EDataType.STRING, count = 20)
- private String trainInfo;
-
- @ApiModelProperty(value = "鐜荤拑id1", position = 13)
- @S7Variable(address = "verticalCar.mesGlassId1", type = EDataType.STRING, count = 20)
- private String mesGlassId1;
-
- @ApiModelProperty(value = "鐜荤拑id2", position = 14)
- @S7Variable(address = "verticalCar.mesGlassId2", type = EDataType.STRING, count = 20)
- private String mesGlassId2;
-
- @ApiModelProperty(value = "鐜荤拑id3", position = 15)
- @S7Variable(address = "verticalCar.mesGlassId3", type = EDataType.STRING, count = 20)
- private String mesGlassId3;
-
- @ApiModelProperty(value = "鐜荤拑id4", position = 16)
- @S7Variable(address = "verticalCar.mesGlassId4", type = EDataType.STRING, count = 20)
- private String mesGlassId4;
-
- @ApiModelProperty(value = "鐜荤拑id5", position = 17)
- @S7Variable(address = "verticalCar.mesGlassId5", type = EDataType.STRING, count = 20)
- private String mesGlassId5;
-
- @ApiModelProperty(value = "鐜荤拑id6", position = 18)
- @S7Variable(address = "verticalCar.mesGlassId6", type = EDataType.STRING, count = 20)
- private String mesGlassId6;
-
- @ApiModelProperty(value = "璧峰鏍煎瓙1", position = 19)
- @S7Variable(address = "verticalCar.start1", type = EDataType.UINT16)
- private Integer start1;
-
- @ApiModelProperty(value = "璧峰鏍煎瓙2", position = 20)
- @S7Variable(address = "verticalCar.start2", type = EDataType.UINT16)
- private Integer start2;
-
- @ApiModelProperty(value = "璧峰鏍煎瓙3", position = 21)
- @S7Variable(address = "verticalCar.start3", type = EDataType.UINT16)
- private Integer start3;
-
- @ApiModelProperty(value = "璧峰鏍煎瓙4", position = 22)
- @S7Variable(address = "verticalCar.start4", type = EDataType.UINT16)
- private Integer start4;
-
- @ApiModelProperty(value = "璧峰鏍煎瓙5", position = 23)
- @S7Variable(address = "verticalCar.start5", type = EDataType.UINT16)
- private Integer start5;
-
- @ApiModelProperty(value = "璧峰鏍煎瓙6", position = 24)
- @S7Variable(address = "verticalCar.start6", type = EDataType.UINT16)
- private Integer start6;
-
- @ApiModelProperty(value = "鐩爣鏍煎瓙1", position = 25)
- @S7Variable(address = "verticalCar.target1", type = EDataType.UINT16)
- private Integer target1;
-
- @ApiModelProperty(value = "鐩爣鏍煎瓙2", position = 26)
- @S7Variable(address = "verticalCar.target2", type = EDataType.UINT16)
- private Integer target2;
-
- @ApiModelProperty(value = "鐩爣鏍煎瓙3", position = 27)
- @S7Variable(address = "verticalCar.target3", type = EDataType.UINT16)
- private Integer target3;
-
- @ApiModelProperty(value = "鐩爣鏍煎瓙4", position = 28)
- @S7Variable(address = "verticalCar.target4", type = EDataType.UINT16)
- private Integer target4;
-
- @ApiModelProperty(value = "鐩爣鏍煎瓙5", position = 29)
- @S7Variable(address = "verticalCar.target5", type = EDataType.UINT16)
- private Integer target5;
-
- @ApiModelProperty(value = "鐩爣鏍煎瓙6", position = 30)
- @S7Variable(address = "verticalCar.target6", type = EDataType.UINT16)
- private Integer target6;
-
- @ApiModelProperty(value = "闀胯竟1", position = 31)
- @S7Variable(address = "verticalCar.width1", type = EDataType.UINT16)
- private Integer width1;
-
- @ApiModelProperty(value = "闀胯竟2", position = 32)
- @S7Variable(address = "verticalCar.width2", type = EDataType.UINT16)
- private Integer width2;
-
- @ApiModelProperty(value = "闀胯竟3", position = 33)
- @S7Variable(address = "verticalCar.width3", type = EDataType.UINT16)
- private Integer width3;
-
- @ApiModelProperty(value = "闀胯竟4", position = 34)
- @S7Variable(address = "verticalCar.width4", type = EDataType.UINT16)
- private Integer width4;
-
- @ApiModelProperty(value = "闀胯竟5", position = 35)
- @S7Variable(address = "verticalCar.width5", type = EDataType.UINT16)
- private Integer width5;
-
- @ApiModelProperty(value = "闀胯竟6", position = 36)
- @S7Variable(address = "verticalCar.width6", type = EDataType.UINT16)
- private Integer width6;
-
- @ApiModelProperty(value = "鐭竟1", position = 37)
- @S7Variable(address = "verticalCar.height1", type = EDataType.UINT16)
- private Integer height1;
-
- @ApiModelProperty(value = "鐭竟2", position = 38)
- @S7Variable(address = "verticalCar.height2", type = EDataType.UINT16)
- private Integer height2;
-
- @ApiModelProperty(value = "鐭竟3", position = 39)
- @S7Variable(address = "verticalCar.height3", type = EDataType.UINT16)
- private Integer height3;
-
- @ApiModelProperty(value = "鐭竟4", position = 40)
- @S7Variable(address = "verticalCar.height4", type = EDataType.UINT16)
- private Integer height4;
-
- @ApiModelProperty(value = "鐭竟5", position = 41)
- @S7Variable(address = "verticalCar.height5", type = EDataType.UINT16)
- private Integer height5;
-
- @ApiModelProperty(value = "鐭竟6", position = 42)
- @S7Variable(address = "verticalCar.height6", type = EDataType.UINT16)
- private Integer height6;
-
- @ApiModelProperty(value = "鍘�1", position = 43)
- @S7Variable(address = "verticalCar.thickness1", type = EDataType.UINT16)
- private Integer thickness1;
-
- @ApiModelProperty(value = "鍘�2", position = 44)
- @S7Variable(address = "verticalCar.thickness2", type = EDataType.UINT16)
- private Integer thickness2;
-
- @ApiModelProperty(value = "鍘�3", position = 45)
- @S7Variable(address = "verticalCar.thickness3", type = EDataType.UINT16)
- private Integer thickness3;
-
- @ApiModelProperty(value = "鍘�4", position = 46)
- @S7Variable(address = "verticalCar.thickness4", type = EDataType.UINT16)
- private Integer thickness4;
-
- @ApiModelProperty(value = "鍘�5", position = 47)
- @S7Variable(address = "verticalCar.thickness5", type = EDataType.UINT16)
- private Integer thickness5;
-
- @ApiModelProperty(value = "鍘�6", position = 48)
- @S7Variable(address = "verticalCar.thickness6", type = EDataType.UINT16)
- private Integer thickness6;
-
- @ApiModelProperty(value = "闈犺竟璺�1", position = 49)
- @S7Variable(address = "verticalCar.edgeDistance1", type = EDataType.UINT16)
- private Integer edgeDistance1;
-
- @ApiModelProperty(value = "闈犺竟璺�2", position = 50)
- @S7Variable(address = "verticalCar.edgeDistance2", type = EDataType.UINT16)
- private Integer edgeDistance2;
-
- @ApiModelProperty(value = "闈犺竟璺�3", position = 51)
- @S7Variable(address = "verticalCar.edgeDistance3", type = EDataType.UINT16)
- private Integer edgeDistance3;
-
- @ApiModelProperty(value = "闈犺竟璺�4", position = 52)
- @S7Variable(address = "verticalCar.edgeDistance4", type = EDataType.UINT16)
- private Integer edgeDistance4;
-
- @ApiModelProperty(value = "闈犺竟璺�5", position = 53)
- @S7Variable(address = "verticalCar.edgeDistance5", type = EDataType.UINT16)
- private Integer edgeDistance5;
-
- @ApiModelProperty(value = "闈犺竟璺�6", position = 54)
- @S7Variable(address = "verticalCar.edgeDistance6", type = EDataType.UINT16)
- private Integer edgeDistance6;
-
- @ApiModelProperty(value = "鐩爣闈犺竟璺�1", position = 55)
- @S7Variable(address = "verticalCar.targetEdgeDistance1", type = EDataType.UINT16)
- private Integer targetEdgeDistance1;
-
- @ApiModelProperty(value = "鐩爣闈犺竟璺�2", position = 56)
- @S7Variable(address = "verticalCar.targetEdgeDistance2", type = EDataType.UINT16)
- private Integer targetEdgeDistance2;
-
- @ApiModelProperty(value = "鐩爣闈犺竟璺�3", position = 57)
- @S7Variable(address = "verticalCar.targetEdgeDistance3", type = EDataType.UINT16)
- private Integer targetEdgeDistance3;
-
- @ApiModelProperty(value = "鐩爣闈犺竟璺�4", position = 58)
- @S7Variable(address = "verticalCar.targetEdgeDistance4", type = EDataType.UINT16)
- private Integer targetEdgeDistance4;
-
- @ApiModelProperty(value = "鐩爣闈犺竟璺�5", position = 59)
- @S7Variable(address = "verticalCar.targetEdgeDistance5", type = EDataType.UINT16)
- private Integer targetEdgeDistance5;
-
- @ApiModelProperty(value = "鐩爣闈犺竟璺�6", position = 60)
- @S7Variable(address = "verticalCar.targetEdgeDistance6", type = EDataType.UINT16)
- private Integer targetEdgeDistance6;
-
- @ApiModelProperty(value = "鎶ヨ淇″彿", position = 61)
- @S7Variable(address = "verticalCar.alarmSignal", type = EDataType.UINT16)
- private Integer alarmSignal;
-
- public List<Integer> getStartSlots() {
- return Arrays.asList(start1, start2, start3, start4, start5, start6);
- }
-
- public List<Integer> getTargetSlots() {
- return Arrays.asList(target1, target2, target3, target4, target5, target6);
- }
-
- public List<Integer> getStates() {
- return Arrays.asList(state1, state2, state3, state4, state5, state6);
- }
-
- public List<String> getGlassIds() {
- return Arrays.asList(mesGlassId1, mesGlassId2, mesGlassId3, mesGlassId4, mesGlassId5, mesGlassId6)
- .stream()
- .filter(glassId -> glassId != null && !glassId.trim().isEmpty())
- .collect(Collectors.toList());
- }
-
- public List<VerticalSheetCageHistoryTask> getTaskList() {
- List<VerticalSheetCageHistoryTask> inTaskList = new ArrayList();
- List<String> glassIdList = this.getGlassIds();
- if (CollectionUtil.isEmpty(glassIdList)) {
- return inTaskList;
- }
- List<Integer> targetList = this.getTargetSlots();
- List<Integer> stateList = this.getStates();
- List<Integer> startList = this.getStartSlots();
- for (int i = 0; i < glassIdList.size(); i++) {
- VerticalSheetCageHistoryTask task = new VerticalSheetCageHistoryTask();
- task.setGlassId(glassIdList.get(i));
- task.setTargetSlot(targetList.get(i));
- task.setTaskState(stateList.get(i));
- task.setStartSlot(startList.get(i));
- inTaskList.add(task);
- }
- return inTaskList;
- }
-
- public VerticalCarData setGlassIdsAndPosition(List<String> glassIds, Integer inPosition) {
- VerticalCarData verticalCarData = new VerticalCarData();
- verticalCarData.setTrainInfo(inPosition.toString());
- int i = 1;
- for (String glassId : glassIds
- ) {
- switch (i) {
- case 1:
- verticalCarData.setMesGlassId1(glassId);
- verticalCarData.setStart1(inPosition);
- break;
- case 2:
- verticalCarData.setMesGlassId2(glassId);
- verticalCarData.setStart2(inPosition);
- break;
- case 3:
- verticalCarData.setMesGlassId3(glassId);
- verticalCarData.setStart3(inPosition);
- break;
- case 4:
- verticalCarData.setMesGlassId4(glassId);
- verticalCarData.setStart4(inPosition);
- break;
- case 5:
- verticalCarData.setMesGlassId5(glassId);
- verticalCarData.setStart5(inPosition);
- break;
- case 6:
- verticalCarData.setMesGlassId6(glassId);
- verticalCarData.setStart6(inPosition);
- break;
- default:
- break;
- }
- i++;
- }
- return verticalCarData;
- }
-
- public VerticalCarData setMesGlassInfo(VerticalCarData verticalCarData, List<VerticalSheetCageHistoryTask> verticalSheetCageHistoryTasks) {
- int i = 1;
- for (VerticalSheetCageHistoryTask verticalSheetCageHistoryTask : verticalSheetCageHistoryTasks
- ) {
- switch (i) {
- case 1:
- verticalCarData.setMesGlassId1(verticalSheetCageHistoryTask.getGlassId());
- verticalCarData.setStart1(verticalSheetCageHistoryTask.getStartSlot());
- verticalCarData.setTarget1(verticalSheetCageHistoryTask.getTargetSlot());
- verticalCarData.setWidth1(Math.max((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setHeight1(Math.min((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setThickness1((int) verticalSheetCageHistoryTask.getThickness().doubleValue());
- verticalCarData.setEdgeDistance1(verticalSheetCageHistoryTask.getEdgeDistance());
- verticalCarData.setTargetEdgeDistance1(verticalSheetCageHistoryTask.getTargetEdgeDistance());
- break;
- case 2:
- verticalCarData.setMesGlassId2(verticalSheetCageHistoryTask.getGlassId());
- verticalCarData.setStart2(verticalSheetCageHistoryTask.getStartSlot());
- verticalCarData.setTarget2(verticalSheetCageHistoryTask.getTargetSlot());
- verticalCarData.setWidth2(Math.max((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setHeight2(Math.min((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setThickness2((int) verticalSheetCageHistoryTask.getThickness().doubleValue());
- verticalCarData.setEdgeDistance2(verticalSheetCageHistoryTask.getEdgeDistance());
- verticalCarData.setTargetEdgeDistance2(verticalSheetCageHistoryTask.getTargetEdgeDistance());
- break;
- case 3:
- // 绗笁缁勭幓鐠冩暟鎹祴鍊�
- verticalCarData.setMesGlassId3(verticalSheetCageHistoryTask.getGlassId());
- verticalCarData.setStart3(verticalSheetCageHistoryTask.getStartSlot());
- verticalCarData.setTarget3(verticalSheetCageHistoryTask.getTargetSlot());
- verticalCarData.setWidth3(Math.max((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setHeight3(Math.min((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setThickness3(Math.min((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setEdgeDistance3(verticalSheetCageHistoryTask.getEdgeDistance());
- verticalCarData.setTargetEdgeDistance3(verticalSheetCageHistoryTask.getTargetEdgeDistance());
- break;
- case 4:
- verticalCarData.setMesGlassId4(verticalSheetCageHistoryTask.getGlassId());
- verticalCarData.setStart4(verticalSheetCageHistoryTask.getStartSlot());
- verticalCarData.setTarget4(verticalSheetCageHistoryTask.getTargetSlot());
- verticalCarData.setWidth4(Math.max((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setHeight4(Math.min((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setThickness4((int) verticalSheetCageHistoryTask.getThickness().doubleValue());
- verticalCarData.setEdgeDistance4(verticalSheetCageHistoryTask.getEdgeDistance());
- verticalCarData.setTargetEdgeDistance4(verticalSheetCageHistoryTask.getTargetEdgeDistance());
- break;
- case 5:
- verticalCarData.setMesGlassId5(verticalSheetCageHistoryTask.getGlassId());
- verticalCarData.setStart5(verticalSheetCageHistoryTask.getStartSlot());
- verticalCarData.setTarget5(verticalSheetCageHistoryTask.getTargetSlot());
- verticalCarData.setWidth5(Math.max((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setHeight5(Math.min((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setThickness5((int) verticalSheetCageHistoryTask.getThickness().doubleValue());
- verticalCarData.setEdgeDistance5(verticalSheetCageHistoryTask.getEdgeDistance());
- verticalCarData.setTargetEdgeDistance5(verticalSheetCageHistoryTask.getTargetEdgeDistance());
- break;
- case 6:
- verticalCarData.setMesGlassId6(verticalSheetCageHistoryTask.getGlassId());
- verticalCarData.setStart6(verticalSheetCageHistoryTask.getStartSlot());
- verticalCarData.setTarget6(verticalSheetCageHistoryTask.getTargetSlot());
- verticalCarData.setWidth6(Math.max((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setHeight6(Math.min((int) verticalSheetCageHistoryTask.getWidth().doubleValue(), (int) verticalSheetCageHistoryTask.getHeight().doubleValue()));
- verticalCarData.setThickness6((int) verticalSheetCageHistoryTask.getThickness().doubleValue());
- verticalCarData.setEdgeDistance6(verticalSheetCageHistoryTask.getEdgeDistance());
- verticalCarData.setTargetEdgeDistance6(verticalSheetCageHistoryTask.getTargetEdgeDistance());
- break;
- default:
- break;
- }
- i++;
- }
- return verticalCarData;
- }
-}
diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/GlassInfoService.java b/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/GlassInfoService.java
index 202de49..53a6f5c 100644
--- a/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/GlassInfoService.java
+++ b/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/GlassInfoService.java
@@ -75,5 +75,14 @@
* 鎵归噺鏇存柊鐜荤拑鐘舵��
*/
boolean updateGlassStatus(List<String> glassIds, String status);
+
+ /**
+ * 灏嗗墠绔笂浼犵殑 Excel 琛屾暟鎹浆鎹负 MES 瀵煎叆宸ョ▼鎵�闇�鐨� JSON 缁撴瀯
+ *
+ * @param excelRows 鍓嶇瑙f瀽鍚庣殑琛屾暟鎹紝瀛楁绀轰緥锛�
+ * glassId,width,height,thickness,quantity,orderNumber,filmsId,flowCardId,productName,customerName
+ * @return 绗﹀悎 MES 鎺ュ彛瑕佹眰鐨勮姹備綋 Map
+ */
+ Map<String, Object> buildEngineerImportPayload(List<Map<String, Object>> excelRows);
}
diff --git a/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/impl/GlassInfoServiceImpl.java b/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/impl/GlassInfoServiceImpl.java
index 5546da4..5d8b503 100644
--- a/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/impl/GlassInfoServiceImpl.java
+++ b/mes-processes/mes-plcSend/src/main/java/com/mes/device/service/impl/GlassInfoServiceImpl.java
@@ -10,12 +10,15 @@
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
+
+import static java.util.stream.IntStream.range;
/**
* 鐜荤拑淇℃伅鏈嶅姟瀹炵幇绫�
@@ -208,5 +211,301 @@
return false;
}
}
+
+ @Override
+ public Map<String, Object> buildEngineerImportPayload(List<Map<String, Object>> excelRows) {
+ Map<String, Object> result = new HashMap<>();
+ if (excelRows == null || excelRows.isEmpty()) {
+ return result;
+ }
+
+ // 宸ョ▼鍙风敓鎴愶細P + yyMMdd + 搴忓彿(2浣�)
+ AtomicInteger seq = new AtomicInteger(1);
+ final String engineerId = generateEngineerId(firstValue(excelRows, "glassId"), seq.getAndIncrement());
+ final String filmsIdDefault = firstValue(excelRows, "filmsId", "鐧界幓");
+ final double thicknessDefault = parseDouble(firstValue(excelRows, "thickness"), 0d);
+
+ // glassInfolList
+ final String engineerIdFinal = engineerId;
+ final String filmsIdDefaultFinal = filmsIdDefault;
+ final double thicknessDefaultFinal = thicknessDefault;
+
+ List<Map<String, Object>> glassInfolList = excelRows.stream()
+ .flatMap(row -> {
+ int qty = (int) parseDouble(row.getOrDefault("quantity", 1), 1);
+ if (qty <= 0) qty = 1;
+ String glassId = str(row.get("glassId"));
+ Integer orderNumber = Integer.parseInt(str(row.get("orderNumber")));
+ String filmsId = strOrDefault(row.get("filmsId"), filmsIdDefaultFinal);
+ String flowCardId = str(row.get("flowCardId"));
+ String productName = str(row.get("productName"));
+ String customerName = str(row.get("customerName"));
+ double width = parseDouble(row.get("width"), 0d);
+ double height = parseDouble(row.get("height"), 0d);
+ double thickness = parseDouble(row.get("thickness"), thicknessDefaultFinal);
+
+ int finalQty = qty;
+ return range(0, qty).mapToObj(idx -> {
+ String finalGlassId = finalQty > 1 ? glassId + "_" + (idx + 1) : glassId;
+ String finalFlowCardId = flowCardId.isEmpty() ? finalGlassId : flowCardId;
+ Map<String, Object> m = new HashMap<>();
+ m.put("xAxis", 0);
+ m.put("xCoordinate", 0);
+ m.put("yAxis", 0);
+ m.put("yCoordinate", 0);
+ m.put("glassId", finalGlassId);
+ m.put("engineerId", engineerIdFinal);
+ m.put("flowCardId", finalFlowCardId);
+ m.put("orderNumber", orderNumber);
+ m.put("productSortNumber", idx + 1);
+ m.put("hollowCombineDirection", "0");
+ m.put("width", width);
+ m.put("height", height);
+ m.put("thickness", thickness);
+ m.put("filmsId", filmsId);
+ m.put("layer", 0);
+ m.put("totalLayer", 0);
+ m.put("edgWidth", width);
+ m.put("edgHeight", height);
+ m.put("isMultiple", 0);
+ m.put("maxWidth", width);
+ m.put("maxHeight", height);
+ m.put("isHorizontal", 0);
+ m.put("rawSequence", 0);
+ m.put("temperingLayoutId", 0);
+ m.put("temperingFeedSequence", 0);
+ m.put("angle", 0);
+ m.put("ruleId", 0);
+ m.put("combine", 0);
+ m.put("markIcon", "");
+ m.put("filmRemove", 0);
+ m.put("flowCardSequence", String.valueOf(idx + 1));
+ m.put("process", "");
+ m.put("rawAngle", 0);
+ m.put("graphNo", 0);
+ m.put("processParam", "");
+ return m;
+ });
+ })
+ .collect(Collectors.toList());
+
+ // 鍘熺墖淇℃伅鍘婚噸
+ Map<String, Map<String, Object>> rawGlassMap = new HashMap<>();
+ for (Map<String, Object> row : excelRows) {
+ double width = parseDouble(row.get("width"), 0d);
+ double height = parseDouble(row.get("height"), 0d);
+ double thickness = parseDouble(row.get("thickness"), thicknessDefaultFinal);
+ String filmsId = strOrDefault(row.get("filmsId"), filmsIdDefaultFinal);
+ String key = width + "_" + height + "_" + thickness + "_" + filmsId;
+ if (!rawGlassMap.containsKey(key)) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("engineeringId", engineerIdFinal);
+ m.put("filmsId", filmsId);
+ m.put("rawGlassWidth", width);
+ m.put("rawGlassHeight", height);
+ m.put("rawGlassThickness", thickness);
+ m.put("rawSequence", rawGlassMap.size() + 1);
+ m.put("usageRate", "0.95");
+ rawGlassMap.put(key, m);
+ }
+ }
+
+ List<Map<String, Object>> engineeringRawQueueList = rawGlassMap.values().stream().collect(Collectors.toList());
+
+ // 娴佺▼鍗′俊鎭�
+ Map<String, Map<String, Object>> flowCardMap = new HashMap<>();
+ for (Map<String, Object> row : excelRows) {
+ String glassId = str(row.get("glassId"));
+ String flowCardId = str(row.get("flowCardId"));
+ if (flowCardId.isEmpty()) {
+ flowCardId = glassId;
+ }
+ double width = parseDouble(row.get("width"), 0d);
+ double height = parseDouble(row.get("height"), 0d);
+ double thickness = parseDouble(row.get("thickness"), thicknessDefaultFinal);
+ String filmsId = strOrDefault(row.get("filmsId"), filmsIdDefaultFinal);
+ Integer orderNumber = Integer.parseInt(str(row.get("orderNumber")));
+ String productName = str(row.get("productName"));
+ String customerName = str(row.get("customerName"));
+
+ Map<String, Object> exist = flowCardMap.get(flowCardId);
+ if (exist == null) {
+ Map<String, Object> m = new HashMap<>();
+ m.put("flowCardId", flowCardId);
+ m.put("width", width);
+ m.put("height", height);
+ m.put("thickness", thickness);
+ m.put("filmsId", filmsId);
+ m.put("totalLayer", 0);
+ m.put("layer", 0);
+ m.put("glassTotal", 1);
+ m.put("orderNumber", orderNumber);
+ m.put("productName", productName);
+ m.put("customerName", customerName);
+ flowCardMap.put(flowCardId, m);
+ } else {
+ int count = (int) exist.getOrDefault("glassTotal", 1);
+ exist.put("glassTotal", count + 1);
+ }
+ }
+ List<Map<String, Object>> flowCardInfoList = flowCardMap.values().stream().collect(Collectors.toList());
+
+ // 姹囨��
+ int glassTotal = glassInfolList.size();
+ double glassTotalArea = glassInfolList.stream()
+ .mapToDouble(m -> parseDouble(m.get("width"), 0d) * parseDouble(m.get("height"), 0d) / 1_000_000d)
+ .sum();
+ double patternArea = engineeringRawQueueList.stream()
+ .mapToDouble(m -> parseDouble(m.get("rawGlassWidth"), 0d) * parseDouble(m.get("rawGlassHeight"), 0d) / 1_000_000d)
+ .sum();
+
+ result.put("engineerId", engineerIdFinal);
+ result.put("engineerName", "宸ョ▼_" + engineerIdFinal);
+ result.put("avgAvailability", "90");
+ result.put("validAvailability", "90");
+ result.put("lastAvailability", "90");
+ result.put("glassTotal", glassTotal);
+ result.put("glassTotalArea", round2(glassTotalArea));
+ result.put("planPatternTotal", engineeringRawQueueList.size());
+ result.put("planPatternTotalArea", round2(patternArea));
+ result.put("realityPatternTotal", engineeringRawQueueList.size());
+ result.put("realityPatternTotalArea", round2(patternArea));
+ result.put("filmsId", filmsIdDefaultFinal);
+ result.put("thickness", thicknessDefaultFinal);
+ result.put("engineeringRawQueueList", engineeringRawQueueList);
+ result.put("glassInfolList", glassInfolList);
+ result.put("flowCardInfoList", flowCardInfoList);
+ result.put("hollowFormulaDetailsList", null);
+ result.put("temperingParameterList", null);
+
+ return result;
+ }
+
+ // 鏃ユ湡鏍煎紡鍖栧櫒锛堢嚎绋嬩笉瀹夊叏锛屼娇鐢═hreadLocal淇濊瘉绾跨▼瀹夊叏锛�
+ private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");
+
+ // 鏁板瓧鍖归厤姝e垯锛堥缂栬瘧鎻愬崌鎬ц兘锛�
+ private static final Pattern DIGIT_PATTERN = Pattern.compile("\\d+");
+
+ /**
+ * 鐢熸垚宸ョ▼甯圛D
+ * 鏍煎紡瑙勫垯锛歅 + 骞存湀鏃�(yyMMdd) + 涓や綅搴忓彿
+ * 搴忓彿浼樺厛浠巊lassId涓彁鍙栨湯灏句袱浣嶆暟瀛楋紝鍚﹀垯浣跨敤浼犲叆鐨刬ndex琛ラ浂
+ *
+ * @param glassId 鐜荤拑ID锛堝彲涓簄ull锛岀敤浜庢彁鍙栨暟瀛楀簭鍙凤級
+ * @param index 澶囩敤搴忓彿锛堝綋glassId鏃犳湁鏁堟暟瀛楁椂浣跨敤锛�
+ * @return 鏍煎紡鍖栫殑宸ョ▼甯圛D锛堝锛歅25010801锛�
+ */
+ private String generateEngineerId(Object glassId, int index) {
+ // 1. 鐢熸垚鏃ユ湡鍓嶇紑锛坹yMMdd锛�
+ String base = LocalDate.now().format(DATE_FORMATTER);
+
+ // 2. 鍒濆鍖栧簭鍙凤紙涓や綅琛ラ浂锛�
+ String seq = String.format("%02d", index);
+
+ // 3. 浠巊lassId涓彁鍙栨湯灏句袱浣嶆暟瀛楋紙瑕嗙洊榛樿搴忓彿锛�
+ if (glassId != null) {
+ String glassIdStr = glassId.toString();
+ Matcher matcher = DIGIT_PATTERN.matcher(glassIdStr);
+ String lastDigitStr = null;
+
+ // 閬嶅巻鍖归厤鎵�鏈夋暟瀛楁锛屽彇鏈�鍚庝竴涓�
+ while (matcher.find()) {
+ lastDigitStr = matcher.group();
+ }
+
+ // 鑻ユ暟瀛楁闀垮害鈮�2锛屽彇鏈�鍚庝袱浣嶏紱鍚﹀垯淇濈暀鍘熷簭鍙�
+ if (lastDigitStr != null && lastDigitStr.length() >= 2) {
+ seq = lastDigitStr.substring(lastDigitStr.length() - 2);
+ }
+ }
+
+ return "P" + base + seq;
+ }
+
+ /**
+ * 鎻愬彇List涓涓�涓狹ap鐨勬寚瀹歬ey鍊硷紙榛樿绌哄瓧绗︿覆锛�
+ *
+ * @param rows 鏁版嵁琛屽垪琛紙鍙负null/绌猴級
+ * @param key 瑕佹彁鍙栫殑閿�
+ * @return 绗竴涓狹ap鐨刱ey瀵瑰簲鍊硷紙绌哄垯杩斿洖""锛�
+ */
+ private String firstValue(List<Map<String, Object>> rows, String key) {
+ return firstValue(rows, key, "");
+ }
+
+ /**
+ * 鎻愬彇List涓涓�涓狹ap鐨勬寚瀹歬ey鍊硷紙鑷畾涔夐粯璁ゅ�硷級
+ *
+ * @param rows 鏁版嵁琛屽垪琛紙鍙负null/绌猴級
+ * @param key 瑕佹彁鍙栫殑閿�
+ * @param defaultVal 绌哄�兼椂鐨勯粯璁よ繑鍥炲��
+ * @return 绗竴涓狹ap鐨刱ey瀵瑰簲鍊硷紙绌哄垯杩斿洖defaultVal锛�
+ */
+ private String firstValue(List<Map<String, Object>> rows, String key, String defaultVal) {
+ if (rows == null || rows.isEmpty() || key == null) {
+ return defaultVal;
+ }
+
+ Map<String, Object> firstRow = rows.get(0);
+ Object value = firstRow.get(key);
+ return value == null ? defaultVal : value.toString();
+ }
+
+ /**
+ * 瀵硅薄杞瓧绗︿覆锛坣ull杞┖涓诧紝鑷姩鍘婚櫎棣栧熬绌烘牸锛�
+ *
+ * @param v 寰呰浆鎹㈠璞�
+ * @return 澶勭悊鍚庣殑瀛楃涓�
+ */
+ private String str(Object v) {
+ return v == null ? "" : v.toString().trim();
+ }
+
+ /**
+ * 瀵硅薄杞瓧绗︿覆锛堢┖涓叉椂杩斿洖榛樿鍊硷紝鑷姩鍘婚櫎棣栧熬绌烘牸锛�
+ *
+ * @param v 寰呰浆鎹㈠璞�
+ * @param def 绌哄�奸粯璁ゅ��
+ * @return 澶勭悊鍚庣殑瀛楃涓�
+ */
+ private String strOrDefault(Object v, String def) {
+ String result = str(v);
+ return result.isEmpty() ? def : result;
+ }
+
+ /**
+ * 瑙f瀽瀵硅薄涓篸ouble锛堝け璐�/绌哄�艰繑鍥為粯璁ゅ�硷級
+ *
+ * @param v 寰呰В鏋愬璞★紙鏀寔鏁板瓧/瀛楃涓茬被鍨嬶級
+ * @param def 瑙f瀽澶辫触鏃剁殑榛樿鍊�
+ * @return 瑙f瀽鍚庣殑double鍊�
+ */
+ private double parseDouble(Object v, double def) {
+ if (v == null) {
+ return def;
+ }
+
+ try {
+ if (v instanceof Number) {
+ return ((Number) v).doubleValue();
+ }
+ return Double.parseDouble(v.toString().trim());
+ } catch (NumberFormatException e) {
+ // 浠呮崟鑾锋暟瀛楁牸寮忓寲寮傚父锛岄伩鍏嶅悶鎺夊叾浠栧紓甯�
+ return def;
+ }
+ }
+
+ /**
+ * 淇濈暀涓や綅灏忔暟锛堝洓鑸嶄簲鍏ワ級
+ *
+ * @param v 鍘熷鏁板��
+ * @return 淇濈暀涓や綅灏忔暟鍚庣殑鏁板��
+ */
+ private double round2(double v) {
+ return Math.round(v * 100.0) / 100.0;
+ }
+
}
diff --git a/mes-processes/mes-plcSend/src/main/resources/application-dev.yml b/mes-processes/mes-plcSend/src/main/resources/application-dev.yml
index bb9e3bf..ae70abb 100644
--- a/mes-processes/mes-plcSend/src/main/resources/application-dev.yml
+++ b/mes-processes/mes-plcSend/src/main/resources/application-dev.yml
@@ -30,6 +30,9 @@
port: 6379
password: 123456
+mes:
+ engineering:
+ import-url: http://10.153.19.208:10015/engineering/importEngineer
# PLC鑷姩娴嬭瘯閰嶇疆
plc:
auto:
diff --git a/mes-web/src/api/engineering.js b/mes-web/src/api/engineering.js
new file mode 100644
index 0000000..7dee2ce
--- /dev/null
+++ b/mes-web/src/api/engineering.js
@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+const BASE_URL = '/api/plcSend/excel'
+
+export const engineeringApi = {
+ /**
+ * 瀵煎叆宸ョ▼鍒楄〃
+ */
+ importEngineer(data) {
+ return request({
+ url: `${BASE_URL}/importExcel`,
+ method: 'post',
+ data
+ })
+ }
+}
+
diff --git a/mes-web/src/views/plcTest/components/MultiDeviceTest/TaskOrchestration.vue b/mes-web/src/views/plcTest/components/MultiDeviceTest/TaskOrchestration.vue
index 3daeeb5..8b669ce 100644
--- a/mes-web/src/views/plcTest/components/MultiDeviceTest/TaskOrchestration.vue
+++ b/mes-web/src/views/plcTest/components/MultiDeviceTest/TaskOrchestration.vue
@@ -18,8 +18,17 @@
<el-icon><Delete /></el-icon>
娓呯┖PLC
</el-button> -->
+ <el-button type="success" :disabled="!group" :loading="importLoading" @click="handleImportExcel">
+ <el-icon>
+ <Upload />
+ </el-icon>
+ 瀵煎叆Excel鏁版嵁
+ </el-button>
+ <input ref="fileInputRef" type="file" accept=".xlsx,.xls" style="display: none" @change="handleFileChange" />
<el-button type="primary" :disabled="!group" :loading="loading" @click="handleSubmit">
- <el-icon><Promotion /></el-icon>
+ <el-icon>
+ <Promotion />
+ </el-icon>
鍚姩娴嬭瘯
</el-button>
</div>
@@ -43,20 +52,18 @@
</el-form>
<!-- 璁惧缁勬嫇鎵戝浘 -->
- <GroupTopology
- v-if="group"
- :group="group"
- class="topology-section"
- />
+ <GroupTopology v-if="group" :group="group" class="topology-section" />
</div>
</template>
<script setup>
import { computed, reactive, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
-import { Delete, Promotion } from '@element-plus/icons-vue'
+import { Delete, Promotion, Upload } from '@element-plus/icons-vue'
+import * as XLSX from 'xlsx'
import { multiDeviceTaskApi } from '@/api/device/multiDeviceTask'
import { deviceGroupApi, deviceInteractionApi } from '@/api/device/deviceManagement'
+import { engineeringApi } from '@/api/engineering'
import GroupTopology from '../DeviceGroup/GroupTopology.vue'
const props = defineProps({
@@ -102,10 +109,12 @@
const glassIdsInput = ref('')
const loading = ref(false)
+const importLoading = ref(false)
const clearLoading = ref(false)
const loadDeviceId = ref(null)
const loadDeviceName = ref('')
const loadDeviceLoading = ref(false)
+const fileInputRef = ref(null)
watch(
() => props.group,
@@ -142,10 +151,10 @@
const deviceList = Array.isArray(rawList)
? rawList
: Array.isArray(rawList?.records)
- ? rawList.records
- : Array.isArray(rawList?.data)
- ? rawList.data
- : []
+ ? rawList.records
+ : Array.isArray(rawList?.data)
+ ? rawList.data
+ : []
const scannerDevice = deviceList.find((item) => {
const type = normalizeType(item.deviceType)
return type.includes('SCANNER') || type.includes('鎵爜')
@@ -172,7 +181,7 @@
ElMessage.warning('璇峰厛閫夋嫨璁惧缁�')
return
}
-
+
// 琛ㄥ崟楠岃瘉
if (!formRef.value) return
try {
@@ -181,35 +190,35 @@
ElMessage.warning('璇锋鏌ヨ〃鍗曡緭鍏�')
return
}
-
+
try {
loading.value = true
-
+
// 鏋勫缓浠诲姟鍙傛暟
// 濡傛灉杈撳叆浜嗙幓鐠僆D锛屼娇鐢ㄨ緭鍏ョ殑锛涘鏋滄病鏈夎緭鍏ワ紝glassIds涓虹┖鏁扮粍锛屽悗绔細浠庢暟鎹簱璇诲彇
const parameters = {
glassIds: glassIds.value.length > 0 ? glassIds.value : []
}
-
+
// 寮傛鍚姩浠诲姟锛岀珛鍗宠繑鍥烇紝涓嶉樆濉�
const response = await multiDeviceTaskApi.startTask({
groupId: props.group.id || props.group.groupId,
parameters
})
-
+
const task = response?.data
if (task && task.taskId) {
ElMessage.success(`浠诲姟宸插惎鍔紙寮傛鎵ц锛�: ${task.taskId}`)
emit('task-started', task)
-
+
// 绔嬪嵆鍒锋柊鐩戞帶鍒楄〃锛屾樉绀烘柊鍚姩鐨勪换鍔�
setTimeout(() => {
emit('task-started')
}, 500)
-
+
// 閲嶇疆琛ㄥ崟锛堜繚鐣欐墽琛岄厤缃級锛屾柟渚跨户缁惎鍔ㄥ叾浠栬澶囩粍
glassIdsInput.value = ''
-
+
// 鎻愮ず鐢ㄦ埛鍙互缁х画鍚姩鍏朵粬璁惧缁�
ElMessage.info('鍙互缁х画閫夋嫨鍏朵粬璁惧缁勫惎鍔ㄦ祴璇曪紝澶氫釜璁惧缁勫皢骞惰鎵ц')
} else {
@@ -253,6 +262,280 @@
ElMessage.error(error?.message || 'PLC娓呯┖澶辫触')
} finally {
clearLoading.value = false
+ }
+}
+
+// 澶勭悊瀵煎叆Excel鎸夐挳鐐瑰嚮
+const handleImportExcel = () => {
+ if (!props.group) {
+ ElMessage.warning('璇峰厛閫夋嫨璁惧缁�')
+ return
+ }
+ if (fileInputRef.value) {
+ fileInputRef.value.click()
+ }
+}
+
+// 澶勭悊鏂囦欢閫夋嫨
+const handleFileChange = async (event) => {
+ const file = event.target.files?.[0]
+ if (!file) {
+ return
+ }
+
+ // 楠岃瘉鏂囦欢绫诲瀷
+ const fileName = file.name.toLowerCase()
+ if (!fileName.endsWith('.xlsx') && !fileName.endsWith('.xls')) {
+ ElMessage.error('璇烽�夋嫨 Excel 鏂囦欢锛�.xlsx 鎴� .xls锛�')
+ event.target.value = ''
+ return
+ }
+
+ try {
+ importLoading.value = true
+
+ // 璇诲彇鏂囦欢
+ const fileReader = new FileReader()
+ fileReader.onload = (e) => {
+ try {
+ const data = new Uint8Array(e.target.result)
+ const workbook = XLSX.read(data, { type: 'array' })
+
+ // 璇诲彇绗竴涓伐浣滆〃
+ const firstSheetName = workbook.SheetNames[0]
+ const worksheet = workbook.Sheets[firstSheetName]
+
+ // 杞崲涓� JSON 鏁扮粍
+ const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 })
+
+ if (!jsonData || jsonData.length === 0) {
+ ElMessage.error('Excel 鏂囦欢涓虹┖')
+ event.target.value = ''
+ return
+ }
+
+ // 瑙f瀽鏁版嵁锛堝亣璁剧涓�琛屾槸琛ㄥご锛�
+ const parsedData = parseExcelData(jsonData)
+
+ if (parsedData.length === 0) {
+ ElMessage.error('鏈兘瑙f瀽鍒版湁鏁堟暟鎹紝璇锋鏌� Excel 鏍煎紡')
+ event.target.value = ''
+ return
+ }
+
+ // 鍙戦�佹暟鎹埌 MES 鎺ュ彛
+ submitGlassData(parsedData)
+
+ } catch (error) {
+ console.error('瑙f瀽 Excel 澶辫触:', error)
+ ElMessage.error('瑙f瀽 Excel 鏂囦欢澶辫触: ' + (error.message || '鏈煡閿欒'))
+ } finally {
+ event.target.value = ''
+ importLoading.value = false
+ }
+ }
+
+ fileReader.onerror = () => {
+ ElMessage.error('璇诲彇鏂囦欢澶辫触')
+ event.target.value = ''
+ importLoading.value = false
+ }
+
+ fileReader.readAsArrayBuffer(file)
+
+ } catch (error) {
+ console.error('瀵煎叆 Excel 澶辫触:', error)
+ ElMessage.error('瀵煎叆 Excel 澶辫触: ' + (error.message || '鏈煡閿欒'))
+ importLoading.value = false
+ event.target.value = ''
+ }
+}
+
+// 瑙f瀽 Excel 鏁版嵁
+const parseExcelData = (jsonData) => {
+ if (!jsonData || jsonData.length < 2) {
+ return []
+ }
+
+ // 灏濊瘯璇嗗埆琛ㄥご锛堟敮鎸佷腑鑻辨枃锛�
+ const headerRow = jsonData[0]
+ const headerMap = {}
+
+ headerRow.forEach((header, index) => {
+ if (!header) return
+ const headerStr = String(header).trim().toLowerCase()
+
+ // 鐜荤拑ID
+ if (headerStr.includes('鐜荤拑id') || headerStr.includes('glassid') ||
+ (headerStr.includes('鐜荤拑') && headerStr.includes('id')) ||
+ headerStr === 'id' || headerStr === 'glass_id') {
+ headerMap.glassId = index
+ }
+ // 瀹藉害
+ else if (headerStr.includes('瀹�') || headerStr.includes('width') ||
+ headerStr === 'w' || headerStr === '瀹藉害') {
+ headerMap.width = index
+ }
+ // 楂樺害
+ else if (headerStr.includes('楂�') || headerStr.includes('height') ||
+ headerStr === 'h' || headerStr === '楂樺害') {
+ headerMap.height = index
+ }
+ // 鍘氬害
+ else if (headerStr.includes('鍘�') || headerStr.includes('thickness') ||
+ headerStr === 't' || headerStr === '鍘氬害') {
+ headerMap.thickness = index
+ }
+ // 鏁伴噺
+ else if (headerStr.includes('鏁伴噺') || headerStr.includes('quantity') ||
+ headerStr.includes('qty') || headerStr === '鏁伴噺') {
+ headerMap.quantity = index
+ }
+ // 璁㈠崟鍙�
+ else if (headerStr.includes('璁㈠崟') || headerStr.includes('order') ||
+ headerStr.includes('orderno') || headerStr === '璁㈠崟鍙�') {
+ headerMap.orderNumber = index
+ }
+ // 鑶滅郴
+ else if (headerStr.includes('鑶滅郴') || headerStr.includes('films') ||
+ headerStr.includes('film') || headerStr === '鑶滅郴id') {
+ headerMap.filmsId = index
+ }
+ // 娴佺▼鍗D
+ else if (headerStr.includes('娴佺▼鍗�') || headerStr.includes('flowcard') ||
+ headerStr.includes('flow') || headerStr === '娴佺▼鍗d') {
+ headerMap.flowCardId = index
+ }
+ // 浜у搧鍚嶇О
+ else if (headerStr.includes('浜у搧') || headerStr.includes('product') ||
+ headerStr === '浜у搧鍚嶇О') {
+ headerMap.productName = index
+ }
+ // 瀹㈡埛鍚嶇О
+ else if (headerStr.includes('瀹㈡埛') || headerStr.includes('customer') ||
+ headerStr === '瀹㈡埛鍚嶇О') {
+ headerMap.customerName = index
+ }
+ })
+
+ // 濡傛灉娌℃湁鎵惧埌琛ㄥご锛屽皾璇曚娇鐢ㄧ涓�琛屼綔涓鸿〃澶达紙绱㈠紩鏂瑰紡锛�
+ if (Object.keys(headerMap).length === 0 && jsonData.length > 1) {
+ // 榛樿鏍煎紡锛氱幓鐠僆D, 瀹�, 楂�, 鍘�, 鏁伴噺锛堟寜鍒楅『搴忥級
+ headerMap.glassId = 0
+ headerMap.width = 1
+ headerMap.height = 2
+ headerMap.thickness = 3
+ headerMap.quantity = 4
+ }
+
+ // 瑙f瀽鏁版嵁琛�
+ const result = []
+ for (let i = 1; i < jsonData.length; i++) {
+ const row = jsonData[i]
+ if (!row || row.length === 0) continue
+
+ const glassId = row[headerMap.glassId] ? String(row[headerMap.glassId]).trim() : ''
+ const width = row[headerMap.width] ? String(row[headerMap.width]).trim() : ''
+ const height = row[headerMap.height] ? String(row[headerMap.height]).trim() : ''
+ const thickness = row[headerMap.thickness] ? String(row[headerMap.thickness]).trim() : ''
+ const quantity = row[headerMap.quantity] ? String(row[headerMap.quantity]).trim() : ''
+ // 璁㈠崟搴忓彿锛堟帴鍙h姹傛暣鏁帮紝杩欓噷灏濊瘯瑙f瀽涓烘暣鏁帮紝涓嶅彲瑙f瀽鍒欑疆绌猴級
+ const orderNumber = parseInt(row[headerMap.orderNumber]) || ''
+ const filmsId = row[headerMap.filmsId] ? String(row[headerMap.filmsId]).trim() : ''
+ const flowCardId = row[headerMap.flowCardId] ? String(row[headerMap.flowCardId]).trim() : ''
+ const productName = row[headerMap.productName] ? String(row[headerMap.productName]).trim() : ''
+ const customerName = row[headerMap.customerName] ? String(row[headerMap.customerName]).trim() : ''
+
+ // 璺宠繃绌鸿
+ if (!glassId && !width && !height && !thickness && !quantity) {
+ continue
+ }
+
+ // 楠岃瘉蹇呭~瀛楁
+ if (!glassId) {
+ ElMessage.warning(`绗� ${i + 1} 琛岋細鐜荤拑ID涓虹┖锛屽凡璺宠繃`)
+ continue
+ }
+
+ // 杞崲鏁板�肩被鍨嬶紝纭繚鏍煎紡姝g‘
+ const parseNumber = (value) => {
+ if (!value) return '0'
+ const num = parseFloat(value)
+ return isNaN(num) ? '0' : String(num)
+ }
+
+ // 澶勭悊鏁伴噺锛氬鏋滄暟閲忓ぇ浜�1锛岄渶瑕佺敓鎴愬鏉¤褰�
+ const qty = parseInt(quantity) || 1
+ for (let j = 0; j < qty; j++) {
+ // 濡傛灉鏁伴噺澶т簬1锛屼负姣忔潯璁板綍鐢熸垚鍞竴鐨勭幓鐠僆D锛堣拷鍔犲簭鍙凤級
+ const finalGlassId = qty > 1 ? `${glassId}_${j + 1}` : glassId
+
+ result.push({
+ glassId: finalGlassId,
+ width: parseNumber(width),
+ height: parseNumber(height),
+ thickness: parseNumber(thickness),
+ quantity: '1', // 姣忔潯璁板綍鏁伴噺涓�1
+ orderNumber: orderNumber,
+ filmsId: filmsId,
+ flowCardId: flowCardId || finalGlassId,
+ productName: productName,
+ customerName: customerName
+ })
+ }
+ }
+
+ return result
+}
+
+// 鎻愪氦鐜荤拑鏁版嵁鍒板悗绔紝鐢卞悗绔畬鎴� JSON 杞崲骞惰皟鐢� MES 鎺ュ彛
+const submitGlassData = async (glassDataList) => {
+ if (!props.group) {
+ ElMessage.warning('璇峰厛閫夋嫨璁惧缁�')
+ return
+ }
+
+ try {
+ importLoading.value = true
+
+ // 浼犻�掑師濮嬭В鏋愭暟鎹粰鍚庣锛屽悗绔畬鎴愯浆鎹笌 MES 璋冪敤
+ const requestData = { excelRows: glassDataList }
+
+ // 鎵撳嵃鍘熷鏁版嵁渚涜皟璇�
+ console.log('涓婁紶鍒板悗绔殑鍘熷 Excel 鏁版嵁:', JSON.stringify(requestData, null, 2))
+
+ const response = await engineeringApi.importEngineer(requestData)
+
+ if (response?.code === 200 || response?.code === 0 || response?.data) {
+ ElMessage.success(`鎴愬姛瀵煎叆 ${glassDataList.length} 鏉$幓鐠冩暟鎹紝宸ョ▼鍙凤細${requestData.engineerId}`)
+
+ // 灏嗗鍏ョ殑鐜荤拑ID濉厖鍒拌緭鍏ユ锛屾柟渚跨敤鎴锋煡鐪嬪拰缂栬緫
+ const glassIds = glassDataList.map(item => item.glassId).filter(id => id)
+ if (glassIds.length > 0) {
+ glassIdsInput.value = glassIds.join('\n')
+ }
+ } else {
+ throw new Error(response?.message || '瀵煎叆澶辫触')
+ }
+ } catch (error) {
+ console.error('鎻愪氦鐜荤拑鏁版嵁澶辫触:', error)
+
+ // 鏄剧ず閿欒淇℃伅
+ const errorMsg = error?.response?.data?.message || error?.message || '鏈煡閿欒'
+ ElMessage.error('鎻愪氦鏁版嵁澶辫触: ' + errorMsg)
+
+ // 鍗充娇澶辫触锛屼篃灏濊瘯濉厖鐜荤拑ID鍒拌緭鍏ユ
+ try {
+ const glassIds = glassDataList.map(item => item.glassId).filter(id => id)
+ if (glassIds.length > 0) {
+ glassIdsInput.value = glassIds.join('\n')
+ ElMessage.info('宸插皢鐜荤拑ID濉厖鍒拌緭鍏ユ锛屾偍鍙互鎵嬪姩鎻愪氦')
+ }
+ } catch (e) {
+ console.error('濉厖鏁版嵁澶辫触:', e)
+ }
+ } finally {
+ importLoading.value = false
}
}
</script>
@@ -309,4 +592,3 @@
margin-top: 24px;
}
</style>
-
--
Gitblit v1.8.0