feat(steady): 完善稳态数据视图功能
- 更新纵坐标刻度算法,优化小数趋势图范围显示 - 添加稳态趋势图全屏模式和共享工具组件 - 实现多图联动的鼠标悬停竖线同步功能 - 调整主线线宽分档策略,降低最大线宽限制 - 重构稳态趋势工具栏,优化谐波次数选择逻辑 - 添加周时间周期搜索支持和自定义时间范围选择 - 完善稳态数据表格和指示器浮动面板功能 - 优化稳态趋势图性能,添加LTB采样和动画控制 - 修复数据表格打开前的趋势数据验证问题 - 统一时间轴标签格式化和网格对齐处理
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<section class="card trend-toolbar">
|
||||
<div class="toolbar-field toolbar-field--time">
|
||||
<span class="toolbar-field__label">时间:</span>
|
||||
<TimePeriodSearch
|
||||
class="trend-toolbar__time"
|
||||
:unit="modelValue.timeUnit"
|
||||
:model-value="modelValue.timeBaseDate"
|
||||
@update:unit="handleTimeUnitChange"
|
||||
@update:model-value="handleTimeBaseDateChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-field">
|
||||
<span class="toolbar-field__label">统计:</span>
|
||||
<el-select
|
||||
:model-value="modelValue.statType"
|
||||
placeholder="选择统计类型"
|
||||
@update:model-value="updateField('statType', $event)"
|
||||
>
|
||||
<el-option v-for="item in statOptions" :key="item" :label="statLabelMap[item]" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-field">
|
||||
<span class="toolbar-field__label">数据质量:</span>
|
||||
<el-switch
|
||||
:model-value="modelValue.qualityFlag ?? 0"
|
||||
class="quality-switch"
|
||||
width="72"
|
||||
inline-prompt
|
||||
active-text="有效"
|
||||
inactive-text="无效"
|
||||
:active-value="0"
|
||||
:inactive-value="1"
|
||||
@update:model-value="handleQualityFlagChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="showHarmonicOrders" class="toolbar-field harmonic-select">
|
||||
<span class="toolbar-field__label">谐波次数:</span>
|
||||
<el-select
|
||||
:model-value="modelValue.harmonicOrders"
|
||||
multiple
|
||||
placeholder="选择谐波次数"
|
||||
@update:model-value="handleHarmonicOrdersChange"
|
||||
>
|
||||
<el-option v-for="item in harmonicOrderOptions" :key="item" :label="`${item}次`" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-actions">
|
||||
<el-button type="primary" :loading="loading" @click="emit('query')">查询</el-button>
|
||||
<el-button @click="emit('reset')">重置</el-button>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ElMessage } from 'element-plus'
|
||||
import type { SteadyTrend } from '@/api/steady/steadyTrend/interface'
|
||||
import TimePeriodSearch from '@/views/components/TimePeriodSearch/index.vue'
|
||||
import { buildTimePeriodRange, type TimePeriodUnit } from '@/views/components/TimePeriodSearch/timePeriod'
|
||||
import { MAX_HARMONIC_ORDER_COUNT } from '../utils/selectionRules'
|
||||
import type { SteadyTrendFormState } from '../utils/trendPayload'
|
||||
|
||||
defineOptions({
|
||||
name: 'SteadyTrendToolbar'
|
||||
})
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: SteadyTrendFormState
|
||||
statOptions: SteadyTrend.SteadyTrendStatType[]
|
||||
showHarmonicOrders: boolean
|
||||
loading: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: SteadyTrendFormState]
|
||||
query: []
|
||||
reset: []
|
||||
}>()
|
||||
|
||||
const harmonicOrderOptions = Array.from({ length: 49 }, (_item, index) => index + 2)
|
||||
const statLabelMap: Record<SteadyTrend.SteadyTrendStatType, string> = {
|
||||
AVG: '平均值',
|
||||
MAX: '最大值',
|
||||
MIN: '最小值',
|
||||
CP95: '95%概率大值'
|
||||
}
|
||||
|
||||
const updateField = <K extends keyof SteadyTrendFormState>(field: K, value: SteadyTrendFormState[K]) => {
|
||||
emit('update:modelValue', {
|
||||
...props.modelValue,
|
||||
[field]: value
|
||||
})
|
||||
}
|
||||
|
||||
const handleQualityFlagChange = (value: string | number | boolean) => {
|
||||
updateField('qualityFlag', Number(value))
|
||||
}
|
||||
|
||||
const normalizeHarmonicOrders = (orders: number[]) => {
|
||||
return Array.from(
|
||||
new Set(
|
||||
orders
|
||||
.map(item => Number(item))
|
||||
.filter(item => Number.isInteger(item) && item >= 2 && item <= 50)
|
||||
)
|
||||
).sort((left, right) => left - right)
|
||||
}
|
||||
|
||||
const updateHarmonicOrders = (orders: number[]) => {
|
||||
const nextOrders = normalizeHarmonicOrders(orders)
|
||||
|
||||
if (nextOrders.length > MAX_HARMONIC_ORDER_COUNT) {
|
||||
ElMessage.warning(`谐波次数最多选择 ${MAX_HARMONIC_ORDER_COUNT} 个`)
|
||||
const currentOrders = normalizeHarmonicOrders(props.modelValue.harmonicOrders)
|
||||
updateField(
|
||||
'harmonicOrders',
|
||||
currentOrders.length ? currentOrders : nextOrders.slice(0, MAX_HARMONIC_ORDER_COUNT)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
updateField('harmonicOrders', nextOrders)
|
||||
}
|
||||
|
||||
const handleHarmonicOrdersChange = (value: number[]) => {
|
||||
updateHarmonicOrders(value)
|
||||
}
|
||||
|
||||
const updateTimeRange = (unit: TimePeriodUnit, baseDate: Date) => {
|
||||
emit('update:modelValue', {
|
||||
...props.modelValue,
|
||||
timeUnit: unit,
|
||||
timeBaseDate: baseDate,
|
||||
timeRange: buildTimePeriodRange(unit, baseDate)
|
||||
})
|
||||
}
|
||||
|
||||
const handleTimeUnitChange = (value: TimePeriodUnit) => {
|
||||
updateTimeRange(value, props.modelValue.timeBaseDate)
|
||||
}
|
||||
|
||||
const handleTimeBaseDateChange = (value: Date) => {
|
||||
updateTimeRange(props.modelValue.timeUnit, value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.trend-toolbar {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(360px, 1.35fr) repeat(3, minmax(0, 1fr)) auto;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.toolbar-field {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.toolbar-field--time {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.toolbar-field__label {
|
||||
flex: 0 0 auto;
|
||||
color: #606266;
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.toolbar-field :deep(.el-select) {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.quality-switch {
|
||||
min-width: 72px;
|
||||
}
|
||||
|
||||
.trend-toolbar__time {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.trend-toolbar__time :deep(.time-period-search__unit) {
|
||||
width: 72px;
|
||||
flex: 0 0 72px;
|
||||
}
|
||||
|
||||
.trend-toolbar__time :deep(.time-period-search__picker) {
|
||||
width: 136px;
|
||||
flex: 0 0 136px;
|
||||
}
|
||||
|
||||
.harmonic-select {
|
||||
grid-column: auto;
|
||||
}
|
||||
|
||||
.toolbar-actions {
|
||||
display: flex;
|
||||
grid-column: 5;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 1280px) {
|
||||
.trend-toolbar {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.toolbar-actions {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user