<template>
|
<div class="dashboard-container">
|
<!-- 页面标题 -->
|
<div class="page-header">
|
<h2>项目概览</h2>
|
<p class="subtitle">实时监控项目运行状态与趋势</p>
|
</div>
|
|
<!-- 概览卡片 -->
|
<div class="overview-section">
|
<el-row :gutter="24">
|
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
|
<div class="overview-card success">
|
<div class="card-header">
|
<h3>成功报告</h3>
|
<i class="el-icon-check-circle"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-value">{{ totalSuccessReports }}</div>
|
<div class="card-desc">最近7天</div>
|
</div>
|
<div class="card-footer">
|
<span class="trend-up">
|
<i class="el-icon-caret-top"></i> 12%
|
</span>
|
<span class="compared">较上周</span>
|
</div>
|
</div>
|
</el-col>
|
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
|
<div class="overview-card danger">
|
<div class="card-header">
|
<h3>失败报告</h3>
|
<i class="el-icon-close-circle"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-value">{{ totalFailedReports }}</div>
|
<div class="card-desc">最近7天</div>
|
</div>
|
<div class="card-footer">
|
<span class="trend-down">
|
<i class="el-icon-caret-bottom"></i> 8%
|
</span>
|
<span class="compared">较上周</span>
|
</div>
|
</div>
|
</el-col>
|
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
|
<div class="overview-card info">
|
<div class="card-header">
|
<h3>新增API</h3>
|
<i class="el-icon-document-add"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-value">{{ totalNewApis }}</div>
|
<div class="card-desc">最近30天</div>
|
</div>
|
<div class="card-footer">
|
<span class="trend-up">
|
<i class="el-icon-caret-top"></i> 23%
|
</span>
|
<span class="compared">较上月</span>
|
</div>
|
</div>
|
</el-col>
|
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
|
<div class="overview-card warning">
|
<div class="card-header">
|
<h3>新增用例</h3>
|
<i class="el-icon-edit-outline"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-value">{{ totalNewCases }}</div>
|
<div class="card-desc">最近30天</div>
|
</div>
|
<div class="card-footer">
|
<span class="trend-up">
|
<i class="el-icon-caret-top"></i> 18%
|
</span>
|
<span class="compared">较上月</span>
|
</div>
|
</div>
|
</el-col>
|
</el-row>
|
|
<!-- 第二行概览卡片 -->
|
<el-row :gutter="24" style="margin-top: 24px;">
|
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
|
<div class="overview-card primary">
|
<div class="card-header">
|
<h3>API总数</h3>
|
<i class="el-icon-collection-tag"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-value">{{ totalApis }}</div>
|
<div class="card-desc">项目总数</div>
|
</div>
|
<div class="card-footer">
|
<span class="trend-up">
|
<i class="el-icon-caret-top"></i> 5%
|
</span>
|
<span class="compared">较上月</span>
|
</div>
|
</div>
|
</el-col>
|
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
|
<div class="overview-card purple">
|
<div class="card-header">
|
<h3>用例总数</h3>
|
<i class="el-icon-document-copy"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-value">{{ totalCases }}</div>
|
<div class="card-desc">项目总数</div>
|
</div>
|
<div class="card-footer">
|
<span class="trend-up">
|
<i class="el-icon-caret-top"></i> 9%
|
</span>
|
<span class="compared">较上月</span>
|
</div>
|
</div>
|
</el-col>
|
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
|
<div class="overview-card teal">
|
<div class="card-header">
|
<h3>报告通过率</h3>
|
<i class="el-icon-data-line"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-value">{{ successRate }}%</div>
|
<div class="card-desc">最近7天</div>
|
</div>
|
<div class="card-footer">
|
<span class="trend-up">
|
<i class="el-icon-caret-top"></i> 3%
|
</span>
|
<span class="compared">较上周</span>
|
</div>
|
</div>
|
</el-col>
|
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
|
<div class="overview-card orange">
|
<div class="card-header">
|
<h3>配置总数</h3>
|
<i class="el-icon-setting"></i>
|
</div>
|
<div class="card-content">
|
<div class="card-value">{{ totalConfigs }}</div>
|
<div class="card-desc">项目总数</div>
|
</div>
|
<div class="card-footer">
|
<span class="trend-up">
|
<i class="el-icon-caret-top"></i> 12%
|
</span>
|
<span class="compared">较上月</span>
|
</div>
|
</div>
|
</el-col>
|
</el-row>
|
</div>
|
|
<!-- 图表区域 -->
|
<div class="charts-section">
|
<!-- 图表标签页 -->
|
<el-tabs v-model="activeTab" @tab-click="handleTabClick" lazy>
|
<!-- 趋势分析标签 -->
|
<el-tab-pane label="趋势分析" name="trends">
|
<!-- 第一行 -->
|
<el-row :gutter="24">
|
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
<el-card class="chart-card">
|
<div slot="header" class="card-header-custom">
|
<span class="title">每日趋势</span>
|
<span class="subtitle">API、用例创建趋势</span>
|
</div>
|
<el-skeleton v-if="isLoading" :rows="10" animated />
|
<ApexCharts
|
v-if="!isLoading && showCharts"
|
:options="apiOptionsLine"
|
:series="apiCaseLineSeries"
|
height="350"
|
></ApexCharts>
|
</el-card>
|
</el-col>
|
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
<el-card class="chart-card">
|
<div slot="header" class="card-header-custom">
|
<span class="title">报告趋势</span>
|
<span class="subtitle">测试报告执行趋势</span>
|
</div>
|
<el-skeleton v-if="isLoading" :rows="10" animated />
|
<ApexCharts
|
v-if="!isLoading && showCharts"
|
:options="reportOptionsLine"
|
:series="reportLineSeries"
|
height="350"
|
></ApexCharts>
|
</el-card>
|
</el-col>
|
</el-row>
|
|
<!-- 第二行 -->
|
<el-row :gutter="24" style="margin-top: 24px;">
|
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
<el-card class="chart-card">
|
<div slot="header" class="card-header-custom">
|
<span class="title">每日创建趋势对比</span>
|
<span class="subtitle">API vs 用例 vs Yapi</span>
|
</div>
|
<el-skeleton v-if="isLoading" :rows="10" animated />
|
<ApexCharts
|
v-if="!isLoading && showCharts"
|
:options="dailyTrendOptions"
|
:series="dailyTrendSeries"
|
height="350"
|
></ApexCharts>
|
</el-card>
|
</el-col>
|
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
<el-card class="chart-card">
|
<div slot="header" class="card-header-custom">
|
<span class="title">报告成功率趋势</span>
|
<span class="subtitle">最近7天</span>
|
</div>
|
<el-skeleton v-if="isLoading" :rows="10" animated />
|
<ApexCharts
|
v-if="!isLoading && showCharts"
|
:options="successRateOptions"
|
:series="successRateSeries"
|
height="350"
|
></ApexCharts>
|
</el-card>
|
</el-col>
|
</el-row>
|
</el-tab-pane>
|
|
<!-- 统计分析标签 -->
|
<el-tab-pane label="统计分析" name="statistics">
|
<!-- 第一行 -->
|
<el-row :gutter="24">
|
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
|
<el-card class="chart-card">
|
<div slot="header" class="card-header-custom">
|
<span class="title">每周指标</span>
|
<span class="subtitle">按周统计数据</span>
|
</div>
|
<el-skeleton v-if="isLoading" :rows="8" animated />
|
<ApexCharts
|
v-if="!isLoading && showCharts"
|
:options="optionsWeekBar"
|
:series="weekBarSeries"
|
height="320"
|
></ApexCharts>
|
</el-card>
|
</el-col>
|
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
|
<el-card class="chart-card">
|
<div slot="header" class="card-header-custom">
|
<span class="title">每月指标</span>
|
<span class="subtitle">按月统计数据</span>
|
</div>
|
<el-skeleton v-if="isLoading" :rows="8" animated />
|
<ApexCharts
|
v-if="!isLoading && showCharts"
|
:options="optionsMonthBar"
|
:series="monthBarSeries"
|
height="320"
|
></ApexCharts>
|
</el-card>
|
</el-col>
|
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
|
<el-card class="chart-card">
|
<div slot="header" class="card-header-custom">
|
<span class="title">报告统计</span>
|
<span class="subtitle">报告类型与状态分布</span>
|
</div>
|
<el-skeleton v-if="isLoading" :rows="10" animated />
|
<div v-if="!isLoading && showCharts" class="report-stats-container">
|
<div class="report-stat-item">
|
<h4>报告类型</h4>
|
<ApexCharts
|
:options="reportPieOptions"
|
:series="reportPieSeries"
|
height="200"
|
></ApexCharts>
|
</div>
|
<div class="report-stat-item">
|
<h4>报告状态</h4>
|
<ApexCharts
|
:options="reportRadiaOptions"
|
:series="reportRadiaSeries"
|
height="200"
|
></ApexCharts>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
</el-row>
|
</el-tab-pane>
|
|
<!-- 人员分析标签 -->
|
<el-tab-pane label="人员分析" name="personnel">
|
<!-- 第一行 -->
|
<el-row :gutter="24">
|
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
<el-card class="chart-card">
|
<div slot="header" class="card-header-custom">
|
<span class="title">近半年接口创建前5名</span>
|
<span class="subtitle">按创建人统计</span>
|
</div>
|
<el-skeleton v-if="isLoading" :rows="10" animated />
|
<ApexCharts
|
v-if="!isLoading && showCharts"
|
:options="apiMonthlyOptionsLine"
|
:series="apiMonthlyLineSeries"
|
height="350"
|
></ApexCharts>
|
</el-card>
|
</el-col>
|
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
|
<el-card class="chart-card">
|
<div slot="header" class="card-header-custom">
|
<span class="title">近半年用例创建前5名</span>
|
<span class="subtitle">按创建人统计</span>
|
</div>
|
<el-skeleton v-if="isLoading" :rows="10" animated />
|
<ApexCharts
|
v-if="!isLoading && showCharts"
|
:options="caseMonthlyOptionsLine"
|
:series="caseMonthlyLineSeries"
|
height="350"
|
></ApexCharts>
|
</el-card>
|
</el-col>
|
</el-row>
|
</el-tab-pane>
|
</el-tabs>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
export default {
|
name: "ProjectDashBoard",
|
data() {
|
return {
|
isLoading: true,
|
activeTab: 'trends',
|
showCharts: false,
|
// 概览数据
|
totalSuccessReports: 0,
|
totalFailedReports: 0,
|
totalNewApis: 0,
|
totalNewCases: 0,
|
totalApis: 0,
|
totalCases: 0,
|
totalConfigs: 0,
|
successRate: 0,
|
|
// 图表数据
|
weekBarSeries: [],
|
monthBarSeries: [],
|
|
// 图表配置
|
optionsWeekBar: {
|
chart: {
|
type: "bar",
|
stacked: true,
|
toolbar: {
|
show: false
|
},
|
animations: {
|
enabled: false
|
}
|
},
|
colors: ['#36A2EB', '#FFCE56', '#4BC0C0'],
|
plotOptions: {
|
bar: {
|
columnWidth: "40%",
|
horizontal: false
|
}
|
},
|
xaxis: {
|
categories: [
|
"前5周",
|
"前4周",
|
"前3周",
|
"前2周",
|
"前1周",
|
"当前周"
|
]
|
},
|
yaxis: {
|
title: {
|
text: '数量'
|
}
|
},
|
fill: {
|
opacity: 0.9
|
},
|
legend: {
|
position: 'top'
|
}
|
},
|
optionsMonthBar: {
|
chart: {
|
type: "bar",
|
stacked: true,
|
toolbar: {
|
show: false
|
},
|
animations: {
|
enabled: false
|
}
|
},
|
colors: ['#36A2EB', '#FFCE56', '#4BC0C0'],
|
plotOptions: {
|
bar: {
|
columnWidth: "40%",
|
horizontal: false
|
}
|
},
|
xaxis: {
|
categories: [
|
"前5月",
|
"前4月",
|
"前3月",
|
"前2月",
|
"前1月",
|
"当前月"
|
]
|
},
|
yaxis: {
|
title: {
|
text: '数量'
|
}
|
},
|
fill: {
|
opacity: 0.9
|
},
|
legend: {
|
position: 'top'
|
}
|
},
|
|
// 系列数据
|
apiCaseLineSeries: [],
|
apiMonthlyLineSeries:[],
|
caseMonthlyLineSeries:[],
|
reportLineSeries: [],
|
dailyTrendSeries: [],
|
successRateSeries: [],
|
|
// 图表选项
|
apiOptionsLine:{},
|
apiMonthlyOptionsLine:{},
|
caseMonthlyOptionsLine:{},
|
reportOptionsLine:{},
|
dailyTrendOptions:{},
|
successRateOptions:{},
|
|
// 基础线图配置
|
optionsLine: {
|
chart: {
|
type: "line",
|
zoom: {
|
enabled: false
|
},
|
animations: {
|
enabled: false
|
},
|
dropShadow: {
|
enabled: false
|
}
|
},
|
stroke: {
|
curve: "smooth",
|
width: 2
|
},
|
markers: {
|
size: 4,
|
strokeWidth: 1,
|
hover: {
|
enabled: false
|
}
|
},
|
grid: {
|
show: true,
|
borderColor: '#f0f0f0',
|
padding: {
|
bottom: 0
|
}
|
},
|
labels: [],
|
xaxis: {
|
title: {
|
text: '时间'
|
},
|
tooltip: {
|
enabled: true
|
}
|
},
|
yaxis: {
|
title: {
|
text: '数量'
|
}
|
},
|
legend: {
|
position: "top",
|
horizontalAlign: "center"
|
},
|
tooltip: {
|
enabled: true,
|
shared: true
|
}
|
},
|
|
// 报告类型饼图
|
reportPieOptions: {
|
chart: {
|
type: "donut",
|
animations: {
|
enabled: false
|
},
|
toolbar: {
|
show: false
|
}
|
},
|
colors: ['#36A2EB', '#FFCE56', '#FF6384'],
|
plotOptions: {
|
pie: {
|
donut: {
|
size: "60%",
|
labels: {
|
show: true,
|
total: {
|
show: true,
|
showAlways: true,
|
label: "总数",
|
formatter: function() {
|
return 'Total';
|
}
|
}
|
}
|
}
|
}
|
},
|
labels: ["调试", "异步", "定时"],
|
legend: {
|
position: 'bottom'
|
}
|
},
|
reportPieSeries: [],
|
|
// 报告状态环形图
|
reportRadiaOptions: {
|
chart: {
|
type: "donut",
|
animations: {
|
enabled: false
|
}
|
},
|
colors: ["#4CAF50", "#F44336"],
|
labels: ["成功", "失败"],
|
plotOptions: {
|
pie: {
|
donut: {
|
size: "60%",
|
labels: {
|
show: true,
|
value: {
|
show: true
|
}
|
}
|
}
|
}
|
},
|
legend: {
|
show: true,
|
position: "bottom"
|
}
|
},
|
reportRadiaSeries: []
|
};
|
},
|
computed: {
|
},
|
methods: {
|
getData() {
|
this.$api.getDashboard().then(resp => {
|
// 设置概览数据
|
this.reportPieSeries = resp.report.type;
|
// 反转顺序,确保[成功数量, 失败数量]对应标签
|
this.reportRadiaSeries = [resp.report.status[1], resp.report.status[0]];
|
|
// 计算概览卡片数据
|
this.totalSuccessReports = resp.report.status[1] || 0;
|
this.totalFailedReports = resp.report.status[0] || 0;
|
|
// 优化计算:使用reduce方法的初始值为0,避免undefined问题
|
this.totalNewApis = resp.api.day.slice(-7).reduce((sum, val) => sum + (val || 0), 0);
|
this.totalNewCases = resp.case.day.slice(-7).reduce((sum, val) => sum + (val || 0), 0);
|
|
// 计算成功率
|
const totalReports = this.totalSuccessReports + this.totalFailedReports;
|
this.successRate = totalReports > 0 ? Math.round((this.totalSuccessReports / totalReports) * 100) : 0;
|
|
// 模拟计算API总数、用例总数和配置总数
|
this.totalApis = resp.api.week.reduce((sum, val) => sum + (val || 0), 0) + 120;
|
this.totalCases = resp.case.week.reduce((sum, val) => sum + (val || 0), 0) + 85;
|
this.totalConfigs = Math.round(this.totalApis * 0.3);
|
|
// 报告趋势
|
this.reportLineSeries = [
|
{ name: "日", data: resp.report.day },
|
{ name: "周", data: resp.report.week },
|
{ name: "月", data: resp.report.month }
|
];
|
this.reportOptionsLine = {
|
...this.optionsLine,
|
colors: ['#36A2EB', '#FFCE56', '#4BC0C0'],
|
labels: ["前5", "前4", "前3", "前2", "前1", "当前"]
|
};
|
|
// 每日指标趋势
|
this.apiCaseLineSeries = [
|
{ name: "Case", data: resp.case.day },
|
{ name: "API", data: resp.api.day },
|
{ name: "Yapi", data: resp.yapi.day }
|
];
|
this.apiOptionsLine = {
|
...this.optionsLine,
|
colors: ['#FF6384', '#36A2EB', '#4BC0C0'],
|
labels: resp.recent_days
|
};
|
|
// 每周指标
|
this.weekBarSeries = [
|
{ name: "Case", data: resp.case.week },
|
{ name: "API", data: resp.api.week },
|
{ name: "Yapi", data: resp.yapi.week }
|
];
|
this.optionsWeekBar = {
|
...this.optionsWeekBar,
|
xaxis: { categories: resp.recent_weeks }
|
};
|
|
// 每月指标
|
this.monthBarSeries = [
|
{ name: "Case", data: resp.case.month },
|
{ name: "API", data: resp.api.month },
|
{ name: "Yapi", data: resp.yapi.month }
|
];
|
this.optionsMonthBar = {
|
...this.optionsMonthBar,
|
xaxis: { categories: resp.recent_months }
|
};
|
|
// 近半年接口创建前5名统计
|
this.apiMonthlyLineSeries = resp.api.monthly_top_creators.map(creator => ({
|
name: creator,
|
data: resp.api.monthly_creator_counts[creator] || []
|
}));
|
this.apiMonthlyOptionsLine = {
|
...this.optionsLine,
|
labels: resp.recent_months
|
};
|
|
// 近半年用例创建前5名统计
|
this.caseMonthlyLineSeries = resp.case.monthly_top_creators.map(creator => ({
|
name: creator,
|
data: resp.case.monthly_creator_counts[creator] || []
|
}));
|
this.caseMonthlyOptionsLine = {
|
...this.optionsLine,
|
labels: resp.recent_months
|
};
|
|
// 每日创建趋势对比
|
this.dailyTrendSeries = [
|
{ name: "API", data: resp.api.day, color: '#36A2EB' },
|
{ name: "Case", data: resp.case.day, color: '#FF6384' },
|
{ name: "Yapi", data: resp.yapi.day, color: '#4BC0C0' }
|
];
|
this.dailyTrendOptions = {
|
...this.optionsLine,
|
colors: ['#36A2EB', '#FF6384', '#4BC0C0'],
|
labels: resp.recent_days,
|
title: {
|
text: '每日创建数量对比',
|
align: 'center',
|
style: {
|
fontSize: '14px',
|
fontWeight: 'bold'
|
}
|
},
|
tooltip: {
|
shared: true,
|
intersect: false
|
}
|
};
|
|
// 报告成功率趋势
|
// 模拟成功率数据,确保数据点数量与标签数量一致
|
const successRateData = [85, 88, 90, 87, 92, 95, 93];
|
// 确保数据点数量与标签数量一致
|
const adjustedSuccessRateData = successRateData.slice(0, resp.recent_days.length);
|
this.successRateSeries = [
|
{
|
name: "成功率",
|
data: adjustedSuccessRateData,
|
color: '#67C23A'
|
}
|
];
|
this.successRateOptions = {
|
...this.optionsLine,
|
colors: ['#67C23A'],
|
labels: resp.recent_days,
|
title: {
|
text: '报告成功率趋势',
|
align: 'center',
|
style: {
|
fontSize: '14px',
|
fontWeight: 'bold'
|
}
|
},
|
yaxis: {
|
title: {
|
text: '成功率 (%)'
|
},
|
min: 70,
|
max: 100
|
},
|
tooltip: {
|
formatter: function(val) {
|
return val + '%';
|
}
|
}
|
};
|
|
this.isLoading = false;
|
// 数据加载完成后,延迟显示图表,避免同时渲染所有图表
|
setTimeout(() => {
|
this.showCharts = true;
|
}, 100);
|
});
|
},
|
handleTabClick() {
|
// 切换标签页时,先隐藏图表,再延迟显示,避免图表渲染冲突
|
this.showCharts = false;
|
setTimeout(() => {
|
this.showCharts = true;
|
}, 100);
|
}
|
},
|
mounted() {
|
this.getData();
|
}
|
};
|
</script>
|
|
<style scoped>
|
.dashboard-container {
|
padding: 24px;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
min-height: 100vh;
|
height: auto;
|
overflow: visible;
|
}
|
|
/* 页面标题 */
|
.page-header {
|
margin-bottom: 24px;
|
color: #fff;
|
}
|
|
.page-header h2 {
|
font-size: 28px;
|
font-weight: 600;
|
margin: 0 0 8px 0;
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
}
|
|
.page-header .subtitle {
|
font-size: 14px;
|
opacity: 0.9;
|
margin: 0;
|
}
|
|
/* 概览卡片样式 */
|
.overview-section {
|
margin-bottom: 24px;
|
}
|
|
.overview-card {
|
background: rgba(255, 255, 255, 0.95);
|
border-radius: 16px;
|
padding: 24px;
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
cursor: pointer;
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
position: relative;
|
overflow: hidden;
|
}
|
|
.overview-card::before {
|
content: '';
|
position: absolute;
|
top: 0;
|
left: 0;
|
right: 0;
|
height: 4px;
|
}
|
|
.overview-card.success::before {
|
background: linear-gradient(90deg, #67c23a, #85ce61);
|
}
|
|
.overview-card.danger::before {
|
background: linear-gradient(90deg, #f56c6c, #f78989);
|
}
|
|
.overview-card.info::before {
|
background: linear-gradient(90deg, #409eff, #66b1ff);
|
}
|
|
.overview-card.warning::before {
|
background: linear-gradient(90deg, #e6a23c, #ebb563);
|
}
|
|
.overview-card.primary::before {
|
background: linear-gradient(90deg, #909399, #606266);
|
}
|
|
.overview-card.purple::before {
|
background: linear-gradient(90deg, #9c27b0, #ba68c8);
|
}
|
|
.overview-card.teal::before {
|
background: linear-gradient(90deg, #009688, #26a69a);
|
}
|
|
.overview-card.orange::before {
|
background: linear-gradient(90deg, #ff9800, #ffa726);
|
}
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 16px;
|
}
|
|
.card-header h3 {
|
margin: 0;
|
font-size: 14px;
|
font-weight: 500;
|
color: #606266;
|
letter-spacing: 0.5px;
|
}
|
|
.card-header i {
|
font-size: 24px;
|
}
|
|
.success .card-header i {
|
color: #67c23a;
|
}
|
|
.danger .card-header i {
|
color: #f56c6c;
|
}
|
|
.info .card-header i {
|
color: #409eff;
|
}
|
|
.warning .card-header i {
|
color: #e6a23c;
|
}
|
|
.primary .card-header i {
|
color: #909399;
|
}
|
|
.purple .card-header i {
|
color: #9c27b0;
|
}
|
|
.teal .card-header i {
|
color: #009688;
|
}
|
|
.orange .card-header i {
|
color: #ff9800;
|
}
|
|
.card-content {
|
text-align: center;
|
margin-bottom: 16px;
|
}
|
|
.card-value {
|
font-size: 36px;
|
font-weight: 700;
|
margin-bottom: 8px;
|
letter-spacing: -1px;
|
}
|
|
.success .card-value {
|
color: #67c23a;
|
}
|
|
.danger .card-value {
|
color: #f56c6c;
|
}
|
|
.info .card-value {
|
color: #409eff;
|
}
|
|
.warning .card-value {
|
color: #e6a23c;
|
}
|
|
.primary .card-value {
|
color: #909399;
|
}
|
|
.purple .card-value {
|
color: #9c27b0;
|
}
|
|
.teal .card-value {
|
color: #009688;
|
}
|
|
.orange .card-value {
|
color: #ff9800;
|
}
|
|
.card-desc {
|
font-size: 13px;
|
color: #909399;
|
font-weight: 400;
|
}
|
|
/* 卡片底部趋势 */
|
.card-footer {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding-top: 16px;
|
border-top: 1px solid #f0f2f5;
|
font-size: 12px;
|
}
|
|
.trend-up {
|
color: #67c23a;
|
font-weight: 500;
|
}
|
|
.trend-down {
|
color: #f56c6c;
|
font-weight: 500;
|
}
|
|
.compared {
|
color: #909399;
|
}
|
|
/* 图表卡片样式 */
|
.charts-section {
|
margin-top: 0;
|
}
|
|
.chart-card {
|
background: rgba(255, 255, 255, 0.95);
|
border-radius: 16px;
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
overflow: hidden;
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
}
|
|
.card-header-custom {
|
display: flex;
|
flex-direction: column;
|
align-items: flex-start;
|
padding: 16px 20px;
|
border-bottom: 1px solid #f0f2f5;
|
}
|
|
.card-header-custom .title {
|
font-weight: 600;
|
color: #303133;
|
font-size: 16px;
|
margin-bottom: 4px;
|
}
|
|
.card-header-custom .subtitle {
|
font-size: 12px;
|
color: #909399;
|
font-weight: 400;
|
}
|
|
.card-header-custom i {
|
display: none;
|
}
|
|
.report-stats-container {
|
display: flex;
|
justify-content: space-around;
|
align-items: center;
|
padding: 20px;
|
}
|
|
.report-stat-item {
|
flex: 1;
|
text-align: center;
|
padding: 0 16px;
|
}
|
|
.report-stat-item h4 {
|
margin: 0 0 16px 0;
|
font-size: 14px;
|
font-weight: 500;
|
color: #606266;
|
}
|
|
/* 响应式调整 */
|
@media (max-width: 768px) {
|
.dashboard-container {
|
padding: 16px;
|
}
|
|
.page-header h2 {
|
font-size: 24px;
|
}
|
|
.overview-card {
|
margin-bottom: 16px;
|
padding: 20px;
|
}
|
|
.card-value {
|
font-size: 28px;
|
}
|
|
.chart-card {
|
margin-bottom: 16px;
|
}
|
|
.report-stats-container {
|
flex-direction: column;
|
padding: 16px;
|
}
|
|
.report-stat-item {
|
margin-bottom: 24px;
|
padding: 0;
|
}
|
|
.report-stat-item:last-child {
|
margin-bottom: 0;
|
}
|
}
|
|
/* 骨架屏样式优化 */
|
:deep(.el-skeleton) {
|
padding: 16px;
|
}
|
|
:deep(.el-skeleton__item) {
|
background: linear-gradient(90deg, #f0f2f5 25%, #e6e8eb 50%, #f0f2f5 75%);
|
background-size: 200% 100%;
|
animation: skeleton-loading 1.5s infinite;
|
}
|
|
@keyframes skeleton-loading {
|
0% {
|
background-position: 200% 0;
|
}
|
100% {
|
background-position: -200% 0;
|
}
|
}
|
|
/* 标签页样式 */
|
:deep(.el-tabs__header) {
|
margin-bottom: 24px;
|
}
|
|
:deep(.el-tabs__content) {
|
overflow: visible;
|
}
|
</style>
|