浏览代码

疏散弹窗

dedsudiyu 10 小时之前
父节点
当前提交
278eb88375
共有 1 个文件被更改,包括 437 次插入32 次删除
  1. 437 32
      src/components/alarmWindow/emergency.vue

+ 437 - 32
src/components/alarmWindow/emergency.vue

@@ -1,74 +1,479 @@
 <template>
-  <div class="emergency">
-    <!--顶部-->
-    <div>
-      <p></p>
+  <div class="emergency-dialog">
+    <!-- 头部 -->
+    <div class="evac-hdr">
+      <span class="evac-hdr-icon">🚪</span>
+      <span class="evac-hdr-title">应急疏散</span>
+      <div class="evac-hdr-close" @click="$emit('close')">✕</div>
     </div>
-    <!--地图/监控-->
-    <div>
-      <!--地图-->
-      <div>
 
+    <!-- 主体 -->
+    <div class="evac-body">
+      <!-- 左侧:平面图 -->
+      <div class="evac-map-col">
+        <div class="evac-legend">
+          <div class="evac-legend-rect"></div>
+          <span class="evac-legend-text">应急疏散路线图</span>
+        </div>
+        <div class="evac-map-wrap">
+          <div></div>
+          <!-- 告警浮层气泡 -->
+          <div class="evac-popup">
+            <div class="evac-popup-hdr">
+              <span class="evac-popup-alarm">🚨</span>
+              <span class="evac-popup-time">{{ alarmData.eventStartTime || '—' }}</span>
+              <span class="evac-popup-x">✕</span>
+            </div>
+            <div class="evac-popup-badge">触发风险</div>
+            <div class="evac-popup-msg">发生风险:{{ alarmData.eventName || '—' }}</div>
+          </div>
+        </div>
       </div>
-      <!--监控-->
-      <div>
 
+      <!-- 右侧:监控画面 -->
+      <div class="evac-right-col">
+        <div class="evac-right-hdr">{{ alarmData.roomNum || '—' }} · {{ alarmData.subName || '实验室名称' }}</div>
+        <div class="evac-cam-slot">实时视频监控</div>
+        <div class="evac-cam-slot">实时视频监控</div>
+        <div class="evac-floor-lbl">楼道 {{ alarmData.floor || '1' }}层</div>
+        <div class="evac-cam-slot">实时视频监控</div>
       </div>
     </div>
-    <!--报警信息/喇叭/操作按钮-->
-    <div>
-      <!--报警信息-->
-      <div>
 
+    <!-- 底部 -->
+    <div class="evac-footer">
+      <!-- 告警指标 -->
+      <div class="evac-metrics">
+        <div v-for="(item, idx) in metricRows" :key="idx" class="evac-metric-row">
+          <div class="evac-metric-col">
+            <div class="evac-ml">{{ item.label }}</div>
+            <div class="evac-mv">{{ item.value }}</div>
+          </div>
+          <div class="evac-metric-rt">{{ item.extra }}</div>
+        </div>
       </div>
-      <!--喇叭-->
-      <div>
 
+      <!-- 语音广播 -->
+      <div class="evac-broadcast">
+        <div class="evac-bc-hdr">
+          <span class="evac-bc-icon">📢</span>
+          <span class="evac-bc-title">语音广播</span>
+          <span class="evac-bc-device">选择播放设备</span>
+        </div>
+        <div class="evac-speaker-row">
+          <button
+            v-for="(sp, idx) in speakers"
+            :key="idx"
+            class="evac-speaker-btn"
+            :class="{ on: sp.active }"
+            @click="sp.active = !sp.active"
+          >{{ sp.name }}</button>
+        </div>
+        <div class="evac-input-row">
+          <input
+            v-model="broadcastText"
+            type="text"
+            class="evac-text-input"
+            placeholder="请输入喊话内容"
+          />
+          <button class="evac-send-btn" @click="sendBroadcast">发送</button>
+        </div>
       </div>
