补充图表

This commit is contained in:
yumaojun03 2025-08-10 21:04:40 +08:00
parent fb832df8e1
commit 68a9b29458
3 changed files with 371 additions and 26 deletions

View File

@ -29,16 +29,7 @@
<a-row :gutter="20">
<!-- 构建状态图表 -->
<a-col :xs="24" :md="16">
<a-card title="构建状态统计" :bordered="false" class="chart-card">
<template #extra>
<a-select v-model="buildTimeRange" size="small" style="width: 120px">
<a-option value="week">最近一周</a-option>
<a-option value="month">最近一月</a-option>
<a-option value="quarter">最近三月</a-option>
</a-select>
</template>
<BuildStatusChar :data="buildData" />
</a-card>
<BuildStatusChar />
</a-col>
<!-- 活动流水线 -->
@ -76,9 +67,7 @@
<a-row :gutter="20">
<!-- 部署统计 -->
<a-col :xs="24" :md="12">
<a-card title="部署统计" :bordered="false" class="chart-card">
<DeployChart :data="deployData" />
</a-card>
<DeployChart />
</a-col>
<!-- 最近活动 -->
@ -117,11 +106,6 @@ import {
import DeployChart from './components/DeployChart.vue';
import BuildStatusChar from './components/BuildStatusChar.vue';
//
const buildTimeRange = ref('week');
const metrics = ref([
{
title: '成功构建',
@ -189,7 +173,7 @@ const activePipelines = ref([
{
id: '2354',
name: 'mobile-app',
status: 'error',
status: 'danger',
duration: '3m 28s',
stage: '构建失败',
tagColor: 'red'
@ -204,9 +188,6 @@ const activePipelines = ref([
}
]);
const buildData = ref({/* 图表数据 */ });
const deployData = ref({/* 图表数据 */ });
const recentActivities = ref([
{
id: 1,

View File

@ -1,9 +1,193 @@
<template>
<div style="height: 300px">构建状态图表</div>
<a-card class="chart-card" title="构建状态统计" :bordered="false">
<template #extra>
<a-select v-model="buildTimeRange" size="small" style="width: 120px">
<a-option value="week">最近一周</a-option>
<a-option value="month">最近一月</a-option>
<a-option value="quarter">最近三月</a-option>
</a-select>
</template>
<div class="chart-wrapper">
<v-chart class="chart" :option="buildOption" autoresize />
</div>
</a-card>
</template>
<script setup>
import { computed, ref } from 'vue';
import { use } from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import { BarChart } from 'echarts/charts';
import {
GridComponent,
TooltipComponent,
LegendComponent,
TitleComponent
} from 'echarts/components';
import VChart from 'vue-echarts';
//
use([
CanvasRenderer,
BarChart,
GridComponent,
TooltipComponent,
LegendComponent,
TitleComponent
]);
// Arco Design
const colors = {
success: 'rgb(76,210,99)', // --green-4
danger: 'rgb(249,137,129)', // --red-4
warning: 'rgb(255,182,93)', // --orange-4
text1: '#1D2129', // --color-text-1
text2: '#4E5969', // --color-text-2
border: '#E5E6EB' // --color-border
};
const buildTimeRange = ref('week');
//
const buildData = computed(() => {
const dataMap = {
week: {
dates: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
success: [32, 45, 38, 52, 47, 60, 42],
fail: [2, 3, 1, 0, 2, 1, 3],
running: [5, 3, 6, 4, 7, 2, 4]
},
month: {
dates: Array.from({ length: 30 }, (_, i) => `${i + 1}`),
success: Array.from({ length: 30 }, () => Math.floor(Math.random() * 50) + 30),
fail: Array.from({ length: 30 }, () => Math.floor(Math.random() * 5)),
running: Array.from({ length: 30 }, () => Math.floor(Math.random() * 8) + 2)
},
quarter: {
dates: ['1月', '2月', '3月'],
success: [1420, 1560, 1890],
fail: [45, 32, 28],
running: [120, 95, 110]
}
};
return dataMap[buildTimeRange.value];
});
//
const buildOption = computed(() => ({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['成功', '失败', '进行中'],
right: 10,
top: 0,
textStyle: {
color: colors.text1
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: buildData.value.dates,
axisLine: {
lineStyle: {
color: colors.border
}
},
axisLabel: {
color: colors.text2,
interval: buildTimeRange.value === 'month' ? 4 : 0
}
},
yAxis: {
type: 'value',
name: '构建次数',
nameTextStyle: {
color: colors.text2
},
axisLine: {
lineStyle: {
color: colors.border
}
},
axisLabel: {
color: colors.text2
},
splitLine: {
lineStyle: {
color: colors.border
}
}
},
series: [
{
name: '成功',
type: 'bar',
stack: 'total',
emphasis: {
focus: 'series'
},
data: buildData.value.success,
itemStyle: {
color: colors.success
}
},
{
name: '失败',
type: 'bar',
stack: 'total',
emphasis: {
focus: 'series'
},
data: buildData.value.fail,
itemStyle: {
color: colors.danger
}
},
{
name: '进行中',
type: 'bar',
stack: 'total',
emphasis: {
focus: 'series'
},
data: buildData.value.running,
itemStyle: {
color: colors.warning
}
}
]
}));
</script>
<style lang="scss" scoped></style>
<style scoped>
.chart-card {
height: 100%;
border-radius: 4px;
}
.chart-card :deep(.arco-card-body) {
padding: 0;
height: calc(100% - 56px);
}
.chart-wrapper {
padding: 16px;
height: 100%;
}
.chart {
width: 100%;
height: 100%;
}
</style>

View File

@ -1,9 +1,189 @@
<template>
<div style="height: 300px">部署统计图表</div>
<a-card title="部署统计" :bordered="false" class="chart-card">
<v-chart class="chart" :option="deployOption" autoresize />
</a-card>
</template>
<script setup>
import { ref, computed } from 'vue';
import { use } from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import { BarChart, LineChart } from 'echarts/charts';
import {
GridComponent,
TooltipComponent,
LegendComponent,
TitleComponent
} from 'echarts/components';
import VChart from 'vue-echarts';
//
use([
CanvasRenderer,
BarChart,
LineChart,
GridComponent,
TooltipComponent,
LegendComponent,
TitleComponent
]);
// Arco Design 使
const colors = {
primary: 'rgb(45,140,240)', // --blue-6
success: 'rgb(76,210,99)', // --green-4
danger: 'rgb(249,137,129)', // --red-4
warning: 'rgb(255,182,93)', // --orange-4
text1: '#1D2129', // --color-text-1
text2: '#4E5969', // --color-text-2
border: '#E5E6EB' // --color-border
};
//
const deployData = ref({
environments: ['开发', '测试', '预发', '生产'],
counts: [120, 85, 45, 32],
successRate: [98.5, 95.2, 99.1, 99.8]
});
//
const deployOption = computed(() => ({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: colors.border
}
},
formatter: params => {
const count = params[0].value;
const rate = params[1].value;
return `
<div style="font-weight:bold;margin-bottom:5px">${params[0].axisValue}</div>
<div>部署次数: <span style="color:${colors.primary}">${count}</span></div>
<div>成功率: <span style="color:${colors.success}">${rate}%</span></div>
`;
}
},
legend: {
data: ['部署次数', '成功率'],
right: 10,
top: 0,
textStyle: {
color: colors.text1
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: deployData.value.environments,
axisLine: {
lineStyle: {
color: colors.border
}
},
axisLabel: {
color: colors.text2
}
},
yAxis: [
{
type: 'value',
name: '部署次数',
min: 0,
max: Math.max(...deployData.value.counts) * 1.2,
axisLine: {
lineStyle: {
color: colors.border
}
},
axisLabel: {
color: colors.text2
},
splitLine: {
lineStyle: {
color: colors.border
}
}
},
{
type: 'value',
name: '成功率',
min: 90,
max: 100,
axisLine: {
lineStyle: {
color: colors.border
}
},
axisLabel: {
color: colors.text2,
formatter: '{value}%'
},
splitLine: {
show: false
}
}
],
series: [
{
name: '部署次数',
type: 'bar',
barWidth: 20,
data: deployData.value.counts,
itemStyle: {
color: colors.primary
},
label: {
show: true,
position: 'top',
color: colors.text1
}
},
{
name: '成功率',
type: 'line',
yAxisIndex: 1,
data: deployData.value.successRate,
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: colors.success
},
lineStyle: {
width: 3
},
label: {
show: true,
formatter: '{c}%',
color: colors.text1,
position: 'top'
}
}
]
}));
</script>
<style lang="scss" scoped></style>
<style scoped>
.chart-card {
height: 100%;
border-radius: 4px;
}
.chart-card :deep(.arco-card-body) {
padding: 0;
height: calc(100% - 56px);
}
.chart {
width: 100%;
height: 100%;
min-height: 300px;
}
</style>