refactor: update SVG circle radius and improve code readability in ReportExportDialog
Build and Push CodeReview / build (push) Waiting to run Details

This commit is contained in:
vinland100 2026-01-12 15:08:33 +08:00
parent 7f951d5451
commit 7c0d95385f
2 changed files with 537 additions and 333 deletions

View File

@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -32,8 +33,17 @@
--code-bg: #0d1117;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
@ -43,7 +53,11 @@
font-size: 14px;
}
.container { max-width: 900px; margin: 0 auto; padding: 0 1.5rem; }
.container {
max-width: 900px;
margin: 0 auto;
padding: 0 1.5rem;
}
/* Header */
.header {
@ -90,7 +104,11 @@
color: white;
}
.brand-text { font-size: 1rem; font-weight: 700; color: var(--text-primary); }
.brand-text {
font-size: 1rem;
font-weight: 700;
color: var(--text-primary);
}
.header-title {
font-size: 1.25rem;
@ -137,19 +155,24 @@
}
.score-ring svg {
transform: rotate(-90deg);
transform: rotate(90deg) scaleY(-1);
width: 56px;
height: 56px;
}
.score-ring-bg { fill: none; stroke: var(--border); stroke-width: 5; }
.score-ring-bg {
fill: none;
stroke: var(--border);
stroke-width: 5;
}
.score-ring-progress {
fill: none;
stroke: #ef4444;
stroke-width: 5;
stroke-linecap: round;
stroke-dasharray: 251.32741228718345;
stroke-dashoffset: 161.35219868837177;
stroke-dasharray: 144.51326206513048;
stroke-dashoffset: 92.48848772168351;
filter: drop-shadow(0 0 4px #ef444440);
}
@ -219,15 +242,48 @@
font-weight: 700;
}
.stat-card-icon.critical { background: var(--critical-bg); color: var(--critical); }
.stat-card-icon.high { background: var(--high-bg); color: var(--high); }
.stat-card-icon.total { background: var(--info-bg); color: var(--info); }
.stat-card-icon.verified { background: rgba(16,185,129,0.1); color: var(--success); }
.stat-card-icon.critical {
background: var(--critical-bg);
color: var(--critical);
}
.stat-card-label { font-size: 0.6rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; }
.stat-card-value { font-size: 1.25rem; font-weight: 700; color: var(--text-primary); font-family: 'SF Mono', monospace; line-height: 1; }
.stat-card-value.critical { color: var(--critical); }
.stat-card-value.high { color: var(--high); }
.stat-card-icon.high {
background: var(--high-bg);
color: var(--high);
}
.stat-card-icon.total {
background: var(--info-bg);
color: var(--info);
}
.stat-card-icon.verified {
background: rgba(16, 185, 129, 0.1);
color: var(--success);
}
.stat-card-label {
font-size: 0.6rem;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.stat-card-value {
font-size: 1.25rem;
font-weight: 700;
color: var(--text-primary);
font-family: 'SF Mono', monospace;
line-height: 1;
}
.stat-card-value.critical {
color: var(--critical);
}
.stat-card-value.high {
color: var(--high);
}
/* Severity Bar */
.severity-section {
@ -257,11 +313,25 @@
background: var(--border);
}
.severity-segment { height: 100%; }
.severity-segment.critical { background: var(--critical); }
.severity-segment.high { background: var(--high); }
.severity-segment.medium { background: var(--medium); }
.severity-segment.low { background: var(--low); }
.severity-segment {
height: 100%;
}
.severity-segment.critical {
background: var(--critical);
}
.severity-segment.high {
background: var(--high);
}
.severity-segment.medium {
background: var(--medium);
}
.severity-segment.low {
background: var(--low);
}
.severity-legend {
display: flex;
@ -276,11 +346,27 @@
color: var(--text-muted);
}
.severity-dot { width: 6px; height: 6px; border-radius: 50%; }
.severity-dot.critical { background: var(--critical); }
.severity-dot.high { background: var(--high); }
.severity-dot.medium { background: var(--medium); }
.severity-dot.low { background: var(--low); }
.severity-dot {
width: 6px;
height: 6px;
border-radius: 50%;
}
.severity-dot.critical {
background: var(--critical);
}
.severity-dot.high {
background: var(--high);
}
.severity-dot.medium {
background: var(--medium);
}
.severity-dot.low {
background: var(--low);
}
/* Main Content */
.main-content {
@ -296,7 +382,10 @@
}
/* Typography */
h1, h2, h3, h4 {
h1,
h2,
h3,
h4 {
color: var(--text-primary);
font-weight: 600;
letter-spacing: -0.01em;
@ -312,7 +401,11 @@
gap: 0.5rem;
}
h1::before { content: "§"; color: var(--accent); font-weight: 400; }
h1::before {
content: "§";
color: var(--accent);
font-weight: 400;
}
h2 {
font-size: 1.1rem;
@ -321,7 +414,13 @@
border-bottom: 1px solid var(--border);
}
h2::before { content: "//"; color: var(--accent); margin-right: 0.35rem; font-weight: 400; opacity: 0.7; }
h2::before {
content: "//";
color: var(--accent);
margin-right: 0.35rem;
font-weight: 400;
opacity: 0.7;
}
h3 {
font-size: 1rem;
@ -330,9 +429,16 @@
border-left: 2px solid var(--accent);
}
h4 { font-size: 0.9rem; margin: 0.75rem 0 0.35rem; color: var(--text-secondary); }
h4 {
font-size: 0.9rem;
margin: 0.75rem 0 0.35rem;
color: var(--text-secondary);
}
p { margin-bottom: 0.6rem; font-size: 0.875rem; }
p {
margin-bottom: 0.6rem;
font-size: 0.875rem;
}
/* Code Blocks */
pre {
@ -369,7 +475,9 @@
color: #e2e8f0;
}
p code, li code, td code {
p code,
li code,
td code {
background: var(--bg-tertiary);
color: var(--accent);
padding: 0.15em 0.35em;
@ -406,13 +514,28 @@
border-bottom: 1px solid var(--border);
}
tr:last-child td { border-bottom: none; }
tr:hover td { background: rgba(255, 255, 255, 0.02); }
tr:last-child td {
border-bottom: none;
}
tr:hover td {
background: rgba(255, 255, 255, 0.02);
}
/* Lists */
ul, ol { margin: 0.5rem 0 0.5rem 1.25rem; }
li { margin-bottom: 0.25rem; font-size: 0.875rem; }
li::marker { color: var(--accent); }
ul,
ol {
margin: 0.5rem 0 0.5rem 1.25rem;
}
li {
margin-bottom: 0.25rem;
font-size: 0.875rem;
}
li::marker {
color: var(--accent);
}
/* Blockquotes */
blockquote {
@ -424,11 +547,19 @@
font-size: 0.85rem;
}
blockquote p:last-child { margin-bottom: 0; }
blockquote p:last-child {
margin-bottom: 0;
}
/* Links */
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
a {
color: var(--accent);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* HR */
hr {
@ -438,8 +569,14 @@
margin: 1.5rem 0;
}
strong { color: var(--text-primary); font-weight: 600; }
em { color: var(--text-muted); }
strong {
color: var(--text-primary);
font-weight: 600;
}
em {
color: var(--text-muted);
}
/* Footer */
.report-footer {
@ -481,14 +618,41 @@
/* Responsive */
@media (max-width: 768px) {
.container { padding: 0 1rem; }
.stats-grid { flex-direction: column; gap: 0.75rem; }
.score-ring-container { width: 100%; justify-content: center; }
.stats-cards { flex-wrap: wrap; }
.stat-card { min-width: calc(50% - 0.25rem); }
.severity-bar-wrap { flex-direction: column; align-items: stretch; gap: 0.5rem; }
.severity-legend { justify-content: center; }
.content-wrapper { padding: 1rem; }
.container {
padding: 0 1rem;
}
.stats-grid {
flex-direction: column;
gap: 0.75rem;
}
.score-ring-container {
width: 100%;
justify-content: center;
}
.stats-cards {
flex-wrap: wrap;
}
.stat-card {
min-width: calc(50% - 0.25rem);
}
.severity-bar-wrap {
flex-direction: column;
align-items: stretch;
gap: 0.5rem;
}
.severity-legend {
justify-content: center;
}
.content-wrapper {
padding: 1rem;
}
}
/* Print */
@ -505,16 +669,42 @@
--border: #e2e8f0;
--code-bg: #f8fafc;
}
body { background: white; font-size: 11pt; }
.header::before { display: none; }
.content-wrapper { border: none; padding: 0; }
pre { break-inside: avoid; }
code { color: #1e293b; }
p code, li code { background: #f1f5f9; color: #c2410c; }
a { color: #2563eb; }
body {
background: white;
font-size: 11pt;
}
.header::before {
display: none;
}
.content-wrapper {
border: none;
padding: 0;
}
pre {
break-inside: avoid;
}
code {
color: #1e293b;
}
p code,
li code {
background: #f1f5f9;
color: #c2410c;
}
a {
color: #2563eb;
}
}
</style>
</head>
<body>
<header class="header">
<div class="container">
@ -592,10 +782,18 @@
</div>
<div class="severity-legend">
<div class="severity-legend-item"><div class="severity-dot critical"></div>2</div>
<div class="severity-legend-item"><div class="severity-dot high"></div>3</div>
<div class="severity-legend-item"><div class="severity-dot medium"></div>2</div>
<div class="severity-legend-item"><div class="severity-dot low"></div>1</div>
<div class="severity-legend-item">
<div class="severity-dot critical"></div>2
</div>
<div class="severity-legend-item">
<div class="severity-dot high"></div>3
</div>
<div class="severity-legend-item">
<div class="severity-dot medium"></div>2
</div>
<div class="severity-legend-item">
<div class="severity-dot low"></div>1
</div>
</div>
</div>
</div>
@ -614,7 +812,8 @@
<th>内容</th>
</tr>
</thead>
<tbody><tr>
<tbody>
<tr>
<td><strong>项目名称</strong></td>
<td>VulnWebApp - 安全演示项目</td>
</tr>
@ -634,10 +833,12 @@
<td><strong>耗时</strong></td>
<td>13.0 分钟</td>
</tr>
</tbody></table>
</tbody>
</table>
<h2>执行摘要</h2>
<p><strong>安全评分: 35/100</strong> [未通过]
<em>严重 - 需要立即进行修复</em></p>
<em>严重 - 需要立即进行修复</em>
</p>
<h3>漏洞发现概览</h3>
<table>
<thead>
@ -647,7 +848,8 @@
<th>已验证</th>
</tr>
</thead>
<tbody><tr>
<tbody>
<tr>
<td><strong>严重 (CRITICAL)</strong></td>
<td>2</td>
<td>2</td>
@ -672,7 +874,8 @@
<td>8</td>
<td>6</td>
</tr>
</tbody></table>
</tbody>
</table>
<h3>审计指标</h3>
<ul>
<li><strong>分析文件数:</strong> 48 / 48</li>
@ -1049,4 +1252,5 @@ app.secret_key = os.environ.get(&#39;SECRET_KEY&#39;, os.urandom(24))
</div>
</footer>
</body>
</html>

View File

@ -866,8 +866,8 @@ export const ReportExportDialog = memo(function ReportExportDialog({
};
const scoreInfo = getScoreGrade(score);
// SVG 圆环进度条
const circumference = 2 * Math.PI * 40; // r=40 (smaller)
// SVG 圆环进度条 (逆时针方向)
const circumference = 2 * Math.PI * 23; // r=23 matches SVG circle radius
const strokeDashoffset = circumference - (score / 100) * circumference;
return `<!DOCTYPE html>
@ -1012,8 +1012,8 @@ export const ReportExportDialog = memo(function ReportExportDialog({
transform: rotate(-90deg);
width: 56px;
height: 56px;
display: block;
}
.score-ring-bg { fill: none; stroke: var(--border); stroke-width: 5; }
.score-ring-progress {
fill: none;