Explorar o código

3d:实时趋势图 dataZoom 锁定 y 轴量程、刷新时重算;扩展区外层圆角+裁剪溢出(内层滚动)

18922397810 hai 2 semanas
pai
achega
e598e45fed

+ 4 - 2
3d/frontend/src/App.vue

@@ -83,8 +83,10 @@ onBeforeUnmount(() => {
       <ViewerCanvas>
         <DataPanel />
         <div class="ext-panel">
-          <PartStatusCard />
-          <AlarmDetailCard />
+          <div class="ext-scroll">
+            <PartStatusCard />
+            <AlarmDetailCard />
+          </div>
         </div>
         <ScenePositionCard v-if="viewerStore.sceneVisible" class="scene-overlay" />
       </ViewerCanvas>

+ 1 - 0
3d/frontend/src/components/AlarmDetailCard.vue

@@ -203,6 +203,7 @@ onBeforeUnmount(stopRealtime)
             :per-series-legend="true"
             :inside-zoom="true"
             :grid-divider="true"
+            :freeze-y="true"
           />
           <div v-if="rtLoading" class="rt-loading">
             <a-spin size="small" />

+ 34 - 2
3d/frontend/src/components/FaultChart.vue

@@ -31,6 +31,7 @@ const props = withDefaults(
     perSeriesLegend?: boolean
     gridHeight?: number
     gridDivider?: boolean
+    freezeY?: boolean
   }>(),
   {
     height: 180,
@@ -45,6 +46,7 @@ const props = withDefaults(
     insideZoom: false,
     perSeriesLegend: false,
     gridDivider: false,
+    freezeY: false,
   },
 )
 
@@ -175,13 +177,15 @@ function buildOption(): Record<string, unknown> {
       splitLine: { show: false },
       axisPointer: { label: { show: false } },
     })
+    const yMin = s.yMin ?? props.yMin
+    const yMax = s.yMax ?? props.yMax
     yAxis.push({
       type: 'value',
       gridIndex: i,
       show: props.showYAxis,
       scale: true,
-      min: s.yMin ?? props.yMin,
-      max: s.yMax ?? props.yMax,
+      ...(yMin != null ? { min: yMin } : {}),
+      ...(yMax != null ? { max: yMax } : {}),
       splitNumber: 4,
       axisLine: { show: false },
       axisTick: { show: false },
@@ -305,9 +309,37 @@ function buildOption(): Record<string, unknown> {
   }
 }
 
+/** dataZoom 时锁定 y 轴:取 echarts 首次自适应出的量程并写回为固定值(下次数据刷新会重算)。 */
+function freezeYAxis(): void {
+  if (!chart) return
+  const model = (chart as unknown as { getModel?: () => unknown }).getModel?.() as
+    | { getComponent?: (type: string, index: number) => unknown }
+    | undefined
+  if (!model?.getComponent) return
+  const patch = props.series.map((s, i) => {
+    if (s.yMin != null || s.yMax != null) return {}
+    try {
+      const axis = model.getComponent?.('yAxis', i) as
+        | { axis?: { scale?: { getExtent?: () => [number, number] } } }
+        | undefined
+      const extent = axis?.axis?.scale?.getExtent?.()
+      if (!extent || extent.length < 2) return {}
+      const [min, max] = extent
+      if (!Number.isFinite(min) || !Number.isFinite(max) || min === max) return {}
+      return { min, max }
+    } catch {
+      return {}
+    }
+  })
+  if (patch.some((item) => Object.keys(item).length)) {
+    chart.setOption({ yAxis: patch } as unknown as echarts.EChartsOption)
+  }
+}
+
 function render(): void {
   if (!chart) return
   chart.setOption(buildOption() as unknown as echarts.EChartsOption, { notMerge: true })
+  if (props.freezeY) freezeYAxis()
 }
 
 onMounted(() => {

+ 11 - 4
3d/frontend/src/styles/index.css

@@ -29,27 +29,34 @@ body {
   -webkit-backdrop-filter: blur(6px);
 }
 
-/* 右侧扩展区域 */
+/* 右侧扩展区域:外层圆角与卡片一致并裁剪溢出,内层负责滚动(隐藏滚动条) */
 .ext-panel {
   position: absolute;
   right: 20px;
   top: 20px;
   bottom: 20px;
   width: 300px;
+  border-radius: 10px;
+  overflow: hidden;
+  pointer-events: none;
+  z-index: 8;
+}
+.ext-scroll {
+  height: 100%;
   display: flex;
   flex-direction: column;
   gap: 12px;
   overflow-y: auto;
+  overflow-x: hidden;
   scrollbar-width: none;
   -ms-overflow-style: none;
   pointer-events: none;
-  z-index: 8;
 }
-.ext-panel::-webkit-scrollbar {
+.ext-scroll::-webkit-scrollbar {
   width: 0;
   height: 0;
 }
-.ext-panel > * {
+.ext-scroll > * {
   pointer-events: auto;
   flex: 0 0 auto;
 }