无人机管理后台前端(已迁走)
张含笑
2025-12-10 93fd50d4705b441125a05439b20a8531a2e453f7
src/views/job/components/JobRelatedEvents.vue
@@ -1,18 +1,21 @@
<template>
   <div class="machineTableDetailsTitle">
      <p>
         关联事件
         <span>{{ total }}</span>
         件
      </p>
   </div>
   <div class="JobRelatedEvents">
      <div class="machineTableDetailsTitle">
         <img src="/src/assets/images/task/sign.svg" alt="">
      <div class="title">
        关联事件<span>{{ total }}</span>件
      </div>
      <div class="exportBtn" v-if="props.isShowExportTheTask">
        <el-button class="playback-video-btn" type="primary" @click="exportTheTask" size="small">导出报表</el-button>
      </div>
     </div>
   <div class="search">
      <div class="searchBox">
         <div class="item">
            <div class="itemchild">模糊查询:</div>
            <el-input v-model="params.event_name" placeholder="请输入事件名称" clearable></el-input>
         </div>
         <div class="item">
         <!-- <div class="item">
            <div class="itemchild">任务执行日期:</div>
            <el-date-picker
               popper-class="custom-date-picker"
@@ -24,10 +27,10 @@
               :disabled-date="disabledDate"
               @change="changeselect"
            />
         </div>
         </div> -->
         <div class="item">
            <div class="itemchild">关联算法:</div>
            <TaskAlgorithmBusiness :setWidth="186 +'px'" :showAlgorithm="true" @algorithmChange="algorithmChange" />
            <TaskAlgorithmBusiness :setWidth="186" :showAlgorithm="true" @algorithmChange="algorithmChange" />
         </div>
      </div>
      <div class="search-btn">
@@ -42,20 +45,26 @@
         :row-class-name="tableRowClassName"
         :data="list"
         style="width: 100%"
         :row-style="{ height: '38px', fontSize: '14px', 'text-align': 'center' }"
         :header-cell-style="{ 'text-align': 'center', height: '36px', fontSize: '14px' }"
      >
         <el-table-column label="序号" type="index" width="60">
            <template #default="{ $index }">
               {{ ($index + 1 + (sizeParams.current - 1) * sizeParams.size).toString().padStart(2, '0') }}
            </template>
         </el-table-column>
         <el-table-column prop="event_num" label="事件编号" />
         <el-table-column show-overflow-tooltip prop="event_name" label="事件名称" />
         <el-table-column show-overflow-tooltip prop="remark" label="事件地址" />
         <el-table-column show-overflow-tooltip prop="ai_types" label="关联算法" />
         <el-table-column show-overflow-tooltip prop="job_create_time" label="事件时间" />
         <el-table-column prop="status" label="事件状态">
      :row-style="{ height: pxToRem(48), fontSize: pxToRem(14), 'text-align': 'center' }"
      :header-cell-style="{ 'text-align': 'center', height: pxToRem(36), fontSize: pxToRem(14) }"
    >
      <el-table-column label="序号" type="index" :width="pxToRemNum(60)">
        <template #default="{ $index }">
          {{ ($index + 1 + (sizeParams.current - 1) * sizeParams.size).toString().padStart(2, '0') }}
        </template>
      </el-table-column>
      <el-table-column show-overflow-tooltip prop="event_num" label="事件编号" :width="pxToRemNum(160)">
        <template #default="scope">
          <el-tooltip-copy :content="scope.row.event_num" :showCopyText="true">
            {{ scope.row.event_num }}
          </el-tooltip-copy>
        </template>
      </el-table-column>
         <el-table-column show-overflow-tooltip prop="event_name" label="事件名称"  align="center"/>
         <el-table-column show-overflow-tooltip prop="remark" label="事件地址"  align="center"/>
         <el-table-column show-overflow-tooltip prop="ai_types" label="关联算法"  align="center"/>
         <el-table-column show-overflow-tooltip prop="job_create_time" label="事件时间"  align="center"/>
         <el-table-column prop="status" label="事件状态" align="center">
            <template #default="scope">
               <div class="pending" v-if="scope.row.status === 0">待处理</div>
               <div class="reviewed" v-if="scope.row.status === 2">待审核</div>
