| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- <template>
- <!--<transition name="alert-fade">-->
- <div v-if="visible" class="alert-overlay" @click.self="close">
- <div class="alert-modal">
- <div class="alert-header">
- <span class="alert-icon">⚠</span>
- <span class="alert-title">安 全 预 警</span>
- </div>
- <div class="alert-body">
- <div class="alert-left">
- <div class="alert-info-row">
- <span class="air-label">实 验 室:</span>
- <span class="air-value bold">{{ info.lab || '-' }}</span>
- </div>
- <div class="alert-info-row">
- <span class="air-label">楼栋楼层:</span>
- <span class="air-value bold">{{ info.building || '-' }}</span>
- </div>
- <div class="alert-info-row">
- <span class="air-label">所属单位:</span>
- <span class="air-value bold">{{ info.unit || '-' }}</span>
- </div>
- <div class="alert-info-row">
- <span class="air-label">异常参数:</span>
- <span class="air-value warn">{{ info.param || '-' }}</span>
- </div>
- <div class="alert-info-row">
- <span class="air-label">当前数值:</span>
- <span class="air-value bold">{{ info.value || '-' }}</span>
- </div>
- <div class="alert-info-row">
- <span class="air-label">实验室负责人:</span>
- <span class="air-value bold">{{ info.person || '-' }}</span>
- </div>
- <div class="alert-info-row">
- <span class="air-label">联系电话:</span>
- <span class="air-value bold">{{ info.phone || '-' }}</span>
- </div>
- <div class="alert-info-row">
- <span class="air-label">预警时间:</span>
- <span class="air-value warn">{{ info.time || '-' }}</span>
- </div>
- </div>
- <div class="alert-right">
- <div class="video-label">
- <span class="video-dot"></span>
- <span>实时监控画面</span>
- </div>
- <div class="video-area">
- <div class="video-header">
- <span class="rec-indicator"><span class="rec-dot"></span> REC</span>
- <span class="rec-name">{{ info.lab || '' }}</span>
- </div>
- <div class="video-placeholder" v-if="!videoData">
- <i class="el-icon-video-camera"></i>
- <span>实时监控画面</span>
- </div>
- <H5PlayerVideo style="margin:10px 0 0 12px;" v-if="videoData" :videoProps="videoData"></H5PlayerVideo>
- </div>
- </div>
- </div>
- <div class="alert-footer">
- <button class="btn-later" @click="$emit('close')">稍后处理</button>
- <button class="btn-emergency" @click="emergency()">应急疏散</button>
- <button class="btn-confirm" @click="shadeButton(7)">确认处理</button>
- </div>
- </div>
- <!--确认弹层-->
- <div class="shade-max-big-box" v-if="shadeType != 0">
- <div class="shade-big-box">
- <p class="off-button el-icon-close" @click="shadeButton(4)"></p>
- <div class="text-box" v-if="shadeType == 2 || shadeType == 3 || shadeType == 4 || shadeType == 5 || shadeType == 6">
- <p>{{shadeText}}</p>
- <p>{{shadeType==5?'关闭报警后,3分钟内系统不再触发预案报警,请核实确认后再执行此操作.':''}}</p>
- </div>
- <div class="button-box">
- <p class="button-null"></p>
- <p class="button-p" style="margin-right:39px;" @click="shadeButton(4)">取消</p>
- <p class="button-p" @click="shadeButton(5)">确认</p>
- <p class="button-null"></p>
- </div>
- </div>
- </div>
- <fullH5PlayerVideo v-if="fullVideoType" :fullVideoProps="fullVideoProps"></fullH5PlayerVideo>
- </div>
- <!--</transition>-->
- </template>
- <script>
- import H5PlayerVideo from '@/components/H5PlayerVideo/H5PlayerVideo.vue'
- import fullH5PlayerVideo from '@/components/fullH5PlayerVideo/fullH5PlayerVideo.vue'
- import { getVideoList,laboratoryPlanCloseRiskPlan } from '@/api'
- export default {
- name: 'AlertModal',
- components: { H5PlayerVideo,fullH5PlayerVideo },
- props: {
- AlertModalData: {
- type: Object,
- default: () => ({})
- }
- },
- data() {
- return {
- visible: false,
- info: {},
- //全屏视频参数
- videoData:null,
- fullVideoProps:{},
- fullVideoType:false,
- //弹窗相关
- shadeType:0,
- shadeText:'',
- shadeData:{},
- //结束预案时使用的预案ID
- checkRiskPlanId:null,
- }
- },
- mounted(){
- this.show(this.AlertModalData);
- },
- methods: {
- emergency(){
- // console.log('疏散切换');
- this.$parent.emergencyButton(2);
- },
- //遮罩层开关/弹层提示确认
- shadeButton(type){
- if(type == 4){
- this.$set(this,'shadeType',0)
- }else if(type == 5){
- if(this.shadeType == 5){
- //结束预案
- laboratoryPlanCloseRiskPlan({eventId:this.checkRiskPlanId}).then(response => {
- this.$emit('close')
- });
- }
- }else if(type == 7){
- // console.log('this.AlertModalData',this.AlertModalData)
- this.$set(this,'shadeText','传感器数据监测异常,确定要强制结束预案?');
- this.$set(this,'checkRiskPlanId',this.AlertModalData.eventId);
- this.$set(this,'shadeType',5);
- }
- },
- show(data) {
- const d = data || {}
- if (!d.time) {
- const now = new Date()
- const pad = n => String(n).padStart(2, '0')
- d.time = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
- }
- this.info = d
- this.visible = true
- this.getVideoList(d);
- },
- close() {
- this.visible = false
- this.$emit('close')
- },
- async getVideoList(data) {
- try {
- let obj = {
- "subIds": [data.subId],
- "streamType": 1,
- "protocol": window.location.href.indexOf('https') !== -1 ? 'wss' : 'ws',
- "source": 4,
- "page": 1,
- "pageSize": 10
- }
- const res = await getVideoList(obj)
- if(res.data.list[0]){
- this.$set(this,'videoData',{
- width: 400, //(宽度:非必传-默认600)
- height: 210, //(高度:非必传-默认338)
- url: res.data.list[0].streamUrl,
- cameraIndexCode: res.data.list[0].deviceNo,
- });
- }
- } catch (e) {
- console.error('AlertModal:', e)
- }
- },
- //全屏开启
- stopTime(cameraIndexCode){
- this.$set(this,'fullVideoProps',{cameraIndexCode:cameraIndexCode});
- this.$set(this,'fullVideoType',true);
- },
- //全屏关闭
- outFullScreen(){
- this.$set(this,'fullVideoType',false);
- this.$set(this,'fullVideoProps',{});
- },
- }
- }
- </script>
- <style lang="scss" scoped>
- .shade-max-big-box{
- height:100%;
- width:100%;
- position: absolute;
- top:0;
- left:0;
- background: rgba(0,0,0,0.5);
- .shade-big-box{
- position: absolute;
- top:50%;
- left:50%;
- margin-left:-315px;
- margin-top:-125px;
- width:630px;
- height:250px;
- background: #011020;
- border:1px solid #116e8e;
- border-radius:10px;
- .off-button{
- position: absolute;
- right:15px;
- top:15px;
- color:#fff;
- font-size:20px;
- cursor: pointer;
- }
- .text-box{
- height:160px;
- color:#fff;
- overflow: hidden;
- p{
- padding:0 45px;
- font-size:20px;
- height:30px;
- line-height:30px;
- font-weight:500;
- }
- p:nth-child(1){
- margin-top:30px;
- }
- p:nth-child(2){
- margin-top:20px;
- }
- }
- .button-box{
- height:88px;
- border-top:2px solid #116e8e;
- display: flex;
- .button-null{
- flex:1;
- }
- .button-p{
- width:80px;
- height:40px;
- line-height:38px;
- margin-top:20px;
- text-align: center;
- border:1px solid #24D1F9;
- color:#fff;
- font-size:20px;
- border-radius:4px;
- cursor: pointer;
- }
- .button-p:hover{
- border:1px solid #24D1F9;
- background: #24D1F9;
- color:#fff;
- }
- }
- }
- }
- .alert-fade-enter-active, .alert-fade-leave-active {
- transition: opacity 0.35s ease;
- }
- .alert-fade-enter, .alert-fade-leave-to {
- opacity: 0;
- }
- .alert-overlay {
- position: fixed;
- inset: 0;
- z-index: 9999;
- display: flex;
- align-items: center;
- justify-content: center;
- background: rgba(10, 0, 0, 0.6);
- animation: alertOverlayGlow 2s ease-in-out infinite;
- }
- @keyframes alertOverlayGlow {
- 0%, 100% { box-shadow: inset 0 0 80px rgba(255, 40, 40, 0.06); }
- 50% { box-shadow: inset 0 0 140px rgba(255, 40, 40, 0.15); }
- }
- .alert-modal {
- width: 900px;
- background: rgba(18, 6, 10, 0.97);
- border: 1px solid rgba(255, 50, 50, 0.4);
- border-radius: 4px;
- overflow: hidden;
- box-shadow: 0 0 50px rgba(255, 0, 0, 0.12), 0 0 100px rgba(255, 0, 0, 0.05);
- }
- /* ---- Header ---- */
- .alert-header {
- display: flex;
- align-items: center;
- gap: 12px;
- padding: 14px 24px;
- background: linear-gradient(135deg, #c41818, #a01414);
- }
- .alert-icon {
- font-size: 22px;
- color: #fff;
- }
- .alert-title {
- font-size: 18px;
- font-weight: 700;
- color: #fff;
- letter-spacing: 6px;
- }
- /* ---- Body ---- */
- .alert-body {
- display: flex;
- padding: 24px 28px;
- gap: 28px;
- }
- .alert-left {
- flex: 1;
- min-width: 0;
- }
- .alert-right {
- width: 400px;
- flex-shrink: 0;
- }
- /* ---- Info Rows ---- */
- .alert-info-row {
- display: flex;
- align-items: baseline;
- padding: 8px 0;
- }
- .air-label {
- width: 112px;
- font-size: 14px;
- color: rgba(255, 90, 90, 0.7);
- flex-shrink: 0;
- }
- .air-value {
- font-size: 14px;
- color: rgba(255, 255, 255, 0.9);
- &.bold {
- font-weight: 600;
- }
- &.warn {
- color: #ff3333;
- font-weight: 600;
- }
- }
- /* ---- Video Section ---- */
- .video-label {
- display: flex;
- align-items: center;
- gap: 6px;
- font-size: 13px;
- color: rgba(255, 255, 255, 0.65);
- margin-bottom: 10px;
- }
- .video-dot {
- width: 8px;
- height: 8px;
- border-radius: 50%;
- background: #ff8c00;
- box-shadow: 0 0 6px rgba(255, 140, 0, 0.5);
- }
- .video-area {
- border: 1px solid rgba(255, 50, 50, 0.35);
- border-radius: 4px;
- overflow: hidden;
- background: rgba(0, 0, 0, 0.3);
- position: relative;
- }
- .video-header {
- position: absolute;
- display: flex;
- align-items: center;
- gap: 8px;
- padding: 8px 12px;
- font-size: 12px;
- color: rgba(255, 255, 255, 0.55);
- }
- .rec-indicator {
- display: flex;
- align-items: center;
- gap: 4px;
- color: rgba(255, 255, 255, 0.55);
- }
- .rec-dot {
- display: inline-block;
- width: 6px;
- height: 6px;
- border-radius: 50%;
- background: #ff4d4f;
- animation: recBlink 1.2s ease-in-out infinite;
- }
- @keyframes recBlink {
- 0%, 100% { opacity: 1; }
- 50% { opacity: 0.2; }
- }
- .rec-name {
- color: rgba(255, 255, 255, 0.55);
- }
- .video-placeholder {
- height: 180px;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- gap: 8px;
- color: rgba(255, 255, 255, 0.12);
- i { font-size: 40px; }
- span { font-size: 12px; }
- }
- /* ---- Footer ---- */
- .alert-footer {
- padding: 16px 28px 22px;
- display: flex;
- justify-content: center;
- }
- .btn-later {
- padding: 10px 52px;
- background-color: rgba(69, 90, 116, 0.2);
- color: rgba(69, 90, 116, 1);
- border: 2px solid rgba(69, 90, 116, 1);
- border-radius: 4px;
- font-size: 15px;
- letter-spacing: 8px;
- cursor: pointer;
- transition: all 0.3s ease;
- &:hover {
- background: rgba(69, 90, 116, 0.25);
- box-shadow: 0 0 20px rgba(69, 90, 116, 0.2);
- }
- }
- .btn-emergency {
- margin:0 40px;
- padding: 10px 52px;
- border-radius: 4px;
- background-color: rgba(245, 158, 11, 0.2);
- color: rgba(245, 158, 11, 1);
- border: 2px solid rgba(245, 158, 11, 1);
- font-size: 15px;
- letter-spacing: 8px;
- cursor: pointer;
- transition: all 0.3s ease;
- &:hover {
- background: rgba(245, 158, 11, 0.25);
- box-shadow: 0 0 20px rgba(245, 158, 11, 0.2);
- }
- }
- .btn-confirm {
- padding: 10px 52px;
- border-radius: 4px;
- background-color: rgba(239, 68, 68, 0.2);
- color: rgba(239, 68, 68, 1);
- border: 2px solid rgba(239, 68, 68, 1);
- font-size: 15px;
- letter-spacing: 8px;
- cursor: pointer;
- transition: all 0.3s ease;
- &:hover {
- background: rgba(239, 68, 68, 0.25);
- box-shadow: 0 0 20px rgba(239, 68, 68, 0.2);
- }
- }
- </style>
|