吉安感知网项目-前端
罗广辉
2026-01-16 4376eb565c603debd4d48d05221219dc1aeb8fc6
applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue
@@ -1,6 +1,12 @@
<template>
   <el-dialog v-model="visible" class="ztzf-page-map-view-dialog" :show-close="false" :close-on-click-modal="false"
      destroy-on-close @closed="handleClosed">
   <el-dialog
      v-model="visible"
      class="ztzf-page-map-view-dialog"
      :show-close="false"
      :close-on-click-modal="false"
      destroy-on-close
      @closed="handleClosed"
   >
      <div class="dialog-container">
         <div class="left-container">
            <div class="leftMap ztzf-cesium" id="detectionRangeMap"></div>
@@ -32,52 +38,90 @@
                     <div class="val">{{ formData.deviceModel || '-' }}</div>
                  </el-col>
                  <el-col :span="24">
                     <div class="label">覆盖范围</div>
                     <div class="label">覆盖范围(m)</div>
                     <div class="val">{{ formatRange(formData.effectiveRangeKm) }}</div>
                  </el-col>
               </el-row>
            </div>
            <el-form v-else ref="formRef" class="dialog-form" :model="formData" :rules="rules" label-width="96px">
            <el-form v-else ref="formRef" class="dialog-form" :model="formData" :rules="rules" label-width="110px">
               <el-form-item label="侦测设备" prop="deviceId">
                  <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper"
                     v-model="formData.deviceId" placeholder="请选择" clearable @change="handleDeviceChange">
                     <el-option v-for="item in deviceOptions" :key="item.value" :label="item.label"
                        :value="item.value" />
                  <el-select
                     class="ztzf-data-cockpit-select"
                     popper-class="ztzf-data-cockpit-select-popper"
                     v-model="formData.deviceId"
                     placeholder="请选择"
                     clearable
                     @change="handleDeviceChange"
                  >
                     <el-option v-for="item in deviceOptions" :key="item.value" :label="item.label" :value="item.value" />
                  </el-select>
               </el-form-item>
               <el-form-item label="设备类型" prop="deviceType">
                  <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper"
                     v-model="formData.deviceType" placeholder="请选择" clearable>
                     <el-option v-for="item in dictObj.deviceType" :key="item.dictKey" :label="item.dictValue"
                        :value="item.dictKey" />
                  <el-select
                     class="ztzf-data-cockpit-select"
                     popper-class="ztzf-data-cockpit-select-popper"
                     v-model="formData.deviceType"
                     placeholder="请选择"
                     clearable
                  >
                     <el-option
                        v-for="item in dictObj.deviceType"
                        :key="item.dictKey"
                        :label="item.dictValue"
                        :value="item.dictKey"
                     />
                  </el-select>
               </el-form-item>
               <el-form-item label="设备位置" prop="deployLocation">
                  <el-input class="ztzf-data-cockpit-search-input" v-model="formData.deployLocation"
                     placeholder="请选择位置">
                  <el-input
                     class="ztzf-data-cockpit-search-input"
                     v-model="formData.deployLocation"
                     disabled
                     placeholder="请选择位置"
                  >
                     <template #suffix>
                        <span class="suffix-action">地图选点</span>
                     </template>
                  </el-input>
               </el-form-item>
               <el-form-item label="设备编号" prop="deviceSn">
                  <el-input class="ztzf-data-cockpit-search-input" v-model="formData.deviceSn" placeholder="请输入"
                     clearable />
                  <el-input
                     class="ztzf-data-cockpit-search-input"
                     v-model="formData.deviceSn"
                     placeholder="请输入"
                     clearable
                  />
               </el-form-item>
               <el-form-item label="设备型号" prop="deviceModel">
                  <el-input class="ztzf-data-cockpit-search-input" v-model="formData.deviceModel"
                     placeholder="请输入" clearable />
                  <el-input
                     class="ztzf-data-cockpit-search-input"
                     v-model="formData.deviceModel"
                     placeholder="请输入"
                     clearable
                  />
               </el-form-item>
               <el-form-item label="覆盖范围" prop="effectiveRangeKm">
                  <el-input-number class="ztzf-data-cockpit-search-input" v-model="formData.effectiveRangeKm" :min="0" :precision="2" :controls="false"
                     placeholder="请输入" />
               <el-form-item label="覆盖范围(m)" prop="effectiveRangeKm">
                  <el-input-number
                     class="ztzf-data-cockpit-search-input"
                     v-model="formData.effectiveRangeKm"
                     :min="0"
                     :precision="2"
                     :controls="false"
                     placeholder="请输入"
                  />
               </el-form-item>
            </el-form>
            <div class="footer">
               <el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
               <el-button color="#284FE3" v-if="!dialogReadonly" type="primary" :loading="submitting"
                  :disabled="submitting" @click="handleSubmit">
               <el-button
                  color="#284FE3"
                  v-if="!dialogReadonly"
                  type="primary"
                  :loading="submitting"
                  :disabled="submitting"
                  @click="handleSubmit"
               >
                  保存
               </el-button>
            </div>
