yeg
4 天以前 f4d7007b89cf565746af4623623a294b82666ff1
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
38
39
40
<script setup lang="ts">
import ProjectCycleCharts from './ProjectCycleCharts.vue'
import type { ProjectSeries } from '@/utils/projectCycleChart'
import { toTestDisplayValue } from '@/utils/testDataUnits'
import { computed, ref, watch } from 'vue'
import type { PersistedTestCycle, PersistedTestStep } from '@/api/tests'
 
interface ConsoleCell { no: string }
const props = defineProps<{ cells: ConsoleCell[]; steps: PersistedTestStep[]; cycles: PersistedTestCycle[]; capacityFactor: string }>()
const palette = ['#3978f6', '#7d42d8', '#f08a3e', '#23a983', '#e15268', '#1b9ac8', '#b5892f', '#6957c8', '#4f8d44', '#d264a3', '#46748e', '#a95d37']
const seriesColors = ref<string[]>(props.cells.map((_, index) => palette[index % palette.length]))
watch(() => props.cells, cells => { seriesColors.value = cells.map((_, index) => seriesColors.value[index] || palette[index % palette.length]) }, { deep: true })
const cycleLabels = computed(() => [...new Set([...props.steps, ...props.cycles].map(row => Number(row.cycleNo)).filter(value => Number.isFinite(value) && value > 0))].sort((a, b) => a - b).map(String))
const capacityFactor = computed(() => { const value = Number(props.capacityFactor); return Number.isFinite(value) && value !== 0 ? value : null })
const capacityFactorUnavailable = computed(() => capacityFactor.value === null)
function numericValue(value: unknown): number | null {
  if (value === null || value === undefined || (typeof value === 'string' && !value.trim())) return null
  const number = Number(value)
  return Number.isFinite(number) ? number : null
}
// 只读取当前有效工步;缺少该循环或最后工步终止电压时保留空点,不补值。
function lastStepVoltage(batteryNo: string, cycleNo: number): number | null {
  const rows = props.steps.filter(row => String(row.batteryNo) === batteryNo && Number(row.cycleNo) === cycleNo).sort((a, b) => Number(a.stepNo) - Number(b.stepNo))
  return rows.length ? numericValue(rows[rows.length - 1].endVoltage) : null
}
// 容量分子按 mAh 展示;F 仅作当前非零数值除数,不推断其物理单位。
function dischargeCapacityPerFactor(batteryNo: string, cycleNo: number): number | null {
  if (capacityFactor.value === null) return null
  const row = props.cycles.find(item => String(item.batteryNo) === batteryNo && Number(item.cycleNo) === cycleNo)
  const capacity = row ? numericValue(row.dischargeCapacity) : null
  return capacity === null ? null : toTestDisplayValue('dischargeCapacity', capacity) / capacityFactor.value
}
const hidden = ref<string[]>([])
// 循环指标可能来自工步层聚合:曲线出自推导值时,图上看得出它是怎么来的。
const aggregatedCycles = computed(() => props.cycles.some(row => String(row.sourceKind || '') === 'AGGREGATED'))
const projectSeries = computed<ProjectSeries[]>(() => props.cells.map(cell => ({ key: cell.no, name: cell.no, points: cycleLabels.value.map(label => ({ position: Number(label), values: { finalVoltage1: lastStepVoltage(cell.no, Number(label)), dischargeCapacityF: dischargeCapacityPerFactor(cell.no, Number(label)) } })) })))
</script>
<template>
  <ProjectCycleCharts :series="projectSeries" :positions="cycleLabels.map(Number)" :colors="seriesColors" :hidden="hidden" :factor-warning="capacityFactorUnavailable" :aggregated-warning="aggregatedCycles" @hidden-change="hidden = $event" />
</template>