添加报警

main
suixy 1 month ago
parent e5978a0f48
commit 7e980242ca

@ -2,17 +2,67 @@
<el-config-provider :locale="appStore.locale" :size="appStore.size">
<router-view />
<RealtimeAlarmModal />
<div v-if="offlineAlertActive" class="offline-breath-overlay"></div>
</el-config-provider>
</template>
<script setup lang="ts">
import { ElMessageBox } from 'element-plus';
import RealtimeAlarmModal from '@/components/alarm/RealtimeAlarmModal.vue';
import { useSettingsStore } from '@/store/modules/settings';
import { handleThemeStyle } from '@/utils/theme';
import { useAppStore } from '@/store/modules/app';
import { closeAlarmReminder, connectAlarmReminder, onAlarmReminderOvertime } from '@/utils/alarmReminder';
const appStore = useAppStore();
const offlineAlertActive = ref(false);
let offlineAlertTimer: ReturnType<typeof setTimeout> | null = null;
const playOfflineVoice = (objid: string) => {
if (typeof window === 'undefined' || !('speechSynthesis' in window)) {
return;
}
window.speechSynthesis.cancel();
const utterance = new SpeechSynthesisUtterance(`设备${objid}离线`);
utterance.lang = 'zh-CN';
window.speechSynthesis.speak(utterance);
};
const triggerOfflineEffect = () => {
offlineAlertActive.value = false;
if (offlineAlertTimer) {
clearTimeout(offlineAlertTimer);
}
requestAnimationFrame(() => {
offlineAlertActive.value = true;
offlineAlertTimer = setTimeout(() => {
offlineAlertActive.value = false;
offlineAlertTimer = null;
}, 6000);
});
};
const showOfflineDialog = (objid: string) => {
ElMessageBox.alert(`设备${objid}离线`, '离线报警', {
type: 'warning',
confirmButtonText: '确定'
}).catch(() => undefined);
};
connectAlarmReminder(() => {});
onAlarmReminderOvertime((device) => {
const objid = String(device?.objid ?? '');
if (!objid) {
return;
}
playOfflineVoice(objid);
showOfflineDialog(objid);
triggerOfflineEffect();
});
onMounted(() => {
nextTick(() => {
@ -20,4 +70,42 @@ onMounted(() => {
handleThemeStyle(useSettingsStore().theme);
});
});
onBeforeUnmount(() => {
if (offlineAlertTimer) {
clearTimeout(offlineAlertTimer);
offlineAlertTimer = null;
}
if (typeof window !== 'undefined' && 'speechSynthesis' in window) {
window.speechSynthesis.cancel();
}
closeAlarmReminder();
});
</script>
<style scoped>
.offline-breath-overlay {
position: fixed;
inset: 0;
pointer-events: none;
z-index: 999998;
box-shadow:
inset 0 0 24px rgba(255, 40, 40, 0.85),
inset 0 0 64px rgba(255, 40, 40, 0.55),
inset 0 0 120px rgba(255, 40, 40, 0.3);
animation: offline-breath 1.5s ease-in-out infinite;
}
@keyframes offline-breath {
0%,
100% {
opacity: 0.25;
}
50% {
opacity: 1;
}
}
</style>

@ -1 +1,119 @@
const websocketUrl = 'ws://119.45.202.115:7181/ws';
const deviceDataTime = {};
const overtime = 1000 * 60 * 10;
// const overtime = 1000;
let alarmReminderSocket = null;
let overtimeTimer = null;
let overtimeCallback = null;
const resolveMessagePayload = (data) => {
if (typeof data !== 'string') {
return data;
}
try {
return JSON.parse(data, (key, value) => {
if (key === 'objid' && value !== null && value !== undefined) {
return String(value);
}
return value;
});
} catch {
return data;
}
};
const updateDeviceDataTime = (payload) => {
const monitorId = payload?.deviceParam?.monitorId;
const objid = payload?.deviceParam?.objid;
if (!monitorId || objid === undefined || objid === null) {
return;
}
deviceDataTime[monitorId] = {
objid: String(objid),
time: Date.now()
};
};
const startOvertimeTimer = () => {
if (overtimeTimer) {
return;
}
overtimeTimer = setInterval(() => {
if (typeof overtimeCallback !== 'function') {
return;
}
const now = Date.now();
Object.keys(deviceDataTime).forEach((monitorId) => {
const item = deviceDataTime[monitorId];
if (!item || now - item.time <= overtime) {
return;
}
overtimeCallback({
monitorId,
...item
});
delete deviceDataTime[monitorId];
});
}, 1000);
};
export const connectAlarmReminder = (onMessage, url = websocketUrl) => {
if (typeof onMessage !== 'function') {
throw new Error('connectAlarmReminder 需要传入消息回调函数');
}
if (alarmReminderSocket) {
alarmReminderSocket.close();
}
alarmReminderSocket = new WebSocket(url);
alarmReminderSocket.onmessage = (event) => {
const payload = resolveMessagePayload(event.data);
updateDeviceDataTime(payload);
onMessage(payload, event);
};
return alarmReminderSocket;
};
export const onAlarmReminderOvertime = (callback) => {
if (typeof callback !== 'function') {
throw new Error('onAlarmReminderOvertime 需要传入超时回调函数');
}
overtimeCallback = callback;
startOvertimeTimer();
};
export const closeAlarmReminder = () => {
if (!alarmReminderSocket) {
if (overtimeTimer) {
clearInterval(overtimeTimer);
overtimeTimer = null;
}
overtimeCallback = null;
return;
}
alarmReminderSocket.close();
alarmReminderSocket = null;
if (overtimeTimer) {
clearInterval(overtimeTimer);
overtimeTimer = null;
}
overtimeCallback = null;
};
export { websocketUrl, deviceDataTime, overtime };

Loading…
Cancel
Save