提交 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 @@
-->
<!doctype html>
<html lang="en">
<head>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link
rel="stylesheet"
href="https://unpkg.com/element-plus/dist/index.css"
/>
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>UE大屏项目</title>
<script>
......@@ -50,19 +48,19 @@
window.receiveLoginInfo(data);
};
</script> -->
</head>
</head>
<body>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
<style>
</body>
<style>
body,
#app {
/* background-color: transparent !important; */
/* background-color: #000000 !important; */
}
</style>
<script>
</style>
<script>
function setRem() {
const baseSize = 16; // 基准
const designWidth = 1920; // 设计稿宽度(你项目很可能是1920大屏)
......@@ -75,5 +73,6 @@
setRem();
window.addEventListener("resize", setRem);
</script>
</script>
</html>
\ No newline at end of file
......@@ -16,6 +16,13 @@ export function stellationInfoApi() {
method: "get",
});
}
//时间
export function timeInfoApi() {
return request({
url: "/time/time",
method: "get",
});
}
// 左侧菜单-卫星列表信息
export function stellateListInfoApi() {
return request({
......
<template>
<div class="dashboard-container">
<!-- 顶部导航栏 -->
<header class="dashboard-header">
......@@ -633,12 +632,6 @@ const calculateConfig = (selectedTemplate = currentSettingConfig.value) => {
z-index: 1001;
overflow: hidden;
}
/* 头部样式 */
......@@ -781,7 +774,6 @@ const calculateConfig = (selectedTemplate = currentSettingConfig.value) => {
border-radius: 8px;
padding: 5px 15px;
}
.equipment-content {
height: 600px;
}
......
......@@ -143,8 +143,6 @@
<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">
<template #default="scope">
<!-- {{typeof scope.row.station }} -->
<div v-if="scope.row.station.length !== 0">
<div v-for="(items, index) in scope.row.station" :key="index">
<div
......@@ -750,20 +748,16 @@ const leftGetAllListInfo = () => {
});
});
satelliteData.value = primitiveSatelliteData.value
// //console.log("4545",primitiveSatelliteData.value ,primitiveSatelliteData.value.length);
})
siteDataInfoListApi().then(res => {
// //console.log(res,"sasa1111111sasa");
equipmentData.value = transformgroudSatelliteData(res.data)
primitiveEquipmentData.value = equipmentData.value
// groundSatelliteData.value = primitiveGroundSatelliteData.value
})
groundSystemStatisticsInfoApi().then(res => {
//console.log(res.data, "s************a");
groundMetrics.value = transformGroundSatelliteData(res.data)
// //console.log(groundMetrics.value,"56555555555555")
})
};
......@@ -834,7 +828,7 @@ const errorDeviceListDetailsDialog = ref([])
const tempCount = ref(0)
watch(() => useAppStoreInstance.globalLeftWssCONTINE, val => {
// console.log("useAppStoreInstance.globalLeftWssCONTINE 60一次推过来", val);
console.log("useAppStoreInstance.globalLeftWssCONTINE 60一次推过来", val);
const JSONdata = val
// console.log("useAppStoreInstance.globalLeftWssCONTINE", JSONdata,(JSONdata.type === 'history' && !(JSONdata?.isLagrangeInterpolation === true) ),JSONdata.type === 'realtime');
if (JSONdata.type === 'history') {
......@@ -913,7 +907,6 @@ watch(() => useAppStoreInstance.globalLeftWssCONTINE, val => {
sensitivity: 'base' // 忽略大小写和重音符号
});
});
//console.log("cao cao2,", primitiveSatelliteData.value,);
satelliteData.value = primitiveSatelliteData.value
primitiveEquipmentData.value = equipmentData.value
......@@ -921,27 +914,27 @@ watch(() => useAppStoreInstance.globalLeftWssCONTINE, val => {
// 地面数据,上层数据
// groundMetrics.value = wssTransformGroundSatelliteData(JSONdata.groundSystem)
groundMetrics.value = wssTransformGroundSatelliteData(JSONdata.groundSystem)
// 地面数据,下层数据
// primitiveFaultData.value = []
// primitiveFaultData.value = wssTransformgroudSatelliteData(JSONdata.deviceFaultCondition)
// faultData.value = primitiveFaultData.value
// //console.log("此时的fault", primitiveFaultData.value);
// if (searchEquipmentValue.value !== '') {
// searchEquipmentList()
// }
primitiveFaultData.value = []
primitiveFaultData.value = wssTransformgroudSatelliteData(JSONdata.deviceFaultCondition)
faultData.value = primitiveFaultData.value
//console.log("此时的fault", primitiveFaultData.value);
if (searchEquipmentValue.value !== '') {
searchEquipmentList()
}
// primitiveEquipmentData.value = []
// primitiveEquipmentData.value = wssTransformgroudSatelliteData(JSONdata.groundStationDeviceCount)
// //console.log("此时的equipment", primitiveEquipmentData.value);
primitiveEquipmentData.value = []
primitiveEquipmentData.value = wssTransformgroudSatelliteData(JSONdata.groundStationDeviceCount)
//console.log("此时的equipment", primitiveEquipmentData.value);
// equipmentData.value = primitiveEquipmentData.value
// if (searchEquipmentValue.value !== '') {
// searchEquipmentList()
// }
equipmentData.value = primitiveEquipmentData.value
if (searchEquipmentValue.value !== '') {
searchEquipmentList()
}
}
tempCount.value++
......@@ -974,7 +967,7 @@ onUnmounted(() => {
gap: 20px;
overflow-y: auto;
background-color: #010102;
/* background-color: rgba(0, 0, 0, 0.2); */
}
/* 顶部容器 */
......@@ -1505,7 +1498,7 @@ onUnmounted(() => {
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: 20px;
......
......@@ -37,10 +37,10 @@ const props = defineProps({
watch(() => props.propsDate, (newVal, oldVal) => {
if (newVal?.isFirstSearch) {
if (newVal.dataX.length === 0 || newVal.dataY.length === 0) {
ElMessage({
message: `${props.propsDate.chartName || 'CDF Curve'}该时间段数据为空,请检查数据`,
type: 'warning'
})
// ElMessage({
// message: `${props.propsDate.chartName || 'CDF Curve'}该时间段数据为空,请检查数据`,
// type: 'warning'
// })
return;
}
changeCharte(props.idName, props.propsDate);
......
......@@ -35,7 +35,7 @@ const useAppStore = defineStore("app", {
islegendShow: true,
isSourceLegendShow: true,
isdataPanelShow: true,
issatelliteOrbitShow: true,
issatelliteOrbitShow: false,
issatelliteBeamShow: true,
iscontrolPanelShow: true,
......
......@@ -3,10 +3,10 @@
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
/* color-scheme: light dark; */
/* color: rgba(255, 255, 255, 0.87); */
/* background-color: #242424; */
background-color: transparent !important;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
......@@ -18,6 +18,7 @@ a {
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
......@@ -46,9 +47,11 @@ button {
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
......@@ -61,7 +64,7 @@ button:focus-visible {
#app {
/* width: 100%; */
/* max-width: 1280px; */
margin: 0 ;
margin: 0;
padding: 0;
/* text-align: center; */
}
......@@ -71,9 +74,11 @@ button:focus-visible {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论