提交 da6185af authored 作者: 周欢凯's avatar 周欢凯

4-1号提交,4-1bug解决还剩余实时播放时间轴固定24h,起止时间都变化

上级 979b21eb
## 2026-03-31 日志
### 用户问题解答
- 解释了 `isChange_flag_firstBackDate` 字段的作用:这是一个时间轴和 WebSocket 数据流同步的状态标志
- 字段含义:首次返回数据变化标志
- 用途:协调用户时间选择和数据更新的时序,防止竞态条件
- 工作机制:拖动时间轴时设为 false,WebSocket 返回数据时设为 true,只有当为 true 时才允许根据时间变化更新子系统数据
- 解释了 `selectedEndTime` 监听的作用:
- 时间驱动的数据分发中心,连接用户操作、WebSocket 数据流、UE 场景和子系统图表
- 主要功能:更新子系统数据、通知 UE 场景、控制自动播放、同步全局状态
- 分析了 `callBackCycleTimePointFn` 一秒发两次的问题:
- 原因:`selectedEndTime` 在短时间内被更新两次,可能是自动播放逻辑中的双重更新
- 解决方案:添加防抖/节流控制,确保一秒内只发送一次
- 查找了 `gridInfoList` 的更新位置:
- 主要更新位置:`header/index.vue` 中的 `getGridInfoListData()` 函数
- 触发时机:页面加载时 (`onMounted`) 获取一次
- 数据用途:热力图组件中合并和显示卫星格网数据
- 查找了 `satelliteData` 通过 WS 赋值的流程:
- 数据流:WebSocket → footer/timers.vue → Pinia Store → lefts/index.vue 监听器 → satelliteData
- 关键赋值位置:lefts/index.vue 第858行(历史模式)和第914行(实时模式)
- 转换函数:`wssTransformSatelliteData()` 将后端数据转换为前端表格格式
- 查找了设置开始时间和结束时间的代码位置:
- 主要设置函数:`handleDateRangeChange()`(用户选择日期范围)
- 核心计算函数:`updateSelectedTimes()`(根据滑块百分比计算选中时间)
- 时间变量:`startDateTime`/`endDateTime`(总范围),`selectedStartTime`/`selectedEndTime`(选中范围)
- 数据流向:用户选择 → 更新 store → 计算选中时间 → 触发监听更新界面
### 之前的 CSS 修复
- 修复了 `screenConfigeDialog.vue` 中的背景图语法错误
- 修正了 `index.vue` 中 el-dialog 的背景色和宽度设置
- 解决了 WebUI 页面透明问题(UE 地球场景透出)
- 修复了时间轴固定时间被覆盖的 Bug:
- 根本原因:`footer/component/timers.vue` 第756行有一个 `setInterval`(每1秒执行),启动时立刻调用 `autoHandleDateRangeChange`,强制将时间重置为"当前时间往前推24小时"
- 修复方案:注释掉该初始 `setInterval`(保留 `watch` 里受 `isDateRangeNotEmpty` 控制的部分)
- 同时修复了 `updateTimeline()``endHandlePercent.value = 0` 的 Bug,改为 `100`
- 修复了时间轴刻度标签多显示1天的 Bug:
- 根本原因:`timeMarkers` 计算中每个 label 都多加了 `.add(1, 'day')`
- 修复方案:去掉 label 生成时的 `.add(1, 'day')`
### 关键发现
- 项目时间轴组件使用 WebSocket 与后端通信,数据流同步机制较为复杂
- `isChange_flag_firstBackDate` 是实现数据时序控制的核心标志之一
- 项目有复杂的 UE 和 WebUI 集成机制,涉及时间同步和数据分发
- 左侧卫星数据表格通过 WebSocket 实时更新,数据流经过多个组件传递
- **时间轴有自动实时滚动机制**:通过 `autoUpdateDateRange` setInterval 每秒更新一次,正常模式下应注释掉初始定时器,用 `isDateRangeNotEmpty` watch 控制实时/历史模式切换
\ No newline at end of file
# 项目核心记忆
## 时间轴和 WebSocket 数据流同步
- `isChange_flag_firstBackDate`:首次返回数据变化标志,用于协调时间轴选择和 WebSocket 数据更新的时序
- 当用户拖动时间轴时重置为 false
- WebSocket 返回新数据时设为 true
- 只有为 true 时,selectedEndTime 变化才会触发子系统数据更新
- 解决"先改时间还是先等数据"的竞态条件
## WebUI 嵌入 UE 的透明问题
- 页面透明:由于多个层级(body、#app、el-dialog、容器)的背景色设置不当导致 UE 场景透出
- Element Plus 的 el-container/el-header 等组件默认没有背景色
- 修复方案:统一设置各层级的背景色或背景图片,确保完全覆盖
## CSS 背景图常见错误
- `background-image` 只接受图片地址,不能包含 no-repeat、center 等参数
- 正确的做法是用 `background` 简写属性:`background: url(...) no-repeat center center / cover`
- 或者分开写:`background-image` + `background-repeat` + `background-position` + `background-size`
## 项目结构特点
- 使用 Vue 3 + Element Plus + Vite
- 时间轴组件在 footer2/timers.vue 和 footer/component/timers.vue
- WebSocket 用于实时数据获取和子系统状态更新
- 卫星数据可视化项目,包含多个图表组件(热力图、曲线图等)
## UE 与 WebUI 集成
- WebUI 嵌入 UE 需要处理渲染层级和光照影响
- 建议使用 Unlit 材质或调整材质 Emissive 值来避免 UE 灯光影响 WebUI 显示
\ No newline at end of file
File added
...@@ -8,13 +8,11 @@ ...@@ -8,13 +8,11 @@
--> -->
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head>
<head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css" />
rel="stylesheet"
href="https://unpkg.com/element-plus/dist/index.css"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>UE大屏项目</title> <title>UE大屏项目</title>
<script> <script>
...@@ -50,19 +48,19 @@ ...@@ -50,19 +48,19 @@
window.receiveLoginInfo(data); window.receiveLoginInfo(data);
}; };
</script> --> </script> -->
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.js"></script>
</body> </body>
<style> <style>
body, body,
#app { #app {
/* background-color: transparent !important; */ /* background-color: #000000 !important; */
} }
</style> </style>
<script> <script>
function setRem() { function setRem() {
const baseSize = 16; // 基准 const baseSize = 16; // 基准
const designWidth = 1920; // 设计稿宽度(你项目很可能是1920大屏) const designWidth = 1920; // 设计稿宽度(你项目很可能是1920大屏)
...@@ -75,5 +73,6 @@ ...@@ -75,5 +73,6 @@
setRem(); setRem();
window.addEventListener("resize", setRem); window.addEventListener("resize", setRem);
</script> </script>
</html> </html>
\ No newline at end of file
...@@ -16,6 +16,13 @@ export function stellationInfoApi() { ...@@ -16,6 +16,13 @@ export function stellationInfoApi() {
method: "get", method: "get",
}); });
} }
//时间
export function timeInfoApi() {
return request({
url: "/time/time",
method: "get",
});
}
// 左侧菜单-卫星列表信息 // 左侧菜单-卫星列表信息
export function stellateListInfoApi() { export function stellateListInfoApi() {
return request({ return request({
......
<template> <template>
<div class="dashboard-container"> <div class="dashboard-container">
<!-- 顶部导航栏 --> <!-- 顶部导航栏 -->
<header class="dashboard-header"> <header class="dashboard-header">
...@@ -633,12 +632,6 @@ const calculateConfig = (selectedTemplate = currentSettingConfig.value) => { ...@@ -633,12 +632,6 @@ const calculateConfig = (selectedTemplate = currentSettingConfig.value) => {
z-index: 1001; z-index: 1001;
overflow: hidden; overflow: hidden;
} }
/* 头部样式 */ /* 头部样式 */
...@@ -781,7 +774,6 @@ const calculateConfig = (selectedTemplate = currentSettingConfig.value) => { ...@@ -781,7 +774,6 @@ const calculateConfig = (selectedTemplate = currentSettingConfig.value) => {
border-radius: 8px; border-radius: 8px;
padding: 5px 15px; padding: 5px 15px;
} }
.equipment-content { .equipment-content {
height: 600px; height: 600px;
} }
......
...@@ -143,8 +143,6 @@ ...@@ -143,8 +143,6 @@
<el-table-column prop="name" label="卫星名称":width="pxScale(80)" align="center"></el-table-column> <el-table-column prop="name" label="卫星名称":width="pxScale(80)" align="center"></el-table-column>
<el-table-column prop="station" label="当前连接" :width="pxScale(80)" align="center"> <el-table-column prop="station" label="当前连接" :width="pxScale(80)" align="center">
<template #default="scope"> <template #default="scope">
<!-- {{typeof scope.row.station }} -->
<div v-if="scope.row.station.length !== 0"> <div v-if="scope.row.station.length !== 0">
<div v-for="(items, index) in scope.row.station" :key="index"> <div v-for="(items, index) in scope.row.station" :key="index">
<div <div
...@@ -750,20 +748,16 @@ const leftGetAllListInfo = () => { ...@@ -750,20 +748,16 @@ const leftGetAllListInfo = () => {
}); });
}); });
satelliteData.value = primitiveSatelliteData.value satelliteData.value = primitiveSatelliteData.value
// //console.log("4545",primitiveSatelliteData.value ,primitiveSatelliteData.value.length);
}) })
siteDataInfoListApi().then(res => { siteDataInfoListApi().then(res => {
// //console.log(res,"sasa1111111sasa"); // //console.log(res,"sasa1111111sasa");
equipmentData.value = transformgroudSatelliteData(res.data) equipmentData.value = transformgroudSatelliteData(res.data)
primitiveEquipmentData.value = equipmentData.value primitiveEquipmentData.value = equipmentData.value
// groundSatelliteData.value = primitiveGroundSatelliteData.value
}) })
groundSystemStatisticsInfoApi().then(res => { groundSystemStatisticsInfoApi().then(res => {
//console.log(res.data, "s************a"); //console.log(res.data, "s************a");
groundMetrics.value = transformGroundSatelliteData(res.data) groundMetrics.value = transformGroundSatelliteData(res.data)
// //console.log(groundMetrics.value,"56555555555555")
}) })
}; };
...@@ -834,7 +828,7 @@ const errorDeviceListDetailsDialog = ref([]) ...@@ -834,7 +828,7 @@ const errorDeviceListDetailsDialog = ref([])
const tempCount = ref(0) const tempCount = ref(0)
watch(() => useAppStoreInstance.globalLeftWssCONTINE, val => { watch(() => useAppStoreInstance.globalLeftWssCONTINE, val => {
// console.log("useAppStoreInstance.globalLeftWssCONTINE 60一次推过来", val); console.log("useAppStoreInstance.globalLeftWssCONTINE 60一次推过来", val);
const JSONdata = val const JSONdata = val
// console.log("useAppStoreInstance.globalLeftWssCONTINE", JSONdata,(JSONdata.type === 'history' && !(JSONdata?.isLagrangeInterpolation === true) ),JSONdata.type === 'realtime'); // console.log("useAppStoreInstance.globalLeftWssCONTINE", JSONdata,(JSONdata.type === 'history' && !(JSONdata?.isLagrangeInterpolation === true) ),JSONdata.type === 'realtime');
if (JSONdata.type === 'history') { if (JSONdata.type === 'history') {
...@@ -913,7 +907,6 @@ watch(() => useAppStoreInstance.globalLeftWssCONTINE, val => { ...@@ -913,7 +907,6 @@ watch(() => useAppStoreInstance.globalLeftWssCONTINE, val => {
sensitivity: 'base' // 忽略大小写和重音符号 sensitivity: 'base' // 忽略大小写和重音符号
}); });
}); });
//console.log("cao cao2,", primitiveSatelliteData.value,);
satelliteData.value = primitiveSatelliteData.value satelliteData.value = primitiveSatelliteData.value
primitiveEquipmentData.value = equipmentData.value primitiveEquipmentData.value = equipmentData.value
...@@ -921,27 +914,27 @@ watch(() => useAppStoreInstance.globalLeftWssCONTINE, val => { ...@@ -921,27 +914,27 @@ watch(() => useAppStoreInstance.globalLeftWssCONTINE, val => {
// 地面数据,上层数据 // 地面数据,上层数据
// groundMetrics.value = wssTransformGroundSatelliteData(JSONdata.groundSystem) groundMetrics.value = wssTransformGroundSatelliteData(JSONdata.groundSystem)
// 地面数据,下层数据 // 地面数据,下层数据
// primitiveFaultData.value = [] primitiveFaultData.value = []
// primitiveFaultData.value = wssTransformgroudSatelliteData(JSONdata.deviceFaultCondition) primitiveFaultData.value = wssTransformgroudSatelliteData(JSONdata.deviceFaultCondition)
// faultData.value = primitiveFaultData.value faultData.value = primitiveFaultData.value
// //console.log("此时的fault", primitiveFaultData.value); //console.log("此时的fault", primitiveFaultData.value);
// if (searchEquipmentValue.value !== '') { if (searchEquipmentValue.value !== '') {
// searchEquipmentList() searchEquipmentList()
// } }
// primitiveEquipmentData.value = [] primitiveEquipmentData.value = []
// primitiveEquipmentData.value = wssTransformgroudSatelliteData(JSONdata.groundStationDeviceCount) primitiveEquipmentData.value = wssTransformgroudSatelliteData(JSONdata.groundStationDeviceCount)
// //console.log("此时的equipment", primitiveEquipmentData.value); //console.log("此时的equipment", primitiveEquipmentData.value);
// equipmentData.value = primitiveEquipmentData.value equipmentData.value = primitiveEquipmentData.value
// if (searchEquipmentValue.value !== '') { if (searchEquipmentValue.value !== '') {
// searchEquipmentList() searchEquipmentList()
// } }
} }
tempCount.value++ tempCount.value++
...@@ -974,7 +967,7 @@ onUnmounted(() => { ...@@ -974,7 +967,7 @@ onUnmounted(() => {
gap: 20px; gap: 20px;
overflow-y: auto; overflow-y: auto;
background-color: #010102; background-color: #010102;
/* background-color: rgba(0, 0, 0, 0.2); */
} }
/* 顶部容器 */ /* 顶部容器 */
...@@ -1505,7 +1498,7 @@ onUnmounted(() => { ...@@ -1505,7 +1498,7 @@ onUnmounted(() => {
transform-origin: top left; transform-origin: top left;
} */ } */
:deep(.i-table-wrapper .el-table__header-wrapper .el-table__header) {} /* :deep(.i-table-wrapper .el-table__header-wrapper .el-table__header) {} */
.margin-top-section { .margin-top-section {
margin-top: 20px; margin-top: 20px;
......
...@@ -37,10 +37,10 @@ const props = defineProps({ ...@@ -37,10 +37,10 @@ const props = defineProps({
watch(() => props.propsDate, (newVal, oldVal) => { watch(() => props.propsDate, (newVal, oldVal) => {
if (newVal?.isFirstSearch) { if (newVal?.isFirstSearch) {
if (newVal.dataX.length === 0 || newVal.dataY.length === 0) { if (newVal.dataX.length === 0 || newVal.dataY.length === 0) {
ElMessage({ // ElMessage({
message: `${props.propsDate.chartName || 'CDF Curve'}该时间段数据为空,请检查数据`, // message: `${props.propsDate.chartName || 'CDF Curve'}该时间段数据为空,请检查数据`,
type: 'warning' // type: 'warning'
}) // })
return; return;
} }
changeCharte(props.idName, props.propsDate); changeCharte(props.idName, props.propsDate);
......
...@@ -35,7 +35,7 @@ const useAppStore = defineStore("app", { ...@@ -35,7 +35,7 @@ const useAppStore = defineStore("app", {
islegendShow: true, islegendShow: true,
isSourceLegendShow: true, isSourceLegendShow: true,
isdataPanelShow: true, isdataPanelShow: true,
issatelliteOrbitShow: true, issatelliteOrbitShow: false,
issatelliteBeamShow: true, issatelliteBeamShow: true,
iscontrolPanelShow: true, iscontrolPanelShow: true,
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
line-height: 1.5; line-height: 1.5;
font-weight: 400; font-weight: 400;
color-scheme: light dark; /* color-scheme: light dark; */
color: rgba(255, 255, 255, 0.87); /* color: rgba(255, 255, 255, 0.87); */
background-color: #242424; /* background-color: #242424; */
background-color: transparent !important;
font-synthesis: none; font-synthesis: none;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
...@@ -18,6 +18,7 @@ a { ...@@ -18,6 +18,7 @@ a {
color: #646cff; color: #646cff;
text-decoration: inherit; text-decoration: inherit;
} }
a:hover { a:hover {
color: #535bf2; color: #535bf2;
} }
...@@ -46,9 +47,11 @@ button { ...@@ -46,9 +47,11 @@ button {
cursor: pointer; cursor: pointer;
transition: border-color 0.25s; transition: border-color 0.25s;
} }
button:hover { button:hover {
border-color: #646cff; border-color: #646cff;
} }
button:focus, button:focus,
button:focus-visible { button:focus-visible {
outline: 4px auto -webkit-focus-ring-color; outline: 4px auto -webkit-focus-ring-color;
...@@ -61,7 +64,7 @@ button:focus-visible { ...@@ -61,7 +64,7 @@ button:focus-visible {
#app { #app {
/* width: 100%; */ /* width: 100%; */
/* max-width: 1280px; */ /* max-width: 1280px; */
margin: 0 ; margin: 0;
padding: 0; padding: 0;
/* text-align: center; */ /* text-align: center; */
} }
...@@ -71,9 +74,11 @@ button:focus-visible { ...@@ -71,9 +74,11 @@ button:focus-visible {
color: #213547; color: #213547;
background-color: #ffffff; background-color: #ffffff;
} }
a:hover { a:hover {
color: #747bff; color: #747bff;
} }
button { button {
background-color: #f9f9f9; background-color: #f9f9f9;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论