| | |
| | | <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" @mouseenter="cardHover=true" @mouseleave="cardHover=false"> |
| | | <div class="overview-card success"> |
| | | <div class="card-header"> |
| | | <h3>成功报告</h3> |
| | | <i class="el-icon-check-circle"></i> |
| | |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6"> |
| | | <div class="overview-card danger" @mouseenter="cardHover=true" @mouseleave="cardHover=false"> |
| | | <div class="overview-card danger"> |
| | | <div class="card-header"> |
| | | <h3>失败报告</h3> |
| | | <i class="el-icon-close-circle"></i> |
| | |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6"> |
| | | <div class="overview-card info" @mouseenter="cardHover=true" @mouseleave="cardHover=false"> |
| | | <div class="overview-card info"> |
| | | <div class="card-header"> |
| | | <h3>新增API</h3> |
| | | <i class="el-icon-document-add"></i> |
| | |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6"> |
| | | <div class="overview-card warning" @mouseenter="cardHover=true" @mouseleave="cardHover=false"> |
| | | <div class="overview-card warning"> |
| | | <div class="card-header"> |
| | | <h3>新增用例</h3> |
| | | <i class="el-icon-edit-outline"></i> |
| | |
| | | <!-- 第二行概览卡片 --> |
| | | <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" @mouseenter="cardHover=true" @mouseleave="cardHover=false"> |
| | | <div class="overview-card primary"> |
| | | <div class="card-header"> |
| | | <h3>API总数</h3> |
| | | <i class="el-icon-collection-tag"></i> |
| | |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6"> |
| | | <div class="overview-card purple" @mouseenter="cardHover=true" @mouseleave="cardHover=false"> |
| | | <div class="overview-card purple"> |
| | | <div class="card-header"> |
| | | <h3>用例总数</h3> |
| | | <i class="el-icon-document-copy"></i> |
| | |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6"> |
| | | <div class="overview-card teal" @mouseenter="cardHover=true" @mouseleave="cardHover=false"> |
| | | <div class="overview-card teal"> |
| | | <div class="card-header"> |
| | | <h3>报告通过率</h3> |
| | | <i class="el-icon-data-line"></i> |
| | |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6"> |
| | | <div class="overview-card orange" @mouseenter="cardHover=true" @mouseleave="cardHover=false"> |
| | | <div class="overview-card orange"> |
| | | <div class="card-header"> |
| | | <h3>配置总数</h3> |
| | | <i class="el-icon-setting"></i> |
| | |
| | | |
| | | <!-- 图表区域 --> |
| | | <div class="charts-section"> |
| | | <!-- 第一行 --> |
| | | <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-else |
| | | :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-else |
| | | :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="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-else |
| | | :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-else |
| | | :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-else class="report-stats-container"> |
| | | <div class="report-stat-item"> |
| | | <h4>报告类型</h4> |
| | | <!-- 图表标签页 --> |
| | | <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 |
| | | :options="reportPieOptions" |
| | | :series="reportPieSeries" |
| | | height="200" |
| | | v-if="!isLoading && showCharts" |
| | | :options="apiOptionsLine" |
| | | :series="apiCaseLineSeries" |
| | | height="350" |
| | | ></ApexCharts> |
| | | </div> |
| | | <div class="report-stat-item"> |
| | | <h4>报告状态</h4> |
| | | </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 |
| | | :options="reportRadiaOptions" |
| | | :series="reportRadiaSeries" |
| | | height="200" |
| | | v-if="!isLoading && showCharts" |
| | | :options="reportOptionsLine" |
| | | :series="reportLineSeries" |
| | | height="350" |
| | | ></ApexCharts> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </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">近半年接口创建前5名</span> |
| | | <span class="subtitle">按创建人统计</span> |
| | | </div> |
| | | <el-skeleton v-if="isLoading" :rows="10" animated /> |
| | | <ApexCharts |
| | | v-else |
| | | :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-else |
| | | :options="caseMonthlyOptionsLine" |
| | | :series="caseMonthlyLineSeries" |
| | | 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-else |
| | | :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-else |
| | | :options="successRateOptions" |
| | | :series="successRateSeries" |
| | | 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> |
| | |
| | | data() { |
| | | return { |
| | | isLoading: true, |
| | | activeTab: 'trends', |
| | | showCharts: false, |
| | | // 概览数据 |
| | | totalSuccessReports: 0, |
| | | totalFailedReports: 0, |
| | |
| | | totalCases: 0, |
| | | totalConfigs: 0, |
| | | successRate: 0, |
| | | |
| | | |
| | | |
| | | // 图表数据 |
| | | weekBarSeries: [], |
| | |
| | | }; |
| | | |
| | | this.isLoading = false; |
| | | // 数据加载完成后,延迟显示图表,避免同时渲染所有图表 |
| | | setTimeout(() => { |
| | | this.showCharts = true; |
| | | }, 100); |
| | | }); |
| | | }, |
| | | handleTabClick() { |
| | | // 切换标签页时,先隐藏图表,再延迟显示,避免图表渲染冲突 |
| | | this.showCharts = false; |
| | | setTimeout(() => { |
| | | this.showCharts = true; |
| | | }, 100); |
| | | } |
| | | }, |
| | | mounted() { |
| | |
| | | .page-header { |
| | | margin-bottom: 24px; |
| | | color: #fff; |
| | | animation: fadeInDown 0.6s ease-out; |
| | | } |
| | | |
| | | .page-header h2 { |
| | |
| | | border-radius: 16px; |
| | | padding: 24px; |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); |
| | | transition: box-shadow 0.2s ease; |
| | | cursor: pointer; |
| | | backdrop-filter: blur(10px); |
| | | border: 1px solid rgba(255, 255, 255, 0.2); |
| | | position: relative; |
| | | overflow: hidden; |
| | |
| | | |
| | | .overview-card.orange::before { |
| | | background: linear-gradient(90deg, #ff9800, #ffa726); |
| | | } |
| | | |
| | | .overview-card:hover { |
| | | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); |
| | | background: rgba(255, 255, 255, 1); |
| | | } |
| | | |
| | | .card-header { |
| | |
| | | |
| | | .success .card-value { |
| | | color: #67c23a; |
| | | text-shadow: 0 2px 4px rgba(103, 194, 58, 0.1); |
| | | } |
| | | |
| | | .danger .card-value { |
| | | color: #f56c6c; |
| | | text-shadow: 0 2px 4px rgba(245, 108, 108, 0.1); |
| | | } |
| | | |
| | | .info .card-value { |
| | | color: #409eff; |
| | | text-shadow: 0 2px 4px rgba(64, 158, 255, 0.1); |
| | | } |
| | | |
| | | .warning .card-value { |
| | | color: #e6a23c; |
| | | text-shadow: 0 2px 4px rgba(230, 162, 60, 0.1); |
| | | } |
| | | |
| | | .primary .card-value { |
| | | color: #909399; |
| | | text-shadow: 0 2px 4px rgba(144, 147, 153, 0.1); |
| | | } |
| | | |
| | | .purple .card-value { |
| | | color: #9c27b0; |
| | | text-shadow: 0 2px 4px rgba(156, 39, 176, 0.1); |
| | | } |
| | | |
| | | .teal .card-value { |
| | | color: #009688; |
| | | text-shadow: 0 2px 4px rgba(0, 150, 136, 0.1); |
| | | } |
| | | |
| | | .orange .card-value { |
| | | color: #ff9800; |
| | | text-shadow: 0 2px 4px rgba(255, 152, 0, 0.1); |
| | | } |
| | | |
| | | .card-desc { |
| | |
| | | .chart-card { |
| | | background: rgba(255, 255, 255, 0.95); |
| | | border-radius: 16px; |
| | | box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); |
| | | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
| | | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); |
| | | overflow: hidden; |
| | | backdrop-filter: blur(10px); |
| | | border: 1px solid rgba(255, 255, 255, 0.2); |
| | | animation: fadeInUp 0.6s ease-out; |
| | | } |
| | | |
| | | .chart-card:hover { |
| | | box-shadow: 0 16px 48px rgba(0, 0, 0, 0.15); |
| | | background: rgba(255, 255, 255, 1); |
| | | } |
| | | |
| | | .card-header-custom { |
| | |
| | | color: #606266; |
| | | } |
| | | |
| | | /* 动画效果 */ |
| | | @keyframes fadeInDown { |
| | | from { |
| | | opacity: 0; |
| | | transform: translateY(-20px); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | @keyframes fadeInUp { |
| | | from { |
| | | opacity: 0; |
| | | transform: translateY(20px); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | transform: translateY(0); |
| | | } |
| | | } |
| | | |
| | | @keyframes countUp { |
| | | from { |
| | | opacity: 0; |
| | | transform: scale(0.8); |
| | | } |
| | | to { |
| | | opacity: 1; |
| | | transform: scale(1); |
| | | } |
| | | } |
| | | |
| | | /* 为不同卡片添加延迟动画 */ |
| | | .chart-card:nth-child(1) { |
| | | animation-delay: 0.1s; |
| | | } |
| | | |
| | | .chart-card:nth-child(2) { |
| | | animation-delay: 0.2s; |
| | | } |
| | | |
| | | .chart-card:nth-child(3) { |
| | | animation-delay: 0.3s; |
| | | } |
| | | |
| | | /* 响应式调整 */ |
| | | @media (max-width: 768px) { |
| | | .dashboard-container { |
| | |
| | | .overview-card { |
| | | margin-bottom: 16px; |
| | | padding: 20px; |
| | | } |
| | | |
| | | .overview-card:hover { |
| | | transform: translateY(-4px) scale(1.01); |
| | | } |
| | | |
| | | .card-value { |
| | |
| | | background-position: -200% 0; |
| | | } |
| | | } |
| | | |
| | | /* 标签页样式 */ |
| | | :deep(.el-tabs__header) { |
| | | margin-bottom: 24px; |
| | | } |
| | | |
| | | :deep(.el-tabs__content) { |
| | | overflow: visible; |
| | | } |
| | | </style> |