Files
it/frontend/src/components/PerformanceCharts.vue

240 lines
5.8 KiB
Vue
Raw Normal View History

2025-11-03 17:03:57 +08:00
<template>
<div class="performance-charts">
<!-- 性能历史趋势图 -->
<div class="bg-white rounded-lg shadow-md p-6 mb-6">
<h2 class="text-lg font-semibold mb-4">性能历史趋势</h2>
<div v-if="!performanceHistory || performanceHistory.length === 0" class="h-64 flex items-center justify-center bg-gray-50 rounded-lg">
<p class="text-gray-500">暂无历史数据</p>
</div>
<div v-else class="h-80">
<v-chart
class="h-full w-full"
:option="historyChartOption"
:loading="loading"
autoresize
/>
</div>
</div>
<!-- 性能指标雷达图 -->
<div class="bg-white rounded-lg shadow-md p-6">
<h2 class="text-lg font-semibold mb-4">性能指标雷达图</h2>
<div v-if="!product || !product.performanceScores || product.performanceScores.length === 0" class="h-64 flex items-center justify-center bg-gray-50 rounded-lg">
<p class="text-gray-500">暂无性能数据</p>
</div>
<div v-else class="h-80">
<v-chart
class="h-full w-full"
:option="radarChartOption"
:loading="loading"
autoresize
/>
</div>
</div>
</div>
</template>
<script>
import { ref, computed, watch } from 'vue'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart, RadarChart } from 'echarts/charts'
import {
TitleComponent,
TooltipComponent,
LegendComponent,
GridComponent,
RadarComponent
} from 'echarts/components'
import VChart from 'vue-echarts'
// 注册必要的组件
use([
CanvasRenderer,
LineChart,
RadarChart,
TitleComponent,
TooltipComponent,
LegendComponent,
GridComponent,
RadarComponent
])
export default {
name: 'PerformanceCharts',
components: {
VChart
},
props: {
product: {
type: Object,
required: true
},
performanceHistory: {
type: Array,
default: () => []
},
loading: {
type: Boolean,
default: false
}
},
setup(props) {
// 性能历史趋势图配置
const historyChartOption = computed(() => {
if (!props.performanceHistory || props.performanceHistory.length === 0) {
return {}
}
// 准备数据
const dates = []
const scores = []
props.performanceHistory.forEach(item => {
dates.push(new Date(item.recordDate).toLocaleDateString())
scores.push(item.score)
})
return {
title: {
text: `${props.product.name} 性能趋势`,
left: 'center'
},
tooltip: {
trigger: 'axis',
formatter: function(params) {
return `${params[0].axisValue}<br/>性能分数: ${params[0].value}`
}
},
xAxis: {
type: 'category',
data: dates,
axisLabel: {
rotate: 45
}
},
yAxis: {
type: 'value',
name: '性能分数'
},
series: [
{
name: '性能分数',
type: 'line',
data: scores,
smooth: true,
symbolSize: 8,
lineStyle: {
width: 3,
color: '#409EFF'
},
itemStyle: {
color: '#409EFF'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(64, 158, 255, 0.5)' },
{ offset: 1, color: 'rgba(64, 158, 255, 0.1)' }
]
}
}
}
],
grid: {
left: '3%',
right: '4%',
bottom: '15%',
containLabel: true
}
}
})
// 性能指标雷达图配置
const radarChartOption = computed(() => {
if (!props.product || !props.product.performanceScores || props.product.performanceScores.length === 0) {
return {}
}
// 准备雷达图数据
const indicators = []
const values = []
// 定义常见的基准测试及其最大值
const benchmarkMaxValues = {
'Geekbench Single-Core': 3000,
'Geekbench Multi-Core': 20000,
'3DMark Time Spy': 20000,
'3DMark Fire Strike': 30000,
'AnTuTu': 1000000,
'PCMark': 8000,
'Cinebench R23': 30000,
'Cinebench R20': 8000
}
props.product.performanceScores.forEach(score => {
const benchmarkName = score.benchmarkName
const maxValue = benchmarkMaxValues[benchmarkName] || 100
indicators.push({
name: benchmarkName,
max: maxValue
})
// 将分数转换为百分比0-100
const percentage = Math.min(100, (score.score / maxValue) * 100)
values.push(percentage)
})
return {
title: {
text: `${props.product.name} 性能指标`,
left: 'center'
},
tooltip: {
trigger: 'item'
},
radar: {
indicator: indicators,
center: ['50%', '55%'],
radius: '70%'
},
series: [
{
name: '性能指标',
type: 'radar',
data: [
{
value: values,
name: props.product.name,
itemStyle: {
color: '#409EFF'
},
areaStyle: {
color: 'rgba(64, 158, 255, 0.3)'
}
}
]
}
]
}
})
return {
historyChartOption,
radarChartOption
}
}
}
</script>
<style scoped>
.performance-charts {
width: 100%;
}
</style>