-      <!--操作按钮-->
-      <div>
 
+      <!-- 操作按钮 -->
+      <div class="evac-actions">
+        <button class="evac-btn-later" @click="later">稍后处理</button>
+        <button class="evac-btn-exec" @click="execute">执行疏散</button>
       </div>
     </div>
   </div>
 </template>
 
 <script>
-
 export default {
-  name: 'emergency',
+  name: 'Emergency',
   props: {
     alarmData: {
       type: Object,
       default: () => ({})
     }
   },
-  data(){
-    return{
-      pageType:1,
+  data() {
+    return {
+      broadcastText: '',
+      speakers: [
+        { name: 'NKL1FB1122 喇叭', active: true },
+        { name: 'NKL1FB1123 喇叭', active: true },
+        { name: 'NKL1FB1124 喇叭', active: true }
+      ]
+    }
+  },
+  computed: {
+    metricRows() {
+      const d = this.alarmData
+      const sensor = d.triggerUploadData && d.triggerUploadData[0] ? d.triggerUploadData[0] : {}
+      return [
+        {
+          label: '告警指标',
+          value: d.eventName || sensor.sensorName || '—',
+          extra: sensor.deviceValue != null ? `${sensor.deviceValue} ${sensor.unit || ''}` : '—'
+        },
+        {
+          label: '当前值 / 安全阈值',
+          value: d.eventName || sensor.sensorName || '—',
+          extra: sensor.min != null ? `${sensor.min} - ${sensor.max} ${sensor.unit || ''}` : '—'
+        }
+      ]
     }
   },
   methods: {
-    //切换疏散弹窗按钮
-    emergency(){
-      console.log('疏散切换');
-      this.$parent.emergencyButton(1);
+    later() {
+      this.$parent.emergencyButton(1)
     },
+    execute() {
+      this.$emit('execute', this.alarmData)
+    },
+    sendBroadcast() {
+      if (!this.broadcastText.trim()) return
+      this.$emit('broadcast', {
+        text: this.broadcastText,
+        speakers: this.speakers.filter(s => s.active).map(s => s.name)
+      })
+      this.broadcastText = ''
+    }
   }
 }
 </script>
 
 <style lang="scss" scoped>
-.emergency {
+.emergency-dialog {
   width: 2200px;
   height: 1210px;
   display: flex;
   flex-direction: column;
-  background: #0d0002;
-  border: 1px solid rgba(255, 40, 40, 0.5);
-  box-shadow: 0 0 60px rgba(255, 0, 0, 0.3), inset 0 0 40px rgba(100, 0, 0, 0.15);
-  border-radius: 8px;
+  background: linear-gradient(135deg, rgba(2, 8, 28, 0.99), rgba(1, 5, 20, 0.99));
+  border: 2px solid rgba(30, 144, 255, 0.45);
+  box-shadow: 0 0 200px rgba(30, 144, 255, 0.22), inset 0 0 120px rgba(0, 50, 140, 0.05);
+  border-radius: 20px;
   overflow: hidden;
   font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
 }
+
+/* 头部 */
+.evac-hdr {
+  display: flex;
+  align-items: center;
+  gap: 28px;
+  padding: 28px 44px;
+  border-bottom: 1px solid rgba(30, 144, 255, 0.2);
+  background: linear-gradient(90deg, rgba(0, 55, 160, 0.12), transparent);
+  flex-shrink: 0;
+
+  .evac-hdr-icon  { font-size: 50px; }
+
+  .evac-hdr-title {
+    font-size: 38px;
+    font-weight: 700;
+    color: #ddf0ff;
+    letter-spacing: 6px;
+    flex: 1;
+  }
+
+  .evac-hdr-close {
+    font-size: 40px;
+    color: rgba(168, 204, 232, 0.5);
+    cursor: pointer;
+    padding: 8px 16px;
+    border-radius: 6px;
+    transition: background 0.2s, color 0.2s;
+
+    &:hover {
+      background: rgba(30, 144, 255, 0.22);
+      color: #ddf0ff;
+    }
+  }
+}
+
+/* 主体 */
+.evac-body {
+  display: flex;
+  flex: 1;
+  min-height: 0;
+  overflow: hidden;
+}
+
+/* 左侧平面图 */
+.evac-map-col {
+  flex: 1;
+  min-width: 0;
+  padding: 20px 22px;
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+
+  .evac-legend {
+    display: flex;
+    align-items: center;
+    gap: 12px;
+    justify-content: flex-end;
+
+    .evac-legend-rect {
+      width: 36px;
+      height: 14px;
+      background: #1e90ff;
+      border-radius: 3px;
+    }
+
+    .evac-legend-text {
+      font-size: 24px;
+      color: rgba(110, 165, 210, 0.55);
+    }
+  }
+
+  .evac-map-wrap {
+    flex: 1;
+    position: relative;
+    min-height: 0;
+
+    svg {
+      width: 100%;
+      height: 100%;
+      display: block;
+    }
+  }
+}
+
+/* 告警浮层气泡 */
+.evac-popup {
+  position: absolute;
+  top: 52%;
+  left: 3%;
+  background: rgba(239, 68, 68, 0.15);
+  border: 1px solid rgba(239, 68, 68, 0.55);
+  border-radius: 10px;
+  padding: 16px 20px;
+  width: 320px;
+  backdrop-filter: blur(6px);
+
+  .evac-popup-hdr {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+    margin-bottom: 10px;
+
+    .evac-popup-alarm { font-size: 24px; }
+    .evac-popup-time  { font-size: 18px; color: rgba(255, 255, 255, 0.65); flex: 1; }
+    .evac-popup-x     { font-size: 18px; color: rgba(255, 255, 255, 0.4); cursor: pointer; }
+  }
+
+  .evac-popup-badge {
+    background: #ef4444;
+    color: #fff;
+    font-size: 16px;
+    font-weight: 700;
+    border-radius: 5px;
+    padding: 3px 12px;
+    display: inline-block;
+    margin-bottom: 10px;
+    letter-spacing: 1px;
+  }
+
+  .evac-popup-msg {
+    font-size: 20px;
+    font-weight: 600;
+    color: #fff;
+    letter-spacing: 1px;
+  }
+}
+
+/* 右侧监控 */
+.evac-right-col {
+  flex: 0 0 420px;
+  border-left: 1px solid rgba(30, 144, 255, 0.15);
+  display: flex;
+  flex-direction: column;
+
+  .evac-right-hdr {
+    padding: 16px 22px;
+    font-size: 22px;
+    color: rgba(110, 165, 210, 0.55);
+    letter-spacing: 3px;
+    border-bottom: 1px solid rgba(30, 144, 255, 0.12);
+    background: rgba(30, 144, 255, 0.04);
+    flex-shrink: 0;
+  }
+
+  .evac-cam-slot {
+    flex: 1;
+    border-bottom: 1px solid rgba(30, 144, 255, 0.1);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: rgba(12, 15, 26, 0.6);
+    color: rgba(255, 255, 255, 0.2);
+    font-size: 22px;
+    letter-spacing: 3px;
+    min-height: 130px;
+  }
+
+  .evac-floor-lbl {
+    padding: 10px 22px;
+    font-size: 20px;
+    color: rgba(110, 165, 210, 0.55);
+    letter-spacing: 3px;
+    background: rgba(30, 144, 255, 0.06);
+    border-top: 1px solid rgba(30, 144, 255, 0.12);
+    border-bottom: 1px solid rgba(30, 144, 255, 0.12);
+    flex-shrink: 0;
+  }
+}
+
+/* 底部 */
+.evac-footer {
+  padding: 18px 38px;
+  display: flex;
+  gap: 22px;
+  align-items: stretch;
+  border-top: 1px solid rgba(30, 144, 255, 0.15);
+  flex-shrink: 0;
+}
+
+/* 告警指标 */
+.evac-metrics {
+  flex: 0 0 380px;
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+  justify-content: center;
+
+  .evac-metric-row {
+    background: rgba(239, 68, 68, 0.06);
+    border: 1px solid rgba(239, 68, 68, 0.2);
+    border-radius: 8px;
+    padding: 10px 16px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+
+  .evac-ml { font-size: 18px; color: rgba(110, 165, 210, 0.55); margin-bottom: 4px; }
+  .evac-mv { font-size: 22px; font-weight: 600; color: #ef4444; }
+  .evac-metric-rt { font-size: 20px; color: rgba(255, 255, 255, 0.75); }
+}
+
+/* 语音广播 */
+.evac-broadcast {
+  flex: 1;
+  border: 1px solid rgba(30, 144, 255, 0.22);
+  border-radius: 12px;
+  padding: 14px 20px;
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+  background: rgba(30, 144, 255, 0.04);
+
+  .evac-bc-hdr {
+    display: flex;
+    align-items: center;
+    gap: 12px;
+
+    .evac-bc-icon   { font-size: 24px; }
+    .evac-bc-title  { font-size: 24px; font-weight: 600; color: #ddf0ff; flex: 1; }
+    .evac-bc-device { font-size: 20px; color: rgba(110, 165, 210, 0.55); }
+  }
+
+  .evac-speaker-row {
+    display: flex;
+    gap: 12px;
+  }
+
+  .evac-speaker-btn {
+    flex: 1;
+    padding: 10px 8px;
+    border-radius: 8px;
+    font-size: 18px;
+    border: 1px solid rgba(30, 144, 255, 0.35);
+    background: rgba(30, 144, 255, 0.1);
+    color: #00d8ff;
+    cursor: pointer;
+    transition: background 0.2s;
+    white-space: nowrap;
+    font-family: inherit;
+
+    &:hover,
+    &.on {
+      background: rgba(30, 144, 255, 0.25);
+      border-color: #00d8ff;
+    }
+  }
+
+  .evac-input-row {
+    display: flex;
+    gap: 12px;
+  }
+
+  .evac-text-input {
+    flex: 1;
+    padding: 10px 16px;
+    border-radius: 8px;
+    font-size: 20px;
+    border: 1px solid rgba(30, 144, 255, 0.25);
+    background: rgba(0, 8, 36, 0.7);
+    color: #ddf0ff;
+    outline: none;
+    font-family: inherit;
+
+    &::placeholder { color: rgba(255, 255, 255, 0.2); }
+  }
+
+  .evac-send-btn {
+    padding: 10px 32px;
+    border-radius: 8px;
+    font-size: 20px;
+    font-weight: 600;
+    border: 1px solid rgba(30, 144, 255, 0.4);
+    background: rgba(30, 144, 255, 0.14);
+    color: #00d8ff;
+    cursor: pointer;
+    transition: background 0.2s;
+    font-family: inherit;
+
+    &:hover { background: rgba(30, 144, 255, 0.3); }
+  }
+}
+
+/* 操作按钮 */
+.evac-actions {
+  flex: 0 0 300px;
+  display: flex;
+  flex-direction: column;
+  gap: 12px;
+  justify-content: center;
+
+  button {
+    padding: 18px;
+    border-radius: 10px;
+    font-size: 26px;
+    font-weight: 700;
+    cursor: pointer;
+    font-family: inherit;
+    transition: background 0.2s;
+  }
+
+  .evac-btn-later {
+    border: 1px solid rgba(255, 255, 255, 0.2);
+    background: rgba(255, 255, 255, 0.05);
+    color: rgba(255, 255, 255, 0.55);
+
+    &:hover { background: rgba(255, 255, 255, 0.1); }
+  }
+
+  .evac-btn-exec {
+    border: 2px solid #ef4444;
+    background: rgba(239, 68, 68, 0.16);
+    color: #ef4444;
+
+    &:hover { background: rgba(239, 68, 68, 0.32); }
+  }
+}
 </style>