吉安感知网项目-前端
chenyao
2026-01-09 ebd0ec4f51288042b6fc5bf714b1febbb63cfacc
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue
New file
@@ -0,0 +1,245 @@
<template>
   <div class="drone-card">
      <div class="header">
         <div class="title">
            <span class="name">{{ data.droneName }}</span>
            <span class="status">
               <span :class="getStatusType(data)">
               </span>
               <span>
                  {{ getStatusText(data) }}
               </span>
            </span>
         </div>
         <div class="actions">
            <span class="star" @click="emit('favorite')">
               {{ data.isFavorite ? '★' : '☆' }}
            </span>
         </div>
      </div>
      <div class="content">
         <div>
            <span class="label">序列号</span>
            {{ data.droneSerialNo }}
         </div>
         <div>
            <span class="label">数据源</span>
            {{ getDataSource(data) }}
         </div>
         <div>
            <span class="label">经纬度</span>
            {{ data.longitude }}, {{ data.latitude }}
         </div>
         <div class="row">
            <div class="col">
               <span class="label">信号频段</span>
               {{ formatFrequency(data.signalFreqMhz) }}
            </div>
            <div class="col">
               <span class="label">发现时间</span>
               {{ getAlarmTime(data.alarmTime) }}
            </div>
         </div>
         <div class="row">
            <div class="col">
               <span class="label">飞行高度</span>
               {{ formatHeight(data.flightHeightM) }}
            </div>
            <div class="col">
               <span class="label">飞行速度</span>
               {{ formatSpeed(data.flightSpeedMs) }}
            </div>
         </div>
      </div>
      <div class="footer">
         <el-button class="general" color="#2B2B4C" @click="emit('signal')">信号干扰</el-button>
         <el-button color="#284FE3" type="primary" @click="emit('counter')">诱导驱离</el-button>
      </div>
   </div>
</template>
<script setup>
const props = defineProps({
   data: {
      type: Object,
      required: true,
      default: () => ({})
   }
})
const emit = defineEmits(['signal', 'counter', 'favorite'])
const getStatusText = (item) => {
   const status = item?.flightStatus
   if (status === 1 || status === '1') return '侦测中'
   if (status === 2 || status === '2') return '反制中'
   return status || '侦测中'
}
const getStatusType = (item) => {
   const statusText = getStatusText(item)
   const counterWay = item?.counterWay
   if (statusText.includes('反制') || counterWay === 2 || counterWay === '2' || counterWay === '诱导驱离') {
      return 'countering'
   }
   return 'detecting'
}
const getDataSource = (item) => {
   return item?.deviceName || item?.areaName || '-'
}
const formatFrequency = (value) => {
   if (value == null || value === '') return '-'
   return `${value}MHz`
}
const getAlarmTime = (value) => {
   if (!value) return '-'
   const parts = value.replace('T', ' ').split(' ')
   return parts[1] || value
}
const formatHeight = (value) => {
   if (value == null || value === '') return '-'
   return `${value}m`
}
const formatSpeed = (value) => {
   if (value == null || value === '') return '-'
   return `${value}m/s`
}
</script>
<style scoped lang="scss">
.drone-card {
   margin-top: 10px;
   padding: 10px;
   color: #fff;
   background: #191933;
   border-radius: 6px 6px 6px 6px;
   &:hover {
      background: #29294D;
      ;
   }
   &:first-child {
      margin-top: 0;
   }
   .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      .title {
         display: flex;
         align-items: center;
         gap: 6px;
         .name {
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: bold;
            font-size: 14px;
            color: #FFFFFF;
            text-align: left;
            font-style: normal;
            text-transform: none;
         }
         .status {
            padding: 0 10px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            height: 21px;
            background: #303041;
            border-radius: 10px;
            gap: 6px;
            span {
               font-family: Source Han Sans CN, Source Han Sans CN;
               font-weight: 400;
               font-size: 10px;
               color: #FFFFFF;
               text-align: center;
               font-style: normal;
               text-transform: none;
            }
            span.detecting {
               width: 4px;
               height: 4px;
               background: #18FF4A;
               border-radius: 50%;
            }
            span.countering {
               width: 4px;
               height: 4px;
               background: #FF4444;
               border-radius: 50%;
            }
         }
      }
      .actions {
         display: flex;
         gap: 8px;
         font-size: 16px;
         cursor: pointer;
      }
   }
   .content {
      font-family: Source Han Sans CN, Source Han Sans CN;
      font-weight: 400;
      font-size: 12px;
      color: #9E9EBA;
      text-align: left;
      font-style: normal;
      text-transform: none;
      &>div {
         margin-top: 10px;
         line-height: 22px;
         span.label {
            margin-right: 10px;
            color: #D4D5D7;
         }
      }
      .row {
         display: flex;
         justify-content: space-between;
      }
   }
   .footer {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 10px;
      margin-top: 10px;
      ::v-deep(.el-button) {
         width: 96px;
         height: 36px;
         &.general.el-button {
            border-radius: 4px 4px 4px 4px;
            border: 1px solid rgba(255, 255, 255, 0.5);
         }
      }
   }
}
</style>