耐受图调整、屏蔽非必要的菜单、登录后跳转到变频器页面

This commit is contained in:
caozehui
2026-04-27 08:39:30 +08:00
parent 8744dfb0d8
commit 8ab1a35f3b
8 changed files with 512 additions and 340 deletions

View File

@@ -130,6 +130,7 @@ const initChart = () => {
chart.resize()
}, 0)
}
const getChartInstance = () => chart
const handlerBar = (options: any) => {
if (Array.isArray(options.series)) {
options.series.forEach((item: any) => {
@@ -253,7 +254,7 @@ onMounted(() => {
initChart()
resizeObserver.observe(chartRef.value!)
})
defineExpose({ initChart })
defineExpose({ initChart, getChartInstance })
onBeforeUnmount(() => {
resizeObserver.unobserve(chartRef.value!)
chart?.dispose()

View File

@@ -1,7 +1,7 @@
// ? 全局默认配置项
// 首页地址(默认)
export const HOME_URL: string = "/home/index";
export const HOME_URL: string = "/machine/freqConverter";
// export const HOME_URL: string = "/machine/controlSource";

View File

@@ -26,6 +26,7 @@
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { HOME_URL } from '@/config'
import { useAuthStore } from '@/stores/modules/auth'
import { useModeStore } from '@/stores/modules/mode' // 引入模式 store
import { useTabsStore } from '@/stores/modules/tabs'
@@ -74,8 +75,8 @@ const handelOpen = async (item: string, key: string) => {
await initDynamicRouter()
// 只有当目标路径与当前路径不同时才跳转
if (router.currentRoute.value.path !== '/home/index') {
await router.push({ path: '/home/index' })
if (router.currentRoute.value.path !== HOME_URL) {
await router.push({ path: HOME_URL })
} else {
// 如果已在目标页面,手动触发组件更新
window.location.reload() // 或者采用其他方式刷新数据

View File

@@ -70,7 +70,7 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { LOGIN_URL } from '@/config'
import { HOME_URL, LOGIN_URL } from '@/config'
import { useRouter } from 'vue-router'
import { useUserStore } from '@/stores/modules/user'
import { ElMessage, ElMessageBox } from 'element-plus'
@@ -132,7 +132,7 @@ const changeScene = async (value: string) => {
//模式切换
const changeMode = async () => {
authStore.changeModel()
await router.push('/home/index')
await router.push(HOME_URL)
}
</script>

View File

@@ -29,6 +29,7 @@ import { useRoute, useRouter } from 'vue-router'
import { useGlobalStore } from '@/stores/modules/global'
import { useTabsStore } from '@/stores/modules/tabs'
import { useAuthStore } from '@/stores/modules/auth'
import { HOME_URL } from '@/config'
import { TabPaneName, TabsPaneContext } from 'element-plus'
import MoreButton from './components/MoreButton.vue'
@@ -73,13 +74,13 @@ watch(
// 初始化需要固定的 tabs
const initTabs = () => {
authStore.flatMenuListGet.forEach(item => {
if (item.meta.isAffix && !item.meta.isHide && !item.meta.isFull) {
if (item.path === HOME_URL && !item.meta.isHide && !item.meta.isFull) {
const tabsParams = {
icon: item.meta.icon,
title: item.meta.title,
path: item.path,
name: item.name,
close: !item.meta.isAffix,
close: false,
isKeepAlive: item.meta.isKeepAlive,
unshift: true
}

View File

@@ -3,6 +3,7 @@ import { type AuthState } from '@/stores/interface'
import { getAuthButtonListApi, getAuthMenuListApi } from '@/api/user/login'
import { getAllBreadcrumbList, getFlatMenuList, getShowMenuList } from '@/utils'
import { AUTH_STORE_KEY } from '@/stores/constant'
import { HOME_URL } from '@/config'
import { useModeStore } from '@/stores/modules/mode'
import { getLicense } from '@/api/activate'
import type { Activate } from '@/api/activate/interface'
@@ -52,7 +53,7 @@ export const useAuthStore = defineStore(AUTH_STORE_KEY, {
? filterMenuByExcludedNames(menuData, ['testSource', 'testScript', 'controlSource'])
: filterMenuByExcludedNames(menuData, ['standardDevice'])
this.authMenuList = filteredMenu
this.authMenuList = normalizeHomeAffix(filteredMenu)
},
// Set RouteName
async setRouteName(name: string) {
@@ -112,3 +113,22 @@ function filterMenuByExcludedNames(menuList: any[], excludedNames: string[]): an
return !excludedNames.includes(menu.name)
})
}
function normalizeHomeAffix(menuList: any[]): any[] {
return menuList.map(menu => {
const nextMenu = { ...menu }
if (nextMenu.meta) {
nextMenu.meta = {
...nextMenu.meta,
isAffix: nextMenu.path === HOME_URL
}
}
if (Array.isArray(nextMenu.children) && nextMenu.children.length > 0) {
nextMenu.children = normalizeHomeAffix(nextMenu.children)
}
return nextMenu
})
}

View File

@@ -120,7 +120,7 @@ const login = (formEl: FormInstance | undefined) => {
await tabsStore.setTabs([])
await keepAliveStore.setKeepAliveName([])
// 登录默认不显示菜单和导航栏
await authStore.resetAuthStore()
await authStore.setShowMenu()
// 跳转到首页
await router.push(HOME_URL)
} finally {

View File

@@ -1,4 +1,4 @@
<template>
<template>
<el-card class="dip-chart-card" shadow="never">
<template #header>
<div class="card-header">
@@ -9,50 +9,59 @@
</div>
</div>
<el-button
<div class="header-actions">
<el-button type="primary" plain :icon="Download" :disabled="!hasChartData" @click="downloadChartImage">
下载图片
</el-button>
<el-button type="primary" plain :icon="Document" :disabled="!hasChartData" @click="exportChartData">
导出数据
</el-button>
<el-button
type="primary"
plain
:loading="curveLoading"
class="draw-curve-button"
@click="drawCharacteristicCurve"
>
绘制特性曲线
</el-button>
>
绘制特性曲线
</el-button>
</div>
</div>
</template>
<div class="chart-wrapper">
<MyEchart :options="chartOptions"/>
<MyEchart ref="chartRef" :options="chartOptions" />
</div>
</el-card>
</template>
<script lang="ts" setup>
import {computed, ref, watch} from 'vue'
import {ElMessage} from 'element-plus'
import { computed, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Document, Download } from '@element-plus/icons-vue'
import * as XLSX from 'xlsx'
import MyEchart from '@/components/echarts/line/index.vue'
import {getFreqConverterSCurve} from '@/api/device/freqConverter'
import { getFreqConverterSCurve } from '@/api/device/freqConverter'
type ChartPointStatus = 'pass' | 'fail'
interface ChartPoint {
duration: number;
residualVoltage: number;
status: ChartPointStatus;
duration: number
residualVoltage: number
status: ChartPointStatus
}
interface NormalizedTolerantPoint {
duration: number;
residualVoltage: number;
tolerant: number | null;
status: ChartPointStatus;
duration: number
residualVoltage: number
tolerant: number | null
status: ChartPointStatus
}
const props = defineProps<{
selectedMapping?: Record<string, any> | null;
webMsgSend?: any;
resultData?: any;
selectedMapping?: Record<string, any> | null
webMsgSend?: any
resultData?: any
}>()
const STATUS_COLOR_MAP: Record<ChartPointStatus, string> = {
@@ -63,6 +72,7 @@ const STATUS_COLOR_MAP: Record<ChartPointStatus, string> = {
const chartPoints = ref<ChartPoint[]>([])
const characteristicCurveData = ref<Array<[number, number]>>([])
const curveLoading = ref(false)
const chartRef = ref<any>(null)
const selectedMappingText = computed(() => {
if (!props.selectedMapping) {
@@ -72,6 +82,91 @@ const selectedMappingText = computed(() => {
return `变频器:${props.selectedMapping.freqConverterName || '-'}`
})
const positiveDurations = computed(() => {
return [
...chartPoints.value.map(item => item.duration),
...characteristicCurveData.value.map(item => item[0])
].filter(item => Number.isFinite(item) && item > 0)
})
const xAxisMin = computed(() => {
if (!positiveDurations.value.length) {
return 0.001
}
const minValue = Math.min(...positiveDurations.value)
return Math.min(0.001, Number(minValue.toFixed(3)))
})
const xAxisMax = computed(() => {
if (!positiveDurations.value.length) {
return 60
}
const maxValue = Math.max(...positiveDurations.value)
return Math.max(Number((maxValue * 1.05).toFixed(3)), 60)
})
const sortedChartPoints = computed(() => {
return [...chartPoints.value].sort((a, b) => {
if (a.duration !== b.duration) {
return a.duration - b.duration
}
return a.residualVoltage - b.residualVoltage
})
})
const sortedCharacteristicCurveData = computed(() => {
return [...characteristicCurveData.value].sort((a, b) => {
if (a[0] !== b[0]) {
return a[0] - b[0]
}
return a[1] - b[1]
})
})
const hasChartData = computed(() => {
return sortedChartPoints.value.length > 0 || sortedCharacteristicCurveData.value.length > 0
})
const formatLogDurationLabel = (value: number) => {
if (!Number.isFinite(value)) {
return ''
}
if (value >= 1) {
return `${Number(value.toFixed(2))}`
}
return `${Number(value.toFixed(3))}`
}
const sanitizeFileName = (value: string) => {
return value.replace(/[\\/:*?"<>|]/g, '_').trim() || '未命名变频器'
}
const buildFileName = (prefix: string, suffix: string) => {
const freqConverterName = sanitizeFileName(props.selectedMapping?.freqConverterName || '未命名变频器')
return `${prefix}_${freqConverterName}.${suffix}`
}
const triggerDownload = (url: string, fileName: string) => {
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.download = fileName
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
const toNumber = (value: unknown) => {
const result = Number(value)
return Number.isFinite(result) ? result : null
}
const normalizeTolerantValue = (value: unknown) => {
if (value === undefined || value === null || value === '') {
return null
@@ -89,246 +184,12 @@ const normalizeDuration = (source: Record<string, any>) => {
return toNumber(
source.durationMs !== undefined && source.durationMs !== null
? Number(source.durationMs) / 1000
: source.duration ??
source.x ??
source.dipDuration ??
source.retainTime ??
source.durationValue
: source.duration ?? source.x ?? source.dipDuration ?? source.retainTime ?? source.durationValue
)
}
const normalizeResidualVoltageValue = (source: Record<string, any>) => {
return toNumber(
source.residualVoltage ??
source.y ??
source.residual ??
source.voltage ??
source.residual_value
)
}
const normalizeCurveData = (source: unknown) => {
if (!Array.isArray(source)) {
return [] as Array<[number, number]>
}
return source
.map(item => {
if (Array.isArray(item) && item.length >= 2) {
const duration = Number(item[0])
const residualVoltage = Number(item[1])
if (Number.isFinite(duration) && Number.isFinite(residualVoltage)) {
return [duration, residualVoltage] as [number, number]
}
}
if (item && typeof item === 'object') {
const record = item as Record<string, any>
const tolerant = normalizeTolerantValue(record.tolerant)
if (tolerant !== null && tolerant !== 2) {
return null
}
const duration = normalizeDuration(record)
const residualVoltage = normalizeResidualVoltageValue(record)
if (duration !== null && residualVoltage !== null) {
return [duration, residualVoltage] as [number, number]
}
}
return null
})
.filter((item): item is [number, number] => !!item)
}
const extractCurveData = (payload: any) => {
if (!payload) {
return [] as Array<[number, number]>
}
const candidates = [
payload,
payload?.data,
payload?.data?.records,
payload?.data?.points,
payload?.points,
payload?.records,
payload?.list
]
for (const candidate of candidates) {
const normalized = normalizeCurveData(candidate)
if (normalized.length) {
return normalized
}
}
return [] as Array<[number, number]>
}
const drawCharacteristicCurve = async () => {
const freqConverterId = props.selectedMapping?.freqConverterId
if (!freqConverterId) {
ElMessage.warning('未获取到变频器ID')
return
}
curveLoading.value = true
try {
const result = await getFreqConverterSCurve({
converterId: freqConverterId
})
const normalizedCurveData = extractCurveData(result)
if (!normalizedCurveData.length) {
characteristicCurveData.value = []
ElMessage.warning('未获取到特性曲线数据')
return
}
characteristicCurveData.value = normalizedCurveData
} catch (error) {
console.error('绘制特性曲线失败:', error)
characteristicCurveData.value = []
} finally {
curveLoading.value = false
}
}
const chartOptions = computed(() => {
const maxDuration = 2
// const maxDuration = Math.max(
// 2,
// ...chartPoints.value.map(item => item.duration).filter(item => Number.isFinite(item)),
// ...characteristicCurveData.value.map(item => item[0]).filter(item => Number.isFinite(item))
// )
return {
title: {
text: ''
},
grid: {
top: 30,
left: 48,
right: 22,
bottom: 52
},
tooltip: {
trigger: 'item',
formatter(params: any) {
if (params.seriesType === 'line') {
return ''
}
const [duration, residualVoltage, statusText] = params.value
return [
`持续时间: ${duration} s`,
`残余电压: ${residualVoltage} %`,
`状态: ${statusText}`
].join('<br/>')
}
},
legend: {
top: 0,
right: 0,
data: ['特性测试曲线']
},
xAxis: {
type: 'log',
name: '持续时间(s)',
nameLocation: 'middle',
nameGap: 34,
min: 0.01,
max: 60,
logBase: 10,
minorTick: {
show: true,
splitNumber: 10
},
minorSplitLine: {
show: true,
lineStyle: {
color: '#e8edf6'
}
},
splitLine: {
lineStyle: {
color: '#cfd8e6'
}
},
axisLabel: {
formatter(value: number) {
return value.toFixed(2)
}
}
},
yAxis: {
type: 'value',
name: '暂降幅值',
min: 0,
max: 100,
interval: 10,
minorTick: {
show: true,
splitNumber: 2
},
minorSplitLine: {
show: true,
lineStyle: {
color: '#e8edf6'
}
},
splitLine: {
lineStyle: {
color: '#cfd8e6'
}
},
axisLabel: {
formatter(value: number) {
return `${value}%`
}
}
},
dataZoom: [],
series: [
{
name: '特性测试曲线',
type: 'line',
smooth: true,
showSymbol: true,
symbolSize: 7,
lineStyle: {
color: '#ff2a2a',
width: 3
},
itemStyle: {
color: '#ff2a2a'
},
data: characteristicCurveData.value
},
{
name: '暂降点',
type: 'scatter',
symbolSize: 10,
data: chartPoints.value.map(item => ({
value: [item.duration, item.residualVoltage, getStatusText(item.status)],
itemStyle: {
color: STATUS_COLOR_MAP[item.status]
}
}))
}
],
options: {
animation: false
}
}
})
const toNumber = (value: unknown) => {
const result = Number(value)
return Number.isFinite(result) ? result : null
return toNumber(source.residualVoltage ?? source.y ?? source.residual ?? source.voltage ?? source.residual_value)
}
const normalizeStatus = (value: unknown): ChartPointStatus => {
@@ -362,14 +223,14 @@ const normalizeTolerantPoint = (source: Record<string, any>): NormalizedTolerant
const tolerant = normalizeTolerantValue(
source.tolerant ??
source.endure ??
source.isEndure ??
source.tolerable ??
source.isTolerable ??
source.status ??
source.pointStatus ??
source.result ??
source.state
source.endure ??
source.isEndure ??
source.tolerable ??
source.isTolerable ??
source.status ??
source.pointStatus ??
source.result ??
source.state
)
return {
@@ -382,25 +243,21 @@ const normalizeTolerantPoint = (source: Record<string, any>): NormalizedTolerant
: tolerant === 1
? 'pass'
: normalizeStatus(
source.tolerant ??
source.endure ??
source.isEndure ??
source.tolerable ??
source.isTolerable ??
source.status ??
source.pointStatus ??
source.result ??
source.state
)
source.tolerant ??
source.endure ??
source.isEndure ??
source.tolerable ??
source.isTolerable ??
source.status ??
source.pointStatus ??
source.result ??
source.state
)
}
}
const getStatusText = (status: ChartPointStatus) => {
if (status === 'fail') {
return '不耐受'
}
return '耐受'
return status === 'fail' ? '不耐受' : '耐受'
}
const normalizePoint = (source: Record<string, any>): ChartPoint | null => {
@@ -416,6 +273,65 @@ const normalizePoint = (source: Record<string, any>): ChartPoint | null => {
}
}
const normalizeCurveData = (source: unknown) => {
if (!Array.isArray(source)) {
return [] as Array<[number, number]>
}
return source
.map(item => {
if (Array.isArray(item) && item.length >= 2) {
const duration = Number(item[0])
const residualVoltage = Number(item[1])
if (Number.isFinite(duration) && Number.isFinite(residualVoltage) && duration > 0) {
return [duration, residualVoltage] as [number, number]
}
}
if (item && typeof item === 'object') {
const record = item as Record<string, any>
const tolerant = normalizeTolerantValue(record.tolerant)
if (tolerant !== null && tolerant !== 2) {
return null
}
const duration = normalizeDuration(record)
const residualVoltage = normalizeResidualVoltageValue(record)
if (duration !== null && residualVoltage !== null && duration > 0) {
return [duration, residualVoltage] as [number, number]
}
}
return null
})
.filter((item): item is [number, number] => !!item)
}
const extractCurveData = (payload: any) => {
if (!payload) {
return [] as Array<[number, number]>
}
const candidates = [
payload,
payload?.data,
payload?.data?.records,
payload?.data?.points,
payload?.points,
payload?.records,
payload?.list
]
for (const candidate of candidates) {
const normalized = normalizeCurveData(candidate)
if (normalized.length) {
return normalized
}
}
return [] as Array<[number, number]>
}
const extractCharacteristicCurvePoints = (payload: any) => {
const result: Array<[number, number]> = []
const seen = new Set<string>()
@@ -494,63 +410,288 @@ const extractPoints = (payload: any) => {
return result
}
watch(
() => props.webMsgSend,
newValue => {
if (!newValue) {
return
}
const drawCharacteristicCurve = async () => {
const freqConverterId = props.selectedMapping?.freqConverterId
if (!freqConverterId) {
ElMessage.warning('未获取到变频器ID')
return
}
const nextPoints = extractPoints(newValue)
if (!nextPoints.length) {
const nextCurvePoints = extractCharacteristicCurvePoints(newValue)
if (nextCurvePoints.length) {
characteristicCurveData.value = nextCurvePoints
}
return
}
curveLoading.value = true
const existingPointMap = new Map(
chartPoints.value.map(item => [`${item.duration}|${item.residualVoltage}`, item] as const)
)
try {
const result = await getFreqConverterSCurve({
converterId: freqConverterId
})
nextPoints.forEach(item => {
const key = `${item.duration}|${item.residualVoltage}`
existingPointMap.set(key, item)
})
const normalizedCurveData = extractCurveData(result)
chartPoints.value = Array.from(existingPointMap.values())
const nextCurvePoints = extractCharacteristicCurvePoints(newValue)
if (nextCurvePoints.length) {
characteristicCurveData.value = nextCurvePoints
}
},
{deep: true}
)
watch(
() => props.resultData,
newValue => {
if (!newValue) {
return
}
chartPoints.value = extractPoints(newValue)
const nextCurvePoints = extractCharacteristicCurvePoints(newValue)
if (nextCurvePoints.length) {
characteristicCurveData.value = nextCurvePoints
}
},
{deep: true, immediate: true}
)
watch(
() => props.selectedMapping,
() => {
chartPoints.value = []
if (!normalizedCurveData.length) {
characteristicCurveData.value = []
ElMessage.warning('未获取到特性曲线数据')
return
}
characteristicCurveData.value = normalizedCurveData
} catch (error) {
console.error('draw characteristic curve failed:', error)
characteristicCurveData.value = []
} finally {
curveLoading.value = false
}
}
const downloadChartImage = async () => {
if (!hasChartData.value) {
ElMessage.warning('暂无可下载的图表数据')
return
}
await nextTick()
const chartInstance = chartRef.value?.getChartInstance?.()
if (!chartInstance) {
ElMessage.warning('图表尚未渲染完成')
return
}
const imageUrl = chartInstance.getDataURL({
type: 'png',
pixelRatio: 2,
backgroundColor: '#ffffff'
})
triggerDownload(imageUrl, buildFileName('变频器耐受图', 'png'))
ElMessage.success('图表图片导出成功')
}
const exportChartData = () => {
if (!hasChartData.value) {
ElMessage.warning('暂无可导出的点位数据')
return
}
const workbook = XLSX.utils.book_new()
if (sortedChartPoints.value.length) {
const pointSheet = XLSX.utils.json_to_sheet(
sortedChartPoints.value.map((item, index) => ({
序号: index + 1,
持续时间_s: item.duration,
暂降幅值_pct: item.residualVoltage,
状态: getStatusText(item.status)
}))
)
XLSX.utils.book_append_sheet(workbook, pointSheet, '暂降点')
}
if (sortedCharacteristicCurveData.value.length) {
const curveSheet = XLSX.utils.json_to_sheet(
sortedCharacteristicCurveData.value.map((item, index) => ({
序号: index + 1,
持续时间_s: item[0],
暂降幅值_pct: item[1]
}))
)
XLSX.utils.book_append_sheet(workbook, curveSheet, '特性曲线')
}
const workbookBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' })
const blob = new Blob([workbookBuffer], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
const blobUrl = window.URL.createObjectURL(blob)
try {
triggerDownload(blobUrl, buildFileName('变频器耐受图数据', 'xlsx'))
ElMessage.success('点位数据导出成功')
} finally {
window.URL.revokeObjectURL(blobUrl)
}
}
const chartOptions = computed(() => {
return {
title: {
text: ''
},
grid: {
top: 30,
left: 48,
right: 22,
bottom: 52
},
tooltip: {
trigger: 'item',
formatter(params: any) {
const rawValue = Array.isArray(params.value) ? params.value : params.value?.value
if (!Array.isArray(rawValue)) {
return ''
}
const [duration, residualVoltage, statusText] = rawValue
return [
`类型: ${params.seriesName}`,
`持续时间: ${duration} s`,
`残余电压: ${residualVoltage} %`,
...(statusText ? [`状态: ${statusText}`] : [])
].join('<br/>')
}
},
legend: {
top: 0,
right: 0,
data: ['特性测试曲线']
},
xAxis: {
type: 'log',
name: '持续时间(s)',
nameLocation: 'middle',
nameGap: 34,
min: xAxisMin.value,
max: xAxisMax.value,
logBase: 10,
minorTick: {
show: true,
splitNumber: 10
},
minorSplitLine: {
show: false,
lineStyle: {
color: '#e8edf6'
}
},
splitLine: {
show: true,
lineStyle: {
color: '#cfd8e6'
}
},
axisLabel: {
formatter(value: number) {
return formatLogDurationLabel(value)
}
}
},
yAxis: {
type: 'value',
name: '暂降幅值',
min: 0,
max: 100,
interval: 10,
minorTick: {
show: true,
splitNumber: 2
},
minorSplitLine: {
show: true,
lineStyle: {
color: '#e8edf6'
}
},
splitLine: {
lineStyle: {
color: '#cfd8e6'
}
},
axisLabel: {
formatter(value: number) {
return `${value}%`
}
}
},
dataZoom: [],
series: [
{
name: '特性测试曲线',
type: 'line',
smooth: true,
showSymbol: true,
symbolSize: 7,
lineStyle: {
color: '#ff2a2a',
width: 3
},
itemStyle: {
color: '#ff2a2a'
},
data: characteristicCurveData.value.map(item => [item[0], item[1], '特性曲线'])
},
{
name: '暂降点',
type: 'scatter',
symbolSize: 10,
data: chartPoints.value.map(item => ({
value: [item.duration, item.residualVoltage, getStatusText(item.status)],
itemStyle: {
color: STATUS_COLOR_MAP[item.status]
}
}))
}
],
options: {
animation: false
}
}
})
watch(
() => props.webMsgSend,
newValue => {
if (!newValue) {
return
}
const nextPoints = extractPoints(newValue)
if (!nextPoints.length) {
const nextCurvePoints = extractCharacteristicCurvePoints(newValue)
if (nextCurvePoints.length) {
characteristicCurveData.value = nextCurvePoints
}
return
}
const existingPointMap = new Map(
chartPoints.value.map(item => [`${item.duration}|${item.residualVoltage}`, item] as const)
)
nextPoints.forEach(item => {
const key = `${item.duration}|${item.residualVoltage}`
existingPointMap.set(key, item)
})
chartPoints.value = Array.from(existingPointMap.values())
const nextCurvePoints = extractCharacteristicCurvePoints(newValue)
if (nextCurvePoints.length) {
characteristicCurveData.value = nextCurvePoints
}
},
{ deep: true }
)
watch(
() => props.resultData,
newValue => {
if (!newValue) {
return
}
chartPoints.value = extractPoints(newValue)
const nextCurvePoints = extractCharacteristicCurvePoints(newValue)
if (nextCurvePoints.length) {
characteristicCurveData.value = nextCurvePoints
}
},
{ deep: true, immediate: true }
)
watch(
() => props.selectedMapping,
() => {
chartPoints.value = []
characteristicCurveData.value = []
}
)
</script>
@@ -574,6 +715,14 @@ watch(
gap: 12px;
}
.header-actions {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8px;
flex-wrap: wrap;
}
.card-header-main {
min-width: 0;
}