diff --git a/src/views/ems/report/vibrationBoard/anomaly/index.vue b/src/views/ems/report/vibrationBoard/anomaly/index.vue index 59746f2..f200731 100644 --- a/src/views/ems/report/vibrationBoard/anomaly/index.vue +++ b/src/views/ems/report/vibrationBoard/anomaly/index.vue @@ -8,7 +8,7 @@ show-metric @update:time-range="setTimeRange" @update:sampling-interval="setSamplingInterval" - @update:vibration-param="setVibrationParam" + @update:vibration-param="handleMetricChange" @query="handleQuery" /> @@ -132,6 +132,7 @@ const { setTimeRange, setSamplingInterval, setVibrationParam, + resetAnomalyThresholds, buildQuery } = useVibrationBoardQueryState(); @@ -151,6 +152,12 @@ const applyThresholdDefaults = (data?: VibrationAnomalyPageVO) => { queryForm.value.stddevThreshold = Number(data.stddevThreshold ?? queryForm.value.stddevThreshold ?? 0); }; +const handleMetricChange = (value: string) => { + // 切换指标后先清空旧阈值覆盖,再触发查询,这样后端才能按新指标返回正确默认阈值。 + resetAnomalyThresholds(); + setVibrationParam(value); +}; + const handleQuery = async () => { loading.value = true; try { diff --git a/src/views/ems/report/vibrationBoard/comparison/index.vue b/src/views/ems/report/vibrationBoard/comparison/index.vue index 8365c89..2509c2b 100644 --- a/src/views/ems/report/vibrationBoard/comparison/index.vue +++ b/src/views/ems/report/vibrationBoard/comparison/index.vue @@ -98,7 +98,7 @@ const renderCharts = () => { series: [ { type: 'scatter', - symbolSize: (value: any[]) => Math.max(12, Math.min(30, value[2] * 2)), + symbolSize: (value: any[]) => Math.max(12, Math.min(40, 8 + Math.log(toNumber(value[2]) + 1) * 3)), 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) => [ diff --git a/src/views/ems/report/vibrationBoard/components/useVibrationBoardQueryState.ts b/src/views/ems/report/vibrationBoard/components/useVibrationBoardQueryState.ts index bbd750f..352b84d 100644 --- a/src/views/ems/report/vibrationBoard/components/useVibrationBoardQueryState.ts +++ b/src/views/ems/report/vibrationBoard/components/useVibrationBoardQueryState.ts @@ -2,30 +2,61 @@ import { getMonitorInfoTree } from '@/api/ems/base/baseMonitorInfo'; import type { VibrationBoardQuery } from '@/api/ems/types'; import { createDefaultTimeRange } from './vibrationBoardShared'; +type VibrationBoardQueryForm = { + compareScope: string; + monitorId: string; + monitorIds: string[]; + selectionLabel: string; + samplingInterval: number; + vibrationParam: string; + highThreshold: number | undefined; + warningThreshold: number | undefined; + minContinuousSamples: number | undefined; + rapidRiseThreshold: number | undefined; + stddevThreshold: number | undefined; +}; + +type BuildQueryOptions = { + includeVibrationParam?: boolean; +}; + +const createDefaultQueryForm = (defaultMetric = 'vibrationSpeed'): VibrationBoardQueryForm => ({ + compareScope: 'all', + monitorId: '', + monitorIds: [], + selectionLabel: '全部振动设备', + samplingInterval: 5, + vibrationParam: defaultMetric, + highThreshold: undefined, + warningThreshold: undefined, + minContinuousSamples: undefined, + rapidRiseThreshold: undefined, + stddevThreshold: undefined +}); + +// 模块级缓存:同一浏览器会话内 7 个页面共享设备树与查询状态,避免重复请求和切页丢筛选。 +const sharedState = reactive({ + treeLoaded: false, + monitorTreeOptions: [] as any[], + deviceDisplayMap: {} as Record, + daterangeRecordTime: createDefaultTimeRange() as string[], + queryForm: createDefaultQueryForm() +}); + export function useVibrationBoardQueryState(defaultMetric = 'vibrationSpeed') { - const state = reactive({ + const localState = reactive({ loading: false, treeLoading: false, - monitorTreeOptions: [] as any[], - treeProps: { label: 'label', children: 'children' }, - deviceDisplayMap: {} as Record, - daterangeRecordTime: createDefaultTimeRange() as string[], - queryForm: { - compareScope: 'all', - monitorId: '', - monitorIds: [] as string[], - selectionLabel: '全部振动设备', - samplingInterval: 5, - vibrationParam: defaultMetric, - highThreshold: undefined as number | undefined, - warningThreshold: undefined as number | undefined, - minContinuousSamples: undefined as number | undefined, - rapidRiseThreshold: undefined as number | undefined, - stddevThreshold: undefined as number | undefined - } + treeProps: { label: 'label', children: 'children' } }); - const { loading, treeLoading, monitorTreeOptions, treeProps, deviceDisplayMap, daterangeRecordTime, queryForm } = toRefs(state); + // 仅在首次进入页面时应用默认主看指标,后续页面切换沿用用户最新选择。 + if (!sharedState.queryForm.vibrationParam) { + sharedState.queryForm.vibrationParam = defaultMetric; + } + + const { loading, treeLoading, treeProps } = toRefs(localState); + const { monitorTreeOptions, deviceDisplayMap, daterangeRecordTime, queryForm } = toRefs(sharedState); const deviceCount = computed(() => queryForm.value.monitorIds?.length || (queryForm.value.monitorId ? 1 : 0)); const hasMultiDevice = computed(() => deviceCount.value > 1 || ['group', 'all'].includes(queryForm.value.compareScope)); @@ -68,12 +99,27 @@ export function useVibrationBoardQueryState(defaultMetric = 'vibrationSpeed') { queryForm.value.vibrationParam = value; }; + const resetAnomalyThresholds = () => { + // 主看指标切换后必须回到“未覆盖”状态,让后端按新指标重新下发默认阈值, + // 否则会把上一指标的阈值误当成当前指标的用户自定义值。 + queryForm.value.highThreshold = undefined; + queryForm.value.warningThreshold = undefined; + queryForm.value.minContinuousSamples = undefined; + queryForm.value.rapidRiseThreshold = undefined; + queryForm.value.stddevThreshold = undefined; + }; + const loadTree = async () => { + // 已加载且有缓存时直接复用,避免 7 个页面重复打同一个树接口。 + if (sharedState.treeLoaded) { + return; + } treeLoading.value = true; try { const response = await getMonitorInfoTree({ monitorType: 10 }); monitorTreeOptions.value = response.data || []; deviceDisplayMap.value = buildDeviceDisplayMap(monitorTreeOptions.value); + sharedState.treeLoaded = true; if (!queryForm.value.monitorIds.length && !queryForm.value.monitorId) { applySelection(buildSelection(getLeafNodes(monitorTreeOptions.value), '全部振动设备', 'all')); } @@ -91,9 +137,11 @@ export function useVibrationBoardQueryState(defaultMetric = 'vibrationSpeed') { applySelection(buildSelection([data], data.label, 'single')); }; - const buildQuery = (): VibrationBoardQuery => ({ + const buildQuery = (options?: BuildQueryOptions): VibrationBoardQuery => ({ samplingInterval: queryForm.value.samplingInterval, - vibrationParam: queryForm.value.vibrationParam, + // 质量页不展示主看指标时,必须禁掉这个隐藏筛选条件, + // 否则会继承其它页面的指标选择,悄悄改变质量统计口径。 + vibrationParam: options?.includeVibrationParam === false ? undefined : queryForm.value.vibrationParam, beginRecordTime: daterangeRecordTime.value[0], endRecordTime: daterangeRecordTime.value[1], highThreshold: queryForm.value.highThreshold, @@ -125,6 +173,7 @@ export function useVibrationBoardQueryState(defaultMetric = 'vibrationSpeed') { setTimeRange, setSamplingInterval, setVibrationParam, + resetAnomalyThresholds, buildQuery, getMonitorDisplayName }; diff --git a/src/views/ems/report/vibrationBoard/distribution/index.vue b/src/views/ems/report/vibrationBoard/distribution/index.vue index 2355dbc..f132438 100644 --- a/src/views/ems/report/vibrationBoard/distribution/index.vue +++ b/src/views/ems/report/vibrationBoard/distribution/index.vue @@ -82,6 +82,13 @@ const distributionData = ref({ const toNumber = (value: number | string | undefined) => Number(value ?? 0); +const clearCharts = () => { + intervalChart.value?.setData(null); + histogramChart.value?.setData(null); + calendarChart.value?.setData(null); + hourlyChart.value?.setData(null); +}; + const renderCharts = () => { const intervalData = distributionData.value.intervalBuckets || []; const histogramData = distributionData.value.histogramBuckets || []; @@ -89,6 +96,8 @@ const renderCharts = () => { const hourlyData = (distributionData.value.hourlyHeatmap || []).map((item) => [toNumber(item.statHour), item.statDate, toNumber(item.avgValue)]); const days = [...new Set(hourlyData.map((item) => item[1] as string))].sort(); if (!intervalData.length && !histogramData.length && !calendarData.length && !hourlyData.length) { + // 查询结果为空时必须主动清空实例,否则会残留上一轮图表数据误导用户。 + clearCharts(); return; } diff --git a/src/views/ems/report/vibrationBoard/quality/index.vue b/src/views/ems/report/vibrationBoard/quality/index.vue index f5787cc..c2604cc 100644 --- a/src/views/ems/report/vibrationBoard/quality/index.vue +++ b/src/views/ems/report/vibrationBoard/quality/index.vue @@ -87,7 +87,8 @@ const renderChart = () => { const handleQuery = async () => { loading.value = true; try { - const { data } = await getVibrationQualityData(buildQuery()); + // 质量页统计的是整批振动样本的数据完整性,不能继承其它页面隐藏的主看指标过滤口径。 + const { data } = await getVibrationQualityData(buildQuery({ includeVibrationParam: false })); qualityData.value = data || { metricQualityItems: [] }; await nextTick(); renderChart();