Merge remote-tracking branch 'origin/master'
| | |
| | | text: `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`, |
| | | font: '14px', |
| | | fillColor: Cesium.Color.WHITE, // 文字颜色:白色 |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.45), //背景颜色 |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.6), //背景颜色 |
| | | backgroundPadding: new Cesium.Cartesian2(5, 5), // 水平/垂直内边距(像素) |
| | | pixelOffset: new Cesium.Cartesian2(0, -20), // 可选:微调位置 |
| | | showBackground: true, // 确保背景显示(某些版本需要) |
| | |
| | | text: `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`, |
| | | font: '14px', |
| | | fillColor: Cesium.Color.WHITE, |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.45), |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.6), |
| | | backgroundPadding: new Cesium.Cartesian2(5, 5), |
| | | pixelOffset: new Cesium.Cartesian2(0, -20), |
| | | showBackground: true, |
| | |
| | | <el-table class="command-table" ref="areaTableRef" |
| | | :data="areaList.filter(item => item.areaName.includes(searchName))" row-key="id" |
| | | @selection-change="handleAreaSelectionChange"> |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column type="selection" width="55" :reserve-selection="true" /> |
| | | <el-table-column prop="areaName" show-overflow-tooltip label="区域名称" /> |
| | | <el-table-column prop="areaType" show-overflow-tooltip label="区域类型"> |
| | | <template v-slot="{ row }"> |
| | |
| | | import { fieldRules, geomAnalysis, getDictLabel } from '@ztzf/utils' |
| | | import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue' |
| | | import * as Cesium from 'cesium' |
| | | import { fwAreaDivideListApi } from '../partition/partitionApi' |
| | | import { fwAreaDivideDetailApi, fwAreaDivideListApi } from '../partition/partitionApi' |
| | | import { DrawPolygon } from '@/utils/cesium/DrawPolygon' |
| | | import commandPost from '@/assets/images/dataCockpit/legend/command-post.png' |
| | | |
| | | const initForm = () => ({ |
| | | sceneName: '', // 场景名称 |
| | |
| | | } |
| | | |
| | | // 关联区域变更 |
| | | function handleAreaSelectionChange (rows) { |
| | | selectedAreaRows.value = rows |
| | | formData.value.areaDivideIds = rows.map(item => item.id) |
| | | formData.value.areaCount = rows.length |
| | | formData.value.defenseArea = calcDefenseArea(rows) |
| | | async function handleAreaSelectionChange (rows) { |
| | | const selectedRows = await ensureAreaGeom(rows) |
| | | selectedAreaRows.value = selectedRows |
| | | const ids = selectedRows.map(item => item.id) |
| | | formData.value.areaDivideIds = ids.join(',') |
| | | formData.value.areaCount = ids.length |
| | | formData.value.defenseArea = calcDefenseArea(selectedRows) |
| | | } |
| | | |
| | | // 渲染面 |
| | | function renderingSurface () { |
| | | console.log(geometricSource, 11111111) |
| | | |
| | | if (!geometricSource) { |
| | | initMap() |
| | | } |
| | | if (!geometricSource) return |
| | | geometricSource && geometricSource.entities.removeAll() |
| | | selectedAreaRows.value.forEach(item => { |
| | | if (item.geom) { |
| | |
| | | return _.round(total, 2) |
| | | } |
| | | |
| | | async function ensureAreaGeom (rows) { |
| | | const missingRows = rows.filter(row => row?.id && !row.geom) |
| | | if (!missingRows.length) return rows |
| | | const detailList = await Promise.all( |
| | | missingRows.map(row => |
| | | fwAreaDivideDetailApi({ id: row.id }) |
| | | .then(res => res?.data?.data) |
| | | .catch(() => null) |
| | | ) |
| | | ) |
| | | const detailMap = new Map( |
| | | detailList.filter(Boolean).map(item => [String(item.id), item]) |
| | | ) |
| | | if (!detailMap.size) return rows |
| | | areaList.value = areaList.value.map(item => { |
| | | const detail = detailMap.get(String(item.id)) |
| | | return detail ? { ...item, ...detail } : item |
| | | }) |
| | | return rows.map(item => { |
| | | const detail = detailMap.get(String(item.id)) |
| | | return detail ? { ...item, ...detail } : item |
| | | }) |
| | | } |
| | | |
| | | // 同步关联区域 |
| | | function syncAreaSelection () { |
| | | if (!areaTableRef.value) return |
| | | areaTableRef.value.clearSelection() |
| | | const rows = [] |
| | | const arr = formData.value.areaDivideIds.split(',') |
| | | const areaDivideIds = formData.value.areaDivideIds |
| | | const arr = Array.isArray(areaDivideIds) |
| | | ? areaDivideIds.map(item => String(item)) |
| | | : String(areaDivideIds || '') |
| | | .split(',') |
| | | .filter(Boolean) |
| | | areaList.value.forEach(row => { |
| | | if (arr.includes(row.id)) { |
| | | if (arr.includes(String(row.id))) { |
| | | areaTableRef.value.toggleRowSelection(row, true) |
| | | rows.push(row) |
| | | } |
| | |
| | | if (!redPointEntity) { |
| | | redPointEntity = viewer.entities.add({ |
| | | position: Cesium.Cartesian3.fromDegrees(longitude, latitude), |
| | | point: { |
| | | color: Cesium.Color.RED, |
| | | pixelSize: 10, |
| | | billboard: { |
| | | image: commandPost, // 这里替换为你的图片路径或变量 deviceZcImg |
| | | width: 40, |
| | | height: 56, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 设置图片底部对齐坐标点 |
| | | }, |
| | | label: { |
| | | text: `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`, |
| | | font: '14px', |
| | | fillColor: Cesium.Color.WHITE, |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.45), |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.6), |
| | | backgroundPadding: new Cesium.Cartesian2(5, 5), |
| | | pixelOffset: new Cesium.Cartesian2(0, -20), |
| | | showBackground: true, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | horizontalOrigin: Cesium.HorizontalOrigin.CENTER, |
| | | verticalOrigin: Cesium.VerticalOrigin.CENTER, |
| | | outlineWidth: 1, |
| | | outlineColor: Cesium.Color.WHITE, |
| | | pixelOffset: new Cesium.Cartesian2(0, -72), |
| | | eyeOffset: new Cesium.Cartesian3(0, 0, -20), |
| | | }, |
| | | }) |
| | |
| | | <div class="val">{{ formData.deviceType }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">设备编码</div> |
| | | <div class="val">{{ formData.deviceSn }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">设备属性</div> |
| | | <div class="val">{{ formData.deviceAtt }}</div> |
| | | </el-col> |
| | |
| | | <el-option v-for="item in dictObj.deviceType" :key="item.dictKey" :label="item.dictValue" |
| | | :value="item.dictKey" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备编码" prop="deviceSn"> |
| | | <el-input class="command-input" v-model="formData.deviceSn" maxlength="50" |
| | | placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | contactPhone: '', // 联系电话 |
| | | deviceAtt: '', // 设备属性 |
| | | deviceType: '', // 设备类型 |
| | | deviceSn: '', // 设备编码 |
| | | deviceModel: '', // 型号 |
| | | deviceSpecification: '', // 规格 |
| | | deviceName: '', // 设备名称 |
| | |
| | | const rules = { |
| | | deviceName: fieldRules(true, 50), |
| | | deviceType: fieldRules(true), |
| | | deviceSn: fieldRules(true, 50), |
| | | deviceAtt: fieldRules(true), |
| | | deviceModel: fieldRules(true, 50), |
| | | deviceSpecification: fieldRules(true, 50), |
| | |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">设备类型</div> |
| | | <div class="val">{{ getDeviceTypeLabel(formData.deviceType) }}</div> |
| | | <div class="val">{{ getDictLabel(formData.deviceType, dictObj.deviceType) }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">设备位置</div> |
| | |
| | | popper-class="command-select-popper" |
| | | v-model="formData.deviceId" |
| | | placeholder="请选择" |
| | | :disabled="dialogMode === 'edit'" |
| | | clearable |
| | | @change="handleDeviceChange" |
| | | > |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getDictLabel } from '@ztzf/utils' |
| | | |
| | | import { Close } from '@element-plus/icons-vue' |
| | | |
| | | import { computed, inject, nextTick, ref, watch } from 'vue' |
| | |
| | | import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue' |
| | | import * as Cesium from 'cesium' |
| | | |
| | | import commandPost from '@/assets/images/dataCockpit/legend/command-post.png' |
| | | import equipment from '@/assets/images/dataCockpit/legend/equipment.png' |
| | | |
| | | const initForm = () => ({ |
| | | deviceId: '', // 侦测设备ID |
| | |
| | | if (!isValid) return |
| | | submitting.value = true |
| | | try { |
| | | const {longitude, latitude} = parseDeployLocation(formData.value.deployLocation) |
| | | |
| | | const payload = { |
| | | ...formData.value, |
| | | id: formData.value.id || formData.value.deviceId || undefined, |
| | | effectiveRangeKmIsNotNull: formData.value.effectiveRangeKm ? 1 : 2, |
| | | effectiveRangeKm: formData.value.effectiveRangeKm, |
| | | longitude, |
| | | latitude |
| | | } |
| | | delete payload.deviceId |
| | | await detectionRangeSubmitApi(payload) |
| | |
| | | redPointEntity = viewer.entities.add({ |
| | | position: Cesium.Cartesian3.fromDegrees(longitude, latitude), |
| | | billboard: { |
| | | image: commandPost, // 这里替换为你的图片路径或变量 deviceZcImg |
| | | image: equipment, // 这里替换为你的图片路径或变量 deviceZcImg |
| | | width: 40, |
| | | height: 56, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 设置图片底部对齐坐标点 |
| | |
| | | text: `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`, |
| | | font: '16px', |
| | | fillColor: Cesium.Color.WHITE, |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.45), |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.6), |
| | | backgroundPadding: new Cesium.Cartesian2(5, 5), |
| | | showBackground: true, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | |
| | | </el-col> |
| | | |
| | | <el-col :span="12"> |
| | | <el-form-item label="区域" prop="areaDivideId"> |
| | | <el-form-item label="场景" prop="defenseSceneId"> |
| | | <el-select class="command-select" popper-class="command-select-popper" |
| | | v-model="formData.areaDivideId" placeholder="请选择" clearable |
| | | @change="handleAreaChange"> |
| | | <el-option v-for="item in areaList" :key="item.id" :label="item.areaName" |
| | | v-model="formData.defenseSceneId" placeholder="请选择" clearable |
| | | @change="handleSceneChange"> |
| | | <el-option v-for="item in sceneList" :key="item.id" :label="item.sceneName" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="12"> |
| | | <el-form-item label="场景" prop="defenseSceneId"> |
| | | <el-form-item label="区域" prop="areaDivideId"> |
| | | <el-select class="command-select" popper-class="command-select-popper" |
| | | v-model="formData.defenseSceneId" placeholder="请先选择区域" clearable |
| | | :disabled="!formData.areaDivideId" @change="handleSceneChange"> |
| | | <el-option v-for="item in sceneList" :key="item.id" :label="item.sceneName" |
| | | v-model="formData.areaDivideId" placeholder="请先选择场景" clearable |
| | | :disabled="!formData.defenseSceneId" @change="handleAreaChange"> |
| | | <el-option v-for="item in areaList" :key="item.id" :label="item.areaName" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | } |
| | | |
| | | async function handleAreaChange (areaId) { |
| | | formData.value.defenseSceneId = '' |
| | | if (areaId) { |
| | | await loadSceneList(areaId) |
| | | } else { |
| | | sceneList.value = [] |
| | | } |
| | | } |
| | | |
| | | // 场景选择变化处理 |
| | | async function handleSceneChange (sceneId) { |
| | | const find = sceneList.value.find(item => item.id === sceneId) |
| | | const find = areaList.value.find(item => item.id === areaId) |
| | | formData.value.longitude = find?.longitude |
| | | formData.value.latitude = find?.latitude |
| | | } |
| | | |
| | | // 场景选择变化处理 |
| | | async function handleSceneChange (sceneId) { |
| | | formData.value.areaDivideId = '' |
| | | |
| | | if (sceneId) { |
| | | await loadAreaList(sceneId) |
| | | } else { |
| | | areaList.value = [] |
| | | } |
| | | } |
| | | |
| | | // 加载区域列表 |
| | | async function loadAreaList () { |
| | | const res = await fwAreaDivideListApi() |
| | | async function loadAreaList (sceneId) { |
| | | const res = await fwAreaDivideListApi({sceneId}) |
| | | areaList.value = res?.data?.data ?? [] |
| | | } |
| | | |
| | | // 加载场景列表 |
| | | async function loadSceneList(areaId) { |
| | | const res = await fwDefenseSceneListApi({areaId}) |
| | | async function loadSceneList() { |
| | | const res = await fwDefenseSceneListApi() |
| | | sceneList.value = res?.data?.data ?? [] |
| | | } |
| | | |
| | |
| | | text: `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`, |
| | | font: '14px', |
| | | fillColor: Cesium.Color.WHITE, |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.45), |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.6), |
| | | backgroundPadding: new Cesium.Cartesian2(5, 5), |
| | | pixelOffset: new Cesium.Cartesian2(0, -20), |
| | | showBackground: true, |
| | |
| | | defineExpose({ open }) |
| | | |
| | | onMounted(() => { |
| | | loadAreaList() |
| | | loadSceneList() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"> |
| | |
| | | } |
| | | } |
| | | |
| | | .el-overlay-dialog{ |
| | | display: flex; |
| | | justify-content: center; /* 水平居中 */ |
| | | align-items: center; /* 垂直居中 */ |
| | | } |
| | | |
| | | .gd-dialog { |
| | | padding: 30px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | background: #FFFFFF; |
| | | border: 1px solid #CCCCCC; |
| | | border-radius: 6px 6px 6px 6px; |
| | | margin-top: auto !important; |
| | | margin: 0 !important; |
| | | max-height: 90vh; |
| | | min-height: 20vh; |
| | | position: absolute; |
| | | left: 50%; |
| | | top: 50%; |
| | | transform: translate(-50%, -50%); |
| | | |
| | | |
| | | .el-dialog__header { |
| | | span { |
| | |
| | | |
| | | .el-dialog__body { |
| | | overflow: auto; |
| | | |
| | | min-height: 20vh; |
| | | .detail-title { |
| | | margin-bottom: 10px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | |
| | | <template> |
| | | <el-dialog class="gd-dialog" :close-on-click-modal="false" v-model="visible" title="查看" @closed="visible = false" width="1000px" destroy-on-close> |
| | | <div class="gd-table-container" v-loading="loading"> |
| | | <div class="gd-table-content gd-table-content-bg"> |
| | | <el-table class="gd-table" :data="list"> |
| | | <div class="" v-loading="loading"> |
| | | <div class="gd-table-content-bg"> |
| | | <el-table :data="list"> |
| | | <el-table-column label="线索缩略图" width="120"> |
| | | <template v-slot="{ row }"> |
| | | <el-image |
| | |
| | | async function open({ mode = 'view', row } = {}) { |
| | | dialogMode.value = mode |
| | | formData.value = { ...initForm(), ...row }; |
| | | ['6','7','8'].includes(row.taskStatus) && getWorkOrderList() |
| | | ['6','7','8'].includes(row.taskStatus) && getList() |
| | | initMap() |
| | | } |
| | | |