<!DOCTYPE html>
|
<html lang="zh-CN">
|
<head>
|
<meta charset="UTF-8">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<title>{{ name }}</title>
|
<style>
|
* {
|
margin: 0;
|
padding: 0;
|
box-sizing: border-box;
|
}
|
|
body {
|
font-family: "Microsoft YaHei", "Segoe UI", Arial, sans-serif;
|
background-color: #f5f7fa;
|
color: #333;
|
line-height: 1.6;
|
padding: 20px;
|
}
|
|
.container {
|
max-width: 1000px;
|
margin: 0 auto;
|
background: #fff;
|
border-radius: 8px;
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
overflow: hidden;
|
}
|
|
/* 报告头部 */
|
.report-header {
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
color: white;
|
padding: 30px 40px;
|
}
|
|
.report-header.Pass {
|
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
|
}
|
|
.report-header.Fail {
|
background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
|
}
|
|
.report-header.Error {
|
background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
|
}
|
|
.report-title-row {
|
display: flex;
|
align-items: center;
|
gap: 15px;
|
margin-bottom: 15px;
|
}
|
|
.report-title {
|
font-size: 28px;
|
font-weight: bold;
|
}
|
|
.report-status {
|
font-size: 16px;
|
font-weight: bold;
|
padding: 6px 20px;
|
border-radius: 20px;
|
background: rgba(255, 255, 255, 0.25);
|
}
|
|
.report-meta {
|
display: flex;
|
gap: 40px;
|
font-size: 14px;
|
opacity: 0.9;
|
}
|
|
/* 筛选区域 */
|
.filter-section {
|
padding: 20px 40px;
|
background: #f8f9fa;
|
border-bottom: 1px solid #eee;
|
display: flex;
|
align-items: center;
|
gap: 20px;
|
}
|
|
.filter-label {
|
font-weight: bold;
|
color: #333;
|
}
|
|
.filter-buttons {
|
display: flex;
|
gap: 10px;
|
}
|
|
.filter-btn {
|
padding: 8px 20px;
|
border: 2px solid #ddd;
|
border-radius: 20px;
|
background: #fff;
|
cursor: pointer;
|
font-size: 14px;
|
font-weight: 500;
|
transition: all 0.2s ease;
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
}
|
|
.filter-btn:hover {
|
border-color: #667eea;
|
background: #f0f0ff;
|
}
|
|
.filter-btn.active {
|
color: white;
|
border-color: transparent;
|
}
|
|
.filter-btn.active.all {
|
background: #667eea;
|
}
|
|
.filter-btn.active.Pass {
|
background: #28a745;
|
}
|
|
.filter-btn.active.Fail {
|
background: #dc3545;
|
}
|
|
.filter-btn.active.Error {
|
background: #dc3545;
|
}
|
|
.filter-btn.active.skipped {
|
background: #ffc107;
|
color: #333;
|
}
|
|
.filter-count {
|
padding: 2px 8px;
|
border-radius: 10px;
|
background: rgba(0, 0, 0, 0.1);
|
font-size: 12px;
|
}
|
|
.filter-btn.active .filter-count {
|
background: rgba(255, 255, 255, 0.3);
|
}
|
|
/* 测试步骤 */
|
.steps-section {
|
padding: 30px 40px;
|
}
|
|
.steps-title {
|
font-size: 18px;
|
font-weight: bold;
|
color: #333;
|
margin-bottom: 20px;
|
padding-bottom: 10px;
|
border-bottom: 2px solid #667eea;
|
display: inline-block;
|
}
|
|
.step-card {
|
border: 1px solid #e0e0e0;
|
border-radius: 8px;
|
margin-bottom: 20px;
|
overflow: hidden;
|
transition: all 0.3s ease;
|
}
|
|
.step-card.hidden {
|
display: none;
|
}
|
|
.step-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 15px 20px;
|
background: #f8f9fa;
|
border-bottom: 1px solid #e0e0e0;
|
}
|
|
.step-header.NotSet {
|
background: #e8e8e8;
|
}
|
|
.step-header.Pass {
|
background: #d4edda;
|
}
|
|
.step-header.Fail {
|
background: #f8d7da;
|
}
|
|
.step-header.Error {
|
background: #f8d7da;
|
}
|
|
.step-header.Abort {
|
background: #fff3cd;
|
}
|
|
.step-title {
|
font-weight: bold;
|
font-size: 16px;
|
display: flex;
|
align-items: center;
|
gap: 10px;
|
}
|
|
.step-badge {
|
display: inline-block;
|
padding: 4px 12px;
|
border-radius: 20px;
|
font-size: 12px;
|
font-weight: normal;
|
}
|
|
.step-badge.NotSet {
|
background: #b4b4b4;
|
}
|
|
.step-badge.Pass {
|
background: #28a745;
|
color: white;
|
}
|
|
.step-badge.Fail {
|
background: #dc3545;
|
color: white;
|
}
|
|
.step-badge.Error {
|
background: #dc3545;
|
color: white;
|
}
|
|
.step-badge.skipped {
|
background: #ffc107;
|
color: #333;
|
}
|
|
.step-info {
|
display: flex;
|
gap: 30px;
|
font-size: 13px;
|
color: #666;
|
}
|
|
.step-content {
|
padding: 20px;
|
}
|
|
.step-params-title {
|
font-weight: bold;
|
font-size: 14px;
|
color: #333;
|
margin-bottom: 10px;
|
}
|
|
/* 参数表格 */
|
.params-table {
|
width: 100%;
|
border-collapse: collapse;
|
font-size: 14px;
|
}
|
|
.params-table th,
|
.params-table td {
|
padding: 12px 15px;
|
text-align: left;
|
border-bottom: 1px solid #eee;
|
}
|
|
.params-table th {
|
background: #f8f9fa;
|
font-weight: bold;
|
color: #333;
|
width: 150px;
|
}
|
|
.params-table tr:last-child td,
|
.params-table tr:last-child th {
|
border-bottom: none;
|
}
|
|
.params-table tr:hover {
|
background: #f8f9fa;
|
}
|
|
/* 空状态提示 */
|
.no-results {
|
text-align: center;
|
padding: 40px;
|
color: #999;
|
font-size: 16px;
|
}
|
|
.no-results-icon {
|
font-size: 48px;
|
margin-bottom: 10px;
|
}
|
|
/* 报告底部 */
|
.report-footer {
|
padding: 20px 40px;
|
background: #f8f9fa;
|
text-align: center;
|
font-size: 12px;
|
color: #999;
|
}
|
|
/* 响应式 */
|
@media (max-width: 768px) {
|
.report-meta {
|
flex-direction: column;
|
gap: 10px;
|
}
|
|
.filter-section {
|
flex-direction: column;
|
align-items: flex-start;
|
}
|
|
.filter-buttons {
|
flex-wrap: wrap;
|
}
|
|
.step-info {
|
flex-direction: column;
|
gap: 5px;
|
}
|
}
|
</style>
|
</head>
|
<body>
|
<div class="container">
|
<!-- 报告头部 - 通过状态 -->
|
<div class="report-header {{ verdict }}">
|
<div class="report-title-row">
|
<h1 class="report-title">{{ name }}</h1>
|
<span class="report-status">{{ verdict }}</span>
|
</div>
|
<div class="report-meta">
|
<span>{{ start_time }}</span>
|
<span>{{ end_time }}</span>
|
</div>
|
</div>
|
|
<!-- 筛选区域 -->
|
<div class="filter-section">
|
<span class="filter-label">筛选:</span>
|
<div class="filter-buttons">
|
<button class="filter-btn active all" onclick="filterSteps('all')">
|
全部 <span class="filter-count" id="count-all"></span>
|
</button>
|
<button class="filter-btn Pass" onclick="filterSteps('Pass')">
|
通过 <span class="filter-count" id="count-passed"></span>
|
</button>
|
<button class="filter-btn Fail" onclick="filterSteps('Fail')">
|
失败 <span class="filter-count" id="count-failed"></span>
|
</button>
|
<button class="filter-btn Error" onclick="filterSteps('Error')">
|
错误 <span class="filter-count" id="count-error"></span>
|
</button>
|
</div>
|
</div>
|
|
<!-- 测试步骤详情 -->
|
<div class="steps-section">
|
<h2 class="steps-title">测试步骤详情</h2>
|
|
{{ for step in steps }}
|
<div class="step-card" data-status="{{ step.verdict }}">
|
<div class="step-header {{ step.verdict }}">
|
<div class="step-title">
|
<span>{{ step.name }}</span>
|
<span class="step-badge {{ step.verdict }}">{{ step.verdict }}</span>
|
</div>
|
<div class="step-info">
|
<span>{{ step.start_time }}</span>
|
<span>{{ step.end_time }}</span>
|
<span>{{ step.consuming }}</span>
|
</div>
|
</div>
|
<div class="step-content">
|
<div class="step-params-title">测试参数</div>
|
<table class="params-table">
|
<tr>
|
<th>参数名称</th>
|
<th>参数类型</th>
|
<th>参数值</th>
|
</tr>
|
{{ for param in step.parameters }}
|
<tr>
|
<td>{{ param.name }}</td>
|
<td>{{ param.type }}</td>
|
<td>{{ param.value }}</td>
|
</tr>
|
{{ end }}
|
</table>
|
</div>
|
</div>
|
{{ end }}
|
|
<!-- 空状态提示(默认隐藏) -->
|
<div class="no-results" id="no-results" style="display: none;">
|
<div class="no-results-icon">🔍</div>
|
<div>没有符合条件的测试步骤</div>
|
</div>
|
</div>
|
|
<!-- 报告底部 -->
|
<div class="report-footer">
|
<p>本报告由自动化测试系统生成 | 生成时间:{{ create_time }}</p>
|
</div>
|
</div>
|
|
<script>
|
// 筛选测试步骤
|
function filterSteps(status) {
|
const cards = document.querySelectorAll('.step-card');
|
const buttons = document.querySelectorAll('.filter-btn');
|
const noResults = document.getElementById('no-results');
|
let visibleCount = 0;
|
|
// 更新按钮状态
|
buttons.forEach(btn => {
|
btn.classList.remove('active');
|
if (btn.classList.contains(status)) {
|
btn.classList.add('active');
|
}
|
});
|
|
// 筛选卡片
|
cards.forEach(card => {
|
const cardStatus = card.getAttribute('data-status');
|
|
if (status === 'all' || cardStatus === status) {
|
card.classList.remove('hidden');
|
visibleCount++;
|
} else {
|
card.classList.add('hidden');
|
}
|
});
|
|
// 显示/隐藏空状态提示
|
if (visibleCount === 0) {
|
noResults.style.display = 'block';
|
} else {
|
noResults.style.display = 'none';
|
}
|
}
|
|
// 页面加载时自动计算各状态数量
|
document.addEventListener('DOMContentLoaded', function() {
|
const cards = document.querySelectorAll('.step-card');
|
let passed = 0, failed = 0, skipped = 0;error = 0;
|
|
cards.forEach(card => {
|
const status = card.getAttribute('data-status');
|
if (status === 'Pass') passed++;
|
else if (status === 'Fail') failed++;
|
else if (status === 'skipped') skipped++;
|
else if (status === 'Error') error++;
|
});
|
|
// 更新计数
|
document.getElementById('count-all').textContent = cards.length;
|
document.getElementById('count-passed').textContent = passed;
|
document.getElementById('count-failed').textContent = failed;
|
document.getElementById('count-error').textContent = error;
|
});
|
</script>
|
</body>
|
</html>
|