@@ -64,11 +73,30 @@
               <div class="ended" v-if="scope.row.status === 5">已完结</div>
            </template>
         </el-table-column>
         <el-table-column label="操作" width="80">
            <template #default="scope">
               <div class="ztzf-view" @click="examine(scope.row)">查看</div>
            </template>
         </el-table-column>
      <el-table-column label="操作" :width="pxToRemNum(150)">
        <template #default="scope">
          <div class="btnGroups">
            <el-popover
              v-if="scope.row.status === 3 || scope.row.status === 0"
              popper-class="ztzf-custom-qrcode-popover"
              :width="pxToRem(119)"
              :visible="scope.row.showQR"
              placement="top"
              title=""
              trigger="click"
            >
              <template #reference>
                <el-button type="text" @click="QRCode(scope.row)">事件导航</el-button>
              </template>
              <div class="qrcode-content">
                <div class="close-btn" @click.stop="scope.row.showQR = false">×</div>
                <CreateQRcode v-if="scope.row.showQR" :latAndLon="latAndLon"></CreateQRcode>
              </div>
            </el-popover>
            <el-button icon="el-icon-view" type="text" @click="examine(scope.row)">查看</el-button>
          </div>
        </template>
      </el-table-column>
      </el-table>
   </div>
   <el-pagination
@@ -82,26 +110,30 @@
      :total="total"
      @change="pageChange"
   />
   </div>
