diff --git a/backend/src/main/java/io/metersphere/websocket/c/to/c/WebSocketUtils.java b/backend/src/main/java/io/metersphere/websocket/c/to/c/WebSocketUtils.java index c1702c673a..c0eeef1ce1 100644 --- a/backend/src/main/java/io/metersphere/websocket/c/to/c/WebSocketUtils.java +++ b/backend/src/main/java/io/metersphere/websocket/c/to/c/WebSocketUtils.java @@ -6,6 +6,7 @@ import io.metersphere.websocket.c.to.c.util.MsgDto; import javax.websocket.RemoteEndpoint; import javax.websocket.Session; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; public class WebSocketUtils { @@ -27,8 +28,8 @@ public class WebSocketUtils { // 单用户推送 public static void sendMessageSingle(MsgDto dto) { - sendMessage(ONLINE_USER_SESSIONS.get(dto.getReportId()), dto.getContent()); - sendMessage(ONLINE_USER_SESSIONS.get(dto.getToReport()), dto.getContent()); + sendMessage(ONLINE_USER_SESSIONS.get(Optional.ofNullable(dto.getReportId()).orElse("")), dto.getContent()); + sendMessage(ONLINE_USER_SESSIONS.get(Optional.ofNullable(dto.getToReport()).orElse("")), dto.getContent()); } // 全用户推送 diff --git a/frontend/src/business/components/api/automation/report/SysnApiReportDetail.vue b/frontend/src/business/components/api/automation/report/SysnApiReportDetail.vue index 4404ec75a9..6e26a31d4b 100644 --- a/frontend/src/business/components/api/automation/report/SysnApiReportDetail.vue +++ b/frontend/src/business/components/api/automation/report/SysnApiReportDetail.vue @@ -151,7 +151,11 @@ export default { infoDb: Boolean, debug: Boolean, scenario: {}, - scenarioId: String + scenarioId: String, + isUi: { + type: Boolean, + default: false + } }, methods: { initTree() { @@ -300,7 +304,12 @@ export default { } const uri = protocol + window.location.host + "/ws/" + this.reportId; this.messageWebSocket = new WebSocket(uri); + //初始化心跳 目前ui的机制容易使得 ws 超时 + if (this.isUi) { + this.initHeartBeat(); + } this.messageWebSocket.onmessage = this.onMessage; + this.messageWebSocket.onerror = this.cleanHeartBeat; }, getReport() { let url = "/api/scenario/report/get/" + this.reportId; @@ -458,6 +467,7 @@ export default { if (e.data && e.data.indexOf("MS_TEST_END") !== -1) { this.getReport(); this.messageWebSocket.close(); + this.cleanHeartBeat(); this.$EventBus.$emit('hide', this.scenarioId); this.$emit('refresh', this.debugResult); } @@ -490,6 +500,32 @@ export default { } } } + }, + websocketKey(){ + return "ui_ws_" + this.reportId; + }, + initHeartBeat() { + if (!window.localStorage.getItem(this.websocketKey())) { + window.localStorage.setItem(this.websocketKey(), this.reportId); + window.heartBeatHandle = setInterval(this.heartBeat, 30000); + } else { + this.cleanHeartBeat(); + this.initHeartBeat(); + } + }, + cleanHeartBeat() { + if (window.heartBeatHandle) { + clearInterval(window.heartBeatHandle); + if (window.localStorage.getItem(this.websocketKey())) + window.localStorage.removeItem(this.websocketKey()); + } + }, + heartBeat() { + let msg = { + reportId: this.reportId, + content: "i'm alive" + }; + this.messageWebSocket.send(JSON.stringify(msg)); } }, computed: {