package com.mes.device.controller; import com.mes.device.entity.EngineeringSequence; import com.mes.device.entity.GlassInfo; import com.mes.device.service.EngineeringSequenceService; import com.mes.device.service.GlassInfoService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; 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.*; import java.util.stream.Collectors; /** * @author :huang * @date :2025-12-08 * 工程导入转发接口(接收前端 Excel 行数据,后端组装后转发 MES) */ @Slf4j @RestController @RequestMapping("excel") @RequiredArgsConstructor public class GlassInfoImportController { private final GlassInfoService glassInfoService; private final EngineeringSequenceService engineeringSequenceService; private final RestTemplate restTemplate = new RestTemplate(); /** * 导入工程 * 前端入参示例: * { * "excelRows": [ * {"glassId":"GL001","width":"1000","height":"2000","thickness":"5","quantity":"2","flowCardId":"NG25082101","filmsId":"白玻"} * ] * } */ @PostMapping("/importExcel") public ResponseEntity importEngineer(@RequestBody Map body) { Object rowsObj = body.get("excelRows"); if (!(rowsObj instanceof List)) { return ResponseEntity.badRequest().body("excelRows 必须是数组"); } @SuppressWarnings("unchecked") List> excelRows = (List>) rowsObj; if (CollectionUtils.isEmpty(excelRows)) { return ResponseEntity.badRequest().body("excelRows 不能为空"); } Map payload = glassInfoService.buildEngineerImportPayload(excelRows); log.info("构建的 MES 导入数据: {}", payload); // 从payload中提取工程号(payload中使用的是engineerId) String engineeringId = (String) payload.get("engineerId"); if (engineeringId == null || engineeringId.isEmpty()) { // 如果payload中没有engineerId,尝试从glassInfolList中获取 @SuppressWarnings("unchecked") List> glassInfoList = (List>) payload.get("glassInfolList"); if (glassInfoList != null && !glassInfoList.isEmpty()) { Object firstEngineerId = glassInfoList.get(0).get("engineerId"); if (firstEngineerId != null) { engineeringId = firstEngineerId.toString(); } } } String mesEngineeringImportUrl = glassInfoService.getMesEngineeringImportUrl(); try { ResponseEntity mesResp = restTemplate.postForEntity(mesEngineeringImportUrl, payload, Map.class); Map mesBody = mesResp.getBody(); // 检查MES响应是否真正成功(不仅检查HTTP状态码,还要检查响应体中的code字段) boolean mesSuccess = false; if (mesResp.getStatusCode().is2xxSuccessful() && mesBody != null) { Object codeObj = mesBody.get("code"); if (codeObj != null) { int code = codeObj instanceof Number ? ((Number) codeObj).intValue() : Integer.parseInt(String.valueOf(codeObj)); // MES成功通常返回code=200或0 mesSuccess = (code == 200 || code == 0); } else { // 如果没有code字段,认为HTTP 2xx就是成功 mesSuccess = true; } } // 只有MES导入真正成功时,才保存玻璃信息到本地数据库,并关联engineering_id if (mesSuccess && engineeringId != null) { try { glassInfoService.saveGlassInfosFromExcel(excelRows, engineeringId); log.info("MES导入成功,已保存玻璃信息到本地数据库,工程号: {}", engineeringId); } catch (Exception e) { log.error("MES导入成功,但保存玻璃信息到本地数据库失败: engineeringId={}", engineeringId, e); // 即使保存失败,也返回MES的成功响应,但记录错误日志 } } else { log.warn("MES导入未成功,不保存玻璃信息到本地数据库: engineeringId={}, mesSuccess={}", engineeringId, mesSuccess); } // 直接返回 MES 的响应,让前端根据响应体中的 code 字段判断是否成功 return ResponseEntity.status(mesResp.getStatusCode()).body(mesBody); } catch (org.springframework.web.client.ResourceAccessException e) { // 连接超时或无法连接 log.error("转发 MES 导入接口失败(连接问题) url={}, error={}", mesEngineeringImportUrl, e.getMessage(), e); Map errorResponse = new java.util.HashMap<>(); errorResponse.put("code", 500); errorResponse.put("message", "无法连接到 MES 接口,请检查网络连接或联系管理员"); errorResponse.put("data", false); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); } catch (Exception e) { // 其他异常 log.error("转发 MES 导入接口失败 url={}, error={}", mesEngineeringImportUrl, e.getMessage(), e); Map errorResponse = new java.util.HashMap<>(); errorResponse.put("code", 500); errorResponse.put("message", "转发 MES 失败: " + e.getMessage()); errorResponse.put("data", false); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); } } /** * 查询所有工程号列表 */ @GetMapping("/engineering/list") public ResponseEntity getEngineeringList() { try { List list = engineeringSequenceService.list(); List> result = list.stream() .map(seq -> { Map map = new LinkedHashMap<>(); map.put("engineeringId", seq.getEngineeringId()); map.put("date", seq.getDate()); map.put("sequence", seq.getSequence()); return map; }) .sorted(Comparator.comparing( (Map map) -> (Date) map.get("date"), Comparator.nullsLast(Comparator.reverseOrder()) ).thenComparing( map -> (Integer) map.get("sequence"), Comparator.nullsLast(Comparator.reverseOrder()) )) .collect(Collectors.toList()); return ResponseEntity.ok(result); } catch (Exception e) { log.error("查询工程号列表失败", e); Map errorResponse = new HashMap<>(); errorResponse.put("code", 500); errorResponse.put("message", "查询工程号列表失败: " + e.getMessage()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); } } /** * 根据工程号查询对应的玻璃ID列表 */ @GetMapping("/engineering/{engineeringId}/glassIds") public ResponseEntity getGlassIdsByEngineeringId(@PathVariable String engineeringId) { try { List glassInfos = glassInfoService.getGlassInfosByEngineeringId(engineeringId); List glassIds = glassInfos.stream() .map(GlassInfo::getGlassId) .filter(id -> id != null && !id.trim().isEmpty()) .collect(Collectors.toList()); Map result = new HashMap<>(); result.put("engineeringId", engineeringId); result.put("glassIds", glassIds); result.put("count", glassIds.size()); return ResponseEntity.ok(result); } catch (Exception e) { log.error("根据工程号查询玻璃ID列表失败: engineeringId={}", engineeringId, e); Map errorResponse = new HashMap<>(); errorResponse.put("code", 500); errorResponse.put("message", "查询玻璃ID列表失败: " + e.getMessage()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); } } /** * 删除工程号及其关联的玻璃信息 */ @DeleteMapping("/engineering/{engineeringId}") public ResponseEntity deleteEngineering(@PathVariable String engineeringId) { try { // 1. 删除glass_info表中对应工程号的玻璃信息 int deletedGlassCount = glassInfoService.deleteGlassInfosByEngineeringId(engineeringId); // 2. 删除engineering_sequence表中的工程号记录(逻辑删除) EngineeringSequence sequence = engineeringSequenceService.getOne( new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() .eq(EngineeringSequence::getEngineeringId, engineeringId) .eq(EngineeringSequence::getIsDeleted, 0) // 只查询未删除的记录 .last("LIMIT 1") ); boolean deletedSequence = false; if (sequence != null) { // removeById 会自动使用逻辑删除(因为实体类有 @TableLogic 注解) deletedSequence = engineeringSequenceService.removeById(sequence.getId()); log.info("已删除工程号记录: engineeringId={}, sequenceId={}", engineeringId, sequence.getId()); } else { log.warn("未找到工程号记录: engineeringId={}", engineeringId); } Map result = new HashMap<>(); result.put("engineeringId", engineeringId); result.put("deletedGlassCount", deletedGlassCount); result.put("deletedSequence", deletedSequence); result.put("success", true); result.put("message", String.format("已删除工程号 %s,共删除 %d 条玻璃信息", engineeringId, deletedGlassCount)); log.info("删除工程号成功: engineeringId={}, deletedGlassCount={}, deletedSequence={}", engineeringId, deletedGlassCount, deletedSequence); return ResponseEntity.ok(result); } catch (Exception e) { log.error("删除工程号失败: engineeringId={}", engineeringId, e); Map errorResponse = new HashMap<>(); errorResponse.put("code", 500); errorResponse.put("message", "删除工程号失败: " + e.getMessage()); errorResponse.put("success", false); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); } } }