// 漏洞管理相关功能 function vulnT(key, opts) { if (typeof window.t === 'function') { return window.t(key, opts); } return key; } function vulnDateLocale() { try { const lang = (window.__locale || '').toLowerCase(); if (lang.indexOf('zh') === 0) { return 'zh-CN'; } } catch (e) { /* ignore */ } return 'en-US'; } function vulnSeverityLabel(code) { const m = { critical: 'dashboard.severityCritical', high: 'dashboard.severityHigh', medium: 'dashboard.severityMedium', low: 'dashboard.severityLow', info: 'dashboard.severityInfo' }; return m[code] ? vulnT(m[code]) : code; } function vulnStatusLabel(code) { const m = { open: 'vulnerabilityPage.statusOpen', confirmed: 'vulnerabilityPage.statusConfirmed', fixed: 'vulnerabilityPage.statusFixed', false_positive: 'vulnerabilityPage.statusFalsePositive', ignored: 'vulnerabilityPage.statusIgnored' }; return m[code] ? vulnT(m[code]) : code; } const VULN_STATUS_CODES = ['open', 'confirmed', 'fixed', 'false_positive', 'ignored']; const VULNERABILITY_REMOVE_ANIM_MS = 200; function getVulnerabilityScrollContainer() { const page = document.getElementById('page-vulnerabilities'); return page ? page.querySelector('.page-content') : null; } function getExpandedVulnerabilityIds() { const ids = []; document.querySelectorAll('#vulnerabilities-list .vulnerability-content').forEach(function (el) { if (el.style.display !== 'none') { const id = (el.id || '').replace(/^content-/, ''); if (id) ids.push(id); } }); return ids; } function restoreExpandedVulnerabilityDetails(expandedIds) { if (!expandedIds || !expandedIds.length) return; expandedIds.forEach(function (id) { const content = document.getElementById('content-' + id); const icon = document.getElementById('expand-icon-' + id); if (!content || content.style.display !== 'none') return; content.style.display = 'block'; if (icon) icon.style.transform = 'rotate(90deg)'; loadVulnerabilityRelatedFacts(id).catch(function (e) { console.warn(e); }); }); } function buildVulnerabilityStatusPicker(vuln) { const current = vuln.status || 'open'; const id = escapeHtml(vuln.id); const label = escapeHtml(vulnT('vulnerabilityPage.statusChangeLabel')); const caretSvg = ''; const options = VULN_STATUS_CODES.map(function (code) { const selected = code === current; const selCls = selected ? ' is-selected' : ''; const ariaSel = selected ? ' aria-selected="true"' : ' aria-selected="false"'; return ''; }).join(''); return '
暂无;可在「项目管理」事实详情中关联或生成漏洞草稿。
'; 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 `${key} — ${sum}加载失败
'; } } 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'); div.textContent = text; return div.innerHTML; } /** 复制详情字段(编码由 encodeURIComponent 传入,避免引号截断) */ function vulnerabilityCopyEncoded(evt, encoded) { if (evt && evt.stopPropagation) { evt.stopPropagation(); } let text = ''; try { text = decodeURIComponent(encoded); } catch (e) { return; } const done = () => { if (evt && evt.target && evt.target.closest) { const btn = evt.target.closest('.vuln-detail-field__copy'); if (btn) { const t0 = btn.getAttribute('title') || ''; btn.setAttribute('title', vulnT('common.copied')); setTimeout(() => btn.setAttribute('title', t0), 1600); } } }; if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') { navigator.clipboard.writeText(text).then(done).catch(() => { try { const ta = document.createElement('textarea'); ta.value = text; ta.style.position = 'fixed'; ta.style.left = '-9999px'; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); done(); } catch (err) { console.error('copy failed', err); } }); } else { try { const ta = document.createElement('textarea'); ta.value = text; ta.style.position = 'fixed'; ta.style.left = '-9999px'; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); done(); } catch (err) { console.error('copy failed', err); } } } function vulnDetailProjectField(vuln) { const label = vulnT('vulnerabilityPage.detailProject'); const hint = escapeHtml(vulnT('vulnerabilityPage.projectBindHint')); return `${escapeHtml(s)}`
: `${escapeHtml(s)}`;
const copyBtn = ``;
return `