feat(waveform): 添加全通道波形数据显示功能

- 实现全通道模式下的波形数据展示
- 添加通道选择器支持全部/单个通道切换
- 新增全通道趋势分组数据结构
- 重构波形数据获取逻辑支持多通道模式
- 更新图表配置支持动态图例显示控制
- 完善波形数据导出功能支持全通道数据
- 优化工具栏界面适配新的通道选择功能
This commit is contained in:
2026-05-06 16:35:48 +08:00
parent bf9f3719a4
commit 407ab0a7f6
4 changed files with 246 additions and 53 deletions

View File

@@ -1,6 +1,5 @@
<template>
<template>
<div class="page-header">
<div class="action-row">
<div class="file-select-row">
<el-input
@@ -31,7 +30,12 @@
placeholder="选择通道"
@update:model-value="handleChannelChange"
>
<el-option v-for="item in channelOptions" :key="item.value" :label="item.label" :value="item.value" />
<el-option
v-for="item in channelOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
@@ -54,7 +58,11 @@
<div class="toolbar-item">
<div class="toolbar-label">数值类型</div>
<el-radio-group :model-value="activeValueMode" class="value-mode-switch" @update:model-value="handleValueModeChange">
<el-radio-group
:model-value="activeValueMode"
class="value-mode-switch"
@update:model-value="handleValueModeChange"
>
<el-radio-button v-for="item in valueModeOptions" :key="item.value" :label="item.value">
{{ item.label }}
</el-radio-button>
@@ -72,14 +80,14 @@
<script setup lang="ts">
import { Download, FolderOpened } from '@element-plus/icons-vue'
import { ref } from 'vue'
import type { DisplayMode, LabelValueOption, ValueMode, WaveformDetailOption } from './types'
import type { ChannelSelectValue, DisplayMode, LabelValueOption, ValueMode, WaveformDetailOption } from './types'
defineProps<{
selectedWaveformFileName: string
isParsing: boolean
waveformFileAccept: string
channelOptions: WaveformDetailOption[]
activeChannelIndex: number
activeChannelIndex: ChannelSelectValue
displayModeOptions: LabelValueOption<DisplayMode>[]
activeDisplayMode: DisplayMode
valueModeOptions: LabelValueOption<ValueMode>[]
@@ -88,7 +96,7 @@ defineProps<{
}>()
const emit = defineEmits<{
'update:activeChannelIndex': [value: number]
'update:activeChannelIndex': [value: ChannelSelectValue]
'update:activeDisplayMode': [value: DisplayMode]
'update:activeValueMode': [value: ValueMode]
'waveform-file-change': [event: Event]
@@ -108,7 +116,7 @@ const handleWaveformFileChange = (event: Event) => {
emit('waveform-file-change', event)
}
const handleChannelChange = (value: number) => {
const handleChannelChange = (value: ChannelSelectValue) => {
emit('update:activeChannelIndex', value)
}
@@ -202,6 +210,4 @@ const handleValueModeChange = (value: string | number | boolean | undefined) =>
max-width: none;
}
}
</style>

View File

@@ -1,4 +1,4 @@
<template>
<template>
<section class="waveform-panel">
<div class="panel-header">
<el-tabs :model-value="activeTrendTab" class="trend-tabs" @update:model-value="handleTrendTabChange">
@@ -7,7 +7,26 @@
</div>
<div class="panel-body">
<div v-if="hasWaveformData && activeDisplayMode === 'multi-channel'" class="chart-container">
<div v-if="hasWaveformData && isAllChannelsActive" class="all-channel-list">
<template v-for="group in allChannelTrendGroups" :key="group.key">
<div v-if="activeDisplayMode === 'multi-channel'" class="all-channel-chart">
<LineChart :options="group.multiChannelOptions" />
</div>
<template v-else>
<div
v-for="item in group.singleChannelOptionsList"
:key="item.key"
class="single-channel-card"
:class="{ 'single-channel-card--with-axis': item.isLastChart }"
>
<div class="single-channel-chart">
<LineChart :options="item.options" :group="item.group" />
</div>
</div>
</template>
</template>
</div>
<div v-else-if="hasWaveformData && activeDisplayMode === 'multi-channel'" class="chart-container">
<LineChart :options="activeTrendOptions" />
</div>
<div v-else-if="hasWaveformData" class="single-channel-list">
@@ -25,7 +44,9 @@
<div v-else class="empty-block">
<div class="empty-title">暂无波形数据</div>
<div class="empty-text">请选择同一组 `.cfg` `.dat` 文件后自动解析并展示</div>
<div v-if="lastParseErrorMessage" class="empty-text error-text">最近一次解析失败{{ lastParseErrorMessage }}</div>
<div v-if="lastParseErrorMessage" class="empty-text error-text">
最近一次解析失败{{ lastParseErrorMessage }}
</div>
</div>
</div>
</section>
@@ -33,15 +54,23 @@
<script setup lang="ts">
import LineChart from '@/components/echarts/line/index.vue'
import type { DisplayMode, LabelValueOption, SingleChannelTrendOption, TrendTabValue } from './types'
import type {
AllChannelTrendGroup,
DisplayMode,
LabelValueOption,
SingleChannelTrendOption,
TrendTabValue
} from './types'
defineProps<{
hasWaveformData: boolean
isAllChannelsActive: boolean
activeDisplayMode: DisplayMode
activeTrendTab: TrendTabValue
trendTabs: LabelValueOption<TrendTabValue>[]
activeTrendOptions: Record<string, unknown>
singleChannelTrendOptionsList: SingleChannelTrendOption[]
allChannelTrendGroups: AllChannelTrendGroup[]
lastParseErrorMessage: string
}>()
@@ -125,6 +154,26 @@ const handleTrendTabChange = (value: string | number) => {
overflow: hidden;
}
.all-channel-list {
display: flex;
flex: 1;
flex-direction: column;
gap: 4px;
min-height: 0;
padding: 8px;
overflow: hidden;
border: 1px solid var(--el-border-color-lighter);
border-radius: 4px;
background: var(--cn-color-canvas-bg);
}
.all-channel-chart {
display: flex;
flex: 1;
min-height: 0;
overflow: hidden;
}
.single-channel-card {
display: flex;
flex: 1;

View File

@@ -1,6 +1,7 @@
export type TrendTabValue = 'instant' | 'rms'
export type TrendTabValue = 'instant' | 'rms'
export type ValueMode = 'primary' | 'secondary'
export type DisplayMode = 'single-channel' | 'multi-channel'
export type ChannelSelectValue = number | 'all'
export interface LabelValueOption<T extends string | number = string | number> {
label: string
@@ -9,7 +10,7 @@ export interface LabelValueOption<T extends string | number = string | number> {
export interface WaveformDetailOption {
label: string
value: number
value: ChannelSelectValue
}
export interface SingleChannelTrendOption {
@@ -19,6 +20,13 @@ export interface SingleChannelTrendOption {
options: Record<string, unknown>
}
export interface AllChannelTrendGroup {
key: string
title: string
singleChannelOptionsList: SingleChannelTrendOption[]
multiChannelOptions: Record<string, unknown>
}
export interface SummaryItem {
label: string
value: string | number