Browse Source

航点定位,代码分离

lbj
sd 2 months ago
parent
commit
a647d56b8a
  1. 257
      ruoyi-ui/src/views/cesiumMap/LocateDialog.vue
  2. 293
      ruoyi-ui/src/views/cesiumMap/index.vue

257
ruoyi-ui/src/views/cesiumMap/LocateDialog.vue

@ -0,0 +1,257 @@
<template>
<div>
<el-dialog
:title="title"
:visible.sync="dialogVisible"
width="500px"
:append-to-body="true"
:modal-append-to-body="true"
:close-on-click-modal="false"
:close-on-press-escape="true"
:destroy-on-close="true"
:before-close="handleCancel"
custom-class="locate-dialog"
:style="{ marginTop: '15vh' }"
>
<el-form ref="form" :model="formData" label-width="80px">
<el-form-item label="方案:">
<el-select
v-model="formData.scenarioId"
placeholder="请选择方案"
clearable
style="width: 100%"
@change="handleScenarioChange"
>
<el-option
v-for="item in scenarioList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="航线:">
<el-select
v-model="formData.routeId"
placeholder="请选择航线"
clearable
style="width: 100%"
:disabled="!formData.scenarioId"
@change="handleRouteChange"
>
<el-option
v-for="item in routeList"
:key="item.id"
:label="item.callSign"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="航点:">
<el-select
v-model="formData.waypointId"
placeholder="请选择航点"
clearable
style="width: 100%"
:disabled="!formData.routeId"
@change="handleWaypointChange"
>
<el-option
v-for="item in waypointList"
:key="item.id"
:label="`${item.name} (${item.lng}, ${item.lat})`"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="经度:">
<el-input
v-model="formData.lng"
type="number"
placeholder="例如 116.40"
step="0.000001"
clearable
/>
</el-form-item>
<el-form-item label="纬度:">
<el-input
v-model="formData.lat"
type="number"
placeholder="例如 39.90"
step="0.000001"
clearable
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listScenario } from '@/api/system/scenario'
import { listRoutes } from '@/api/system/routes'
import { listWaypoints } from '@/api/system/waypoints'
export default {
name: 'LocateDialog',
props: {
title: {
type: String,
default: '定位'
},
visible: {
type: Boolean,
default: false
}
},
data() {
return {
dialogVisible: false,
formData: {
scenarioId: null,
routeId: null,
waypointId: null,
lng: '116.3974',
lat: '39.9093'
},
scenarioList: [],
routeList: [],
waypointList: []
}
},
watch: {
visible: {
handler(newVal) {
this.dialogVisible = newVal
},
immediate: true
},
dialogVisible(newVal) {
if (newVal) {
this.resetForm()
this.loadScenarios()
}
this.$emit('update:visible', newVal)
}
},
methods: {
resetForm() {
this.formData = {
scenarioId: null,
routeId: null,
waypointId: null,
lng: '116.3974',
lat: '39.9093'
}
this.routeList = []
this.waypointList = []
},
async loadScenarios() {
try {
const res = await listScenario({})
this.scenarioList = res.rows || []
} catch (error) {
console.error('加载方案列表失败:', error)
this.$message.error('加载方案列表失败')
}
},
async handleScenarioChange(value) {
this.formData.routeId = null
this.formData.waypointId = null
this.routeList = []
this.waypointList = []
if (value) {
try {
const res = await listRoutes({ scenarioId: value })
this.routeList = res.rows || []
} catch (error) {
console.error('加载航线列表失败:', error)
this.$message.error('加载航线列表失败')
}
}
},
async handleRouteChange(value) {
this.formData.waypointId = null
this.waypointList = []
if (value) {
try {
const res = await listWaypoints({ routeId: value })
this.waypointList = res.rows || []
} catch (error) {
console.error('加载航点列表失败:', error)
this.$message.error('加载航点列表失败')
}
}
},
handleWaypointChange(value) {
if (value) {
const waypoint = this.waypointList.find(w => w.id === value)
if (waypoint) {
this.formData.lng = waypoint.lng
this.formData.lat = waypoint.lat
}
}
},
handleCancel() {
this.$emit('update:visible', false)
this.$emit('cancel')
},
handleConfirm() {
const { lng, lat } = this.formData
if (!lng || !lat || isNaN(parseFloat(lng)) || isNaN(parseFloat(lat))) {
this.$message.error('请输入有效的经度和纬度!')
return
}
if (lng < -180 || lng > 180 || lat < -90 || lat > 90) {
this.$message.error('经纬度超出有效范围!')
return
}
this.$emit('confirm', {
lng: parseFloat(lng),
lat: parseFloat(lat)
})
this.$emit('update:visible', false)
}
}
}
</script>
<style scoped>
.dialog-footer {
text-align: right;
}
.locate-dialog {
z-index: 99999 !important;
}
.locate-dialog >>> .el-dialog {
margin-top: 15vh !important;
position: fixed !important;
top: 15vh !important;
}
.locate-dialog >>> .el-dialog__body {
padding: 20px;
}
</style>

