import type { SteadyDataView } from '@/api/steady/steadyDataView/interface' export const MAX_TREND_SERIES_COUNT = 24 export const MAX_SELECTED_LINE_COUNT = 6 export const MAX_SELECTED_INDICATOR_COUNT = 6 export const MAX_HARMONIC_ORDER_COUNT = 6 const isSelectableLineNode = (node: SteadyDataView.SteadyLedgerNode) => { return node.level === 3 && node.selectable !== false } export const collectSelectedLineIds = (nodes: SteadyDataView.SteadyLedgerNode[]) => { const lineIds = new Set() const collect = (node: SteadyDataView.SteadyLedgerNode) => { if (isSelectableLineNode(node)) { 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 seenIndicatorKeys = new Set() const collect = (node: SteadyDataView.SteadyIndicatorNode) => { if (node.children?.length) { node.children.forEach(collect) return } const indicatorKey = node.indicatorCode || node.treeKey || node.id if (!indicatorKey || seenIndicatorKeys.has(indicatorKey)) return seenIndicatorKeys.add(indicatorKey) indicators.push(node) } nodes.forEach(collect) return indicators } export const findFirstSelectableLedgerNode = ( nodes: SteadyDataView.SteadyLedgerNode[] ): SteadyDataView.SteadyLedgerNode | null => { for (const node of nodes) { if (isSelectableLineNode(node)) { 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[], statType: 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 * (statType ? 1 : 0) * 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[] statType: SteadyDataView.SteadyTrendStatType harmonicOrders: number[] }) => { const { lineIds, indicators, statType, harmonicOrders } = params if (!lineIds.length) return '请选择监测点' if (!indicators.length) return '请选择趋势指标' if (lineIds.length > 1 && indicators.length > 1) return '多监测点查询时只能选择 1 个指标' if (lineIds.length > MAX_SELECTED_LINE_COUNT) return '监测点最多选择 6 个' if (indicators.length > MAX_SELECTED_INDICATOR_COUNT) return '趋势指标最多选择 6 个' if (!statType) return '请选择统计类型' const harmonicError = validateHarmonicOrders(indicators, harmonicOrders) if (harmonicError) return harmonicError const seriesCount = estimateTrendSeriesCount(lineIds, indicators, statType, harmonicOrders) if (seriesCount > MAX_TREND_SERIES_COUNT) { return '趋势曲线数量不能超过 24 条,请缩小监测点、指标或统计类型范围' } return '' }