diff --git a/web/static/css/style.css b/web/static/css/style.css
index 8a58241b..694cbaff 100644
--- a/web/static/css/style.css
+++ b/web/static/css/style.css
@@ -14768,8 +14768,70 @@ header {
stroke: #ffffff;
stroke-width: 4;
stroke-linejoin: round;
+ cursor: pointer;
+ outline: none;
+ transform-origin: 240px 215px;
+ transition: opacity 0.22s ease, filter 0.22s ease, transform 0.28s cubic-bezier(0.34, 1.4, 0.64, 1);
+}
+
+.dashboard-severity-donut.donut-ready .donut-segment {
+ animation: donut-segment-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) backwards;
+}
+
+.dashboard-severity-donut.donut-ready .donut-segment.seg-critical { animation-delay: 0.02s; }
+.dashboard-severity-donut.donut-ready .donut-segment.seg-high { animation-delay: 0.06s; }
+.dashboard-severity-donut.donut-ready .donut-segment.seg-medium { animation-delay: 0.10s; }
+.dashboard-severity-donut.donut-ready .donut-segment.seg-low { animation-delay: 0.14s; }
+.dashboard-severity-donut.donut-ready .donut-segment.seg-info { animation-delay: 0.18s; }
+
+@keyframes donut-segment-in {
+ from {
+ opacity: 0;
+ transform: scale(0.92);
+ }
+ to {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+.dashboard-severity-donut.is-highlighting .donut-segment.is-dimmed,
+.dashboard-severity-donut.is-highlighting .donut-label-text.is-dimmed,
+.dashboard-severity-donut.is-highlighting .donut-leader.is-dimmed {
+ opacity: 0.32;
+}
+
+.dashboard-severity-donut .donut-segment.is-active {
+ filter: drop-shadow(0 3px 10px rgba(15, 23, 42, 0.18));
+ transform: scale(1.045);
+ stroke-width: 5;
+ z-index: 1;
+}
+
+.dashboard-severity-donut .donut-segment:focus-visible {
+ outline: 2px solid rgba(0, 102, 255, 0.55);
+ outline-offset: 2px;
+}
+
+.dashboard-severity-donut .donut-leader {
+ stroke: rgba(148, 163, 184, 0.55);
+ stroke-width: 1;
+ pointer-events: none;
+ transition: opacity 0.2s ease, stroke 0.2s ease;
+}
+
+.dashboard-severity-donut .donut-leader.is-active {
+ stroke: rgba(100, 116, 139, 0.85);
+ stroke-width: 1.5;
+}
+
+.dashboard-severity-donut .donut-label-text {
+ pointer-events: none;
transition: opacity 0.2s ease;
- cursor: default;
+}
+
+.dashboard-severity-donut .donut-label-text.is-active {
+ font-weight: 800;
}
.dashboard-severity-donut .donut-segment.is-empty {
@@ -14799,12 +14861,7 @@ header {
.dashboard-severity-donut .donut-label-text.label-low { fill: #14b8a6; }
.dashboard-severity-donut .donut-label-text.label-info { fill: #3b82f6; }
-/* 半环形配色:保持原有浅色基调(红→橙→黄→青→蓝) */
-.dashboard-severity-donut .donut-segment.seg-critical { fill: #f87171; }
-.dashboard-severity-donut .donut-segment.seg-high { fill: #fb923c; }
-.dashboard-severity-donut .donut-segment.seg-medium { fill: #facc15; }
-.dashboard-severity-donut .donut-segment.seg-low { fill: #2dd4bf; }
-.dashboard-severity-donut .donut-segment.seg-info { fill: #60a5fa; }
+/* 半环形配色由 SVG linearGradient(#donut-grad-*)提供 */
.dashboard-severity-center {
position: absolute;
@@ -14816,6 +14873,17 @@ header {
text-align: center;
pointer-events: none;
width: 60%;
+ transition: transform 0.25s ease;
+}
+
+.dashboard-severity-center.is-hovering {
+ transform: translate(-50%, -52%) scale(1.04);
+}
+
+.dashboard-severity-center-label.is-severity {
+ font-weight: 700;
+ color: var(--text-primary);
+ letter-spacing: 0.02em;
}
.dashboard-severity-center-value {
@@ -14856,12 +14924,46 @@ header {
padding: 10px 4px;
font-size: 0.9375rem;
border-bottom: 1px solid transparent;
- transition: background 0.2s, border-color 0.2s;
+ transition: background 0.2s, border-color 0.2s, box-shadow 0.2s, opacity 0.2s;
border-radius: 4px;
+ cursor: pointer;
}
-.dashboard-severity-legend-item:hover {
- background: rgba(0, 0, 0, 0.025);
+.dashboard-severity-legend-item:hover,
+.dashboard-severity-legend-item.is-active {
+ background: rgba(0, 102, 255, 0.06);
+ border-radius: 8px;
+}
+
+.dashboard-severity-legend-item.is-active {
+ box-shadow: inset 3px 0 0 var(--accent-color, #0066ff);
+}
+
+.dashboard-severity-legend-item.is-zero {
+ opacity: 0.55;
+}
+
+.dashboard-severity-legend-item:focus-visible {
+ outline: 2px solid rgba(0, 102, 255, 0.45);
+ outline-offset: 2px;
+}
+
+.dashboard-severity-donut-tooltip {
+ display: none;
+ position: fixed;
+ left: 0;
+ top: 0;
+ z-index: 10000;
+ max-width: 280px;
+ padding: 8px 12px;
+ font-size: 0.8125rem;
+ line-height: 1.45;
+ color: #fff;
+ background: rgba(15, 23, 42, 0.94);
+ border-radius: 8px;
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);
+ pointer-events: none;
+ white-space: nowrap;
}
.dashboard-severity-legend-dot {
diff --git a/web/static/i18n/en-US.json b/web/static/i18n/en-US.json
index 26d435d7..f2a87da9 100644
--- a/web/static/i18n/en-US.json
+++ b/web/static/i18n/en-US.json
@@ -147,6 +147,7 @@
"active": "Active",
"highFreq": "High frequency",
"noCallData": "No call data",
+ "severityClickHint": "Click to view",
"lastUpdated": "Last updated",
"viewAll": "View all →",
"recentVulns": "Recent vulnerabilities",
diff --git a/web/static/i18n/zh-CN.json b/web/static/i18n/zh-CN.json
index c1c4beac..6a6568ac 100644
--- a/web/static/i18n/zh-CN.json
+++ b/web/static/i18n/zh-CN.json
@@ -147,6 +147,7 @@
"active": "活跃",
"highFreq": "高频",
"noCallData": "暂无调用数据",
+ "severityClickHint": "点击查看",
"lastUpdated": "上次更新",
"viewAll": "查看全部 →",
"recentVulns": "最近漏洞",
diff --git a/web/static/js/dashboard.js b/web/static/js/dashboard.js
index 546aa261..10eed416 100644
--- a/web/static/js/dashboard.js
+++ b/web/static/js/dashboard.js
@@ -1390,6 +1390,17 @@ function dashboardBarTooltipOnOut(ev) {
if (dashboardBarTooltipEl) dashboardBarTooltipEl.style.display = 'none';
}
+// 仪表盘 → 漏洞管理:带严重程度/状态筛选跳转
+function navigateToVulnerabilitiesWithFilter(opts) {
+ opts = opts || {};
+ var params = new URLSearchParams();
+ if (opts.severity) params.set('severity', opts.severity);
+ if (opts.status) params.set('status', opts.status);
+ var qs = params.toString();
+ window.location.hash = qs ? 'vulnerabilities?' + qs : 'vulnerabilities';
+}
+window.navigateToVulnerabilitiesWithFilter = navigateToVulnerabilitiesWithFilter;
+
// 漏洞严重程度分布:半环形(donut)渲染
// 几何参数固定,便于配合 viewBox 0 0 560 320 的 SVG 容器
// 段间分隔由 CSS 的白色 stroke 完成,不再使用 gapRad
@@ -1402,9 +1413,27 @@ var SEVERITY_DONUT_CFG = {
rOuter: 165,
rInner: 115, // 环厚 = 50(介于原 90 和上一版 35 之间,自然且有质感)
labelOffset: 14,
- gapRad: 0
+ gapRad: 0.012
};
+var SEVERITY_DONUT_GRADIENTS = {
+ critical: ['#fca5a5', '#ef4444'],
+ high: ['#fdba74', '#f97316'],
+ medium: ['#fde047', '#eab308'],
+ low: ['#5eead4', '#14b8a6'],
+ info: ['#93c5fd', '#3b82f6']
+};
+
+var severityDonutState = {
+ bySeverity: {},
+ total: 0,
+ hoverId: null,
+ bound: false
+};
+
+var severityDonutTooltipEl = null;
+var severityDonutTooltipTimer = null;
+
var SEVERITY_DEFAULT_LABELS = {
critical: '严重',
high: '高危',
@@ -1422,13 +1451,35 @@ function severityLabel(id) {
return SEVERITY_DEFAULT_LABELS[id] || id;
}
+function ensureSeverityDonutGradients() {
+ var defsEl = document.getElementById('dashboard-severity-donut-defs');
+ if (!defsEl || defsEl.hasChildNodes()) return;
+ var html = '';
+ Object.keys(SEVERITY_DONUT_GRADIENTS).forEach(function (id) {
+ var stops = SEVERITY_DONUT_GRADIENTS[id];
+ html += '';
+ html += '';
+ html += '';
+ html += '';
+ });
+ defsEl.innerHTML = html;
+}
+
function renderSeverityDonut(bySeverity, total) {
+ var svgEl = document.getElementById('dashboard-severity-donut');
var trackEl = document.getElementById('dashboard-severity-donut-track');
+ var leadersEl = document.getElementById('dashboard-severity-donut-leaders');
var segmentsEl = document.getElementById('dashboard-severity-donut-segments');
var labelsEl = document.getElementById('dashboard-severity-donut-labels');
if (!trackEl || !segmentsEl || !labelsEl) return;
+ severityDonutState.bySeverity = bySeverity && typeof bySeverity === 'object' ? bySeverity : {};
+ severityDonutState.total = total || 0;
+ severityDonutState.hoverId = null;
+ resetSeverityDonutCenter();
+
var cfg = SEVERITY_DONUT_CFG;
+ ensureSeverityDonutGradients();
// 背景轨迹(完整半环)只渲染一次
if (!trackEl.hasChildNodes()) {
@@ -1441,9 +1492,12 @@ function renderSeverityDonut(bySeverity, total) {
});
var visible = severities.filter(function (s) { return s.value > 0; });
+ if (svgEl) svgEl.classList.remove('is-highlighting');
if (!total || total <= 0 || visible.length === 0) {
segmentsEl.innerHTML = '';
labelsEl.innerHTML = '';
+ if (leadersEl) leadersEl.innerHTML = '';
+ clearSeverityDonutLegendHighlight();
return;
}
@@ -1457,6 +1511,7 @@ function renderSeverityDonut(bySeverity, total) {
var segmentsHtml = '';
var labelsHtml = '';
+ var leadersHtml = '';
var cumRad = 0;
visible.forEach(function (seg, i) {
@@ -1466,17 +1521,19 @@ function renderSeverityDonut(bySeverity, total) {
var angleEnd = angleStart - segRad;
var path = arcSegmentPath(cfg.cx, cfg.cy, cfg.rOuter, cfg.rInner, angleStart, angleEnd);
- segmentsHtml += '';
+ var pctOfTotal = (seg.value / total) * 100;
+ var pctRounded = Math.round(pctOfTotal);
+ var name = esc(severityLabel(seg.id));
+ var ariaLabel = name + ' ' + seg.value + ' (' + pctRounded + '%)';
+ segmentsHtml += '';
// 仅当占比 >= 5% 时显示外置标签,避免小段标签互相重叠
- var pctOfTotal = (seg.value / total) * 100;
if (pctOfTotal >= 5) {
var midAngle = (angleStart + angleEnd) / 2;
- var labelR = cfg.rOuter + cfg.labelOffset;
+ var labelR = cfg.rOuter + cfg.labelOffset + 6;
var sinMid = Math.sin(midAngle);
var cosMid = Math.cos(midAngle);
var lx = cfg.cx + labelR * cosMid;
- // 顶部区域标签整体向上抬一些,避免与外弧贴住;侧边标签则不调整
var topLift = sinMid > 0.4 ? Math.round((sinMid - 0.3) * 10) : 0;
var ly = cfg.cy - labelR * sinMid - topLift;
@@ -1484,11 +1541,15 @@ function renderSeverityDonut(bySeverity, total) {
if (cosMid < -0.15) anchor = 'end';
else if (cosMid > 0.15) anchor = 'start';
- var pctText = Math.round(pctOfTotal) + '%';
- var name = esc(severityLabel(seg.id));
+ var pctText = pctRounded + '%';
+ var arcR = cfg.rOuter + 4;
+ var lineX1 = cfg.cx + arcR * cosMid;
+ var lineY1 = cfg.cy - arcR * sinMid;
+ var lineX2 = cfg.cx + (cfg.rOuter + cfg.labelOffset - 2) * cosMid;
+ var lineY2 = cfg.cy - (cfg.rOuter + cfg.labelOffset - 2) * sinMid;
+ leadersHtml += '';
- // 两行:第一行 "数量 (百分比)"(弧色),第二行 "严重度名称"(同色但稍小)
- labelsHtml += '';
+ labelsHtml += '';
labelsHtml += '' + seg.value + ' (' + pctText + ')';
labelsHtml += '' + name + '';
labelsHtml += '';
@@ -1498,8 +1559,224 @@ function renderSeverityDonut(bySeverity, total) {
if (i < visibleCount - 1) cumRad += cfg.gapRad;
});
+ if (leadersEl) leadersEl.innerHTML = leadersHtml;
segmentsEl.innerHTML = segmentsHtml;
labelsEl.innerHTML = labelsHtml;
+ if (svgEl) svgEl.classList.add('donut-ready');
+ attachSeverityDonutInteractivity();
+}
+
+function resetSeverityDonutCenter() {
+ var totalEl = document.getElementById('dashboard-severity-total');
+ var labelEl = document.getElementById('dashboard-severity-center-label');
+ var centerEl = document.getElementById('dashboard-severity-center');
+ if (totalEl) totalEl.textContent = String(severityDonutState.total || 0);
+ if (labelEl) {
+ labelEl.textContent = (typeof window.t === 'function' ? window.t('dashboard.totalVulns') : '总漏洞数');
+ labelEl.classList.remove('is-severity');
+ }
+ if (centerEl) centerEl.classList.remove('is-hovering');
+}
+
+function setSeverityDonutHover(severityId) {
+ var svgEl = document.getElementById('dashboard-severity-donut');
+ var centerEl = document.getElementById('dashboard-severity-center');
+ var totalEl = document.getElementById('dashboard-severity-total');
+ var labelEl = document.getElementById('dashboard-severity-center-label');
+ if (!severityId) {
+ severityDonutState.hoverId = null;
+ if (svgEl) svgEl.classList.remove('is-highlighting');
+ clearSeverityDonutLegendHighlight();
+ resetSeverityDonutCenter();
+ return;
+ }
+ var count = (severityDonutState.bySeverity && severityDonutState.bySeverity[severityId]) || 0;
+ severityDonutState.hoverId = severityId;
+ if (svgEl) svgEl.classList.add('is-highlighting');
+ highlightSeverityDonutParts(severityId);
+ highlightSeverityLegendItem(severityId);
+ if (totalEl) totalEl.textContent = String(count);
+ if (labelEl) {
+ labelEl.textContent = severityLabel(severityId);
+ labelEl.classList.add('is-severity');
+ }
+ if (centerEl) centerEl.classList.add('is-hovering');
+}
+
+function highlightSeverityDonutParts(severityId) {
+ var svgEl = document.getElementById('dashboard-severity-donut');
+ if (!svgEl) return;
+ svgEl.querySelectorAll('[data-severity]').forEach(function (el) {
+ var match = el.getAttribute('data-severity') === severityId;
+ el.classList.toggle('is-active', match);
+ el.classList.toggle('is-dimmed', !match);
+ });
+}
+
+function highlightSeverityLegendItem(severityId) {
+ var legend = document.getElementById('dashboard-vuln-bars');
+ if (!legend) return;
+ legend.querySelectorAll('.dashboard-severity-legend-item').forEach(function (item) {
+ var match = item.getAttribute('data-severity') === severityId;
+ item.classList.toggle('is-active', match);
+ });
+}
+
+function clearSeverityDonutLegendHighlight() {
+ var legend = document.getElementById('dashboard-vuln-bars');
+ if (legend) {
+ legend.querySelectorAll('.dashboard-severity-legend-item.is-active').forEach(function (el) {
+ el.classList.remove('is-active');
+ });
+ }
+ var svgEl = document.getElementById('dashboard-severity-donut');
+ if (svgEl) {
+ svgEl.querySelectorAll('.is-active, .is-dimmed').forEach(function (el) {
+ el.classList.remove('is-active', 'is-dimmed');
+ });
+ }
+}
+
+function severityDonutTooltipText(severityId) {
+ var count = (severityDonutState.bySeverity && severityDonutState.bySeverity[severityId]) || 0;
+ var pct = severityDonutState.total > 0 ? Math.round((count / severityDonutState.total) * 100) : 0;
+ var hint = (typeof window.t === 'function' ? window.t('dashboard.severityClickHint') : '点击查看');
+ return severityLabel(severityId) + ' · ' + count + ' (' + pct + '%) — ' + hint;
+}
+
+function showSeverityDonutTooltip(ev, severityId) {
+ if (!severityDonutTooltipEl) {
+ severityDonutTooltipEl = document.createElement('div');
+ severityDonutTooltipEl.className = 'dashboard-severity-donut-tooltip';
+ severityDonutTooltipEl.setAttribute('role', 'tooltip');
+ document.body.appendChild(severityDonutTooltipEl);
+ }
+ clearTimeout(severityDonutTooltipTimer);
+ severityDonutTooltipTimer = setTimeout(function () {
+ severityDonutTooltipEl.textContent = severityDonutTooltipText(severityId);
+ severityDonutTooltipEl.style.display = 'block';
+ requestAnimationFrame(function () {
+ var x = ev.clientX;
+ var y = ev.clientY;
+ var ttRect = severityDonutTooltipEl.getBoundingClientRect();
+ var left = x - ttRect.width / 2;
+ var top = y - ttRect.height - 12;
+ if (top < 8) top = y + 16;
+ var pad = 8;
+ if (left < pad) left = pad;
+ if (left + ttRect.width > window.innerWidth - pad) left = window.innerWidth - ttRect.width - pad;
+ severityDonutTooltipEl.style.left = left + 'px';
+ severityDonutTooltipEl.style.top = top + 'px';
+ });
+ }, 120);
+}
+
+function hideSeverityDonutTooltip() {
+ clearTimeout(severityDonutTooltipTimer);
+ severityDonutTooltipTimer = null;
+ if (severityDonutTooltipEl) severityDonutTooltipEl.style.display = 'none';
+}
+
+function attachSeverityDonutInteractivity() {
+ var svgEl = document.getElementById('dashboard-severity-donut');
+ var legend = document.getElementById('dashboard-vuln-bars');
+ if (!svgEl) return;
+
+ if (!severityDonutState.bound) {
+ severityDonutState.bound = true;
+ svgEl.addEventListener('mouseover', severityDonutPointerOver);
+ svgEl.addEventListener('mouseout', severityDonutPointerOut);
+ svgEl.addEventListener('click', severityDonutClick);
+ svgEl.addEventListener('keydown', severityDonutKeydown);
+ if (legend) {
+ legend.addEventListener('mouseover', severityLegendPointerOver);
+ legend.addEventListener('mouseout', severityLegendPointerOut);
+ legend.addEventListener('click', severityLegendClick);
+ legend.addEventListener('keydown', severityLegendKeydown);
+ }
+ }
+
+ legend && legend.querySelectorAll('.dashboard-severity-legend-item').forEach(function (item) {
+ if (!item.getAttribute('data-severity')) return;
+ var sev = item.getAttribute('data-severity');
+ var count = (severityDonutState.bySeverity && severityDonutState.bySeverity[sev]) || 0;
+ item.classList.toggle('is-zero', count === 0);
+ item.setAttribute('aria-label', severityDonutTooltipText(sev));
+ });
+}
+
+function severityDonutTarget(el) {
+ return el && el.closest && el.closest('[data-severity]');
+}
+
+function severityDonutPointerOver(ev) {
+ var target = severityDonutTarget(ev.target);
+ if (!target || !target.classList.contains('donut-segment')) return;
+ var id = target.getAttribute('data-severity');
+ if (!id) return;
+ setSeverityDonutHover(id);
+ showSeverityDonutTooltip(ev, id);
+}
+
+function severityDonutPointerOut(ev) {
+ var from = severityDonutTarget(ev.target);
+ var to = ev.relatedTarget && severityDonutTarget(ev.relatedTarget);
+ if (from && from === to) return;
+ setSeverityDonutHover(null);
+ hideSeverityDonutTooltip();
+}
+
+function severityDonutClick(ev) {
+ var target = severityDonutTarget(ev.target);
+ if (!target || !target.classList.contains('donut-segment')) return;
+ var id = target.getAttribute('data-severity');
+ if (!id) return;
+ ev.preventDefault();
+ navigateToVulnerabilitiesWithFilter({ severity: id });
+}
+
+function severityDonutKeydown(ev) {
+ if (ev.key !== 'Enter' && ev.key !== ' ') return;
+ var target = severityDonutTarget(ev.target);
+ if (!target || !target.classList.contains('donut-segment')) return;
+ ev.preventDefault();
+ var id = target.getAttribute('data-severity');
+ if (id) navigateToVulnerabilitiesWithFilter({ severity: id });
+}
+
+function severityLegendPointerOver(ev) {
+ var item = ev.target && ev.target.closest && ev.target.closest('.dashboard-severity-legend-item[data-severity]');
+ if (!item) return;
+ var id = item.getAttribute('data-severity');
+ if (!id) return;
+ setSeverityDonutHover(id);
+ showSeverityDonutTooltip(ev, id);
+}
+
+function severityLegendPointerOut(ev) {
+ var item = ev.target && ev.target.closest && ev.target.closest('.dashboard-severity-legend-item[data-severity]');
+ var related = ev.relatedTarget && ev.relatedTarget.closest && ev.relatedTarget.closest('.dashboard-severity-legend-item[data-severity]');
+ if (item && item === related) return;
+ setSeverityDonutHover(null);
+ hideSeverityDonutTooltip();
+}
+
+function severityLegendClick(ev) {
+ var item = ev.target && ev.target.closest && ev.target.closest('.dashboard-severity-legend-item[data-severity]');
+ if (!item) return;
+ var id = item.getAttribute('data-severity');
+ if (!id) return;
+ ev.preventDefault();
+ navigateToVulnerabilitiesWithFilter({ severity: id });
+}
+
+function severityLegendKeydown(ev) {
+ if (ev.key !== 'Enter' && ev.key !== ' ') return;
+ var item = ev.target && ev.target.closest && ev.target.closest('.dashboard-severity-legend-item[data-severity]');
+ if (!item) return;
+ ev.preventDefault();
+ var id = item.getAttribute('data-severity');
+ if (id) navigateToVulnerabilitiesWithFilter({ severity: id });
}
// SVG 半环(背景轨迹)路径
diff --git a/web/static/js/vulnerability.js b/web/static/js/vulnerability.js
index 67df391f..82711ee3 100644
--- a/web/static/js/vulnerability.js
+++ b/web/static/js/vulnerability.js
@@ -72,19 +72,27 @@ function syncVulnerabilityFiltersFromLocationHash() {
const vid = (params.get('id') || '').trim();
const cid = (params.get('conversation_id') || '').trim();
const tid = (params.get('task_id') || '').trim();
- if (!vid && !cid && !tid) {
+ const sev = (params.get('severity') || '').trim();
+ const st = (params.get('status') || '').trim();
+ if (!vid && !cid && !tid && !sev && !st) {
return;
}
vulnerabilityFilters.id = '';
vulnerabilityFilters.conversation_id = '';
vulnerabilityFilters.task_id = '';
+ vulnerabilityFilters.severity = '';
+ vulnerabilityFilters.status = '';
const idEl = document.getElementById('vulnerability-id-filter');
const convEl = document.getElementById('vulnerability-conversation-filter');
const taskEl = document.getElementById('vulnerability-task-filter');
+ const sevEl = document.getElementById('vulnerability-severity-filter');
+ const stEl = document.getElementById('vulnerability-status-filter');
if (idEl) idEl.value = '';
if (convEl) convEl.value = '';
if (taskEl) taskEl.value = '';
+ if (sevEl) sevEl.value = '';
+ if (stEl) stEl.value = '';
if (vid) {
vulnerabilityFilters.id = vid;
@@ -98,6 +106,14 @@ function syncVulnerabilityFiltersFromLocationHash() {
vulnerabilityFilters.task_id = tid;
if (taskEl) taskEl.value = tid;
}
+ if (sev) {
+ vulnerabilityFilters.severity = sev;
+ if (sevEl) sevEl.value = sev;
+ }
+ if (st) {
+ vulnerabilityFilters.status = st;
+ if (stEl) stEl.value = st;
+ }
vulnerabilityPagination.currentPage = 1;
}
diff --git a/web/templates/index.html b/web/templates/index.html
index b4aac558..3d8d04da 100644
--- a/web/templates/index.html
+++ b/web/templates/index.html
@@ -449,42 +449,45 @@