yeg
2026-09-08 45f82842224b64e15308a858778b6fdb62bcdf2d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import type { CompareCandidate, CompareItem, CompareSettings } from '@/api/compareReports'
 
/** 同一来源的不同循环和工步共用详情,测量比对项仍保留完整范围身份。 */
export function compareSourceKey(source: CompareCandidate) {
  return `${source.selection.testId}|${source.selection.testBatteryId}`
}
 
export function compareDetailSources(items: CompareItem[]) {
  return [...new Map(items.map(item => [compareSourceKey(item.source), item.source])).values()]
}
 
/** 控制台名称不映射为共享字段编号或单位;两类同名字段也分别保留。 */
export function compareSourceFields(sources: CompareCandidate[], overrides?: CompareSettings['sourceDetailOverrides']) {
  const fields = sources.flatMap(source => (['battery', 'special'] as const).flatMap(category =>
    (source.consoleDetail?.[category === 'battery' ? 'batteryFields' : 'specialFields'] || [])
      .map(name => ({ key: `${category}|${name}`, name, category }))))
  // 主动更新时来源字段可以消失,已经人工改过的报表格仍保留其名称和分类。
  for (const source of sources) for (const key of Object.keys(overrides?.[compareSourceKey(source)]?.fieldValues || {})) {
    const category = key.startsWith('battery|') ? 'battery' : 'special'
    fields.push({ key, name: key.slice(category.length + 1), category })
  }
  return [...new Map(fields.map(field => [field.key, field])).values()]
}
 
/** 旧版人工格以完整范围保存,不能在来源详情去重时合并或丢弃这些值。 */
export function compareHasRangeDetailValues(settings: Pick<CompareSettings, 'sourceDetailOverrides' | 'detailFieldValues'>) {
  return settings.sourceDetailOverrides === undefined || Object.values(settings.detailFieldValues).some(values => Object.keys(values).some(key => key.split('|').length > 2))
}
 
export function compareSourceValue(source: CompareCandidate, overrides: CompareSettings['sourceDetailOverrides'], field?: ReturnType<typeof compareSourceFields>[number]) {
  const manual = overrides?.[compareSourceKey(source)]
  if (!field) return manual?.experimentName ?? source.consoleDetail?.experimentName ?? ''
  const value = manual?.fieldValues?.[field.key]
  if (value !== undefined) return value
  const fields = source.consoleDetail?.[field.category === 'battery' ? 'batteryFields' : 'specialFields'] || []
  return fields.includes(field.name) ? source.consoleDetail?.fieldValues[field.name]?.[source.batteryNo] ?? '' : ''
}