</template>
<script setup>
import { useStore } from 'vuex'
import { wgs84ToGcj02 } from '@/utils/coordinateTransformation'
import CreateQRcode from '@/components/CreateQRcode/CreateQRcode.vue'
import { getDeviceEventList } from '@/api/job/task'
import { dayjs, ElMessage } from 'element-plus'
// import { pxToRem } from '@/utils/rem'
import { useRouter } from 'vue-router';
import { NestDetailApi, exportTaskReports } from '@/api/home'
import { pxToRem, pxToRemNum } from '@/utils/rem'
import TaskAlgorithmBusiness from './TaskAlgorithmBusiness.vue'
const router = useRouter();
const emit = defineEmits(['refresh'])
const props = defineProps({
   jobTimes: Array,
   batchNo: Number,
})
const props = defineProps(['jobTimes', 'batchNo', 'waylineJobId','detailName','isShowExportTheTask'])
const taskData = ref('')
const algorithmChange = val => {
   params.value.ai_types = val
  handleSearch()
}
const loading = ref(false)
const list = ref()
const params = ref({
   way_line_jod_info_id: null,
   way_line_job_info_id: null,
   event_name: '',
   ai_types: [], // 算法类型
   start_date: null,
@@ -109,7 +141,7 @@
})
const sizeParams = ref({
   current: 1,
   size: 10,
   size: 5,
})
// 日期选择
const changeselect = () => {
@@ -121,23 +153,30 @@
const total = ref(0)
const examine = row => {
   const orderNumber = row.event_num
   const adminUrl = import.meta.env.VITE_APP_ADMIN_URL
   const targetPath = `/tickets/ticket?orderNumber=${orderNumber}`
   window.open(`${adminUrl}?redirect=${encodeURIComponent(targetPath)}`, '_blank')
   router.push({
      path: `/tickets/ticket`,
      query: {
        orderNumber,
      },
    });
}
const wayLineJodInfoId = inject('wayLineJodInfoId')
const wayLineJobInfoId = inject('wayLineJobInfoId')
const getList = () => {
   if (!wayLineJodInfoId.value) return
   params.value.way_line_jod_info_id = wayLineJodInfoId.value
   params.value.batchNo = props.batchNo
   loading.value = true
   getDeviceEventList(params.value, sizeParams.value).then(res => {
      const resData = res?.data?.data || {}
      list.value = resData.records
      total.value = resData.total
      loading.value = false
   })
  if (!wayLineJobInfoId.value) return
  params.value.way_line_job_info_id = wayLineJobInfoId.value
  params.value.batch_no = props.batchNo
  loading.value = true
  getDeviceEventList(params.value, sizeParams.value).then(res => {
    const resData = res?.data?.data || {}
    list.value = resData.records.map(item => ({
      ...item,
      showQR: false, // 为每条数据添加showQR状态
    }))
    total.value = resData.total
    loading.value = false
    // store.commit('setJobEventList', list.value)
  })
}
const pageChange = val => {
@@ -168,41 +207,73 @@
   getList()
}
const handleSearch = () => {
   // console.log('sousuo', params.value)
   getList()
}
// 二维码
const latAndLon = ref(null)
const QRCode = item => {
  const [gcjLng, gcjLat] = wgs84ToGcj02(Number(item.longitude), Number(item.latitude))
  latAndLon.value = `${gcjLng},${gcjLat}`
  list.value.forEach(i => {
    i.showQR = i.id === item.id ? !i.showQR : false
  })
}
// 导出任务报表
const exportTheTask = () => {
  const params = {
    wayLineJobInfoId: wayLineJobInfoId.value,
    waylineJobId: props.waylineJobId,
    batchNo: props.batchNo,
  }
  exportTaskReports(params).then(res => {
    const elink = document.createElement('a')
    elink.download = props.detailName + '.docx'
    elink.style.display = 'none'
    const blob = new Blob([res.data])
    elink.href = URL.createObjectURL(blob)
    document.body.appendChild(elink)
    elink.click()
    document.body.removeChild(elink)
  })
}
onMounted(() => {
   getList()
})
</script>
<style lang="scss">
// .custom-date-picker .el-picker-panel__content .el-date-table td.disabled div {
//    background-color: #00193b !important;
//    color: #505050 !important;
//    cursor: not-allowed;
// }
</style>
<style scoped lang="scss">
.machineTableDetailsTitle {
   margin-bottom: 16px;
   background: url('/src/assets/images/task/detailtitle.png') no-repeat center;
   background-size: 100% 100%;
   p {
      display: inline-block;
      margin-left: 30px;
      font-size: 16px;
      color: #363636;
      line-height: 20px;
      text-align: left;
      margin-bottom: 8px;
      span {
         font-size: 26px;
         color: #0282ff;
         font-weight: bold;
      }
   }
}
.JobRelatedEvents {
   .machineTableDetailsTitle {
    display: flex;
    border-bottom: 2px solid #e4e7ed;
    margin-bottom: 16px;
    //justify-content: space-between;
    align-content: center;
    .exportBtn {
      margin-left: 16px;
      //margin-bottom: 8px;
      //line-height: 20px;
    }
    img {
      margin-top: 6px;
        width: 15px;
        height: 15px;
    }
    .title {
      display: inline-block;
      margin-left: 10px;
      font-size: 16px;
      color: #363636;
      line-height: 20px;
      text-align: left;
      margin-bottom: 8px;
      span {
        font-size: 26px;
        color: #0282ff;
        font-weight: bold;
      }
    }
  }
// 待处理
.pending {
@@ -214,7 +285,7 @@
}
// 处理中
.processing {
   color: #ffff61;
   color: #FFC300;
}
// 已完成
.done {
@@ -255,7 +326,7 @@
         display: flex;
         justify-content: space-between;
         font-size: 14px;
         .btn {
            width: 80px;
            height: 32px;
@@ -264,6 +335,7 @@
            display: flex;
            justify-content: center;
            align-items: center;
            img {
               width: 14px;
               height: 14px;
@@ -273,15 +345,33 @@
            background: #409EFF;
            color: #fff;
            margin-right: 10px;
            cursor: pointer;
         }
         .clear {
            border: 1px solid #D2D1D1;
            color: #676767;
            margin-right: 10px;
            cursor: pointer;
         }
         .add {
            background: #FF9243;
            color: #fff;
         }
      }
      .btnItem {
         height: 27px;
         line-height: 27px;
         border-radius: 0px 0px 0px 0px;
         border: 1px solid #51a8ff;
         font-family: Segoe UI, Segoe UI;
         font-weight: 400;
         font-size: 14px;
         color: #1C5CFF;
         padding: 0 10px;
         display: inline-block;
         margin-right: 10px;
         cursor: pointer;
   }
}
</style>