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
138 lines
4.9 KiB
Vue
|
2 months ago
|
<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>
|