Merge remote-tracking branch 'origin/master'

This commit is contained in:
liangdaliang
2025-07-01 16:37:12 +08:00
15 changed files with 397 additions and 37 deletions

View File

@@ -9,6 +9,8 @@ const api = {
testPlanProjectList: '/test/testPlanProject/list',
addTestReport: 'test/testReport/addTestReport',
getTestReportList: 'test/testReport/reportList',
delExecuteCaseReport: 'test/testReport/delExecuteCaseReport',
updateExecuteCaseReport: 'test/testReport/updateExecuteCaseReport',
getPlanOverview:'test/testPlan/planOverview',
getPlanCaseTrendData: 'test/testPlan/planCaseTrendData',
}
@@ -77,6 +79,22 @@ export function getTestReportList(data) {
})
}
export function delExecuteCaseReport(id) {
return request({
url: api.delExecuteCaseReport,
method: 'post',
data: {id}
})
}
export function updateExecuteCaseReport(data) {
return request({
url: api.updateExecuteCaseReport,
method: 'post',
data: data
})
}
export function getPlanOverview(id) {
return request({
url: api.getPlanOverview,

View File

@@ -35,6 +35,11 @@
</el-table-column>
<el-table-column prop="updateBy" label="最后更新人" align="center"/>
<el-table-column prop="updateTime" label="最后更新时间" align="center"/>
<el-table-column label="操作" align="center">
<template #default="{ row }">
<el-button type="text" size="mini" @click.native.stop="handleDel(row.id)">删除</el-button>
</template>
</el-table-column>
</el-Table>
</el-tabs>
<pagination
@@ -65,7 +70,7 @@
</template>
<script>
import SimpleOptions from "@/components/FormItem/option/SimpleOptions.vue";
import {addTestReport, getTestReportList} from "@/api/test/testPlan";
import {addTestReport, delExecuteCaseReport, getTestReportList} from "@/api/test/testPlan";
export default {
name: 'caseReport',
@@ -101,19 +106,34 @@ export default {
}
}
},
activated() {
this.$nextTick(() => {
console.log('getlist')
this.getList()
})
},
mounted() {
this.getList()
},
methods: {
handleRowClick(row){
this.$tab.openPage('平台报告', '/testplan/casereport/platformReport',
{id: row.id,
name: row.name,
type: row.result,
type: row.type,
planId: row.planId,
report: row.report
}
)
},
handleDel(id) {
this.$modal.confirm('是否确认删除测试报告?').then(function () {
return delExecuteCaseReport(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
});
},
getList() {
this.loading = true
this.queryParams.id = Number(this.planId)

View File

@@ -3,9 +3,9 @@
<el-row :gutter="10" class="mb8">
<el-col :span="24" class="page-header">
<el-page-header :title="reportTitle" @back="goBack" ></el-page-header>
<div class="header-buttons">
<div class="header-buttons" v-if="isEdit">
<span>测试结果</span>
<el-select v-model="selectedResult" placeholder="请选择" clearable>
<el-select v-model="selectedResult" placeholder="请选择">
<el-option
v-for="item in resultOptions"
:key="item.value"
@@ -15,28 +15,42 @@
</el-select>
<el-button type="primary" icon="el-icon-setting" @click="configureModule">配置模块</el-button>
<el-button type="primary" size="medium" @click="saveReport">保存报告</el-button>
<el-button type="danger" size="medium" @click="isEdit = false">取消编辑</el-button>
</div>
<div class="header-buttons" v-else>
<el-button type="primary" icon="el-icon-setting" @click="configureModule">下载报告</el-button>
<el-button type="primary" size="medium" @click="isEdit = true">编辑报告</el-button>
</div>
</el-col>
</el-row>
<div class="report-container">
<div class="report-container" :class="testStatusClass">
<div class="report-header">
<div class="report-title">
<span>{{ reportTitle }}</span>
<div class="report-title" v-if="isEdit">
<el-input v-model="reportTitle" style="width: 300px" placeholder="请输入报告名称"/>
<div class="report-info">
<span>关联项目中移商业保理平台</span>
<span>测试阶段{{ reportType }}</span>
</div>
</div>
<div class="report-info">
<span>关联项目中移商业保理平台</span>
<span>测试阶段{{ reportType }}</span>
<div class="report-title" v-else>
<span>{{ reportTitle }}</span>
<div class="report-info">
<span>关联项目中移商业保理平台</span>
<span>测试阶段{{ reportType }}</span>
</div>
</div>
</div>
<div class="report-overview">
<div class="overview-item">
<div class="value">1</div>
<div class="value">{{ reportData.caseNum }}</div>
<span class="label">执行用例数</span>
</div>
<div class="overview-item">
<span class="value">100%</span>
<div class="progress-bar"></div>
<span class="value">{{ passRate }}%</span>
<div class="progress-bar-container">
<div class="progress-bar" :style="{ width: passRate + '%' }"></div>
</div>
<div class="label">用例通过率</div>
</div>
<div class="overview-item">
@@ -71,6 +85,7 @@
<script>
import * as echarts from 'echarts';
import router from "@/router";
import {updateExecuteCaseReport} from "@/api/test/testPlan";
export default {
name: 'report',
@@ -83,13 +98,15 @@ export default {
},
data() {
return {
isEdit: false,
reportId: '',
reportType: '',
reportTitle: '',
reportData: {},
selectedResult: '', // 选择的测试结果
resultOptions: [ // 测试结果选项
{ value: 'all', label: '全部' },
{ value: 'passed', label: '通过' },
{ value: 'failed', label: '失败' }
{ value: '1', label: '通过' },
{ value: '0', label: '通过' }
],
// 执行结果分布数据
@@ -106,14 +123,24 @@ export default {
// 用例类型分布数据
caseTypeDistributionData: {
series: [
{ value: 1, name: '接口用例' ,itemStyle: {color: '#6fcdac'} }
{ value: 0, name: '接口用例' ,itemStyle: {color: '#6fcdac'} }
]
}
};
},
created() {
this.reportId = this.$route.query.id;
this.reportTitle = this.$route.query.name;
this.reportType = this.$route.query.type;
this.reportData = JSON.parse(this.$route.query.report);
this.selectedResult = this.reportData.result;
// 更新饼图数据
this.resultDistributionData.series[0].value = this.reportData.passNum || 0;
this.resultDistributionData.series[1].value = this.reportData.caseNum - this.reportData.passNum || 0;
// 更新接口用例饼图数据
this.caseTypeDistributionData.series[0].value = this.reportData.caseNum || 0;
},
watch: {
'dict.type.test_type': {
@@ -127,11 +154,33 @@ export default {
}
},
computed: {
passRate() {
if (this.reportData.caseNum === 0) return 0;
return (this.reportData.passNum / this.reportData.caseNum) * 100;
},
testStatusClass() {
return this.selectedResult === '0' ? 'status-not-passed' : 'status-passed';
}
},
mounted() {
this.initResultDistributionChart();
this.initCaseTypeDistributionChart();
// 强制重绘图表以应用最新数据
this.$nextTick(() => {
const chartDom = document.getElementById('result-distribution-chart');
if (chartDom) {
const myChart = echarts.getInstanceByDom(chartDom);
myChart.setOption({
series: [{
type: 'pie',
radius: ['40%', '70%'],
data: this.resultDistributionData.series
}]
}, true); // true 表示合并选项
}
});
},
methods: {
initResultDistributionChart() {
@@ -219,9 +268,31 @@ export default {
},
saveReport() {
// 保存报告的逻辑
console.log('Save report');
}
let reportData = {
caseNum: this.reportData.caseNum,
name: this.reportData.name,
passNum: this.reportData.passNum,
result: this.selectedResult // 使用外部的 result 值替换
};
// 构造要提交的数据对象
const reportDataToSave = {
id: this.reportId,
name: this.reportTitle,
result: this.selectedResult,
report: JSON.stringify(reportData)
};
updateExecuteCaseReport(reportDataToSave)
.then(response => {
this.$message.success('报告保存成功');
// 可选:更新页面状态为非编辑模式
this.isEdit = false;
})
.catch(error => {
this.$message.error('报告保存失败');
console.error('保存报告失败:', error);
});
},
},
}
</script>
@@ -230,7 +301,12 @@ export default {
.report-container {
height: 300px;
margin-bottom: 20px;
background: linear-gradient(90deg, #6fcdac, #9ed2bb);
&.status-not-passed {
background: linear-gradient(180deg, #e7998b, #e8b1b0);
}
&.status-passed {
background: linear-gradient(180deg, #6fcdac, #9ed2bb);
}
.report-header {
color: white;
@@ -268,13 +344,29 @@ export default {
font-size: 14px;
}
.progress-bar {
.progress-bar-container {
width: 100px;
height: 10px;
background-color: white;
background-color: #e0e0e0; /* 背景颜色表示未完成部分 */
border-radius: 5px;
overflow: hidden;
margin-top: 10px;
}
.progress-bar {
height: 100%;
background-color: white; /* 进度条颜色 */
border-radius: 5px;
}
//.progress-bar {
// width: 100px;
// height: 10px;
// background-color: white;
// margin-top: 10px;
// border-radius: 5px;
//}
}
}
}