From 74550c615b13da914ac4cae28f2d71f8103a49e2 Mon Sep 17 00:00:00 2001 From: "Mr.j" <2221464500@qq.com> Date: Fri, 8 Aug 2025 17:35:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E7=94=B3=E8=AF=B7=E9=87=87?= =?UTF-8?q?=E8=B4=AD=E6=8E=A8=E9=80=81=E4=BF=A1=E6=81=AF=E5=88=B0=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E5=8F=B0=E5=87=BA=E7=8E=B0=E8=AF=AD=E9=9F=B3=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E5=92=8C=E9=97=AA=E7=83=81=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/pom.xml | 6 ++ .../com/dite/znpt/config/WebSocketConfig.java | 27 ++++++ .../impl/EquipmentApprovalServiceImpl.java | 40 +++++++- .../websocket/SimpleWebSocketHandler.java | 96 +++++++++++++++++++ 4 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/com/dite/znpt/config/WebSocketConfig.java create mode 100644 core/src/main/java/com/dite/znpt/websocket/SimpleWebSocketHandler.java diff --git a/core/pom.xml b/core/pom.xml index a1e8bba..8d32f0d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -197,6 +197,12 @@ jaxb-api 2.3.1 + + + + org.springframework.boot + spring-boot-starter-websocket + diff --git a/core/src/main/java/com/dite/znpt/config/WebSocketConfig.java b/core/src/main/java/com/dite/znpt/config/WebSocketConfig.java new file mode 100644 index 0000000..8635b51 --- /dev/null +++ b/core/src/main/java/com/dite/znpt/config/WebSocketConfig.java @@ -0,0 +1,27 @@ +package com.dite.znpt.config; + +import com.dite.znpt.websocket.SimpleWebSocketHandler; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + +/** + * WebSocket配置 + */ +@Configuration +@EnableWebSocket +public class WebSocketConfig implements WebSocketConfigurer { + + private final SimpleWebSocketHandler simpleWebSocketHandler; + + public WebSocketConfig(SimpleWebSocketHandler simpleWebSocketHandler) { + this.simpleWebSocketHandler = simpleWebSocketHandler; + } + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(simpleWebSocketHandler, "/websocket") + .setAllowedOrigins("*"); // 在生产环境中应该限制允许的源 + } +} diff --git a/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java b/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java index 03ce776..1fa86dd 100644 --- a/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java +++ b/core/src/main/java/com/dite/znpt/service/impl/EquipmentApprovalServiceImpl.java @@ -10,6 +10,7 @@ import com.dite.znpt.domain.vo.EquipmentApprovalReq; import com.dite.znpt.domain.vo.EquipmentApprovalResp; import com.dite.znpt.domain.vo.EquipmentProcurementApplyReq; import com.dite.znpt.service.EquipmentApprovalService; +import com.dite.znpt.websocket.SimpleWebSocketHandler; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; @@ -261,6 +262,21 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService { // 保存到数据库 equipmentApprovalMapper.insert(entity); + // 发送通知 - 使用日志记录,后续可以扩展为WebSocket通知 + log.info("采购申请提交成功,设备名称: {}, 申请人: {}", + req.getEquipmentName(), getCurrentUserName()); + + // 发送WebSocket通知 + try { + SimpleWebSocketHandler.sendProcurementNotification( + req.getEquipmentName(), + getCurrentUserName() + ); + log.info("WebSocket通知发送成功"); + } catch (Exception e) { + log.error("WebSocket通知发送失败", e); + } + log.info("采购申请提交成功,审批ID: {}", entity.getApprovalId()); } @@ -317,15 +333,31 @@ public class EquipmentApprovalServiceImpl implements EquipmentApprovalService { * 获取当前用户名 */ private String getCurrentUserName() { - // TODO: 从安全上下文获取当前用户名 - return "当前用户"; + try { + // 从Sa-Token上下文获取当前用户名 + Object loginId = cn.dev33.satoken.stp.StpUtil.getLoginId(); + if (loginId != null) { + return loginId.toString(); + } + } catch (Exception e) { + log.warn("获取当前用户名失败: {}", e.getMessage()); + } + return "未知用户"; } /** * 获取当前用户ID */ private String getCurrentUserId() { - // TODO: 从安全上下文获取当前用户ID - return "current_user_id"; + try { + // 从Sa-Token上下文获取当前用户ID + Object loginId = cn.dev33.satoken.stp.StpUtil.getLoginId(); + if (loginId != null) { + return loginId.toString(); + } + } catch (Exception e) { + log.warn("获取当前用户ID失败: {}", e.getMessage()); + } + return "unknown_user_id"; } } diff --git a/core/src/main/java/com/dite/znpt/websocket/SimpleWebSocketHandler.java b/core/src/main/java/com/dite/znpt/websocket/SimpleWebSocketHandler.java new file mode 100644 index 0000000..4851e0c --- /dev/null +++ b/core/src/main/java/com/dite/znpt/websocket/SimpleWebSocketHandler.java @@ -0,0 +1,96 @@ +package com.dite.znpt.websocket; + +import org.springframework.stereotype.Component; +import org.springframework.web.socket.*; + +import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.Map; + +/** + * 简单的WebSocket处理器 + */ +@Component +public class SimpleWebSocketHandler implements WebSocketHandler { + + // 存储所有连接的会话 + private static final Map sessions = new ConcurrentHashMap<>(); + + @Override + public void afterConnectionEstablished(WebSocketSession session) throws Exception { + String sessionId = session.getId(); + sessions.put(sessionId, session); + System.out.println("WebSocket连接建立,sessionId: " + sessionId); + } + + @Override + public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception { + // 处理接收到的消息 + System.out.println("收到WebSocket消息: " + message.getPayload()); + } + + @Override + public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { + System.err.println("WebSocket传输错误,sessionId: " + session.getId()); + exception.printStackTrace(); + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { + String sessionId = session.getId(); + sessions.remove(sessionId); + System.out.println("WebSocket连接关闭,sessionId: " + sessionId); + } + + @Override + public boolean supportsPartialMessages() { + return false; + } + + /** + * 发送简单消息给所有连接的客户端 + */ + public static void sendMessageToAll(String message) { + System.out.println("准备发送WebSocket消息给 " + sessions.size() + " 个连接的客户端"); + System.out.println("消息内容: " + message); + + final int[] successCount = {0}; + final int[] failCount = {0}; + + sessions.values().forEach(session -> { + try { + if (session.isOpen()) { + session.sendMessage(new TextMessage(message)); + successCount[0]++; + System.out.println("成功发送消息给sessionId: " + session.getId()); + } else { + System.out.println("跳过已关闭的sessionId: " + session.getId()); + } + } catch (IOException e) { + failCount[0]++; + System.err.println("发送消息失败,sessionId: " + session.getId()); + e.printStackTrace(); + } + }); + + System.out.println("WebSocket消息发送完成 - 成功: " + successCount[0] + ", 失败: " + failCount[0]); + } + + /** + * 发送采购申请通知 + */ + public static void sendProcurementNotification(String equipmentName, String applicantName) { + String notificationMessage = String.format( + "{\"type\":\"PROCUREMENT_APPLICATION\",\"title\":\"新的采购申请\",\"content\":\"收到来自 %s 的设备采购申请:%s\"}", + applicantName, equipmentName + ); + + System.out.println("=== 发送采购申请通知 ==="); + System.out.println("设备名称: " + equipmentName); + System.out.println("申请人: " + applicantName); + System.out.println("通知消息: " + notificationMessage); + System.out.println("当前连接数: " + sessions.size()); + + sendMessageToAll(notificationMessage); + } +}