Add files via upload

This commit is contained in:
公明
2026-07-03 10:46:04 +08:00
committed by GitHub
parent 1ff2df68ac
commit 5254ca52fb
5 changed files with 164 additions and 50 deletions
+62 -16
View File
@@ -1303,9 +1303,14 @@ function renderVulnerabilities(vulnerabilities, renderOptions) {
${vuln.conversation_tag ? vulnDetailField(vulnT('vulnerabilityPage.detailConversationTag'), vuln.conversation_tag, false) : ''}
${vuln.task_tag ? vulnDetailField(vulnT('vulnerabilityPage.detailTaskTag'), vuln.task_tag, false) : ''}
</div>
${vuln.proof ? `<div class="vulnerability-proof"><strong>${escapeHtml(vulnT('vulnerabilityPage.detailProof'))}:</strong><pre>${escapeHtml(vuln.proof)}</pre></div>` : ''}
${vuln.impact ? `<div class="vulnerability-impact"><strong>${escapeHtml(vulnT('vulnerabilityPage.detailImpact'))}:</strong> ${escapeHtml(vuln.impact)}</div>` : ''}
${vuln.recommendation ? `<div class="vulnerability-recommendation"><strong>${escapeHtml(vulnT('vulnerabilityPage.detailRecommendation'))}:</strong> ${escapeHtml(vuln.recommendation)}</div>` : ''}
<div class="vulnerability-repro">
${vulnNarrativeSection(vulnT('vulnerabilityPage.detailPreconditions'), vuln.preconditions)}
${vulnNarrativeSection(vulnT('vulnerabilityPage.detailReproductionSteps'), vuln.reproduction_steps)}
${vulnNarrativeSection(vulnT('vulnerabilityPage.detailEvidence'), vuln.evidence, { code: true })}
${vulnNarrativeSection(vulnT('vulnerabilityPage.detailImpact'), vuln.impact)}
${vulnNarrativeSection(vulnT('vulnerabilityPage.detailRecommendation'), vuln.recommendation)}
${vulnNarrativeSection(vulnT('vulnerabilityPage.detailRetestNotes'), vuln.retest_notes)}
</div>
<div class="vulnerability-related-facts" id="vuln-related-facts-${vuln.id}" data-project-id="${escapeHtml(vuln.project_id || '')}" data-vuln-id="${escapeHtml(vuln.id)}" hidden></div>
</div>
</div>
@@ -1467,9 +1472,12 @@ async function showAddVulnerabilityModal() {
document.getElementById('vulnerability-status').value = 'open';
document.getElementById('vulnerability-type').value = '';
document.getElementById('vulnerability-target').value = '';
document.getElementById('vulnerability-proof').value = '';
document.getElementById('vulnerability-preconditions').value = '';
document.getElementById('vulnerability-reproduction-steps').value = '';
document.getElementById('vulnerability-evidence').value = '';
document.getElementById('vulnerability-impact').value = '';
document.getElementById('vulnerability-recommendation').value = '';
document.getElementById('vulnerability-retest-notes').value = '';
openAppModal('vulnerability-modal');
}
@@ -1493,9 +1501,12 @@ async function editVulnerability(id) {
document.getElementById('vulnerability-status').value = vuln.status || 'open';
document.getElementById('vulnerability-type').value = vuln.type || '';
document.getElementById('vulnerability-target').value = vuln.target || '';
document.getElementById('vulnerability-proof').value = vuln.proof || '';
document.getElementById('vulnerability-preconditions').value = vuln.preconditions || '';
document.getElementById('vulnerability-reproduction-steps').value = vuln.reproduction_steps || '';
document.getElementById('vulnerability-evidence').value = vuln.evidence || '';
document.getElementById('vulnerability-impact').value = vuln.impact || '';
document.getElementById('vulnerability-recommendation').value = vuln.recommendation || '';
document.getElementById('vulnerability-retest-notes').value = vuln.retest_notes || '';
await populateVulnerabilityModalProjectSelect(vuln.project_id || '');
document.getElementById('vulnerability-title')?.focus();
});
@@ -1510,9 +1521,16 @@ async function editVulnerability(id) {
async function saveVulnerability() {
const conversationId = document.getElementById('vulnerability-conversation-id').value.trim();
const title = document.getElementById('vulnerability-title').value.trim();
const description = document.getElementById('vulnerability-description').value.trim();
const severity = document.getElementById('vulnerability-severity').value;
const type = document.getElementById('vulnerability-type').value.trim();
const target = document.getElementById('vulnerability-target').value.trim();
const reproductionSteps = document.getElementById('vulnerability-reproduction-steps').value.trim();
const evidence = document.getElementById('vulnerability-evidence').value.trim();
const impact = document.getElementById('vulnerability-impact').value.trim();
const recommendation = document.getElementById('vulnerability-recommendation').value.trim();
if (!conversationId || !title || !severity) {
if (!conversationId || !title || !description || !severity || !type || !target || !reproductionSteps || !evidence || !impact || !recommendation) {
alert(vulnT('vulnerabilityPage.saveRequiredFields'));
return;
}
@@ -1525,14 +1543,17 @@ async function saveVulnerability() {
conversation_tag: document.getElementById('vulnerability-conversation-tag').value.trim(),
task_tag: document.getElementById('vulnerability-task-tag').value.trim(),
title: title,
description: document.getElementById('vulnerability-description').value.trim(),
description: description,
severity: severity,
status: document.getElementById('vulnerability-status').value,
type: document.getElementById('vulnerability-type').value.trim(),
target: document.getElementById('vulnerability-target').value.trim(),
proof: document.getElementById('vulnerability-proof').value.trim(),
impact: document.getElementById('vulnerability-impact').value.trim(),
recommendation: document.getElementById('vulnerability-recommendation').value.trim()
type: type,
target: target,
preconditions: document.getElementById('vulnerability-preconditions').value.trim(),
reproduction_steps: reproductionSteps,
evidence: evidence,
impact: impact,
recommendation: recommendation,
retest_notes: document.getElementById('vulnerability-retest-notes').value.trim()
};
try {
@@ -1553,9 +1574,12 @@ async function saveVulnerability() {
status: data.status,
type: data.type,
target: data.target,
proof: data.proof,
preconditions: data.preconditions,
reproduction_steps: data.reproduction_steps,
evidence: data.evidence,
impact: data.impact,
recommendation: data.recommendation,
retest_notes: data.retest_notes,
};
}
@@ -1864,6 +1888,17 @@ function vulnDetailField(label, value, asCode) {
</div>`;
}
function vulnNarrativeSection(label, value, options) {
if (value === undefined || value === null || String(value).trim() === '') return '';
const opts = options || {};
const tag = opts.code ? 'pre' : 'div';
const cls = opts.code ? 'vulnerability-section-body vulnerability-section-body--code' : 'vulnerability-section-body';
return `<section class="vulnerability-section">
<strong>${escapeHtml(label)}</strong>
<${tag} class="${cls}">${escapeHtml(String(value))}</${tag}>
</section>`;
}
// 将漏洞格式化为Markdown(章节标题随界面语言)
function formatVulnerabilityAsMarkdown(vuln) {
const severityText = vulnSeverityLabel(vuln.severity);
@@ -1905,8 +1940,16 @@ function formatVulnerabilityAsMarkdown(vuln) {
markdown += `## ${L('headingDescription')}\n\n${vuln.description}\n\n`;
}
if (vuln.proof) {
markdown += `## ${L('headingProof')}\n\n\`\`\`\n${vuln.proof}\n\`\`\`\n\n`;
if (vuln.preconditions) {
markdown += `## ${L('headingPreconditions')}\n\n${vuln.preconditions}\n\n`;
}
if (vuln.reproduction_steps) {
markdown += `## ${L('headingReproductionSteps')}\n\n${vuln.reproduction_steps}\n\n`;
}
if (vuln.evidence) {
markdown += `## ${L('headingEvidence')}\n\n\`\`\`\n${vuln.evidence}\n\`\`\`\n\n`;
}
if (vuln.impact) {
@@ -1917,6 +1960,10 @@ function formatVulnerabilityAsMarkdown(vuln) {
markdown += `## ${L('headingRecommendation')}\n\n${vuln.recommendation}\n\n`;
}
if (vuln.retest_notes) {
markdown += `## ${L('headingRetestNotes')}\n\n${vuln.retest_notes}\n\n`;
}
return markdown;
}
@@ -2194,4 +2241,3 @@ window.setVulnerabilityIdFilter = setVulnerabilityIdFilter;
window.bindVulnerabilityProject = bindVulnerabilityProject;
window.buildVulnerabilityProjectOptionsHtml = buildVulnerabilityProjectOptionsHtml;
window.changeVulnerabilityStatus = changeVulnerabilityStatus;