You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
4.4 KiB
Vue

<template>
<div v-loading="loading" class="app-container">
<VibrationBoardFilter
:selection-label="queryForm.selectionLabel"
:time-range="daterangeRecordTime"
:sampling-interval="queryForm.samplingInterval"
:vibration-param="queryForm.vibrationParam"
show-metric
@update:time-range="setTimeRange"
@update:sampling-interval="setSamplingInterval"
@update:vibration-param="setVibrationParam"
@query="handleQuery"
/>
<el-row :gutter="16" class="mt-4">
<el-col :span="6">
<VibrationBoardDeviceTree :loading="treeLoading" :tree-data="monitorTreeOptions" :tree-props="treeProps" @node-click="handleTreeNodeClick" />
</el-col>
<el-col :span="18">
<el-card>
<template #header>振动流向图</template>
<Chart ref="sankeyChart" class="chart-xl" />
</el-card>
<el-row :gutter="16" class="mt-4">
<el-col :span="12">
<el-card>
<template #header>矩形树图</template>
<Chart ref="treemapChart" class="chart-lg" />
</el-card>
</el-col>
<el-col :span="12">
<el-card>
<template #header>平行坐标画像</template>
<Chart ref="parallelChart" class="chart-lg" />
</el-card>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import Chart from '@/components/Charts/Chart.vue';
import { getVibrationAdvancedData, type VibrationAdvancedPageVO } from '@/api/ems/report/vibrationBoard';
import VibrationBoardFilter from '../components/VibrationBoardFilter.vue';
import VibrationBoardDeviceTree from '../components/VibrationBoardDeviceTree.vue';
import { useVibrationBoardQueryState } from '../components/useVibrationBoardQueryState';
defineOptions({ name: 'VibrationBoardAdvanced' });
const sankeyChart = ref<any>();
const treemapChart = ref<any>();
const parallelChart = ref<any>();
const {
loading,
treeLoading,
monitorTreeOptions,
treeProps,
daterangeRecordTime,
queryForm,
loadTree,
handleTreeNodeClick,
setTimeRange,
setSamplingInterval,
setVibrationParam,
buildQuery
} = useVibrationBoardQueryState();
const advancedData = ref<VibrationAdvancedPageVO>({
sankeyNodes: [],
sankeyLinks: [],
treemapItems: [],
parallelAxes: [],
parallelSeries: []
});
const toNumber = (value: number | string | undefined) => Number(value ?? 0);
const renderCharts = () => {
sankeyChart.value?.setData({
tooltip: { trigger: 'item' },
series: [
{
type: 'sankey',
data: advancedData.value.sankeyNodes || [],
links: (advancedData.value.sankeyLinks || []).map((item) => ({
source: item.source,
target: item.target,
value: toNumber(item.value)
})),
emphasis: { focus: 'adjacency' },
lineStyle: { color: 'gradient', curveness: 0.5 }
}
]
});
treemapChart.value?.setData({
tooltip: { trigger: 'item' },
series: [
{
type: 'treemap',
roam: false,
data: (advancedData.value.treemapItems || []).map((item) => ({
name: item.name,
value: toNumber(item.value),
itemStyle: {
color: item.levelTag === '高位' ? '#f56c6c' : item.levelTag === '关注' ? '#e6a23c' : '#67c23a'
}
})),
label: { show: true, formatter: '{b}\n{c}' }
}
]
});
parallelChart.value?.setData({
parallelAxis: (advancedData.value.parallelAxes || []).map((item) => ({
dim: toNumber(item.dim),
name: item.name,
max: toNumber(item.max)
})),
parallel: { left: '10%', right: '10%', bottom: 40, top: 40 },
series: [
{
type: 'parallel',
lineStyle: { width: 1, opacity: 0.4 },
data: (advancedData.value.parallelSeries || []).map((item) => item.values?.map((value) => toNumber(value)) || [])
}
]
});
};
const handleQuery = async () => {
loading.value = true;
try {
const { data } = await getVibrationAdvancedData(buildQuery());
advancedData.value = data || {
sankeyNodes: [],
sankeyLinks: [],
treemapItems: [],
parallelAxes: [],
parallelSeries: []
};
await nextTick();
renderCharts();
} finally {
loading.value = false;
}
};
onMounted(async () => {
await loadTree();
await handleQuery();
});
</script>
<style scoped>
.chart-lg {
height: 360px;
}
.chart-xl {
height: 420px;
}
</style>