247 lines
4.5 KiB
Vue
247 lines
4.5 KiB
Vue
<template>
|
||
<teleport to="body">
|
||
<transition name="emergency-modal">
|
||
<div class="modal-mask" @click.self="$emit('close')">
|
||
<div class="emergency-modal" :class="{ 'emergency-pulse': show }">
|
||
<div class="glow"></div>
|
||
<div class="modal-header">
|
||
<div class="warning-icon">⚠️</div>
|
||
<h2>{{ title }}</h2>
|
||
</div>
|
||
|
||
<div class="modal-content">
|
||
<p>{{ content }}</p>
|
||
</div>
|
||
|
||
<button class="emergency-button" @click="handleAudioEnd">
|
||
<span class="button-text">立即处理</span>
|
||
<div class="button-glow"></div>
|
||
</button>
|
||
|
||
<!-- <audio ref="audioPlayer" autoplay loop>
|
||
<source src="../assets/audio/alarm.mp3" type="video/mp3" />
|
||
</audio> -->
|
||
</div>
|
||
</div>
|
||
</transition>
|
||
</teleport>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { onMounted, ref } from "vue";
|
||
const audioPlayer = ref(null);
|
||
|
||
defineProps({
|
||
show: Boolean,
|
||
title: {
|
||
type: String,
|
||
default: "紧急警报!",
|
||
},
|
||
content: {
|
||
type: String,
|
||
default: "检测到危险操作,请立即处理!",
|
||
},
|
||
});
|
||
|
||
defineEmits(["close", "confirm"]);
|
||
|
||
const handleAudioEnd = () => {
|
||
if (audioPlayer.value) {
|
||
audioPlayer.value.play().catch((error) => {
|
||
console.error("自动播放被阻止:", error);
|
||
});
|
||
}
|
||
};
|
||
|
||
onMounted(() => {
|
||
// 确保在DOM完全加载后播放音频
|
||
// if (audioPlayer.value) {
|
||
// setTimeout(() => {
|
||
// audioPlayer.value.play();
|
||
// });
|
||
// audioPlayer.value.play();
|
||
// // 设置音频静音,浏览器允许自动播放
|
||
// audioPlayer.value
|
||
// .play()
|
||
// .then(() => {
|
||
// // 自动播放成功后取消静音
|
||
// audioPlayer.value.muted = false;
|
||
// })
|
||
// .catch((error) => {
|
||
// console.log("自动播放失败", error);
|
||
// });
|
||
// }
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
.modal-mask {
|
||
position: fixed;
|
||
z-index: 9998;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100vw;
|
||
height: 100vh;
|
||
background-color: rgba(0, 0, 0, 0.6);
|
||
backdrop-filter: blur(4px);
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.emergency-modal {
|
||
position: relative;
|
||
width: 300px;
|
||
padding: 2rem;
|
||
background: #2a0a0a;
|
||
border-radius: 12px;
|
||
border: 2px solid #ff4444;
|
||
box-shadow: 0 0 40px rgba(255, 68, 68, 0.3);
|
||
transform-origin: center;
|
||
overflow: hidden;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
|
||
.glow {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: radial-gradient(circle at 50% 50%, rgba(255, 68, 68, 0.3) 0%, rgba(255, 68, 68, 0) 70%);
|
||
animation: glow-pulse 2s infinite;
|
||
}
|
||
|
||
.modal-header {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
.warning-icon {
|
||
font-size: 3rem;
|
||
margin-right: 1rem;
|
||
animation: shake 0.8s ease infinite;
|
||
}
|
||
|
||
h2 {
|
||
color: #ff4444;
|
||
font-size: 1.8rem;
|
||
margin: 0;
|
||
}
|
||
|
||
.modal-content {
|
||
color: #ffaaaa;
|
||
margin-bottom: 2rem;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.emergency-button {
|
||
position: relative;
|
||
padding: 1rem 2rem;
|
||
background: linear-gradient(45deg, #ff4444, #ff0000);
|
||
border: none;
|
||
border-radius: 8px;
|
||
color: white;
|
||
font-weight: bold;
|
||
cursor: pointer;
|
||
overflow: hidden;
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
.button-glow {
|
||
position: absolute;
|
||
top: 0;
|
||
left: -100%;
|
||
width: 200%;
|
||
height: 100%;
|
||
background: linear-gradient(45deg, transparent 25%, rgba(255, 255, 255, 0.2) 50%, transparent 75%);
|
||
animation: slide 1.5s infinite;
|
||
}
|
||
|
||
.emergency-button:hover {
|
||
transform: scale(1.05);
|
||
}
|
||
|
||
.emergency-button:active {
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
/* 动画效果 */
|
||
@keyframes emergency-pulse {
|
||
0% {
|
||
transform: scale(1);
|
||
}
|
||
50% {
|
||
transform: scale(1.02);
|
||
}
|
||
100% {
|
||
transform: scale(1);
|
||
}
|
||
}
|
||
|
||
@keyframes shake {
|
||
0% {
|
||
transform: translateX(0);
|
||
}
|
||
25% {
|
||
transform: translateX(-5px);
|
||
}
|
||
50% {
|
||
transform: translateX(5px);
|
||
}
|
||
75% {
|
||
transform: translateX(-3px);
|
||
}
|
||
100% {
|
||
transform: translateX(0);
|
||
}
|
||
}
|
||
|
||
@keyframes glow-pulse {
|
||
0% {
|
||
opacity: 0.6;
|
||
}
|
||
50% {
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
opacity: 0.6;
|
||
}
|
||
}
|
||
|
||
@keyframes slide {
|
||
to {
|
||
left: 100%;
|
||
}
|
||
}
|
||
|
||
.emergency-modal-enter-active {
|
||
animation: emergency-modal-in 0.3s;
|
||
}
|
||
|
||
.emergency-modal-leave-active {
|
||
animation: emergency-modal-in 0.3s reverse;
|
||
}
|
||
|
||
@keyframes emergency-modal-in {
|
||
0% {
|
||
transform: scale(0.5);
|
||
opacity: 0;
|
||
}
|
||
60% {
|
||
transform: scale(1.05);
|
||
}
|
||
100% {
|
||
transform: scale(1);
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
.emergency-pulse {
|
||
animation: emergency-pulse 1.5s infinite;
|
||
}
|
||
</style>
|