293
ruoyi-ui/src/views/cesiumMap/index.vue

@ -35,6 +35,15 @@
@delete="deleteEntityFromContextMenu"
@update-property="updateEntityProperty"
/>
<!-- 定位弹窗 -->
<locate-dialog
:visible="locateDialogVisible"
@update:visible="locateDialogVisible = $event"
@confirm="handleLocateConfirm"
@cancel="handleLocateCancel"
/>
<!-- 地图右下角比例尺 + 经纬度 -->
<div class="map-info-panel">
<div class="scale-bar">
@ -57,12 +66,10 @@ import DrawingToolbar from './DrawingToolbar.vue'
import MeasurementPanel from './MeasurementPanel.vue'
import HoverTooltip from './HoverTooltip.vue'
import ContextMenu from './ContextMenu.vue'
import LocateDialog from './LocateDialog.vue'
import axios from 'axios'
import request from '@/utils/request'
import { getToken } from '@/utils/auth'
import { listScenario } from '@/api/system/scenario'
import { listRoutes } from '@/api/system/routes'
import { listWaypoints } from '@/api/system/waypoints'
export default {
name: 'CesiumMap',
props: {
@ -143,19 +150,15 @@ export default {
scaleBarText: '--',
scaleBarWidthPx: 80,
//
scenarioList: [],
routeList: [],
waypointList: [],
selectedScenario: null,
selectedRoute: null,
selectedWaypoint: null
locateDialogVisible: false
}
},
components: {
DrawingToolbar,
MeasurementPanel,
HoverTooltip,
ContextMenu
ContextMenu,
LocateDialog
},
mounted() {
console.log(this.drawDomClick,999999)
@ -2716,256 +2719,28 @@ export default {
})
}
},
async handleLocate() {
const h = this.$createElement
//
this.scenarioList = []
this.routeList = []
this.waypointList = []
this.selectedScenario = null
this.selectedRoute = null
this.selectedWaypoint = null
try {
const scenarioRes = await listScenario({})
this.scenarioList = scenarioRes.rows || []
} catch (error) {
console.error('加载方案列表失败:', error)
}
const getSelectByClass = (className) => {
return document.querySelector(`.${className}`)
}
const resetSelects = () => {
const scenarioSelect = getSelectByClass('scenario-select')
const routeSelect = getSelectByClass('route-select')
const waypointSelect = getSelectByClass('waypoint-select')
if (scenarioSelect) scenarioSelect.value = ''
if (routeSelect) {
routeSelect.disabled = true
routeSelect.innerHTML = '<option value="">请选择航线</option>'
}
if (waypointSelect) {
waypointSelect.disabled = true
waypointSelect.innerHTML = '<option value="">请选择航点</option>'
}
}
const handleScenarioChange = async (e) => {
const value = parseInt(e.target.value)
console.log('方案变化:', value)
this.selectedScenario = value
this.selectedRoute = null
this.selectedWaypoint = null
this.routeList = []
this.waypointList = []
const routeSelect = getSelectByClass('route-select')
const waypointSelect = getSelectByClass('waypoint-select')
if (routeSelect) {
routeSelect.disabled = true
routeSelect.innerHTML = '<option value="">请选择航线</option>'
}
if (waypointSelect) {
waypointSelect.disabled = true
waypointSelect.innerHTML = '<option value="">请选择航点</option>'
}
if (value) {
try {
const routeRes = await listRoutes({ scenarioId: value })
this.routeList = routeRes.rows || []
console.log('航线列表:', this.routeList)
if (routeSelect) {
routeSelect.disabled = false
routeSelect.innerHTML = '<option value="">请选择航线</option>'
this.routeList.forEach(item => {
const option = document.createElement('option')
option.value = item.id
option.textContent = item.callSign
routeSelect.appendChild(option)
})
}
} catch (error) {
console.error('加载航线列表失败:', error)
}
}
}
const handleRouteChange = async (e) => {
const value = parseInt(e.target.value)
console.log('航线变化:', value)
this.selectedRoute = value
this.selectedWaypoint = null
this.waypointList = []
const waypointSelect = getSelectByClass('waypoint-select')
if (waypointSelect) {
waypointSelect.disabled = true
waypointSelect.innerHTML = '<option value="">请选择航点</option>'
}
if (value) {
try {
const waypointRes = await listWaypoints({ routeId: value })
this.waypointList = waypointRes.rows || []
console.log('航点列表:', this.waypointList)
if (waypointSelect) {
waypointSelect.disabled = false
waypointSelect.innerHTML = '<option value="">请选择航点</option>'
this.waypointList.forEach(item => {
const option = document.createElement('option')
option.value = item.id
option.textContent = `${item.name} (${item.lng}, ${item.lat})`
waypointSelect.appendChild(option)
})
}
} catch (error) {
console.error('加载航点列表失败:', error)
}
}
}
const handleWaypointChange = (e) => {
const value = parseInt(e.target.value)
console.log('航点变化:', value)
this.selectedWaypoint = value
const waypoint = this.waypointList.find(w => w.id === value)
if (waypoint) {
const lngInput = document.querySelector('input[placeholder="例如 116.40"]')
const latInput = document.querySelector('input[placeholder="例如 39.90"]')
if (lngInput) lngInput.value = waypoint.lng
if (latInput) latInput.value = waypoint.lat
console.log('填充经纬度:', waypoint.lng, waypoint.lat)
}
handleLocate() {
this.locateDialogVisible = true
},
handleLocateConfirm(location) {
const { lng, lat } = location
if (this.viewer) {
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(lng, lat, 100000),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: 0.0
},
duration: 2
})
this.$message.success(`已定位到经度 ${lng.toFixed(4)},纬度 ${lat.toFixed(4)}`)
}
this.$msgbox({
title: '定位',
message: h('div', {style: 'padding: 10px 0;'}, [
h('div', {style: 'margin-bottom: 15px;'}, [
h('label', {style: 'display: block; margin-bottom: 5px; color: #606266;'}, '方案:'),
h('select', {
attrs: {
class: 'scenario-select',
style: 'width: 100%; padding: 8px; border: 1px solid #dcdfe6; border-radius: 4px; box-sizing: border-box;'
},
on: {
change: handleScenarioChange
}
}, [
h('option', { attrs: { value: '' } }, '请选择方案'),
...this.scenarioList.map(item => h('option', { attrs: { value: item.id } }, item.name))
])
]),
h('div', {style: 'margin-bottom: 15px;'}, [
h('label', {style: 'display: block; margin-bottom: 5px; color: #606266;'}, '航线:'),
h('select', {
attrs: {
class: 'route-select',
disabled: true,
style: 'width: 100%; padding: 8px; border: 1px solid #dcdfe6; border-radius: 4px; box-sizing: border-box;'
},
on: {
change: handleRouteChange
}
}, [
h('option', { attrs: { value: '' } }, '请选择航线')
])
]),
h('div', {style: 'margin-bottom: 15px;'}, [
h('label', {style: 'display: block; margin-bottom: 5px; color: #606266;'}, '航点:'),
h('select', {
attrs: {
class: 'waypoint-select',
disabled: true,
style: 'width: 100%; padding: 8px; border: 1px solid #dcdfe6; border-radius: 4px; box-sizing: border-box;'
},
on: {
change: handleWaypointChange
}
}, [
h('option', { attrs: { value: '' } }, '请选择航点')
])
]),
h('div', {style: 'margin-bottom: 15px;'}, [
h('label', {style: 'display: block; margin-bottom: 5px; color: #606266;'}, '经度:'),
h('input', {
attrs: {
type: 'number',
placeholder: '例如 116.40',
step: '0.000001',
value: '116.3974'
},
style: 'width: 100%; padding: 8px; border: 1px solid #dcdfe6; border-radius: 4px; box-sizing: border-box;',
ref: 'lngInput'
})
]),
h('div', null, [
h('label', {style: 'display: block; margin-bottom: 5px; color: #606266;'}, '纬度:'),
h('input', {
attrs: {
type: 'number',
placeholder: '例如 39.90',
step: '0.000001',
value: '39.9093'
},
style: 'width: 100%; padding: 8px; border: 1px solid #dcdfe6; border-radius: 4px; box-sizing: border-box;',
ref: 'latInput'
})
])
]),
showCancelButton: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
const lngInput = instance.$el.querySelector('input[placeholder="例如 116.40"]')
const latInput = instance.$el.querySelector('input[placeholder="例如 39.90"]')
const lng = parseFloat(lngInput.value)
const lat = parseFloat(latInput.value)
if (!lng || !lat || isNaN(lng) || isNaN(lat)) {
this.$message.error('请输入有效的经度和纬度!')
return
}
if (lng < -180 || lng > 180 || lat < -90 || lat > 90) {
this.$message.error('经纬度超出有效范围!')
return
}
if (this.viewer) {
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(lng, lat, 100000),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: 0.0
},
duration: 2
})
this.$message.success(`已定位到经度 ${lng.toFixed(4)},纬度 ${lat.toFixed(4)}`)
}
done()
} else {
this.$message.info('已取消定位')
done()
}
}
}).then(() => {
//
resetSelects()
}).catch(() => {
this.$message.info('已取消定位')
//
resetSelects()
})
},
handleLocateCancel() {
this.$message.info('已取消定位')
},
updateSelectOptions(refName, dataList, labelField) {
const select = document.querySelector(`select[ref="${refName}"]`)

Loading…
Cancel
Save