吉安感知网项目-前端
罗广辉
2026-01-16 4376eb565c603debd4d48d05221219dc1aeb8fc6
feat: 回显并飞行到点位
3 files modified
160 ■■■■■ changed files
applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue 123 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/detectionRange/index.vue 25 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/taskSchedule/index.vue 12 ●●●● patch | view | raw | blame | history
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 })
        }
    }
}
applications/drone-command/src/views/detectionCountermeasure/detectionRange/index.vue
@@ -1,7 +1,7 @@
<template>
    <basic-container>
        <el-form ref="queryParamsRef" :model="searchParams" class="ztzf-page-history-search">
            <el-form-item label="名称" prop="deviceName">
            <el-form-item label="设备名称" prop="deviceName">
                <el-input
                    class="ztzf-data-cockpit-search-input"
                    v-model="searchParams.deviceName"
@@ -11,7 +11,7 @@
                />
            </el-form-item>
            <el-form-item label="类型" prop="deviceType">
            <el-form-item label="设备类型" prop="deviceType">
                <el-select
                    class="ztzf-data-cockpit-select"
                    popper-class="ztzf-data-cockpit-select-popper"
@@ -55,7 +55,7 @@
                        </template>
                    </el-table-column>
                    <el-table-column prop="deviceModel" show-overflow-tooltip label="型号" />
                    <el-table-column show-overflow-tooltip label="覆盖范围">
                    <el-table-column show-overflow-tooltip label="覆盖范围(m)">
                        <template v-slot="{ row }">
                            {{ formatRange(row) }}
                        </template>
@@ -87,7 +87,7 @@
            </div>
        </div>
        <DetectionRangeDialog ref="dialogRef" @success="getList" />
        <DetectionRangeDialog ref="dialogRef" @success="getList" v-model="visible" v-if="visible" />
    </basic-container>
</template>
<script setup>
@@ -115,7 +115,7 @@
const dictObj = ref({
    deviceType: [], // 设备类型
})
const visible = ref(false)
provide('dictObj', dictObj)
// 获取列表
@@ -145,17 +145,26 @@
// 新增
function handleAdd() {
    dialogRef.value?.open({ mode: 'add' })
    visible.value = true
    nextTick(() => {
        dialogRef.value?.open({ mode: 'add' })
    })
}
// 查看
function handleView(row) {
    dialogRef.value?.open({ mode: 'view', row: { ...row } })
    visible.value = true
    nextTick(() => {
        dialogRef.value?.open({ mode: 'view', row: { ...row } })
    })
}
// 编辑
function handleEdit(row) {
    dialogRef.value?.open({ mode: 'edit', row: { ...row } })
    visible.value = true
    nextTick(() => {
        dialogRef.value?.open({ mode: 'edit', row: { ...row } })
    })
}
// 删除
applications/drone-command/src/views/detectionCountermeasure/taskSchedule/index.vue
@@ -15,11 +15,11 @@
                </el-select>
            </el-form-item>
            <el-form-item label="设备状态" prop="deviceStatus">
            <el-form-item label="设备状态" prop="status">
                <el-select
                    class="ztzf-data-cockpit-select"
                    popper-class="ztzf-data-cockpit-select-popper"
                    v-model="searchParams.deviceStatus"
                    v-model="searchParams.status"
                    placeholder="请选择"
                    clearable
                    @clear="handleSearch"
@@ -34,7 +34,7 @@
                </el-select>
            </el-form-item>
            <el-form-item label="设备编号" prop="deviceSn">
            <el-form-item label="设备编码" prop="deviceSn">
                <el-input
                    class="ztzf-data-cockpit-search-input"
                    v-model="searchParams.deviceSn"
@@ -62,9 +62,9 @@
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="deviceName" show-overflow-tooltip width="140" label="设备名称" />
                    <el-table-column prop="deviceSn" show-overflow-tooltip width="140" label="设备编码" />
                    <el-table-column prop="deviceStatus" show-overflow-tooltip width="100" label="设备状态">
                    <el-table-column prop="status" show-overflow-tooltip width="100" label="设备状态">
                        <template v-slot="{ row }">
                            {{ getDictLabel(row.deviceStatus, dictObj.deviceStatus) }}
                            {{ getDictLabel(row.status, dictObj.deviceStatus) }}
                        </template>
                    </el-table-column>
                    <el-table-column prop="areaName" show-overflow-tooltip width="120" label="区域" />
@@ -127,7 +127,7 @@
// 初始化查询参数
const initSearchParams = () => ({
    deviceId: '', // 设备名称
    deviceStatus: '', // 设备状态
    status: '', // 设备状态
    deviceSn: '', // 设备编号
    current: 1, // 当前页
    size: 10, // 每页大小