Files
sgxt_web/src/components/common/TestDiv.vue
2026-04-28 11:26:26 +08:00

338 lines
8.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="test-div" v-if="dataList && dataList.length > 0">
<div class="test-header">
<span class="test-title">消息通知</span>
<div class="header-right">
<span class="test-countdown">{{ countdown }}s</span>
<el-icon class="close-icon" @click="handleClose">
<Close />
</el-icon>
</div>
</div>
<div class="test-content">
<Item v-for="(item, index) in dataList" :key="index" :item="item" />
</div>
</div>
</template>
<script setup>
// 测试div组件用于在后台和大屏页面都显示
import { ref, onMounted, onUnmounted } from "vue";
import { Close } from "@element-plus/icons-vue";
import emitter from "@/utils/eventBus.js"; // 导入事件总线
import { qcckGet } from "@/api/qcckApi";
import Item from "./item.vue";
import { AudioPlayerClass } from "@/utils/audioPlayer.js";
import { getItem } from "@/utils/storage.js";
const dataList = ref([]);
const timekeeping = ref(null);
const countdown = ref(0); // 倒计时时间(秒)
// 音频播放器实例映射
const audioPlayers = new Map();
// 预加载音频播放器(仅加载 playAudioByType 中实际用到的类型)
const initAudioPlayers = async () => {
const usedTypes = ["03", "09", "10", "11", "12", "13", "16", "17", "18", "19"];
await Promise.all(
usedTypes.map(
(type) =>
new Promise((resolve) => {
const player = new AudioPlayerClass();
audioPlayers.set(type, player);
player.init(audioPaths[type], false).then(resolve).catch(resolve);
})
)
);
};
// 获取指定类型的音频播放器
const getAudioPlayer = (type) => {
return audioPlayers.get(type);
};
// 音频文件路径映射
const audioPaths = {
"01": require("@/assets/images/01.mp3"), //高级预计信息前置
"02": require("@/assets/images/02.mp3"), //一般预警信息前置
"03": require("@/assets/images/03.mp3"), //信息前置
"04": require("@/assets/images/04.mp3"), //红色预警
"05": require("@/assets/images/05.mp3"), //新的重点人
"06": require("@/assets/images/06.mp3"), //一级临控预警
"07": require("@/assets/images/07.mp3"), //有新的布控预警情
"08": require("@/assets/images/08.mp3"), //有新的标签预警
"09": require("@/assets/images/09.mp3"), //信息汇聚系统有新信息
"10": require("@/assets/images/10.mp3"), //林安码
"11": require("@/assets/images/11.mp3"), //发布了新的"线索"
"12": require("@/assets/images/12.mp3"), //有新的研判指令
"13": require("@/assets/images/13.mp3"), //有新的研判约稿通知
"14": require("@/assets/images/14.mp3"), //有新的公文发布
"15": require("@/assets/images/15.mp3"), //有新的警情监测预警,请注意查收
"16": require("@/assets/images/16.mp3"), //有新的一级临控预警,请及时签收处理!
"17": require("@/assets/images/17.mp3"), //有新的紧急预警信息,请及时签收处理!
"18": require("@/assets/images/18.mp3"), //滴滴滴~~~叮~~~~
"19": require("@/assets/images/19.mp3") //有新的预警信息,请您注意查收
};
// 根据类型播放音频
const playAudioByType = (val) => {
switch (val.typeMasgeLx) {
case "01": //预警
// 01 布控预警、02 七类重点人、03 政保
switch (val.yjlb) {
case "01":
case "02":
if (val.yjJb == "01") {
getAudioPlayer("18")?.play();
getAudioPlayer("17")?.play();
} else {
getAudioPlayer("19")?.play();
}
break;
}
break;
case "02": //信息汇聚
getAudioPlayer("03")?.play();
getAudioPlayer("09")?.play();
break;
case "03": //约稿
getAudioPlayer("03")?.play();
getAudioPlayer("13")?.play();
break;
case "04": //指令
getAudioPlayer("03")?.play();
getAudioPlayer("12")?.play();
break;
case "05": //新线索
getAudioPlayer("03")?.play();
getAudioPlayer("11")?.play();
break;
case "06": //检测警情
if (val.jqdjdm == "01") {
getAudioPlayer("18")?.play();
getAudioPlayer("17")?.play();
} else {
getAudioPlayer("19")?.play();
}
break;
case "08": //林安码
getAudioPlayer("03")?.play();
getAudioPlayer("10")?.play();
break;
case "11":
getAudioPlayer("03")?.play();
getAudioPlayer("19")?.play();
break;
default:
break;
}
};
// 手动关闭
const handleClose = () => {
if (timekeeping.value) {
clearInterval(timekeeping.value);
timekeeping.value = null;
}
dataList.value = [];
};
// 重置倒计时
const resetCountdown = () => {
if (timekeeping.value) {
clearInterval(timekeeping.value);
}
countdown.value = 15;
timekeeping.value = setInterval(() => {
countdown.value--;
if (countdown.value <= 0) {
clearInterval(timekeeping.value);
dataList.value = [];
timekeeping.value = null;
}
}, 1000);
};
// 做一个定时器15s一次
const checkNews = ref(null);
const checkNewsInterval = 15000; // 15秒
const idEntityCard = ref(getItem("idEntityCard"));
onMounted(() => {
// 音频初始化在后台进行,不阻塞组件渲染
initAudioPlayers().then(() => {
// 音频预加载完成后再启动轮询
checkNews.value = setInterval(() => {
dataModel();
}, checkNewsInterval);
});
// 注册事件监听(需在 onUnmounted 中精确解绑)
emitter.on("webSocketMessage", handleWebSocketMessage);
});
// 处理 WebSocket 消息事件(需在 onUnmounted 中解绑,提取到模块作用域)
const handleWebSocketMessage = (newsDate) => {
if (newsDate) {
dataList.value = newsDate;
playAudioByType(newsDate[0]);
resetCountdown();
}
};
const dataModel = () => {
qcckGet({}, "/mosty-gsxt/dsjJbxx/message").then((res) => {
if (res) {
const data = res.filter((item) =>
item.sfzList.includes(idEntityCard.value)
);
const infoMasge = data.map((item) => {
return {
...item.obj,
typeMasgeLx: item.type
};
});
emitter.emit("webSocketMessage", infoMasge);
}
});
};
onUnmounted(() => {
emitter.off("webSocketMessage", handleWebSocketMessage);
if (timekeeping.value) {
clearInterval(timekeeping.value);
}
// 销毁所有音频播放器实例
audioPlayers.forEach((player) => {
player.destroy();
});
audioPlayers.clear();
// 清除定时器
if (checkNews.value) {
clearInterval(checkNews.value);
checkNews.value = null;
}
});
</script>
<style scoped lang="scss">
.test-div {
width: 400px;
max-height: 250px;
position: fixed;
bottom: 2%;
right: 2%;
z-index: 1999;
background: linear-gradient(135deg, #0a3b6d 0%, #1a5a9e 100%);
border: 1px solid rgba(0, 255, 255, 0.3);
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 255, 255, 0.3), 0 0 20px rgba(0, 255, 255, 0.1);
overflow: hidden;
animation: slideIn 0.3s ease-out;
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
}
.test-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
background: rgba(0, 255, 255, 0.1);
border-bottom: 1px solid rgba(0, 255, 255, 0.3);
}
.test-title {
font-size: 16px;
font-weight: bold;
color: #00ffff;
display: flex;
align-items: center;
gap: 8px;
text-shadow: 0 0 10px rgba(0, 255, 255, 0.7);
&::before {
content: "";
display: inline-block;
width: 8px;
height: 8px;
background-color: #00ffff;
border-radius: 50%;
box-shadow: 0 0 10px rgba(0, 255, 255, 0.8);
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
0%,
100% {
opacity: 1;
transform: scale(1);
box-shadow: 0 0 10px rgba(0, 255, 255, 0.8);
}
50% {
opacity: 0.8;
transform: scale(1.2);
box-shadow: 0 0 20px rgba(0, 255, 255, 1);
}
}
}
.header-right {
display: flex;
align-items: center;
gap: 10px;
}
.test-countdown {
font-size: 14px;
color: #00ffff;
background: rgba(0, 255, 255, 0.1);
padding: 4px 12px;
border: 1px solid rgba(0, 255, 255, 0.3);
border-radius: 12px;
font-weight: 500;
text-shadow: 0 0 5px rgba(0, 255, 255, 0.5);
}
.close-icon {
font-size: 18px;
color: #00ffff;
cursor: pointer;
transition: all 0.3s ease;
padding: 4px;
border-radius: 4px;
text-shadow: 0 0 5px rgba(0, 255, 255, 0.5);
&:hover {
background: rgba(0, 255, 255, 0.2);
transform: rotate(90deg);
box-shadow: 0 0 10px rgba(0, 255, 255, 0.8);
}
}
.test-content {
max-height: 150px;
overflow-y: auto;
padding: 12px;
scrollbar-width: none;
/* Firefox */
-ms-overflow-style: none;
/* IE and Edge */
&::-webkit-scrollbar {
display: none;
/* Chrome, Safari and Opera */
}
}
</style>