Files
CN_Tool_client/frontend/src/views/steady/steadyTrend/components/SteadyTrendFullscreen.vue
yexb 055e69fff7 feat(steady): 完善稳态数据视图功能
- 更新纵坐标刻度算法,优化小数趋势图范围显示
- 添加稳态趋势图全屏模式和共享工具组件
- 实现多图联动的鼠标悬停竖线同步功能
- 调整主线线宽分档策略,降低最大线宽限制
- 重构稳态趋势工具栏,优化谐波次数选择逻辑
- 添加周时间周期搜索支持和自定义时间范围选择
- 完善稳态数据表格和指示器浮动面板功能
- 优化稳态趋势图性能,添加LTB采样和动画控制
- 修复数据表格打开前的趋势数据验证问题
- 统一时间轴标签格式化和网格对齐处理
2026-05-27 08:06:12 +08:00

201 lines
5.8 KiB
Vue

<template>
<Teleport to="body">
<div v-if="modelValue" class="steady-trend-fullscreen">
<header class="steady-trend-fullscreen__header">
<span class="steady-trend-fullscreen__title">趋势图全屏展示</span>
<el-button class="steady-trend-fullscreen__close" :icon="Close" text circle @click="closeFullscreen" />
</header>
<main class="steady-trend-fullscreen__body">
<div class="steady-trend-fullscreen__tool-row">
<SteadyTrendChartTools
class="steady-trend-fullscreen__tools"
:tool-groups="toolGroups"
:is-tool-active="isToolActive"
:is-tool-disabled="isToolDisabled"
:get-tool-tooltip="getToolTooltip"
@tool-action="emit('tool-action', $event)"
/>
</div>
<div
v-if="chartGroups.length"
class="steady-trend-fullscreen__chart-list"
:style="{ '--steady-trend-visible-chart-count': visibleChartCount }"
>
<div v-for="group in chartGroups" :key="group.key" class="steady-trend-fullscreen__chart-group">
<div class="steady-trend-fullscreen__chart-body">
<SteadyTrendChartRenderer
:group="group"
:zoom-range="zoomRange"
:active-tool="activeTool"
:wheel-zoom-enabled="wheelZoomEnabled"
:y-zoom-scale="yZoomScale"
:show-time-axis="chartGroups.indexOf(group) === chartGroups.length - 1"
@chart-data-zoom="handleChartDataZoom"
/>
</div>
</div>
</div>
<el-empty v-else class="steady-trend-fullscreen__empty" description="请选择监测点和指标后查询趋势" />
</main>
</div>
</Teleport>
</template>
<script setup lang="ts">
import { Close } from '@element-plus/icons-vue'
import { onBeforeUnmount, onMounted } from 'vue'
import type { SteadyTrendToolAction, SteadyTrendToolGroup, SteadyTrendToolItem } from './chartTools'
import SteadyTrendChartTools from './SteadyTrendChartTools.vue'
import SteadyTrendChartRenderer from './SteadyTrendChartRenderer.vue'
import type { SteadyTrendActiveTool, SteadyTrendChartGroup, SteadyTrendZoomRange } from '../utils/trendOptions'
defineOptions({
name: 'SteadyTrendFullscreen'
})
const props = defineProps<{
modelValue: boolean
chartGroups: SteadyTrendChartGroup[]
visibleChartCount: number
toolGroups: SteadyTrendToolGroup[]
zoomRange: SteadyTrendZoomRange
activeTool: SteadyTrendActiveTool
wheelZoomEnabled: boolean
yZoomScale: number
isToolActive: (action: SteadyTrendToolAction) => boolean
isToolDisabled: (action: SteadyTrendToolAction) => boolean
getToolTooltip: (item: SteadyTrendToolItem) => string
}>()
const emit = defineEmits<{
'update:modelValue': [value: boolean]
'chart-data-zoom': [value: SteadyTrendZoomRange]
'tool-action': [action: SteadyTrendToolAction]
}>()
const closeFullscreen = () => {
emit('update:modelValue', false)
}
const handleKeydown = (event: KeyboardEvent) => {
if (!props.modelValue || event.key !== 'Escape') return
closeFullscreen()
}
const handleChartDataZoom = (value: SteadyTrendZoomRange) => {
emit('chart-data-zoom', value)
}
onMounted(() => {
window.addEventListener('keydown', handleKeydown)
})
onBeforeUnmount(() => {
window.removeEventListener('keydown', handleKeydown)
})
</script>
<style scoped lang="scss">
.steady-trend-fullscreen {
position: fixed;
inset: 0;
z-index: 3000;
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
overflow: hidden;
background: var(--el-bg-color);
}
.steady-trend-fullscreen__header {
display: flex;
flex: none;
align-items: center;
justify-content: space-between;
height: 44px;
padding: 0 10px;
color: #ffffff;
background: var(--el-color-primary);
}
.steady-trend-fullscreen__title {
min-width: 0;
overflow: hidden;
font-size: 16px;
font-weight: 600;
text-overflow: ellipsis;
white-space: nowrap;
}
.steady-trend-fullscreen__close {
flex: none;
color: #ffffff;
}
.steady-trend-fullscreen__body {
--steady-trend-chart-gap: 8px;
--steady-trend-visible-chart-count: 6;
display: flex;
flex: 1 1 auto;
flex-direction: column;
gap: 8px;
min-height: 0;
padding: 12px;
overflow: hidden;
}
.steady-trend-fullscreen__tool-row {
position: static;
display: flex;
flex: none;
align-items: center;
justify-content: flex-start;
min-width: 0;
}
.steady-trend-fullscreen__tools {
flex: 0 1 auto;
min-width: 0;
}
.steady-trend-fullscreen__chart-list {
display: flex;
flex: 1 1 auto;
flex-direction: column;
gap: var(--steady-trend-chart-gap);
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
}
.steady-trend-fullscreen__chart-group {
box-sizing: border-box;
display: flex;
flex: 0 0
calc(
(100% - var(--steady-trend-chart-gap) * (var(--steady-trend-visible-chart-count) - 1)) /
var(--steady-trend-visible-chart-count)
);
flex-direction: column;
min-height: 0;
overflow: hidden;
border: 1px solid var(--el-border-color-lighter);
border-radius: 4px;
background: var(--cn-color-canvas-bg);
}
.steady-trend-fullscreen__chart-body {
flex: 1;
min-height: 0;
padding: 0 8px 8px;
}
.steady-trend-fullscreen__empty {
flex: 1;
}
</style>