153 lines
4.1 KiB
Vue
153 lines
4.1 KiB
Vue
<template>
|
|
<div class="settings-container">
|
|
<el-row class="popup-row">
|
|
<el-checkbox v-model="isPopupEnabled" @change="handleCheckboxChange">开启弹窗</el-checkbox>
|
|
</el-row>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
|
import { ElMessageBox, ElMessage } from 'element-plus';
|
|
|
|
// 用于控制复选框的勾选状态
|
|
const isPopupEnabled = ref(false);
|
|
let websocket: WebSocket | null = null;
|
|
let heartbeatInterval: number | null = null; // 用于心跳检测的定时器
|
|
|
|
// 从 localStorage 中读取勾选状态
|
|
onMounted(() => {
|
|
const storedState = localStorage.getItem('isPopupEnabled');
|
|
isPopupEnabled.value = storedState === 'true';
|
|
|
|
if (isPopupEnabled.value) {
|
|
connectWebSocket();
|
|
}
|
|
});
|
|
|
|
// 当页面离开或组件卸载时,清理 WebSocket 连接和心跳检测
|
|
onBeforeUnmount(() => {
|
|
closeWebSocket();
|
|
});
|
|
|
|
// 当用户勾选或取消勾选时触发的函数
|
|
const handleCheckboxChange = () => {
|
|
if (isPopupEnabled.value) {
|
|
// 如果复选框被勾选,弹出确认对话框
|
|
ElMessageBox.confirm('是否开启弹窗提示?', '提示', {
|
|
confirmButtonText: '是',
|
|
cancelButtonText: '否',
|
|
type: 'warning',
|
|
})
|
|
.then(() => {
|
|
// 用户点击确认,开启 WebSocket
|
|
localStorage.setItem('isPopupEnabled', 'true'); // 保存状态到 localStorage
|
|
connectWebSocket();
|
|
})
|
|
.catch(() => {
|
|
// 用户取消,重置勾选状态
|
|
isPopupEnabled.value = false;
|
|
localStorage.setItem('isPopupEnabled', 'false'); // 更新 localStorage
|
|
});
|
|
} else {
|
|
// 取消勾选时关闭 WebSocket 连接
|
|
closeWebSocket();
|
|
}
|
|
};
|
|
|
|
// WebSocket 连接函数
|
|
const connectWebSocket = () => {
|
|
websocket = new WebSocket('ws://192.168.28.11:8080/event/ws');
|
|
|
|
websocket.onopen = () => {
|
|
ElMessage.success('弹窗告警开启成功');
|
|
startHeartbeat(); // 启动心跳检测
|
|
};
|
|
|
|
websocket.onmessage = (event) => {
|
|
// 接收到消息时,显示浏览器通知
|
|
showNotification(event.data);
|
|
};
|
|
|
|
websocket.onclose = () => {
|
|
ElMessage.warning('WebSocket 已关闭');
|
|
isPopupEnabled.value = false; // 如果连接异常关闭,取消勾选状态
|
|
localStorage.setItem('isPopupEnabled', 'false'); // 更新 localStorage
|
|
stopHeartbeat(); // 停止心跳检测
|
|
};
|
|
|
|
websocket.onerror = () => {
|
|
ElMessage.error('WebSocket 连接出错');
|
|
isPopupEnabled.value = false;
|
|
localStorage.setItem('isPopupEnabled', 'false');
|
|
stopHeartbeat(); // 停止心跳检测
|
|
};
|
|
};
|
|
|
|
// 关闭 WebSocket 连接
|
|
const closeWebSocket = () => {
|
|
if (websocket) {
|
|
websocket.close();
|
|
ElMessage.info('WebSocket 连接已关闭');
|
|
localStorage.setItem('isPopupEnabled', 'false'); // 更新 localStorage
|
|
stopHeartbeat(); // 停止心跳检测
|
|
}
|
|
};
|
|
|
|
// 显示浏览器通知
|
|
const showNotification = (message: string) => {
|
|
if (Notification.permission === 'granted') {
|
|
new Notification('新消息', {
|
|
body: message,
|
|
icon: '/path/to/icon.png', // 可以指定通知的图标
|
|
});
|
|
} else if (Notification.permission !== 'denied') {
|
|
// 请求用户授权通知
|
|
Notification.requestPermission().then((permission) => {
|
|
if (permission === 'granted') {
|
|
new Notification('新消息', {
|
|
body: message,
|
|
icon: '/path/to/icon.png',
|
|
});
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
// 心跳检测,定时发送消息或 ping WebSocket
|
|
const startHeartbeat = () => {
|
|
if (heartbeatInterval) return;
|
|
|
|
heartbeatInterval = window.setInterval(() => {
|
|
if (websocket && websocket.readyState === WebSocket.OPEN) {
|
|
websocket.send('ping'); // 发送心跳消息
|
|
}
|
|
}, 5000); // 每5秒发送一次心跳消息
|
|
};
|
|
|
|
// 停止心跳检测
|
|
const stopHeartbeat = () => {
|
|
if (heartbeatInterval) {
|
|
clearInterval(heartbeatInterval);
|
|
heartbeatInterval = null;
|
|
}
|
|
};
|
|
|
|
// 检查通知权限
|
|
onMounted(() => {
|
|
if (Notification.permission !== 'granted') {
|
|
Notification.requestPermission();
|
|
}
|
|
});
|
|
|
|
</script>
|
|
|
|
<style scoped>
|
|
.settings-container {
|
|
padding: 20px;
|
|
}
|
|
.popup-row {
|
|
margin-bottom: 20px;
|
|
}
|
|
</style>
|