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.

138 lines
4.9 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-alert type="info" :closable="false" show-icon title="对比分析页面建议选择设备组或全量振动设备,以获得更高价值的横向结果。" class="mb-4" />
<el-row :gutter="16">
<el-col :span="12"
><el-card><template #header>设备排名对比图</template><Chart ref="rankChart" class="chart-lg" /></el-card
></el-col>
<el-col :span="12"
><el-card><template #header>设备散点图</template><Chart ref="scatterChart" 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 { getVibrationComparisonData, type VibrationComparisonPageVO } from '@/api/ems/report/vibrationBoard';
import VibrationBoardFilter from '../components/VibrationBoardFilter.vue';
import VibrationBoardDeviceTree from '../components/VibrationBoardDeviceTree.vue';
import { useVibrationBoardQueryState } from '../components/useVibrationBoardQueryState';
import { vibrationMetricOptions } from '../components/vibrationBoardShared';
defineOptions({ name: 'VibrationBoardComparison' });
const rankChart = ref<any>();
const scatterChart = ref<any>();
const {
loading,
treeLoading,
monitorTreeOptions,
treeProps,
daterangeRecordTime,
queryForm,
loadTree,
handleTreeNodeClick,
setTimeRange,
setSamplingInterval,
setVibrationParam,
buildQuery
} = useVibrationBoardQueryState();
const comparisonData = ref<VibrationComparisonPageVO>({ rankItems: [], scatterItems: [] });
const metricColorMap = Object.fromEntries(vibrationMetricOptions.map((item) => [item.field, item.color]));
const toNumber = (value: number | string | undefined) => Number(value ?? 0);
const formatValue = (value: number | string | undefined) => (value === null || value === undefined || value === '' ? '--' : Number(value).toFixed(2));
const renderCharts = () => {
rankChart.value?.setData({
tooltip: { trigger: 'axis' },
legend: { top: 8, data: ['均值', '最新值'] },
xAxis: { type: 'value' },
yAxis: { type: 'category', data: (comparisonData.value.rankItems || []).map((item) => item.monitorName) },
series: [
{
name: '均值',
type: 'bar',
data: (comparisonData.value.rankItems || []).map((item) => toNumber(item.avg)),
itemStyle: { color: metricColorMap[comparisonData.value.metricField || queryForm.value.vibrationParam] || '#5b8ff9' }
},
{
name: '最新值',
type: 'bar',
data: (comparisonData.value.rankItems || []).map((item) => toNumber(item.latest)),
itemStyle: { color: '#36cfc9' }
}
]
});
scatterChart.value?.setData({
tooltip: {
formatter: (params: any) =>
[
`设备: ${params.value[3]}`,
`均值: ${formatValue(params.value[0])}${comparisonData.value.unit || ''}`,
`峰值: ${formatValue(params.value[1])}${comparisonData.value.unit || ''}`,
`采样量: ${params.value[2]}`
].join('<br/>')
},
xAxis: { type: 'value', name: `均值(${comparisonData.value.unit || ''})` },
yAxis: { type: 'value', name: `峰值(${comparisonData.value.unit || ''})` },
series: [
{
type: 'scatter',
symbolSize: (value: any[]) => Math.max(12, Math.min(30, value[2] * 2)),
itemStyle: { color: metricColorMap[comparisonData.value.metricField || queryForm.value.vibrationParam] || '#5b8ff9', opacity: 0.8 },
label: { show: true, formatter: (params: any) => params.value[3], position: 'top', fontSize: 11 },
data: (comparisonData.value.scatterItems || []).map((item) => [
toNumber(item.avg),
toNumber(item.max),
toNumber(item.sampleCount),
item.monitorName
])
}
]
});
};
const handleQuery = async () => {
loading.value = true;
try {
const { data } = await getVibrationComparisonData(buildQuery());
comparisonData.value = data || { rankItems: [], scatterItems: [] };
await nextTick();
renderCharts();
} finally {
loading.value = false;
}
};
onMounted(async () => {
await loadTree();
await handleQuery();
});
</script>
<style scoped>
.chart-lg {
height: 420px;
}
</style>