Files
sgxt_web/src/components/common/TestDiv.vue

338 lines
8.8 KiB
Vue
Raw Normal View History

2026-02-07 10:24:29 +08:00
<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组件用于在后台和大屏页面都显示
2026-04-07 11:12:09 +08:00
import { ref, onMounted, onUnmounted } from "vue";
import { Close } from "@element-plus/icons-vue";
2026-02-07 10:24:29 +08:00
import emitter from "@/utils/eventBus.js"; // 导入事件总线
2026-04-07 11:12:09 +08:00
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); // 倒计时时间(秒)
2026-02-07 10:24:29 +08:00
// 音频播放器实例映射
2026-04-15 16:04:50 +08:00
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);
};
2026-02-07 10:24:29 +08:00
// 音频文件路径映射
const audioPaths = {
2026-04-07 11:12:09 +08:00
"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"), //有新的警情监测预警,请注意查收
2026-04-07 17:18:19 +08:00
"16": require("@/assets/images/16.mp3"), //有新的一级临控预警,请及时签收处理!
"17": require("@/assets/images/17.mp3"), //有新的紧急预警信息,请及时签收处理!
"18": require("@/assets/images/18.mp3"), //滴滴滴~~~叮~~~~
2026-04-15 16:04:50 +08:00
"19": require("@/assets/images/19.mp3") //有新的预警信息,请您注意查收
2026-04-07 11:12:09 +08:00
};
2026-02-07 10:24:29 +08:00
// 根据类型播放音频
2026-03-24 12:18:39 +08:00
const playAudioByType = (val) => {
switch (val.typeMasgeLx) {
2026-04-07 11:12:09 +08:00
case "01": //预警
2026-03-24 12:18:39 +08:00
// 01 布控预警、02 七类重点人、03 政保
switch (val.yjlb) {
2026-04-07 11:12:09 +08:00
case "01":
case "02":
2026-04-15 16:04:50 +08:00
if (val.yjJb == "01") {
getAudioPlayer("18")?.play();
getAudioPlayer("17")?.play();
} else {
getAudioPlayer("19")?.play();
2026-03-24 12:18:39 +08:00
}
2026-04-07 11:12:09 +08:00
break;
2026-03-24 12:18:39 +08:00
}
2026-04-07 11:12:09 +08:00
break;
case "02": //信息汇聚
2026-04-15 16:04:50 +08:00
getAudioPlayer("03")?.play();
getAudioPlayer("09")?.play();
2026-04-07 11:12:09 +08:00
break;
case "03": //约稿
2026-04-15 16:04:50 +08:00
getAudioPlayer("03")?.play();
getAudioPlayer("13")?.play();
2026-04-07 11:12:09 +08:00
break;
case "04": //指令
2026-04-15 16:04:50 +08:00
getAudioPlayer("03")?.play();
getAudioPlayer("12")?.play();
2026-04-07 11:12:09 +08:00
break;
case "05": //新线索
2026-04-15 16:04:50 +08:00
getAudioPlayer("03")?.play();
getAudioPlayer("11")?.play();
2026-04-07 11:12:09 +08:00
break;
2026-04-07 17:18:19 +08:00
case "06": //检测警情
2026-04-15 16:04:50 +08:00
if (val.jqdjdm == "01") {
getAudioPlayer("18")?.play();
getAudioPlayer("17")?.play();
} else {
getAudioPlayer("19")?.play();
2026-04-07 17:18:19 +08:00
}
2026-04-07 11:12:09 +08:00
break;
case "08": //林安码
2026-04-15 16:04:50 +08:00
getAudioPlayer("03")?.play();
getAudioPlayer("10")?.play();
2026-04-07 11:12:09 +08:00
break;
case "11":
2026-04-15 16:04:50 +08:00
getAudioPlayer("03")?.play();
2026-04-28 11:26:26 +08:00
getAudioPlayer("19")?.play();
2026-04-07 11:12:09 +08:00
break;
2026-03-24 12:18:39 +08:00
default:
2026-04-07 11:12:09 +08:00
break;
2026-02-07 10:24:29 +08:00
}
2026-04-07 11:12:09 +08:00
};
2026-02-07 10:24:29 +08:00
// 手动关闭
const handleClose = () => {
if (timekeeping.value) {
2026-04-07 11:12:09 +08:00
clearInterval(timekeeping.value);
timekeeping.value = null;
2026-02-07 10:24:29 +08:00
}
2026-04-07 11:12:09 +08:00
dataList.value = [];
};
2026-02-07 10:24:29 +08:00
// 重置倒计时
const resetCountdown = () => {
if (timekeeping.value) {
2026-04-07 11:12:09 +08:00
clearInterval(timekeeping.value);
2026-02-07 10:24:29 +08:00
}
2026-04-07 11:12:09 +08:00
countdown.value = 15;
2026-02-07 10:24:29 +08:00
timekeeping.value = setInterval(() => {
2026-04-07 11:12:09 +08:00
countdown.value--;
2026-02-07 10:24:29 +08:00
if (countdown.value <= 0) {
2026-04-07 11:12:09 +08:00
clearInterval(timekeeping.value);
dataList.value = [];
timekeeping.value = null;
2026-02-07 10:24:29 +08:00
}
2026-04-07 11:12:09 +08:00
}, 1000);
};
2026-02-07 16:54:04 +08:00
// 做一个定时器15s一次
2026-04-07 11:12:09 +08:00
const checkNews = ref(null);
const checkNewsInterval = 15000; // 15秒
const idEntityCard = ref(getItem("idEntityCard"));
2026-04-15 16:04:50 +08:00
2026-04-28 11:26:26 +08:00
onMounted(() => {
// 音频初始化在后台进行,不阻塞组件渲染
initAudioPlayers().then(() => {
// 音频预加载完成后再启动轮询
checkNews.value = setInterval(() => {
dataModel();
}, checkNewsInterval);
});
2026-04-15 16:04:50 +08:00
// 注册事件监听(需在 onUnmounted 中精确解绑)
emitter.on("webSocketMessage", handleWebSocketMessage);
});
// 处理 WebSocket 消息事件(需在 onUnmounted 中解绑,提取到模块作用域)
const handleWebSocketMessage = (newsDate) => {
if (newsDate) {
dataList.value = newsDate;
playAudioByType(newsDate[0]);
resetCountdown();
}
};
2026-02-07 16:54:04 +08:00
const dataModel = () => {
2026-04-07 11:12:09 +08:00
qcckGet({}, "/mosty-gsxt/dsjJbxx/message").then((res) => {
2026-02-07 16:54:04 +08:00
if (res) {
2026-04-07 11:12:09 +08:00
const data = res.filter((item) =>
item.sfzList.includes(idEntityCard.value)
);
const infoMasge = data.map((item) => {
2026-03-24 12:18:39 +08:00
return {
...item.obj,
typeMasgeLx: item.type
2026-04-07 11:12:09 +08:00
};
});
emitter.emit("webSocketMessage", infoMasge);
2026-02-07 16:54:04 +08:00
}
2026-04-07 11:12:09 +08:00
});
};
2026-02-07 16:54:04 +08:00
2026-02-07 10:24:29 +08:00
onUnmounted(() => {
2026-04-15 16:04:50 +08:00
emitter.off("webSocketMessage", handleWebSocketMessage);
2026-02-07 10:24:29 +08:00
if (timekeeping.value) {
2026-04-07 11:12:09 +08:00
clearInterval(timekeeping.value);
2026-02-07 10:24:29 +08:00
}
// 销毁所有音频播放器实例
2026-04-15 16:04:50 +08:00
audioPlayers.forEach((player) => {
player.destroy();
2026-04-07 11:12:09 +08:00
});
2026-04-15 16:04:50 +08:00
audioPlayers.clear();
2026-02-07 16:54:04 +08:00
// 清除定时器
if (checkNews.value) {
2026-04-07 11:12:09 +08:00
clearInterval(checkNews.value);
checkNews.value = null;
2026-02-07 16:54:04 +08:00
}
2026-04-07 11:12:09 +08:00
});
2026-02-07 10:24:29 +08:00
</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;
}
2026-02-07 16:54:04 +08:00
2026-02-07 10:24:29 +08:00
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 {
2026-04-07 11:12:09 +08:00
content: "";
2026-02-07 10:24:29 +08:00
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 {
2026-04-28 11:26:26 +08:00
2026-02-07 16:54:04 +08:00
0%,
100% {
2026-02-07 10:24:29 +08:00
opacity: 1;
transform: scale(1);
box-shadow: 0 0 10px rgba(0, 255, 255, 0.8);
}
2026-02-07 16:54:04 +08:00
2026-02-07 10:24:29 +08:00
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;
2026-02-07 16:54:04 +08:00
scrollbar-width: none;
/* Firefox */
-ms-overflow-style: none;
/* IE and Edge */
2026-02-07 10:24:29 +08:00
&::-webkit-scrollbar {
2026-02-07 16:54:04 +08:00
display: none;
/* Chrome, Safari and Opera */
2026-02-07 10:24:29 +08:00
}
}
</style>