@@ -111,7 +155,7 @@
const emit = defineEmits(['success'])
const formRef = ref(null) // 表单实例
const formData = ref(initForm()) // 表单数据
const visible = ref(false) // 弹框显隐
const visible = defineModel() // 弹框显隐
const dialogMode = ref('add') // 弹框模式
const submitting = ref(false) // 提交中
const deviceOptions = ref([])
@@ -135,7 +179,7 @@
   effectiveRangeKm: [{ required: true, message: '请输入覆盖范围', trigger: ['blur', 'change'] }],
}
function handleDeviceChange (value) {
function handleDeviceChange(value) {
   const target = deviceOptions.value.find(item => item.value === value)
   const raw = target?.raw
   if (!raw) return
@@ -148,24 +192,24 @@
      raw.deployLocation ?? raw.address ?? raw.location ?? raw.deployAddress ?? formData.value.deployLocation
}
function getDeviceTypeLabel (value) {
function getDeviceTypeLabel(value) {
   const list = dictObj?.deviceType ?? []
   const target = list.find(item => item.dictKey === value)
   return target?.dictValue ?? value ?? '-'
}
function formatRange (value) {
function formatRange(value) {
   if (value == null || value === '') return '-'
   return `${value}km`
   return `${value}`
}
// 关闭弹框
function handleCancel () {
function handleCancel() {
   visible.value = false
}
// 提交新增/编辑
async function handleSubmit () {
async function handleSubmit() {
   const isValid = await formRef.value?.validate().catch(() => false)
   if (!isValid) return
   submitting.value = true
@@ -186,13 +230,13 @@
}
// 加载详情
async function loadDetail (id) {
async function loadDetail(id) {
   if (!id) return null
   const res = await detectionRangeDetailApi({ id })
   return res?.data?.data ?? null
}
async function loadDeviceOptions () {
async function loadDeviceOptions() {
   const res = await detectionRangePageApi({
      current: 1,
      size: 200,
@@ -207,13 +251,13 @@
}
// 关闭后重置
function handleClosed () {
function handleClosed() {
   formData.value = initForm()
   viewer = null
   redPointEntity = null
}
function setMapPoint (longitude, latitude) {
function setMapPoint(longitude, latitude) {
   if (!viewer || longitude == null || latitude == null) return
   if (!redPointEntity) {
      redPointEntity = viewer.entities.add({
@@ -224,7 +268,7 @@
         },
         label: {
            text: `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`,
            font: '14px',
            font: '16px',
            fillColor: Cesium.Color.WHITE,
            backgroundColor: Cesium.Color.BLACK.withAlpha(0.45),
            backgroundPadding: new Cesium.Cartesian2(5, 5),
@@ -244,7 +288,7 @@
   }
}
function initMap () {
function initMap() {
   if (viewer) return
   const publicCesiumInstance = new PublicCesium({
      dom: 'detectionRangeMap',
@@ -259,7 +303,7 @@
   viewer = publicCesiumInstance.getViewer()
}
function handleMapClick (click) {
function handleMapClick(click) {
   const pos = click.position
   const cartesian3 = viewer.camera.pickEllipsoid(pos, viewer.scene.globe.ellipsoid)
   if (!cartesian3) return
@@ -271,9 +315,8 @@
}
// 打开弹框
async function open ({ mode, row } = {}) {
async function open({ mode, row } = {}) {
   dialogMode.value = mode || 'add'
   visible.value = true
   await nextTick()
   initMap()
   if (dialogMode.value === 'add') {
@@ -286,6 +329,7 @@
      const detail = await loadDetail(row?.id)
      formData.value = detail ?? row
   }
   formData.value.deployLocation = `${formData.value.longitude}, ${formData.value.latitude}`
   formData.value.deviceId = formData.value.id ?? formData.value.deviceId
   await loadDeviceOptions()
   const currentName = formData.value.deviceName
@@ -298,6 +342,7 @@
      const [longitude, latitude] = location.split(',').map(item => Number(item.trim()))
      if (!Number.isNaN(longitude) && !Number.isNaN(latitude)) {
         setMapPoint(longitude, latitude)
         viewer.flyTo(redPointEntity, { duration: 0 })
      }
   }
}