Add files via upload

This commit is contained in:
公明
2026-05-27 11:40:10 +08:00
committed by GitHub
parent c0f0861b31
commit 3f9dbb4214
22 changed files with 988 additions and 153 deletions
+65
View File
@@ -932,6 +932,7 @@ function renderVulnerabilities(vulnerabilities) {
${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-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>
`;
@@ -1295,12 +1296,76 @@ function toggleVulnerabilityDetails(id) {
if (content.style.display === 'none') {
content.style.display = 'block';
icon.style.transform = 'rotate(90deg)';
loadVulnerabilityRelatedFacts(id).catch((e) => console.warn(e));
} else {
content.style.display = 'none';
icon.style.transform = 'rotate(0deg)';
}
}
/** 展开漏洞详情时加载关联项目事实 */
async function loadVulnerabilityRelatedFacts(vulnId) {
const el = document.getElementById(`vuln-related-facts-${vulnId}`);
if (!el || el.dataset.loaded === '1') return;
const projectId = (el.dataset.projectId || '').trim();
if (!projectId) {
el.hidden = true;
el.dataset.loaded = '1';
return;
}
el.hidden = false;
el.innerHTML = '<span>加载关联事实…</span>';
try {
const res = await apiFetch(
`/api/projects/${encodeURIComponent(projectId)}/facts?related_vulnerability_id=${encodeURIComponent(vulnId)}&limit=20&exclude_deprecated=true`,
);
if (!res.ok) throw new Error('fetch failed');
const facts = await res.json();
if (!Array.isArray(facts) || !facts.length) {
el.innerHTML =
'<strong>关联事实</strong><p style="margin:6px 0 0;color:#64748b">暂无;可在「项目管理」事实详情中关联或生成漏洞草稿。</p>';
el.dataset.loaded = '1';
return;
}
const items = facts
.map((f) => {
const key = escapeHtml(f.fact_key);
const sum = escapeHtml((f.summary || '').slice(0, 120));
const pid = escapeHtml(projectId);
const rawKey = escapeHtml(f.fact_key);
return `<li><a role="button" href="#" data-project-id="${pid}" data-fact-key="${rawKey}" onclick="event.preventDefault();openProjectFactFromVulnerability(this.dataset.projectId,this.dataset.factKey)"><code>${key}</code></a> — ${sum}</li>`;
})
.join('');
el.innerHTML = `<strong>关联事实(${facts.length}</strong><ul>${items}</ul>`;
el.dataset.loaded = '1';
} catch (e) {
el.innerHTML = '<strong>关联事实</strong><p style="margin:6px 0 0;color:#b91c1c">加载失败</p>';
}
}
function openProjectFactFromVulnerability(projectId, factKey) {
if (!projectId || !factKey) return;
if (typeof switchPage === 'function') {
switchPage('projects');
}
setTimeout(async () => {
if (typeof window.initProjectsPage === 'function') {
await window.initProjectsPage();
}
if (typeof window.selectProject === 'function') {
await window.selectProject(projectId);
}
if (typeof window.switchProjectTab === 'function') {
window.switchProjectTab('facts');
}
if (typeof window.viewProjectFactBody === 'function') {
window.viewProjectFactBody(factKey);
}
}, 350);
}
window.openProjectFactFromVulnerability = openProjectFactFromVulnerability;
// HTML转义
function escapeHtml(text) {
const div = document.createElement('div');