local_alert/src/components/Settings.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>