import type { SteadyDataView } from '@/api/steady/steadyDataView/interface' export const MAX_TREND_SERIES_COUNT = 24 export const MAX_HARMONIC_ORDER_COUNT = 6 export const collectSelectedLineIds = (nodes: SteadyDataView.SteadyLedgerNode[]) => { const lineIds = new Set() const collect = (node: SteadyDataView.SteadyLedgerNode) => { if (node.level === 3 || node.selectable) { lineIds.add(node.id) } node.children?.forEach(collect) } nodes.forEach(collect) return Array.from(lineIds) } export const collectLeafIndicators = (nodes: SteadyDataView.SteadyIndicatorNode[]) => { const indicators: SteadyDataView.SteadyIndicatorNode[] = [] const collect = (node: SteadyDataView.SteadyIndicatorNode) => { if (node.children?.length) { node.children.forEach(collect) return } if (node.indicatorCode) { indicators.push(node) } } nodes.forEach(collect) return indicators } export const findFirstSelectableLedgerNode = ( nodes: SteadyDataView.SteadyLedgerNode[] ): SteadyDataView.SteadyLedgerNode | null => { for (const node of nodes) { if (node.level === 3 || node.selectable) { return node } const childNode = findFirstSelectableLedgerNode(node.children || []) if (childNode) return childNode } return null } export const findFirstLeafIndicator = ( nodes: SteadyDataView.SteadyIndicatorNode[] ): SteadyDataView.SteadyIndicatorNode | null => { for (const node of nodes) { if (node.children?.length) { const childNode = findFirstLeafIndicator(node.children) if (childNode) return childNode continue } if (node.indicatorCode) { return node } } return null } export const hasHarmonicIndicator = (indicators: SteadyDataView.SteadyIndicatorNode[]) => { return indicators.some(item => item.harmonic || Boolean(item.harmonicOrderStart || item.harmonicOrderEnd)) } export const resolveAvailableStats = (indicators: SteadyDataView.SteadyIndicatorNode[]) => { const statSet = new Set() indicators.forEach(indicator => { indicator.supportStats?.forEach(stat => statSet.add(stat)) }) return Array.from(statSet) } export const estimateTrendSeriesCount = ( lineIds: string[], indicators: SteadyDataView.SteadyIndicatorNode[], statTypes: SteadyDataView.SteadyTrendStatType[], harmonicOrders: number[] ) => { const harmonicMultiplier = hasHarmonicIndicator(indicators) ? Math.max(harmonicOrders.length, 1) : 1 return indicators.reduce((count, indicator) => { const phaseCount = indicator.phaseCodes?.length || 1 const fieldCount = Math.max(indicator.seriesFields?.length || indicator.baseFields?.length || 1, 1) return count + lineIds.length * phaseCount * Math.max(statTypes.length, 1) * fieldCount * harmonicMultiplier }, 0) } export const validateHarmonicOrders = ( indicators: SteadyDataView.SteadyIndicatorNode[], harmonicOrders: number[] ) => { if (!hasHarmonicIndicator(indicators)) return '' if (!harmonicOrders.length) return '谐波指标必须选择谐波次数' if (harmonicOrders.length > MAX_HARMONIC_ORDER_COUNT) return '谐波次数最多选择 6 个' return '' } export const validateTrendSelection = (params: { lineIds: string[] indicators: SteadyDataView.SteadyIndicatorNode[] statTypes: SteadyDataView.SteadyTrendStatType[] harmonicOrders: number[] }) => { const { lineIds, indicators, statTypes, harmonicOrders } = params if (!lineIds.length) return '请选择监测点' if (!indicators.length) return '请选择趋势指标' if (lineIds.length > 1 && indicators.length > 1) return '多监测点查询时只能选择 1 个指标' if (!statTypes.length) return '请选择统计类型' const harmonicError = validateHarmonicOrders(indicators, harmonicOrders) if (harmonicError) return harmonicError const seriesCount = estimateTrendSeriesCount(lineIds, indicators, statTypes, harmonicOrders) if (seriesCount > MAX_TREND_SERIES_COUNT) { return '趋势曲线数量不能超过 24 条,请缩小监测点、指标或统计类型范围' } return '' }