feat(steady): 实现台账指标树默认选中及图标展示功能

- 添加findFirstSelectableLedgerNode和findFirstLeafIndicator工具函数
- 实现台账树首次加载后默认选中第一个可查询监测点
- 实现指标树首次加载后默认选中第一个叶子指标
- 添加台账层级图标展示及样式配置
- 集成defaultCheckedKeys属性到台账和指标树组件
- 更新趋势查询参数移除bucket字段
- 修复数据质量标识默认值设置问题
This commit is contained in:
2026-05-18 16:30:02 +08:00
parent f9ed6c6245
commit 6755476969
11 changed files with 203 additions and 34 deletions

View File

@@ -19,6 +19,7 @@
:key="selectorResetKey"
:tree-data="treeData"
:loading="loading"
:default-checked-keys="defaultCheckedKeys"
@refresh="emit('refresh')"
@change="emit('change', $event)"
/>
@@ -39,6 +40,7 @@ defineProps<{
collapsed: boolean
treeData: SteadyDataView.SteadyIndicatorNode[]
loading: boolean
defaultCheckedKeys: string[]
selectorResetKey: number
}>()

View File

@@ -13,6 +13,7 @@
node-key="treeKey"
show-checkbox
default-expand-all
:default-checked-keys="defaultCheckedKeys"
:expand-on-click-node="false"
:props="{ label: 'name', children: 'children' }"
@check="handleCheck"
@@ -29,7 +30,7 @@
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import { computed, nextTick, ref, watch } from 'vue'
import { Refresh } from '@element-plus/icons-vue'
import type { TreeInstance } from 'element-plus'
import type { SteadyDataView } from '@/api/steady/steadyDataView/interface'
@@ -42,6 +43,7 @@ defineOptions({
const props = defineProps<{
treeData: SteadyDataView.SteadyIndicatorNode[]
loading: boolean
defaultCheckedKeys: string[]
}>()
const emit = defineEmits<{
@@ -70,6 +72,19 @@ const handleCheck = () => {
const checkedNodes = (treeRef.value?.getCheckedNodes(false, false) || []) as SteadyDataView.SteadyIndicatorNode[]
emit('change', collectLeafIndicators(checkedNodes))
}
const applyDefaultCheckedKeys = async () => {
await nextTick()
treeRef.value?.setCheckedKeys(props.defaultCheckedKeys, false)
}
watch(
() => [normalizedTreeData.value, props.defaultCheckedKeys],
() => {
applyDefaultCheckedKeys()
},
{ immediate: true }
)
</script>
<style scoped lang="scss">

View File

@@ -20,13 +20,19 @@
node-key="id"
show-checkbox
default-expand-all
:default-checked-keys="defaultCheckedKeys"
:expand-on-click-node="false"
:props="{ label: 'name', children: 'children' }"
@check="handleCheck"
>
<template #default="{ data }">
<div class="tree-node">
<span class="node-name">{{ data.name }}</span>
<span class="node-main">
<el-icon :class="['node-icon', `is-level-${normalizeLedgerLevel(data.level)}`]">
<component :is="resolveLedgerIcon(data.level)" />
</el-icon>
<span class="node-name">{{ data.name }}</span>
</span>
<span class="node-count">
<template v-if="Number(data.deviceCount) || Number(data.lineCount)">
{{ Number(data.deviceCount || 0) }} / {{ Number(data.lineCount || 0) }}
@@ -40,8 +46,9 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { Refresh } from '@element-plus/icons-vue'
import { nextTick, ref, watch } from 'vue'
import type { Component } from 'vue'
import { Folder, Location, Monitor, OfficeBuilding, Refresh } from '@element-plus/icons-vue'
import type { TreeInstance } from 'element-plus'
import type { SteadyDataView } from '@/api/steady/steadyDataView/interface'
@@ -49,10 +56,11 @@ defineOptions({
name: 'SteadyLedgerTree'
})
defineProps<{
const props = defineProps<{
treeData: SteadyDataView.SteadyLedgerNode[]
loading: boolean
keyword: string
defaultCheckedKeys: string[]
}>()
const emit = defineEmits<{
@@ -62,6 +70,26 @@ const emit = defineEmits<{
}>()
const treeRef = ref<TreeInstance>()
type LedgerLevel = SteadyDataView.SteadyLedgerNode['level']
const ledgerIcons: Record<LedgerLevel, Component> = {
0: OfficeBuilding,
1: Folder,
2: Monitor,
3: Location
}
const normalizeLedgerLevel = (value: unknown): LedgerLevel => {
const level = Number(value)
if (level === 0 || level === 1 || level === 2 || level === 3) {
return level
}
return 0
}
const resolveLedgerIcon = (value: unknown) => {
return ledgerIcons[normalizeLedgerLevel(value)]
}
const handleKeywordChange = (value: string) => {
emit('search', value)
@@ -70,6 +98,19 @@ const handleKeywordChange = (value: string) => {
const handleCheck = () => {
emit('change', (treeRef.value?.getCheckedNodes(false, false) || []) as SteadyDataView.SteadyLedgerNode[])
}
const applyDefaultCheckedKeys = async () => {
await nextTick()
treeRef.value?.setCheckedKeys(props.defaultCheckedKeys, false)
}
watch(
() => [props.treeData, props.defaultCheckedKeys],
() => {
applyDefaultCheckedKeys()
},
{ immediate: true }
)
</script>
<style scoped lang="scss">
@@ -105,6 +146,35 @@ const handleCheck = () => {
min-width: 0;
}
.node-main {
display: inline-flex;
min-width: 0;
align-items: center;
gap: 6px;
}
.node-icon {
flex: none;
font-size: 15px;
color: var(--el-text-color-secondary);
}
.node-icon.is-level-0 {
color: var(--el-color-primary);
}
.node-icon.is-level-1 {
color: var(--el-color-success);
}
.node-icon.is-level-2 {
color: var(--el-color-warning);
}
.node-icon.is-level-3 {
color: var(--el-color-info);
}
.node-name {
overflow: hidden;
text-overflow: ellipsis;

View File

@@ -25,17 +25,6 @@
</el-select>
</div>
<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>
<div class="toolbar-field">
<span class="toolbar-field__label">数据</span>
<el-select
@@ -44,8 +33,8 @@
placeholder="选择数据质量"
@update:model-value="updateField('qualityFlag', $event)"
>
<el-option label="仅有效数据" :value="1" />
<el-option label="仅无效数据" :value="0" />
<el-option label="仅有效数据" :value="0" />
<el-option label="仅无效数据" :value="1" />
</el-select>
</div>
@@ -93,13 +82,6 @@ const emit = defineEmits<{
reset: []
}>()
const bucketOptions = [
{ label: '1分钟', value: '1m' },
{ label: '5分钟', value: '5m' },
{ label: '10分钟', value: '10m' },
{ label: '30分钟', value: '30m' },
{ label: '1小时', value: '1h' }
]
const harmonicOrderOptions = Array.from({ length: 49 }, (_item, index) => index + 2)
const statLabelMap: Record<SteadyDataView.SteadyTrendStatType, string> = {
AVG: '平均值',
@@ -136,7 +118,7 @@ const handleTimeBaseDateChange = (value: Date) => {
<style scoped lang="scss">
.trend-toolbar {
display: grid;
grid-template-columns: minmax(312px, 1.4fr) repeat(3, minmax(178px, 0.8fr)) auto;
grid-template-columns: minmax(312px, 1.4fr) repeat(2, minmax(178px, 0.8fr)) auto;
gap: 10px;
align-items: center;
padding: 12px;

View File

@@ -6,6 +6,7 @@
:tree-data="ledgerTree"
:loading="loading.ledger"
:keyword="ledgerKeyword"
:default-checked-keys="defaultLedgerCheckedKeys"
@refresh="emit('refreshLedger')"
@search="emit('ledgerSearch', $event)"
@change="emit('ledgerChange', $event)"
@@ -30,6 +31,7 @@
:selector-reset-key="selectorResetKey"
:tree-data="indicatorTree"
:loading="loading.indicator"
:default-checked-keys="defaultIndicatorCheckedKeys"
@refresh="emit('refreshIndicator')"
@change="emit('indicatorChange', $event)"
/>
@@ -63,6 +65,8 @@ const props = defineProps<{
trend: boolean
}
ledgerKeyword: string
defaultLedgerCheckedKeys: string[]
defaultIndicatorCheckedKeys: string[]
indicatorPanelCollapsed: boolean
selectorResetKey: number
}>()