247 lines
4.5 KiB
Vue
Raw Normal View History

2025-04-02 18:40:20 +08:00
<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>