refactor(event): 重构事件列表和稳态数据视图组件结构
- 将事件列表页面逻辑拆分为 EventListTable 组件 - 新增 MeasurementPointDialog 和 VoltageToleranceDialog 弹窗组件 - 重构稳态数据视图为主工作台组件 SteadyTrendWorkbench - 移除不再使用的相别参数和相关逻辑 - 更新事件详情工具函数和接口参数映射 - 优化波形查看功能的数据传递方式 - 修正事件描述字段命名和严重程度解析逻辑
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<aside class="indicator-floating-panel" :class="{ 'is-collapsed': collapsed }">
|
||||
<el-button
|
||||
class="indicator-toggle"
|
||||
:icon="collapsed ? ArrowLeft : ArrowRight"
|
||||
circle
|
||||
@click="emit('update:collapsed', !collapsed)"
|
||||
/>
|
||||
<button
|
||||
v-if="collapsed"
|
||||
class="indicator-collapsed-trigger"
|
||||
type="button"
|
||||
@click="emit('update:collapsed', false)"
|
||||
>
|
||||
{{ collapsedLabel }}
|
||||
</button>
|
||||
<div v-show="!collapsed" class="indicator-panel-body">
|
||||
<SteadyIndicatorTree
|
||||
:key="selectorResetKey"
|
||||
:tree-data="treeData"
|
||||
:loading="loading"
|
||||
@refresh="emit('refresh')"
|
||||
@change="emit('change', $event)"
|
||||
/>
|
||||
</div>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
|
||||
import type { SteadyDataView } from '@/api/steady/steadyDataView/interface'
|
||||
import SteadyIndicatorTree from './SteadyIndicatorTree.vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'SteadyIndicatorFloatingPanel'
|
||||
})
|
||||
|
||||
defineProps<{
|
||||
collapsed: boolean
|
||||
treeData: SteadyDataView.SteadyIndicatorNode[]
|
||||
loading: boolean
|
||||
selectorResetKey: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:collapsed': [value: boolean]
|
||||
refresh: []
|
||||
change: [nodes: SteadyDataView.SteadyIndicatorNode[]]
|
||||
}>()
|
||||
|
||||
const collapsedLabel = '\u7a33\u6001\u6307\u6807'
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.indicator-floating-panel {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
bottom: 12px;
|
||||
z-index: 2;
|
||||
width: 360px;
|
||||
transition: width 0.2s ease;
|
||||
}
|
||||
|
||||
.indicator-floating-panel.is-collapsed {
|
||||
width: 44px;
|
||||
}
|
||||
|
||||
.indicator-toggle {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
left: -18px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.indicator-panel-body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.indicator-panel-body :deep(.steady-tree-card) {
|
||||
height: 100%;
|
||||
box-shadow: var(--el-box-shadow-light);
|
||||
}
|
||||
|
||||
.indicator-collapsed-trigger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 8px 0;
|
||||
border: 1px solid var(--el-border-color-light);
|
||||
border-radius: 4px;
|
||||
background: var(--el-bg-color);
|
||||
box-shadow: var(--el-box-shadow-light);
|
||||
color: var(--el-text-color-primary);
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
|
||||
.indicator-collapsed-trigger:hover {
|
||||
border-color: var(--el-color-primary-light-5);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
@media (max-width: 1360px) {
|
||||
.indicator-floating-panel {
|
||||
width: 320px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -67,7 +67,7 @@ const normalizedTreeData = computed(() => {
|
||||
})
|
||||
|
||||
const handleCheck = () => {
|
||||
const checkedNodes = (treeRef.value?.getCheckedNodes(false, true) || []) as SteadyDataView.SteadyIndicatorNode[]
|
||||
const checkedNodes = (treeRef.value?.getCheckedNodes(false, false) || []) as SteadyDataView.SteadyIndicatorNode[]
|
||||
emit('change', collectLeafIndicators(checkedNodes))
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -68,7 +68,7 @@ const handleKeywordChange = (value: string) => {
|
||||
}
|
||||
|
||||
const handleCheck = () => {
|
||||
emit('change', (treeRef.value?.getCheckedNodes(false, true) || []) as SteadyDataView.SteadyLedgerNode[])
|
||||
emit('change', (treeRef.value?.getCheckedNodes(false, false) || []) as SteadyDataView.SteadyLedgerNode[])
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,65 +1,67 @@
|
||||
<template>
|
||||
<section class="card trend-toolbar">
|
||||
<TimePeriodSearch
|
||||
class="trend-toolbar__time"
|
||||
:unit="modelValue.timeUnit"
|
||||
:model-value="modelValue.timeBaseDate"
|
||||
@update:unit="handleTimeUnitChange"
|
||||
@update:model-value="handleTimeBaseDateChange"
|
||||
/>
|
||||
<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>
|
||||
|
||||
<el-select
|
||||
:model-value="modelValue.phases"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
placeholder="选择相别"
|
||||
@update:model-value="updateField('phases', $event)"
|
||||
>
|
||||
<el-option v-for="item in phaseOptions" :key="item" :label="resolvePhaseLabel(item)" :value="item" />
|
||||
</el-select>
|
||||
<div class="toolbar-field">
|
||||
<span class="toolbar-field__label">统计:</span>
|
||||
<el-select
|
||||
:model-value="modelValue.statTypes"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
placeholder="选择统计类型"
|
||||
@update:model-value="updateField('statTypes', $event)"
|
||||
>
|
||||
<el-option v-for="item in statOptions" :key="item" :label="statLabelMap[item]" :value="item" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<el-select
|
||||
:model-value="modelValue.statTypes"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
placeholder="选择统计类型"
|
||||
@update:model-value="updateField('statTypes', $event)"
|
||||
>
|
||||
<el-option v-for="item in statOptions" :key="item" :label="statLabelMap[item]" :value="item" />
|
||||
</el-select>
|
||||
<div class="toolbar-field">
|
||||
<span class="toolbar-field__label">粒度:</span>
|
||||
<el-select
|
||||
:model-value="modelValue.bucket"
|
||||
placeholder="选择时间粒度"
|
||||
@update:model-value="updateField('bucket', $event)"
|
||||
>
|
||||
<el-option v-for="item in bucketOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<el-select
|
||||
:model-value="modelValue.bucket"
|
||||
placeholder="选择时间粒度"
|
||||
@update:model-value="updateField('bucket', $event)"
|
||||
>
|
||||
<el-option v-for="item in bucketOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<div class="toolbar-field">
|
||||
<span class="toolbar-field__label">数据:</span>
|
||||
<el-select
|
||||
:model-value="modelValue.qualityFlag"
|
||||
clearable
|
||||
placeholder="选择数据质量"
|
||||
@update:model-value="updateField('qualityFlag', $event)"
|
||||
>
|
||||
<el-option label="仅有效数据" :value="1" />
|
||||
<el-option label="仅无效数据" :value="0" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<el-select
|
||||
:model-value="modelValue.qualityFlag"
|
||||
clearable
|
||||
placeholder="选择数据质量"
|
||||
@update:model-value="updateField('qualityFlag', $event)"
|
||||
>
|
||||
<el-option label="仅有效数据" :value="1" />
|
||||
<el-option label="仅无效数据" :value="0" />
|
||||
</el-select>
|
||||
|
||||
<el-select
|
||||
v-if="showHarmonicOrders"
|
||||
:model-value="modelValue.harmonicOrders"
|
||||
class="harmonic-select"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
placeholder="选择谐波次数"
|
||||
@update:model-value="updateField('harmonicOrders', $event)"
|
||||
>
|
||||
<el-option v-for="item in harmonicOrderOptions" :key="item" :label="`${item}次`" :value="item" />
|
||||
</el-select>
|
||||
<div v-if="showHarmonicOrders" class="toolbar-field harmonic-select">
|
||||
<span class="toolbar-field__label">谐波次数:</span>
|
||||
<el-select
|
||||
:model-value="modelValue.harmonicOrders"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
placeholder="选择谐波次数"
|
||||
@update:model-value="updateField('harmonicOrders', $event)"
|
||||
>
|
||||
<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>
|
||||
@@ -80,7 +82,6 @@ defineOptions({
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: SteadyTrendFormState
|
||||
phaseOptions: string[]
|
||||
statOptions: SteadyDataView.SteadyTrendStatType[]
|
||||
showHarmonicOrders: boolean
|
||||
loading: boolean
|
||||
@@ -106,14 +107,6 @@ const statLabelMap: Record<SteadyDataView.SteadyTrendStatType, string> = {
|
||||
MIN: '最小值',
|
||||
CP95: '95%概率大值'
|
||||
}
|
||||
const phaseLabelMap: Record<string, string> = {
|
||||
A: 'A相',
|
||||
B: 'B相',
|
||||
C: 'C相',
|
||||
T: '总相'
|
||||
}
|
||||
|
||||
const resolvePhaseLabel = (phase: string) => phaseLabelMap[phase] || `${phase}相`
|
||||
|
||||
const updateField = <K extends keyof SteadyTrendFormState>(field: K, value: SteadyTrendFormState[K]) => {
|
||||
emit('update:modelValue', {
|
||||
@@ -143,13 +136,37 @@ const handleTimeBaseDateChange = (value: Date) => {
|
||||
<style scoped lang="scss">
|
||||
.trend-toolbar {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(260px, 1.3fr) repeat(4, minmax(132px, 0.7fr)) auto;
|
||||
grid-template-columns: minmax(312px, 1.4fr) repeat(3, minmax(178px, 0.8fr)) 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: 312px;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.trend-toolbar__time {
|
||||
flex: 1 1 0;
|
||||
min-width: 260px;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<div class="steady-trend-layout">
|
||||
<aside class="selector-column">
|
||||
<SteadyLedgerTree
|
||||
:key="selectorResetKey"
|
||||
:tree-data="ledgerTree"
|
||||
:loading="loading.ledger"
|
||||
:keyword="ledgerKeyword"
|
||||
@refresh="emit('refreshLedger')"
|
||||
@search="emit('ledgerSearch', $event)"
|
||||
@change="emit('ledgerChange', $event)"
|
||||
/>
|
||||
</aside>
|
||||
|
||||
<main class="trend-main">
|
||||
<SteadyTrendToolbar
|
||||
v-model="trendFormProxy"
|
||||
:stat-options="statOptions"
|
||||
:show-harmonic-orders="showHarmonicOrders"
|
||||
:loading="loading.trend"
|
||||
@query="emit('queryTrend')"
|
||||
@reset="emit('resetTrend')"
|
||||
/>
|
||||
|
||||
<div class="trend-content">
|
||||
<SteadyTrendChartPanel :trend-result="trendResult" :loading="loading.trend" />
|
||||
|
||||
<SteadyIndicatorFloatingPanel
|
||||
v-model:collapsed="indicatorPanelCollapsedProxy"
|
||||
:selector-reset-key="selectorResetKey"
|
||||
:tree-data="indicatorTree"
|
||||
:loading="loading.indicator"
|
||||
@refresh="emit('refreshIndicator')"
|
||||
@change="emit('indicatorChange', $event)"
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { SteadyDataView } from '@/api/steady/steadyDataView/interface'
|
||||
import type { SteadyTrendFormState } from '../utils/trendPayload'
|
||||
import SteadyIndicatorFloatingPanel from './SteadyIndicatorFloatingPanel.vue'
|
||||
import SteadyLedgerTree from './SteadyLedgerTree.vue'
|
||||
import SteadyTrendChartPanel from './SteadyTrendChartPanel.vue'
|
||||
import SteadyTrendToolbar from './SteadyTrendToolbar.vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'SteadyTrendWorkbench'
|
||||
})
|
||||
|
||||
const props = defineProps<{
|
||||
ledgerTree: SteadyDataView.SteadyLedgerNode[]
|
||||
indicatorTree: SteadyDataView.SteadyIndicatorNode[]
|
||||
trendResult: SteadyDataView.SteadyTrendQueryResult | null
|
||||
trendForm: SteadyTrendFormState
|
||||
statOptions: SteadyDataView.SteadyTrendStatType[]
|
||||
showHarmonicOrders: boolean
|
||||
loading: {
|
||||
ledger: boolean
|
||||
indicator: boolean
|
||||
trend: boolean
|
||||
}
|
||||
ledgerKeyword: string
|
||||
indicatorPanelCollapsed: boolean
|
||||
selectorResetKey: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:trendForm': [value: SteadyTrendFormState]
|
||||
'update:indicatorPanelCollapsed': [value: boolean]
|
||||
refreshLedger: []
|
||||
ledgerSearch: [value: string]
|
||||
ledgerChange: [nodes: SteadyDataView.SteadyLedgerNode[]]
|
||||
refreshIndicator: []
|
||||
indicatorChange: [nodes: SteadyDataView.SteadyIndicatorNode[]]
|
||||
queryTrend: []
|
||||
resetTrend: []
|
||||
}>()
|
||||
|
||||
const trendFormProxy = computed({
|
||||
get: () => props.trendForm,
|
||||
set: value => emit('update:trendForm', value)
|
||||
})
|
||||
|
||||
const indicatorPanelCollapsedProxy = computed({
|
||||
get: () => props.indicatorPanelCollapsed,
|
||||
set: value => emit('update:indicatorPanelCollapsed', value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.steady-trend-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 320px minmax(0, 1fr);
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.selector-column {
|
||||
display: grid;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.trend-main {
|
||||
display: grid;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
gap: 12px;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.trend-content {
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.trend-content :deep(.trend-chart-panel) {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 1360px) {
|
||||
.steady-trend-layout {
|
||||
grid-template-columns: 280px minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user