From e3c6eae37e2170c8ee6b95176406c55dbc3a21dc Mon Sep 17 00:00:00 2001 From: jiangs <373297395@qq.com> Date: Mon, 31 Aug 2026 17:09:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B6=88=E6=81=AF=E7=B3=BB=E7=BB=9F=EF=BC=8C?= =?UTF-8?q?=E8=BE=93=E8=A1=80=E7=94=B3=E8=AF=B7=E6=B6=88=E6=81=AF=EF=BC=8C?= =?UTF-8?q?=E5=8F=91=E8=A1=80=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../XkTransfuseApplyBloodbreedMapper.java | 1 + .../bus/pojo/websocket/WebSocketParam.java | 5 +- .../com/czblood/bus/websocket/MsgType.java | 2 +- .../bus/websocket/SendMessageUtil.java | 68 ++++++++++ .../bus/websocket/WebSocketConfig.java | 25 +++- .../bus/websocket/WebSocketServer.java | 123 ++++++++++++------ .../com/czblood/bus/websocket/WsMessage.java | 8 +- .../XkTransfuseApplyBloodbreedMapper.xml | 3 + .../service/impl/BloodOutServiceImpl.java | 4 +- .../busDoctor/utils/TransfuseApplyUtil.java | 16 +-- .../common/core/domain/entity/SysDept.java | 2 + .../resources/mapper/system/SysDeptMapper.xml | 3 + 12 files changed, 202 insertions(+), 58 deletions(-) create mode 100644 blood_bus/src/main/java/com/czblood/bus/websocket/SendMessageUtil.java diff --git a/blood_bus/src/main/java/com/czblood/bus/mapper/XkTransfuseApplyBloodbreedMapper.java b/blood_bus/src/main/java/com/czblood/bus/mapper/XkTransfuseApplyBloodbreedMapper.java index f97c266..920ca24 100644 --- a/blood_bus/src/main/java/com/czblood/bus/mapper/XkTransfuseApplyBloodbreedMapper.java +++ b/blood_bus/src/main/java/com/czblood/bus/mapper/XkTransfuseApplyBloodbreedMapper.java @@ -9,4 +9,5 @@ public interface XkTransfuseApplyBloodbreedMapper { List queryOne(String bill_no); void insert(XkTransfuseApplyBloodbreed xkTransfuseApplyBloodbreed); void update(XkTransfuseApplyBloodbreed xkTransfuseApplyBloodbreed); + void deleteByBillNo(String bill_no); } diff --git a/blood_bus/src/main/java/com/czblood/bus/pojo/websocket/WebSocketParam.java b/blood_bus/src/main/java/com/czblood/bus/pojo/websocket/WebSocketParam.java index f99496f..fd01198 100644 --- a/blood_bus/src/main/java/com/czblood/bus/pojo/websocket/WebSocketParam.java +++ b/blood_bus/src/main/java/com/czblood/bus/pojo/websocket/WebSocketParam.java @@ -1,5 +1,6 @@ package com.czblood.bus.pojo.websocket; +import com.czblood.common.core.domain.entity.SysUser; import com.czblood.common.core.domain.model.LoginUser; import lombok.AllArgsConstructor; import lombok.Data; @@ -13,10 +14,10 @@ import java.util.concurrent.ConcurrentHashMap; public class WebSocketParam { private Set sessionSet; private final String userId; - private LoginUser loginUser; + private SysUser loginUser; // 方便快速构建对象 - public static WebSocketParam create(String userId, LoginUser loginUser){ + public static WebSocketParam create(String userId, SysUser loginUser){ // ConcurrentHashMap.newKeySet()线程安全set Set set = ConcurrentHashMap.newKeySet(); return new WebSocketParam(set, userId, loginUser); diff --git a/blood_bus/src/main/java/com/czblood/bus/websocket/MsgType.java b/blood_bus/src/main/java/com/czblood/bus/websocket/MsgType.java index d844c78..e6f36c5 100644 --- a/blood_bus/src/main/java/com/czblood/bus/websocket/MsgType.java +++ b/blood_bus/src/main/java/com/czblood/bus/websocket/MsgType.java @@ -8,7 +8,7 @@ public enum MsgType { //取血通知消息 BLOOD_OUT_NOTICE("BLOOD_OUT_NOTICE"), - //申请单消息 + //输血申请单保存消息 APPLY_NOTICE("APPLY_NOTICE"), /** 单发消息 */ diff --git a/blood_bus/src/main/java/com/czblood/bus/websocket/SendMessageUtil.java b/blood_bus/src/main/java/com/czblood/bus/websocket/SendMessageUtil.java new file mode 100644 index 0000000..3b1349c --- /dev/null +++ b/blood_bus/src/main/java/com/czblood/bus/websocket/SendMessageUtil.java @@ -0,0 +1,68 @@ +package com.czblood.bus.websocket; + + +import com.czblood.bus.mapper.XkMsgDetailMapper; +import com.czblood.bus.mapper.XkMsgMainMapper; +import com.czblood.bus.mapper.XkTransfuseApplyMapper; +import com.czblood.bus.pojo.XkMsgDetail; +import com.czblood.bus.pojo.XkMsgMain; +import com.czblood.bus.pojo.XkTransfuseApply; +import com.czblood.bus.utils.BloodBankUtil; +import com.czblood.common.utils.spring.SpringUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Date; + +@Component +public class SendMessageUtil { + + @Resource + XkTransfuseApplyMapper xkTransfuseApplyMapper; + @Resource + BloodBankUtil bloodBankUtil; + @Resource + XkMsgMainMapper xkMsgMainMapper; + @Resource + XkMsgDetailMapper xkMsgDetailMapper; + + public void saveMessage(String billNo,String content) { + + XkTransfuseApply xkTransfuseApply = xkTransfuseApplyMapper.queryOne(billNo); + if (xkTransfuseApply == null) return ; + + Date currentTimeDate = bloodBankUtil.getCurrentTimeDate(); + + //保存消息数据,写一条消息记录 + //写消息数据主表 + XkMsgMain xkMsgMainTemp = new XkMsgMain(); + xkMsgMainTemp.setAccept_Dept("输血科"); + xkMsgMainTemp.setSend_Dept(xkTransfuseApply.getDept_id()); + xkMsgMainTemp.setSend_Person(xkTransfuseApply.getApply_medic()); + xkMsgMainTemp.setSend_Date(xkTransfuseApply.getApply_date()); + xkMsgMainTemp.setAccept_Person(""); //接收人 + //xkMsgMainTemp.setAccept_Date(currentTimeDate); //接收时间,先默认一个,后面确认之后在更新 + xkMsgMainTemp.setRead_Flag("N"); //是否已读 + xkMsgMainTemp.setSend_Flag("Y"); //是否已发送 + xkMsgMainTemp.setAccept_Flag("N"); //是否已接收 + xkMsgMainTemp.setMsg_Title("输血申请单保存"); + xkMsgMainTemp.setMsg_Type(MsgType.APPLY_NOTICE.getCode()); //发血消息 + xkMsgMainTemp.setWrite_Date(currentTimeDate); + + //写消息数据明细表 + XkMsgDetail xkMsgDetailTemp = new XkMsgDetail(); + xkMsgDetailTemp.setMsg_Body(content); + xkMsgDetailTemp.setAccept_Dept("输血科"); + xkMsgDetailTemp.setSend_Dept(xkTransfuseApply.getDept_id()); + SpringUtils.getBean(SendMessageUtil.class).saveData(xkMsgMainTemp,xkMsgDetailTemp); + } + + @Transactional(rollbackFor = Exception.class) + public void saveData(XkMsgMain xkMsgMain, XkMsgDetail xkMsgDetail) { + xkMsgMainMapper.insert(xkMsgMain); + xkMsgDetailMapper.insert(xkMsgDetail); + } + + +} diff --git a/blood_bus/src/main/java/com/czblood/bus/websocket/WebSocketConfig.java b/blood_bus/src/main/java/com/czblood/bus/websocket/WebSocketConfig.java index 2d3d32f..e00ed51 100644 --- a/blood_bus/src/main/java/com/czblood/bus/websocket/WebSocketConfig.java +++ b/blood_bus/src/main/java/com/czblood/bus/websocket/WebSocketConfig.java @@ -1,5 +1,6 @@ package com.czblood.bus.websocket; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @@ -8,10 +9,32 @@ import org.springframework.web.socket.server.standard.ServerEndpointExporter; * WebSocket配置类(Spring Boot 原生方式) */ @Configuration +@Slf4j public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { - return new ServerEndpointExporter(); + return new ServerEndpointExporter() { + @Override + public void afterPropertiesSet() { + try { + super.afterPropertiesSet(); + } catch (IllegalStateException e) { + // 测试环境或无WebSocket容器时ServerContainer不可用,跳过注册 + log.error("WebSocket ServerContainer不可用,跳过端点注册(测试环境可忽略此警告)"); + } + } + @Override + public void afterSingletonsInstantiated() { + try { + super.afterSingletonsInstantiated(); + } catch (IllegalStateException e) { + // 测试环境或无WebSocket容器时ServerContainer不可用,跳过注册 + log.warn("WebSocket ServerContainer不可用,跳过端点注册(测试环境可忽略)"); + } catch (Exception e) { + log.warn("WebSocket afterSingletonsInstantiated 跳过(测试环境可忽略): {}", e.getMessage()); + } + } + }; } } diff --git a/blood_bus/src/main/java/com/czblood/bus/websocket/WebSocketServer.java b/blood_bus/src/main/java/com/czblood/bus/websocket/WebSocketServer.java index 23d697d..a70da62 100644 --- a/blood_bus/src/main/java/com/czblood/bus/websocket/WebSocketServer.java +++ b/blood_bus/src/main/java/com/czblood/bus/websocket/WebSocketServer.java @@ -1,15 +1,22 @@ package com.czblood.bus.websocket; +import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; +import com.czblood.bus.pojo.XkMsgDetail; +import com.czblood.bus.pojo.XkMsgMain; import com.czblood.bus.pojo.websocket.WebSocketParam; -import com.czblood.common.core.domain.model.LoginUser; -import com.czblood.common.utils.SecurityUtils; +import com.czblood.bus.utils.BloodBankUtil; +import com.czblood.common.core.domain.entity.SysDept; +import com.czblood.common.core.domain.entity.SysUser; +import com.czblood.common.utils.spring.SpringUtils; +import com.czblood.system.mapper.SysDeptMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -32,10 +39,22 @@ public class WebSocketServer { public void onOpen(Session session, @PathParam("userId") String userId) { log.info("客户端:{} 建立连接", userId); session.setMaxTextMessageBufferSize(8192000); - LoginUser loginUser = SecurityUtils.getLoginUser(); - WebSocketParam param = onlineUsers.computeIfAbsent(userId, k -> WebSocketParam.create(k, loginUser)); - boolean addOk = param.getSessionSet().add(session); - log.info("客户端:{} 加入sessionSet:{}", userId, addOk); + SysUser loginUser = null; + try{ + loginUser = SpringUtils.getBean(BloodBankUtil.class).getUserInfo(userId); + }catch (Exception e){ + log.error("获取登录用户信息失败 userId={}", userId, e); + }finally { + if(loginUser != null){ + SysUser finalLoginUser = loginUser; + WebSocketParam param = onlineUsers.computeIfAbsent(userId, k -> WebSocketParam.create(k, finalLoginUser)); + boolean addOk = param.getSessionSet().add(session); + log.info("客户端:{} 加入sessionSet:{}", userId, addOk); + } + + + } + } /** @@ -62,7 +81,7 @@ public class WebSocketServer { case BLOOD_OUT_NOTICE: case APPLY_NOTICE: //给指定的一批人发消息 - //sendToSomeOne(message,userId); + sendToSomeOne(msg); break; case NOTICE: // 群发 / 系统通知:发给所有在线用户 @@ -97,11 +116,11 @@ public class WebSocketServer { log.info("用户[{}]ws连接关闭", userId); } - @OnError - public void onError(Session session, @PathParam("userId") String userId, Throwable throwable) { - onClose(session, userId); - log.error("ws错误 userId={}", userId, throwable); - } +// @OnError +// public void onError(Session session, @PathParam("userId") String userId, Throwable throwable) { +// //onClose(session, userId); +// log.error("ws错误 userId={}", userId, throwable); +// } /** * 群发:给所有在线用户发消息 @@ -140,32 +159,56 @@ public class WebSocketServer { } } -// /** -// * 给指定的人发消息 -// * @param msg -// */ -// public static void sendToSomeOne(WsMessage msg){ -// MsgType type = msg.getType(); -// String content = msg.getContent(); -// String userId = msg.getTo(); -// WebSocketParam param = onlineUsers.get(userId); -// if (param == null || param.getSessionSet().isEmpty()) { -// return; -// } -// for (Session wsSession : param.getSessionSet()) { -// if (wsSession.isOpen()) { -// try { -// wsSession.getBasicRemote().sendText(content); -// } catch (Exception e) { -// log.error("单发消息失败 userId={}: {}", userId, e.getMessage()); -// } -// } -// } -// -// switch (type) { -// //取血通知,传入的人,是取血人 ,但是我们需要通知这个取血人所对应的整个科室,比较合理 -// case BLOOD_OUT_NOTICE: -// -// } -// } + /** + * 给指定的人发消息 + * @param msg + */ + public static void sendToSomeOne(WsMessage msg){ + MsgType type = msg.getType(); + String content = msg.getContent(); + String userId = msg.getTo(); + WebSocketParam param = onlineUsers.get(userId); + String billNo = ""; + try{ + JSONObject data = (JSONObject)msg.getData(); + billNo = data.getStr("billNo"); + }catch (Exception e){ + log.error("消息数据解析异常:", e); + return; + } + + if (param == null || param.getSessionSet().isEmpty()) { + return; + } + for (Session wsSession : param.getSessionSet()) { + if (wsSession.isOpen()) { + try { + wsSession.getBasicRemote().sendText(content); + } catch (Exception e) { + log.error("单发消息失败 userId={}: {}", userId, e.getMessage()); + } + } + } + switch (type) { + //输血申请单保存通知 + case APPLY_NOTICE: + //需要通知整个输血科人员 + SysDept sysDept = new SysDept(); + sysDept.setDeptType("002"); //输血科室 + List sysDeptList = SpringUtils.getBean(SysDeptMapper.class).selectDeptList(sysDept); + for (SysDept dept : sysDeptList) { + Long deptId = dept.getDeptId(); + SysUser sysUserQuery = new SysUser(); + sysUserQuery.setDeptId(deptId); + List sysUserList = SpringUtils.getBean(BloodBankUtil.class).queryUserList(sysUserQuery); + for (SysUser sysUser : sysUserList) { + sendMsg(sysUser.getUserName(), content); + } + } + break; + } + + //保存消息数据,写一条消息记录 + SpringUtils.getBean(SendMessageUtil.class).saveMessage(billNo,content); + } } \ No newline at end of file diff --git a/blood_bus/src/main/java/com/czblood/bus/websocket/WsMessage.java b/blood_bus/src/main/java/com/czblood/bus/websocket/WsMessage.java index 93bf3c2..068628d 100644 --- a/blood_bus/src/main/java/com/czblood/bus/websocket/WsMessage.java +++ b/blood_bus/src/main/java/com/czblood/bus/websocket/WsMessage.java @@ -15,9 +15,11 @@ import java.io.Serializable; * "to": "1002", // 接收者 userId;群发时可为 null 或 "ALL" * "title": "你好", // 可选,消息标题 * "content": "在吗?", // 业务正文(字符串) - * "data": {...}, // 业务扩展字段(对象),不同 type 结构不同 - * "timestamp": 1729999999999,// 时间戳 - * "extra": {...} // 预留扩展 + * "data": { + * "billNo": "" + * }, // 业务扩展字段(对象),不同 type 结构不同 + * "timestamp": "2023-04-01 13:59:59",// 时间格式:yyyy-MM-dd HH:mm:ss,例如:2023-04-01 13:59:59 + * "extra": {} // 预留扩展 * } */ @Data diff --git a/blood_bus/src/main/resources/mapper/XkTransfuseApplyBloodbreedMapper.xml b/blood_bus/src/main/resources/mapper/XkTransfuseApplyBloodbreedMapper.xml index f84b866..82d7f30 100644 --- a/blood_bus/src/main/resources/mapper/XkTransfuseApplyBloodbreedMapper.xml +++ b/blood_bus/src/main/resources/mapper/XkTransfuseApplyBloodbreedMapper.xml @@ -48,6 +48,9 @@ where bill_no = #{bill_no} and blood_breed = #{blood_breed} + + delete from xk_transfuse_apply_bloodbreed where bill_no = #{billNo} +