Compare commits
No commits in common. "48b05625ebf73904e9a25176b790c51ff1264473" and "568e89686f7fa0330d06df56854c4f71168f6560" have entirely different histories.
48b05625eb
...
568e89686f
@ -13,11 +13,7 @@
|
|||||||
<DisasterAnalysis />
|
<DisasterAnalysis />
|
||||||
</CollapsiblePanel>
|
</CollapsiblePanel>
|
||||||
|
|
||||||
<CollapsiblePanel
|
<CollapsiblePanel title="快速匹配" subtitle="「力量预置」">
|
||||||
title="快速匹配"
|
|
||||||
subtitle="「力量预置」"
|
|
||||||
@title-click="handleForcePresetToggle"
|
|
||||||
>
|
|
||||||
<ForcePreset />
|
<ForcePreset />
|
||||||
</CollapsiblePanel>
|
</CollapsiblePanel>
|
||||||
|
|
||||||
@ -114,7 +110,7 @@ const handleCloseVideoModal = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 定义对外事件
|
// 定义对外事件
|
||||||
const emit = defineEmits(['start-dispatch', 'view-plan', 'force-preset-toggle'])
|
const emit = defineEmits(['start-dispatch', 'view-plan'])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理力量调度启动事件,向上传递给父组件
|
* 处理力量调度启动事件,向上传递给父组件
|
||||||
@ -129,14 +125,6 @@ const handleStartDispatch = (payload) => {
|
|||||||
const handleViewPlan = (plan) => {
|
const handleViewPlan = (plan) => {
|
||||||
emit('view-plan', plan)
|
emit('view-plan', plan)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理快速匹配面板标题点击事件
|
|
||||||
*/
|
|
||||||
const handleForcePresetToggle = () => {
|
|
||||||
console.log('[LeftPanel] 快速匹配标题被点击')
|
|
||||||
emit('force-preset-toggle')
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@ -41,23 +41,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from "vue";
|
import { ref } from "vue";
|
||||||
import { MAP_TOOLS, DEVICE_WATCH } from "../../constants";
|
import { MAP_TOOLS, DEVICE_WATCH } from "../../constants";
|
||||||
|
|
||||||
// 定义props
|
|
||||||
const props = defineProps({
|
|
||||||
// 当前激活的工具
|
|
||||||
activeToolKey: {
|
|
||||||
type: String,
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 卫星设备观看状态
|
// 卫星设备观看状态
|
||||||
const isWatchingDevice = ref(false);
|
const isWatchingDevice = ref(false);
|
||||||
|
|
||||||
// 当前激活的测量工具 - 使用computed从props获取
|
// 当前激活的测量工具(默认激活模型对比)
|
||||||
const activeTool = computed(() => props.activeToolKey)
|
const activeTool = ref('modelCompare');
|
||||||
|
|
||||||
// 定义对外事件
|
// 定义对外事件
|
||||||
const emit = defineEmits(["device-watch", "tool-change"]);
|
const emit = defineEmits(["device-watch", "tool-change"]);
|
||||||
@ -114,13 +105,15 @@ const handleDeviceWatch = () => {
|
|||||||
*/
|
*/
|
||||||
const handleToolClick = (toolKey) => {
|
const handleToolClick = (toolKey) => {
|
||||||
// 点击同一个工具则取消激活
|
// 点击同一个工具则取消激活
|
||||||
const newActiveState = activeTool.value === toolKey ? null : toolKey
|
if (activeTool.value === toolKey) {
|
||||||
const isActive = newActiveState === toolKey
|
activeTool.value = null;
|
||||||
|
} else {
|
||||||
console.log("切换地图工具:", toolKey, "激活状态:", isActive);
|
activeTool.value = toolKey;
|
||||||
|
}
|
||||||
|
console.log("切换地图工具:", toolKey);
|
||||||
emit("tool-change", {
|
emit("tool-change", {
|
||||||
tool: toolKey,
|
tool: toolKey,
|
||||||
active: isActive,
|
active: activeTool.value === toolKey,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
<!-- 延迟渲染确保目标元素已存在 -->
|
<!-- 延迟渲染确保目标元素已存在 -->
|
||||||
<Teleport to="#sa-controls" v-if="isMounted">
|
<Teleport to="#sa-controls" v-if="isMounted">
|
||||||
<MapControls
|
<MapControls
|
||||||
:active-tool-key="activeToolKey"
|
|
||||||
@tool-change="handleToolChange"
|
@tool-change="handleToolChange"
|
||||||
@device-watch="handleDeviceWatch"
|
@device-watch="handleDeviceWatch"
|
||||||
/>
|
/>
|
||||||
@ -20,15 +19,6 @@ import { ref, onMounted } from 'vue'
|
|||||||
import { MapViewport } from '@/map'
|
import { MapViewport } from '@/map'
|
||||||
import MapControls from './MapControls.vue'
|
import MapControls from './MapControls.vue'
|
||||||
|
|
||||||
// 定义props
|
|
||||||
const props = defineProps({
|
|
||||||
// 当前激活的工具键
|
|
||||||
activeToolKey: {
|
|
||||||
type: String,
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向外抛出的事件
|
* 向外抛出的事件
|
||||||
* @event tool-change - 地图工具变化事件,包含 { tool: string, active: boolean }
|
* @event tool-change - 地图工具变化事件,包含 { tool: string, active: boolean }
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
<section class="collapsible-panel" :class="{ 'collapsible-panel--collapsed': isCollapsed }">
|
<section class="collapsible-panel" :class="{ 'collapsible-panel--collapsed': isCollapsed }">
|
||||||
<div
|
<div
|
||||||
class="collapsible-panel__header"
|
class="collapsible-panel__header"
|
||||||
@click="handleHeaderClick"
|
:class="{ 'collapsible-panel__header--clickable': collapsible }"
|
||||||
|
@click="collapsible && toggle()"
|
||||||
>
|
>
|
||||||
<PanelHeader :title="title" :subtitle="subtitle">
|
<PanelHeader :title="title" :subtitle="subtitle">
|
||||||
<template #title-icon>
|
<template #title-icon>
|
||||||
@ -84,7 +85,7 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:collapsed', 'toggle', 'title-click'])
|
const emit = defineEmits(['update:collapsed', 'toggle'])
|
||||||
|
|
||||||
// 判断是否受控组件
|
// 判断是否受控组件
|
||||||
const isControlled = computed(() => props.collapsed !== undefined)
|
const isControlled = computed(() => props.collapsed !== undefined)
|
||||||
@ -107,11 +108,6 @@ const isCollapsed = computed({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 处理标题点击事件
|
|
||||||
function handleHeaderClick() {
|
|
||||||
emit('title-click')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换收起/展开
|
// 切换收起/展开
|
||||||
function toggle() {
|
function toggle() {
|
||||||
if (!props.collapsible) return
|
if (!props.collapsible) return
|
||||||
|
|||||||
@ -142,11 +142,9 @@ export function useDualMapCompare() {
|
|||||||
const enableCompareMode = async (rightViewerInstance, options = {}) => {
|
const enableCompareMode = async (rightViewerInstance, options = {}) => {
|
||||||
const { skipLeftModelLoad = false, loadLeftModel = false } = options
|
const { skipLeftModelLoad = false, loadLeftModel = false } = options
|
||||||
|
|
||||||
// 前置检查: viewer
|
|
||||||
if (!rightViewerInstance) {
|
if (!rightViewerInstance) {
|
||||||
const error = new Error('右侧主地图Viewer未初始化')
|
console.error('[useDualMapCompare] 右侧主地图Viewer未初始化')
|
||||||
console.error('[useDualMapCompare]', error.message)
|
return
|
||||||
throw error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果只是加载左侧模型(Viewer已存在)
|
// 如果只是加载左侧模型(Viewer已存在)
|
||||||
@ -171,9 +169,8 @@ export function useDualMapCompare() {
|
|||||||
// 查找左侧容器(容器已存在于DOM中)
|
// 查找左侧容器(容器已存在于DOM中)
|
||||||
const leftContainer = document.getElementById('leftCesiumContainer')
|
const leftContainer = document.getElementById('leftCesiumContainer')
|
||||||
if (!leftContainer) {
|
if (!leftContainer) {
|
||||||
const error = new Error('找不到左侧容器元素 #leftCesiumContainer')
|
console.error('[useDualMapCompare] 找不到左侧容器元素')
|
||||||
console.error('[useDualMapCompare]', error.message)
|
return
|
||||||
throw error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 先设置状态,触发CSS动画
|
// 先设置状态,触发CSS动画
|
||||||
@ -185,10 +182,9 @@ export function useDualMapCompare() {
|
|||||||
// 初始化左侧Viewer
|
// 初始化左侧Viewer
|
||||||
const leftViewerInstance = initLeftViewer(leftContainer)
|
const leftViewerInstance = initLeftViewer(leftContainer)
|
||||||
if (!leftViewerInstance) {
|
if (!leftViewerInstance) {
|
||||||
const error = new Error('左侧Viewer初始化失败')
|
console.error('[useDualMapCompare] 左侧Viewer初始化失败')
|
||||||
console.error('[useDualMapCompare]', error.message)
|
isCompareMode.value = false
|
||||||
isCompareMode.value = false // 回滚状态
|
return
|
||||||
throw error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 立即同步右侧相机的当前位置到左侧
|
// 立即同步右侧相机的当前位置到左侧
|
||||||
@ -284,33 +280,13 @@ export function useDualMapCompare() {
|
|||||||
* @param {boolean} active - true启用,false禁用
|
* @param {boolean} active - true启用,false禁用
|
||||||
* @param {Cesium.Viewer} rightViewerInstance - 右侧Viewer实例(主地图)
|
* @param {Cesium.Viewer} rightViewerInstance - 右侧Viewer实例(主地图)
|
||||||
* @param {Object} options - 配置选项(传递给 enableCompareMode)
|
* @param {Object} options - 配置选项(传递给 enableCompareMode)
|
||||||
* @throws {Error} 当切换失败时抛出错误
|
|
||||||
*/
|
*/
|
||||||
const toggleCompareMode = async (active, rightViewerInstance, options) => {
|
const toggleCompareMode = async (active, rightViewerInstance, options) => {
|
||||||
try {
|
|
||||||
console.log(`[useDualMapCompare] 切换对比模式: ${active}`)
|
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
// 前置检查
|
|
||||||
if (!rightViewerInstance) {
|
|
||||||
throw new Error('右侧Viewer未初始化,无法启用对比模式')
|
|
||||||
}
|
|
||||||
|
|
||||||
await enableCompareMode(rightViewerInstance, options)
|
await enableCompareMode(rightViewerInstance, options)
|
||||||
} else {
|
} else {
|
||||||
disableCompareMode()
|
disableCompareMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[useDualMapCompare] 对比模式切换成功: ${active}`)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[useDualMapCompare] 切换对比模式失败:', error)
|
|
||||||
|
|
||||||
// 确保状态回滚
|
|
||||||
isCompareMode.value = !active
|
|
||||||
|
|
||||||
// 向上层传播错误
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清理
|
// 清理
|
||||||
|
|||||||
@ -24,10 +24,7 @@
|
|||||||
|
|
||||||
<!-- 右侧地图(主地图 - 灾后场景) -->
|
<!-- 右侧地图(主地图 - 灾后场景) -->
|
||||||
<div class="situational-awareness__right-map">
|
<div class="situational-awareness__right-map">
|
||||||
<MapViewer
|
<MapViewer @tool-change="handleMapToolChange" />
|
||||||
:active-tool-key="activeToolKey"
|
|
||||||
@tool-change="handleMapToolChange"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -60,7 +57,6 @@
|
|||||||
<LeftPanel
|
<LeftPanel
|
||||||
@start-dispatch="handleStartDispatch"
|
@start-dispatch="handleStartDispatch"
|
||||||
@view-plan="handleViewPlan"
|
@view-plan="handleViewPlan"
|
||||||
@force-preset-toggle="handleForcePresetToggle"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
@ -231,7 +227,7 @@
|
|||||||
* 4. 用户交互事件处理
|
* 4. 用户交互事件处理
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ref, provide, onMounted, onUnmounted, watch } from 'vue'
|
import { ref, provide, onMounted, onUnmounted } from 'vue'
|
||||||
import * as Cesium from 'cesium'
|
import * as Cesium from 'cesium'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
@ -324,9 +320,6 @@ const {
|
|||||||
clearEmergencyResourceMarkers,
|
clearEmergencyResourceMarkers,
|
||||||
addReserveCenterMarkers,
|
addReserveCenterMarkers,
|
||||||
clearReserveCenterMarkers,
|
clearReserveCenterMarkers,
|
||||||
showMarkers,
|
|
||||||
hideMarkers,
|
|
||||||
markerEntities,
|
|
||||||
} = useMapMarkers()
|
} = useMapMarkers()
|
||||||
|
|
||||||
// 3D Tiles 加载
|
// 3D Tiles 加载
|
||||||
@ -344,13 +337,8 @@ const mockDataService = useMockData()
|
|||||||
|
|
||||||
// 范围圈管理
|
// 范围圈管理
|
||||||
const rangeCircleComposable = useRangeCircle()
|
const rangeCircleComposable = useRangeCircle()
|
||||||
const {
|
const { rangeCircleEntity, createOrUpdateRangeCircle, clearRangeCircle } =
|
||||||
rangeCircleEntity,
|
rangeCircleComposable
|
||||||
createOrUpdateRangeCircle,
|
|
||||||
clearRangeCircle,
|
|
||||||
showRangeCircle,
|
|
||||||
hideRangeCircle,
|
|
||||||
} = rangeCircleComposable
|
|
||||||
|
|
||||||
// 路径线管理
|
// 路径线管理
|
||||||
const pathLinesComposable = usePathLines()
|
const pathLinesComposable = usePathLines()
|
||||||
@ -384,18 +372,6 @@ const { showLoading, startDispatch } = useEmergencyDispatch({
|
|||||||
const isLeftPanelCollapsed = ref(false)
|
const isLeftPanelCollapsed = ref(false)
|
||||||
const isRightPanelCollapsed = ref(false)
|
const isRightPanelCollapsed = ref(false)
|
||||||
|
|
||||||
// 标记点和范围圈显示状态
|
|
||||||
const showMarkersAndRange = ref(false)
|
|
||||||
|
|
||||||
// 地图工具激活状态 - 默认激活模型对比
|
|
||||||
const activeToolKey = ref('modelCompare')
|
|
||||||
|
|
||||||
// 工具键常量
|
|
||||||
const COMPARE_TOOL_KEY = 'modelCompare'
|
|
||||||
|
|
||||||
// 对比模式切换锁,防止并发操作
|
|
||||||
const isCompareTogglePending = ref(false)
|
|
||||||
|
|
||||||
// 弹窗状态
|
// 弹窗状态
|
||||||
const showPersonnelDetail = ref(false)
|
const showPersonnelDetail = ref(false)
|
||||||
const showCenterDetail = ref(false)
|
const showCenterDetail = ref(false)
|
||||||
@ -543,117 +519,14 @@ const handleModalStartDispatch = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 统一的对比模式状态管理助手
|
|
||||||
* 职责:
|
|
||||||
* 1. 同步管理 activeToolKey 和 isCompareMode
|
|
||||||
* 2. 提供失败回滚机制
|
|
||||||
* 3. 防止并发操作
|
|
||||||
*
|
|
||||||
* @param {boolean} shouldActivate - 是否激活对比模式
|
|
||||||
* @param {string} source - 调用来源(用于日志追踪)
|
|
||||||
* @returns {Promise<boolean>} 操作是否成功
|
|
||||||
*/
|
|
||||||
const setCompareToolState = async (shouldActivate, source = 'unknown') => {
|
|
||||||
// 1. 并发保护
|
|
||||||
if (isCompareTogglePending.value) {
|
|
||||||
console.warn(`[index.vue] ${source} - 对比模式正在切换中,忽略本次操作`)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCompareMode.value === shouldActivate) {
|
|
||||||
console.log(`[index.vue] ${source} - 对比模式已是目标状态 (${shouldActivate}),无需操作`)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 保存当前状态(用于失败回滚)
|
|
||||||
const prevToolKey = activeToolKey.value
|
|
||||||
const prevCompareMode = isCompareMode.value
|
|
||||||
|
|
||||||
// 3. 设置锁
|
|
||||||
isCompareTogglePending.value = true
|
|
||||||
|
|
||||||
// 4. 乐观更新UI状态(立即响应)
|
|
||||||
activeToolKey.value = shouldActivate ? COMPARE_TOOL_KEY : null
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 5. 执行实际的模式切换
|
|
||||||
console.log(`[index.vue] ${source} - 开始切换对比模式: ${shouldActivate}`)
|
|
||||||
await toggleCompareMode(shouldActivate, mapStore.viewer)
|
|
||||||
|
|
||||||
console.log(`[index.vue] ${source} - 对比模式切换成功`)
|
|
||||||
return true
|
|
||||||
} catch (error) {
|
|
||||||
// 6. 失败回滚
|
|
||||||
console.error(`[index.vue] ${source} - 切换对比模式失败:`, error)
|
|
||||||
|
|
||||||
activeToolKey.value = prevToolKey
|
|
||||||
if (isCompareMode.value !== prevCompareMode) {
|
|
||||||
console.warn(`[index.vue] isCompareMode状态不一致,强制回滚`)
|
|
||||||
isCompareMode.value = prevCompareMode
|
|
||||||
}
|
|
||||||
|
|
||||||
ElMessage.error({
|
|
||||||
message: `切换对比模式失败: ${error.message || '未知错误'}`,
|
|
||||||
duration: 3000,
|
|
||||||
})
|
|
||||||
|
|
||||||
return false
|
|
||||||
} finally {
|
|
||||||
// 7. 释放锁
|
|
||||||
isCompareTogglePending.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理快速匹配标题点击事件 - 切换显示/隐藏标记和范围圈
|
|
||||||
*/
|
|
||||||
const handleForcePresetToggle = async () => {
|
|
||||||
console.log('[index.vue] 快速匹配标题点击, 当前状态:', showMarkersAndRange.value ? '已显示' : '已隐藏')
|
|
||||||
|
|
||||||
// 切换显示状态
|
|
||||||
if (!showMarkersAndRange.value) {
|
|
||||||
// 当前隐藏,切换为显示
|
|
||||||
|
|
||||||
// 1. 关闭地图对比模式(使用统一助手)
|
|
||||||
if (isCompareMode.value) {
|
|
||||||
console.log('[index.vue] 快速匹配需要关闭对比模式')
|
|
||||||
const success = await setCompareToolState(false, 'force-preset')
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
// 如果关闭对比模式失败,不继续执行后续操作
|
|
||||||
console.error('[index.vue] 关闭地图对比模式失败,中止快速匹配操作')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('[index.vue] 已关闭地图对比模式')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 显示所有标记和范围圈
|
|
||||||
showAllMarkersAndRange()
|
|
||||||
|
|
||||||
// 3. 调整相机到最佳视角
|
|
||||||
flyToBestViewForMarkers()
|
|
||||||
|
|
||||||
// 更新状态
|
|
||||||
showMarkersAndRange.value = true
|
|
||||||
} else {
|
|
||||||
// 当前显示,切换为隐藏
|
|
||||||
hideAllMarkersAndRange()
|
|
||||||
|
|
||||||
// 更新状态
|
|
||||||
showMarkersAndRange.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理地图工具变化事件
|
* 处理地图工具变化事件
|
||||||
*/
|
*/
|
||||||
const handleMapToolChange = async ({ tool, active }) => {
|
const handleMapToolChange = async ({ tool, active }) => {
|
||||||
console.log(`[index.vue] 地图工具变化: ${tool}, 激活状态: ${active}`)
|
console.log(`地图工具变化: ${tool}, 激活状态: ${active}`)
|
||||||
|
|
||||||
if (tool === COMPARE_TOOL_KEY) {
|
if (tool === 'modelCompare') {
|
||||||
// 模型对比工具: 使用统一助手管理状态
|
try {
|
||||||
const loadingMessage = ElMessage({
|
const loadingMessage = ElMessage({
|
||||||
message: active ? '正在启用模型对比...' : '正在关闭模型对比...',
|
message: active ? '正在启用模型对比...' : '正在关闭模型对比...',
|
||||||
type: 'info',
|
type: 'info',
|
||||||
@ -661,18 +534,17 @@ const handleMapToolChange = async ({ tool, active }) => {
|
|||||||
showClose: false,
|
showClose: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const success = await setCompareToolState(active, 'map-controls')
|
await toggleCompareMode(active, mapStore.viewer)
|
||||||
|
|
||||||
loadingMessage.close()
|
loadingMessage.close()
|
||||||
|
|
||||||
if (success) {
|
|
||||||
ElMessage.success(active ? '模型对比已启用' : '模型对比已关闭')
|
ElMessage.success(active ? '模型对比已启用' : '模型对比已关闭')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('切换模型对比模式失败:', error)
|
||||||
|
ElMessage.error({
|
||||||
|
message: `切换模型对比失败: ${error.message || '未知错误'}`,
|
||||||
|
duration: 3000,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
// 失败消息已在助手函数中处理
|
|
||||||
} else {
|
|
||||||
// 其他工具: 保持原有逻辑
|
|
||||||
activeToolKey.value = active ? tool : null
|
|
||||||
console.log(`[index.vue] 工具 ${tool} ${active ? '激活' : '取消'}`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,103 +569,6 @@ const handleDistanceChange = async (newDistance) => {
|
|||||||
await loadReserveCentersAndPresets(DISASTER_CENTER.lon, DISASTER_CENTER.lat)
|
await loadReserveCentersAndPresets(DISASTER_CENTER.lon, DISASTER_CENTER.lat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示所有标记点和范围圈
|
|
||||||
*/
|
|
||||||
const showAllMarkersAndRange = () => {
|
|
||||||
const viewer = mapStore.viewer
|
|
||||||
if (!viewer) return
|
|
||||||
|
|
||||||
// 1. 显示模拟点位
|
|
||||||
viewer.entities.values.forEach((entity) => {
|
|
||||||
if (entity.properties) {
|
|
||||||
const props = entity.properties
|
|
||||||
if (props.type?.getValue() === 'soldier' ||
|
|
||||||
props.type?.getValue() === 'device' ||
|
|
||||||
props.isPathStartMarker?.getValue()) {
|
|
||||||
entity.show = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 2. 显示接口标记
|
|
||||||
showMarkers()
|
|
||||||
|
|
||||||
// 3. 显示范围圈
|
|
||||||
showRangeCircle()
|
|
||||||
|
|
||||||
console.log('[index.vue] 已显示所有标记点和范围圈')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 隐藏所有标记点和范围圈
|
|
||||||
*/
|
|
||||||
const hideAllMarkersAndRange = () => {
|
|
||||||
const viewer = mapStore.viewer
|
|
||||||
if (!viewer) return
|
|
||||||
|
|
||||||
// 1. 隐藏模拟点位
|
|
||||||
viewer.entities.values.forEach((entity) => {
|
|
||||||
if (entity.properties) {
|
|
||||||
const props = entity.properties
|
|
||||||
if (props.type?.getValue() === 'soldier' ||
|
|
||||||
props.type?.getValue() === 'device' ||
|
|
||||||
props.isPathStartMarker?.getValue()) {
|
|
||||||
entity.show = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 2. 隐藏接口标记
|
|
||||||
hideMarkers()
|
|
||||||
|
|
||||||
// 3. 隐藏范围圈
|
|
||||||
hideRangeCircle()
|
|
||||||
|
|
||||||
console.log('[index.vue] 已隐藏所有标记点和范围圈')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 调整相机到显示范围圈区域
|
|
||||||
* 根据当前搜索半径动态调整视角
|
|
||||||
*/
|
|
||||||
const flyToBestViewForMarkers = () => {
|
|
||||||
const viewer = mapStore.viewer
|
|
||||||
if (!viewer) return
|
|
||||||
|
|
||||||
const { camera } = mapStore.services()
|
|
||||||
|
|
||||||
// 获取当前搜索半径(公里)
|
|
||||||
const radiusKm = disasterData.forcePreset.value.searchRadius
|
|
||||||
const radiusMeters = radiusKm * 1000
|
|
||||||
|
|
||||||
// 范围圈中心点
|
|
||||||
const centerLon = DISASTER_CENTER.lon
|
|
||||||
const centerLat = DISASTER_CENTER.lat
|
|
||||||
|
|
||||||
// 计算范围圈边界的4个点(东西南北)
|
|
||||||
// 1度纬度 ≈ 111km
|
|
||||||
const latOffset = radiusKm / 111.32
|
|
||||||
// 1度经度 ≈ 111km * cos(纬度)
|
|
||||||
const lonOffset = radiusKm / (111.32 * Math.cos(Cesium.Math.toRadians(centerLat)))
|
|
||||||
|
|
||||||
const boundaryPoints = [
|
|
||||||
{ lon: centerLon, lat: centerLat + latOffset }, // 北
|
|
||||||
{ lon: centerLon + lonOffset, lat: centerLat }, // 东
|
|
||||||
{ lon: centerLon, lat: centerLat - latOffset }, // 南
|
|
||||||
{ lon: centerLon - lonOffset, lat: centerLat }, // 西
|
|
||||||
{ lon: centerLon, lat: centerLat }, // 中心
|
|
||||||
]
|
|
||||||
|
|
||||||
// 使用智能聚焦方法飞向范围圈区域
|
|
||||||
camera.fitBoundsWithTrajectory(boundaryPoints, {
|
|
||||||
duration: 2, // 2秒飞行时间
|
|
||||||
padding: 0.1, // 10%边距,确保范围圈完整显示
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log(`[index.vue] 相机已调整到范围圈视角 (半径: ${radiusKm}km)`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====================
|
// ====================
|
||||||
// 数据加载函数
|
// 数据加载函数
|
||||||
// ====================
|
// ====================
|
||||||
@ -879,62 +654,6 @@ const loadReserveCentersAndPresets = async (longitude, latitude) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 统计应急基地与预置点、应急装备、应急物资、应急人员的数量 /snow-ops-platform/yhYjll/statistics
|
|
||||||
*/
|
|
||||||
const loadEmergencyBaseAndPreset = async (longitude, latitude, maxDistance) => {
|
|
||||||
try {
|
|
||||||
const response = await request({
|
|
||||||
url: `/snow-ops-platform/yhYjll/statistics`,
|
|
||||||
method: 'GET',
|
|
||||||
params: {
|
|
||||||
longitude,
|
|
||||||
latitude,
|
|
||||||
maxDistance: disasterData.forcePreset.value.searchRadius,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if (response?.data) {
|
|
||||||
console.log('[index.vue] 应急基地与预置点、应急装备、应急物资、应急人员的数量加载成功:', response.data)
|
|
||||||
} else {
|
|
||||||
console.warn('[index.vue] 应急基地与预置点、应急装备、应急物资、应急人员的数量接口返回数据为空')
|
|
||||||
}
|
|
||||||
return response
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[index.vue] 加载应急基地与预置点、应急装备、应急物资、应急人员的数量失败:', error)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询应急装备和应急物资列表 /snow-ops-platform/yhYjll/listMaterials
|
|
||||||
*/
|
|
||||||
const loadEmergencyEquipmentAndMaterial = async (longitude, latitude) => {
|
|
||||||
try {
|
|
||||||
const response = await request({
|
|
||||||
url: `/snow-ops-platform/yhYjll/listMaterials`,
|
|
||||||
method: 'GET',
|
|
||||||
params: {
|
|
||||||
longitude,
|
|
||||||
latitude,
|
|
||||||
maxDistance: disasterData.forcePreset.value.searchRadius,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if (response?.data) {
|
|
||||||
console.log('[index.vue] 应急装备和应急物资列表加载成功:', response.data)
|
|
||||||
} else {
|
|
||||||
console.warn('[index.vue] 应急装备和应急物资列表接口返回数据为空')
|
|
||||||
}
|
|
||||||
return response
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[index.vue] 查询应急装备和应急物资列表失败:', error)
|
|
||||||
ElMessage.warning({
|
|
||||||
message: '应急装备和应急物资列表数据加载失败',
|
|
||||||
duration: 3000,
|
|
||||||
})
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====================
|
// ====================
|
||||||
// 场景初始化函数
|
// 场景初始化函数
|
||||||
// ====================
|
// ====================
|
||||||
@ -1060,10 +779,6 @@ const initializeScene = async () => {
|
|||||||
// 9. 创建范围圈
|
// 9. 创建范围圈
|
||||||
createOrUpdateRangeCircle(viewer, disasterData.forcePreset.value.searchRadius)
|
createOrUpdateRangeCircle(viewer, disasterData.forcePreset.value.searchRadius)
|
||||||
|
|
||||||
// 默认隐藏范围圈(等待快速匹配激活)
|
|
||||||
hideRangeCircle()
|
|
||||||
console.log('[index.vue] 已隐藏范围圈(等待快速匹配激活)')
|
|
||||||
|
|
||||||
// 10. 额外等待确保地形完全就绪(避免标记悬浮)
|
// 10. 额外等待确保地形完全就绪(避免标记悬浮)
|
||||||
console.log('[index.vue] 等待地形完全就绪...')
|
console.log('[index.vue] 等待地形完全就绪...')
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||||
@ -1095,28 +810,10 @@ const initializeScene = async () => {
|
|||||||
// 触发立即渲染,确保 CLAMP_TO_GROUND 生效
|
// 触发立即渲染,确保 CLAMP_TO_GROUND 生效
|
||||||
viewer.scene.requestRender()
|
viewer.scene.requestRender()
|
||||||
|
|
||||||
// 默认隐藏模拟点位(等待快速匹配点击时显示)
|
|
||||||
viewer.entities.values.forEach((entity) => {
|
|
||||||
if (entity.properties) {
|
|
||||||
const props = entity.properties
|
|
||||||
// 隐藏模拟点位(soldier/device)和路径起点标记
|
|
||||||
if (props.type?.getValue() === 'soldier' ||
|
|
||||||
props.type?.getValue() === 'device' ||
|
|
||||||
props.isPathStartMarker?.getValue()) {
|
|
||||||
entity.show = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
console.log('[index.vue] 已隐藏模拟点位(等待快速匹配激活)')
|
|
||||||
|
|
||||||
// 11. 加载应急资源数据(在地形就绪后)
|
// 11. 加载应急资源数据(在地形就绪后)
|
||||||
console.log('[index.vue] 加载应急资源数据...')
|
console.log('[index.vue] 加载应急资源数据...')
|
||||||
await loadEmergencyResources(DISASTER_CENTER.lon, DISASTER_CENTER.lat)
|
await loadEmergencyResources(DISASTER_CENTER.lon, DISASTER_CENTER.lat)
|
||||||
|
|
||||||
// 默认隐藏接口标记(等待快速匹配激活)
|
|
||||||
hideMarkers()
|
|
||||||
console.log('[index.vue] 已隐藏应急资源标记(等待快速匹配激活)')
|
|
||||||
|
|
||||||
// 12. 加载储备中心和预置点数据
|
// 12. 加载储备中心和预置点数据
|
||||||
console.log('[index.vue] 加载储备中心和预置点数据...')
|
console.log('[index.vue] 加载储备中心和预置点数据...')
|
||||||
await loadReserveCentersAndPresets(DISASTER_CENTER.lon, DISASTER_CENTER.lat)
|
await loadReserveCentersAndPresets(DISASTER_CENTER.lon, DISASTER_CENTER.lat)
|
||||||
@ -1165,18 +862,6 @@ onUnmounted(() => {
|
|||||||
console.log('[index.vue] 资源清理完成')
|
console.log('[index.vue] 资源清理完成')
|
||||||
})
|
})
|
||||||
|
|
||||||
// ====================
|
|
||||||
// 防御性watch - 确保状态始终一致
|
|
||||||
// ====================
|
|
||||||
|
|
||||||
// 作为保险机制,确保即使有新入口直接操作useDualMapCompare,状态也能保持一致
|
|
||||||
watch(isCompareMode, (newValue) => {
|
|
||||||
if (!newValue && activeToolKey.value === COMPARE_TOOL_KEY) {
|
|
||||||
console.warn('[index.vue] 检测到对比模式被外部关闭,同步更新工具状态')
|
|
||||||
activeToolKey.value = null
|
|
||||||
}
|
|
||||||
}, { immediate: false })
|
|
||||||
|
|
||||||
// ====================
|
// ====================
|
||||||
// Provide 给子组件
|
// Provide 给子组件
|
||||||
// ====================
|
// ====================
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user