2026-01-28 14:42:14 +08:00

170 lines
4.5 KiB
Vue

<template>
<div ref="chart" class="chart-container"></div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, nextTick } from 'vue';
import * as echarts from 'echarts';
interface HistoryItem {
ts: number;
currentDis: number;
dphi_deg: number;
amp2_pp_adc: number;
f0_hz: number;
[key: string]: any;
}
const props = defineProps<{
data: HistoryItem[];
}>();
const emit = defineEmits<{
(e: 'select', index: number): void;
}>();
const chart = ref<HTMLElement | null>(null);
let chartInstance: echarts.ECharts | null = null;
const initChart = () => {
if (chart.value && !chartInstance) {
chartInstance = echarts.init(chart.value);
chartInstance.on('click', (params) => {
if (params.dataIndex !== undefined) {
emit('select', params.dataIndex);
}
});
}
};
const updateChart = () => {
if (!chartInstance) return;
const dataPhase = props.data.map(item => [(item.currentDis / 1600).toFixed(3), item.dphi_deg]);
const dataP2P = props.data.map(item => [(item.currentDis / 1600).toFixed(3), item.amp2_pp_adc]);
const option = {
animation: false,
legend: {
data: ['相位差 (Deg)', '峰峰值 (ADC)'],
show: true,
top: 0,
left: 'center',
textStyle: { color: '#333' }
},
grid: {
show: true,
backgroundColor: '#fff',
borderColor: '#333',
borderWidth: 1,
left: '8%',
right: '8%',
bottom: '10%',
top: '24',
containLabel: false
},
tooltip: {
trigger: 'axis',
showContent: false,
axisPointer: { type: 'cross' }
},
xAxis: {
type: 'category',
name: '距离 (mm)',
nameLocation: 'middle',
nameGap: 3,
nameTextStyle: { color: '#333', fontSize: 12 },
axisTick: { show: true, alignWithLabel: true },
axisLine: { show: true, lineStyle: { color: '#333' } },
axisLabel: { color: '#333' },
splitLine: { show: true, lineStyle: { color: '#ccc' } }
},
yAxis: [
{
type: 'value',
name: '相位差 (deg)',
nameLocation: 'middle',
nameGap: 45,
nameTextStyle: { color: '#333', fontSize: 12 },
position: 'left',
axisLine: { show: true, lineStyle: { color: '#333' } },
axisLabel: { color: '#333' },
splitLine: { show: true, lineStyle: { color: '#ccc' } }
},
{
type: 'value',
name: '峰峰值 (ADC)',
nameLocation: 'middle',
nameGap: 45,
nameTextStyle: { color: '#333', fontSize: 12 },
position: 'right',
axisLine: { show: true, lineStyle: { color: '#333' } },
axisLabel: { color: '#333' },
splitLine: { show: false }
}
],
series: [
{
name: '相位差 (Deg)',
type: 'line',
data: dataPhase,
yAxisIndex: 0,
smooth: 0.3,
symbol: 'circle',
symbolSize: 4,
itemStyle: { color: '#c23531' },
lineStyle: { color: '#c23531', width: 2 }
},
{
name: '峰峰值 (ADC)',
type: 'line',
data: dataP2P,
yAxisIndex: 1,
smooth: 0.3,
symbol: 'circle',
symbolSize: 4,
itemStyle: { color: '#2f4554' },
lineStyle: { color: '#2f4554', width: 2 }
}
]
};
chartInstance.setOption(option);
};
const showTip = (index: number) => {
if (!chartInstance) return;
chartInstance.dispatchAction({
type: 'showTip',
seriesIndex: 0,
dataIndex: index
});
};
onMounted(() => {
initChart();
window.addEventListener('resize', () => {
chartInstance?.resize();
});
if (props.data.length > 0) {
updateChart();
}
});
watch(() => props.data, () => {
nextTick(() => {
if (!chartInstance) initChart();
updateChart();
});
}, { deep: true });
defineExpose({ showTip });
</script>
<style scoped>
.chart-container {
width: 100%;
height: 100%;
}
</style>