Files
erqi-web/src/views/business/drone/cockpit.vue
2025-12-26 02:53:44 +08:00

253 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="fh2-container">
<div id="cockpit-header-container"></div>
<div ref="Detail" class="project-details router-cockpit">
<div id="project-app-container"></div>
<div id="project-middle-container"></div>
<div id="project-right-micro-app" class="right-micro-app">
<div class="maps-micro-app">
<div class="cockpit-left-border-container"></div>
<div id="project-map-app-placeholder" class="map-app-placeholder">
<div class="cockpit-dock-live-container"></div>
<div id="map-app-global" class="map-app-container"></div>
<div class="cockpit-bottom-border-container"></div>
</div>
</div>
<div class="project-right">
<div id="cockpit-app-container"></div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed, nextTick, onMounted, ref } from 'vue'
import useMapStore from '@/store/modules/map'
const mapStore = useMapStore()
const Detail = ref(null)
const data = computed(() => mapStore.windowInfo.data)
const ip = '198.16.74.210'
onMounted(() => {
// ******* 接入步骤 4 - START使用组件前初始化配置具体配置参数请按实际替换 *******
if(window.FH2) {
window.FH2.initConfig({
serverUrl: `http://${ip}:30812`,
wssUrl: `ws://${ip}:30812/duplex/web`,
hostUrl: `http://${ip}`,
prjId: '4bd996b8-5201-4e5d-82b1-6879be360c20', // 项目 id按实际传入
projectToken: 'eyJhbGciOiJIUzUxMiIsImNyaXQiOlsidHlwIiwiYWxnIiwia2lkIl0sImtpZCI6IjU3YmQyNmEwLTYyMDktNGE5My1hNjg4LWY4NzUyYmU1ZDE5MSIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50IjoiIiwiZXhwIjoyMDc1OTQ3NzIyLCJuYmYiOjE3NjA0MTQ5MjIsIm9yZ2FuaXphdGlvbl91dWlkIjoiOWRmMjlmYTgtNGI5OS00MThlLWJhMmQtMGY5ZWY5ZWVlMzkyIiwicHJvamVjdF91dWlkIjoiIiwic3ViIjoiZmgyIiwidXNlcl9pZCI6IjE3NjA0MTQxMDkzNTcwMDI0MjkifQ.DC_aS37W2fkqOjCtfvysDfhTn-4XVn3_IrXBnPD9rICGyrIBKBG3oPldeW_pqele5H_gCn1EgM0KXcbDgvq-dw' // 组织密钥,按实际传入
})
// ******* 接入步骤 5 - START加载组件传入航线ID *******
window.FH2.loadCockpit('cockpit-app-container', {
gateway_sn: data.value.gatewaySn, // 网关 sn按实际传入
drone_sn: data.value.droneSn // 飞机 sn按实际传入
})
}
// // 使用轮询方式等待内容加载完成后再滚动
// waitForContentAndScroll()
})
const waitForContentAndScroll = () => {
let attempts = 0
let previousScrollWidth = 0
let stableCount = 0
const maxAttempts = 30
const checkAndScroll = () => {
attempts++
if (Detail.value) {
// 检查目标容器是否已加载内容
const mapContainer = document.getElementById('map-app-global')
// 判断内容是否加载完成
const isContentLoaded = mapContainer && mapContainer.children.length > 0
// console.log('Content loaded:', isContentLoaded, mapContainer)
// 获取当前尺寸
const currentScrollWidth = Detail.value.scrollWidth
const clientWidth = Detail.value.clientWidth
// console.log('Size check:', {
// attempt: attempts,
// scrollWidth: currentScrollWidth,
// clientWidth: clientWidth,
// isContentLoaded: isContentLoaded
// })
// 检查尺寸是否稳定(连续几次尺寸相同)
if (currentScrollWidth === previousScrollWidth && currentScrollWidth > clientWidth) {
stableCount++
} else {
stableCount = 0
}
previousScrollWidth = currentScrollWidth
// 当内容加载完成且尺寸稳定,或者达到最大尝试次数时执行滚动
if (isContentLoaded && stableCount >= 2 && currentScrollWidth > clientWidth ||
attempts >= maxAttempts) {
// 强制重新计算布局
forceLayoutRecalculation(() => {
executeScroll()
})
} else {
// 内容未加载完成或尺寸不稳定,继续等待
setTimeout(checkAndScroll, 300)
}
}
}
// 开始检查
setTimeout(checkAndScroll, 300)
}
const forceLayoutRecalculation = (callback) => {
if (!Detail.value) {
if (callback) {
callback()
}
return
}
// 方法1: 强制重排
Detail.value.style.display = 'none'
void Detail.value.offsetHeight // 强制重排
Detail.value.style.display = 'flex'
// 方法2: 临时修改overflow触发重新计算
const originalOverflow = Detail.value.style.overflow
Detail.value.style.overflow = 'hidden'
void Detail.value.offsetWidth
Detail.value.style.overflow = originalOverflow
setTimeout(() => {
if (callback) {
callback()
}
}, 100)
}
const executeScroll = () => {
if (!Detail.value) {
return
}
// 重新获取准确的尺寸
const scrollWidth = Detail.value.scrollWidth
const clientWidth = Detail.value.clientWidth
const maxScroll = scrollWidth - clientWidth
// console.log('Final size calculation:', {
// scrollWidth,
// clientWidth,
// maxScroll
// })
if (maxScroll > 0) {
const targetPosition = 1388
const scrollPosition = targetPosition > maxScroll ? maxScroll : targetPosition
// 修复:正确处理 scrollPosition 为 0 的情况
const finalPosition = typeof scrollPosition === 'number' ? scrollPosition : 645
// 激活滚动机制后再执行滚动
activateScrollMechanism(() => {
Detail.value.scrollTo({
left: finalPosition,
behavior: 'smooth'
})
// console.log('Scrolled to position:', finalPosition,
// 'Max scroll:', maxScroll,
// 'Container width:', clientWidth,
// 'Scroll width:', scrollWidth)
})
} else {
// console.log('No scrollable content, but content is loaded')
// 即使没有滚动内容,也尝试激活滚动机制
activateScrollMechanism(() => {
Detail.value.scrollTo({
left: 645,
behavior: 'smooth'
})
})
}
}
const activateScrollMechanism = (callback) => {
if (!Detail.value) {
if (callback) {
callback()
}
return
}
// 预激活滚动机制
Detail.value.scrollTo({ left: 1, behavior: 'instant' })
setTimeout(() => {
Detail.value.scrollTo({ left: 0, behavior: 'instant' })
setTimeout(() => {
if (callback) {
callback()
}
}, 50)
}, 20)
}
</script>
<style lang="scss">
.fh2-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
}
#project-app-container>div, #cockpit-app-container>div,
.map-app-container>div {
width: 100%;
height: 100%;
}
.project-details {
position: relative;
width: 100%;
display: flex;
flex: 1;
overflow: scroll;
// &::-webkit-scrollbar {display: none;}
}
.project-details .right-micro-app {
position: relative;
display: flex;
flex: 1;
width: 1388px;
}
.project-details .right-micro-app .maps-micro-app {
display: flex;
flex: 1;
position: relative;
}
.project-details .right-micro-app .map-app-placeholder {
flex: 1;
position: relative;
display: flex;
flex-direction: column;
}
.project-details .right-micro-app .map-app-container {
height: 100%;
width: 100%;
}
</style>
<style>
.cockpit-app-ant-modal-root{
position: relative;
z-index: 9999;
}
.cockpit-app-ant-popover{
z-index: 9999 !important;
}
</style>