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 localState = reactive({ loading: false, treeLoading: false, treeProps: { label: 'label', children: 'children' } }); // 仅在首次进入页面时应用默认主看指标,后续页面切换沿用用户最新选择。 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)); const buildDeviceDisplayMap = (nodes: any[]): Record => (nodes || []).reduce( (acc, item) => { if (item.code && !item.children?.length) acc[item.code] = item.label; if (item.children?.length) Object.assign(acc, buildDeviceDisplayMap(item.children)); return acc; }, {} as Record ); const getLeafNodes = (nodes: any[]): any[] => (nodes || []).flatMap((item) => (item.children?.length ? getLeafNodes(item.children) : item.code ? [item] : [])); const buildSelection = (nodes: any[], selectionLabel: string, compareScope?: string) => { const monitorIds = nodes.map((item) => item.code); return { compareScope: compareScope || (monitorIds.length > 1 ? 'group' : 'single'), monitorId: monitorIds.length === 1 ? monitorIds[0] : '', monitorIds, selectionLabel }; }; const applySelection = (selection: any) => { Object.assign(queryForm.value, selection); }; const setTimeRange = (value: string[]) => { daterangeRecordTime.value = value; }; const setSamplingInterval = (value: number) => { queryForm.value.samplingInterval = value; }; const setVibrationParam = (value: string) => { 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')); } } finally { treeLoading.value = false; } }; const handleTreeNodeClick = (data: any) => { if (!data) return; if (data.children?.length) { applySelection(buildSelection(getLeafNodes(data.children), `${data.label}设备组`, 'group')); return; } applySelection(buildSelection([data], data.label, 'single')); }; const buildQuery = (options?: BuildQueryOptions): VibrationBoardQuery => ({ samplingInterval: queryForm.value.samplingInterval, // 质量页不展示主看指标时,必须禁掉这个隐藏筛选条件, // 否则会继承其它页面的指标选择,悄悄改变质量统计口径。 vibrationParam: options?.includeVibrationParam === false ? undefined : queryForm.value.vibrationParam, beginRecordTime: daterangeRecordTime.value[0], endRecordTime: daterangeRecordTime.value[1], highThreshold: queryForm.value.highThreshold, warningThreshold: queryForm.value.warningThreshold, minContinuousSamples: queryForm.value.minContinuousSamples, rapidRiseThreshold: queryForm.value.rapidRiseThreshold, stddevThreshold: queryForm.value.stddevThreshold, monitorId: queryForm.value.monitorIds?.length > 1 ? undefined : queryForm.value.monitorIds?.[0] || queryForm.value.monitorId, monitorIds: queryForm.value.monitorIds?.length > 1 ? queryForm.value.monitorIds : undefined, params: { beginRecordTime: daterangeRecordTime.value[0], endRecordTime: daterangeRecordTime.value[1] } }); const getMonitorDisplayName = (monitorId?: string) => (monitorId ? deviceDisplayMap.value[monitorId] || monitorId : '--'); return { loading, treeLoading, monitorTreeOptions, treeProps, daterangeRecordTime, queryForm, deviceCount, hasMultiDevice, loadTree, handleTreeNodeClick, setTimeRange, setSamplingInterval, setVibrationParam, resetAnomalyThresholds, buildQuery, getMonitorDisplayName }; }