From c446e22d0c74e57ee64dd6551f360862fc0daf90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AC=E6=98=8E?= <83812544+Ed1s0nZ@users.noreply.github.com> Date: Fri, 22 May 2026 11:28:51 +0800 Subject: [PATCH] Add files via upload --- web/static/css/style.css | 217 +++++++++++++++++++------------ web/static/i18n/en-US.json | 8 ++ web/static/i18n/zh-CN.json | 10 +- web/static/js/vulnerability.js | 229 ++++++++++++++++++++++----------- web/templates/index.html | 87 ++++++++----- 5 files changed, 358 insertions(+), 193 deletions(-) diff --git a/web/static/css/style.css b/web/static/css/style.css index a0594302..4593ecf3 100644 --- a/web/static/css/style.css +++ b/web/static/css/style.css @@ -16990,8 +16990,8 @@ header { } .vulnerability-controls { - margin-bottom: 16px; - padding: 10px 12px; + margin-bottom: 12px; + padding: 8px 10px; background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 10px; @@ -17016,6 +17016,117 @@ header { min-width: 0; } +.vulnerability-filter-actions { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 6px; + flex-shrink: 0; +} + +.vulnerability-search-wrap { + position: relative; + gap: 0; +} + +.vulnerability-search-wrap .vulnerability-search-icon { + position: absolute; + left: 10px; + top: 50%; + transform: translateY(-50%); + color: var(--text-secondary); + pointer-events: none; + flex-shrink: 0; +} + +.vulnerability-search-wrap input[type="search"] { + padding-left: 32px; +} + +.vulnerability-more-filters-anchor { + position: relative; +} + +.vulnerability-more-filters-btn { + display: inline-flex; + align-items: center; + gap: 4px; + white-space: nowrap; + padding: 8px 12px; + font-size: 0.875rem; +} + +.vulnerability-more-filters-btn.is-active { + border-color: #3b82f6; + color: #2563eb; + background: rgba(59, 130, 246, 0.06); +} + +.vulnerability-more-filters-popover { + position: absolute; + top: calc(100% + 6px); + right: 0; + z-index: 120; + width: min(420px, calc(100vw - 32px)); + padding: 12px; + background: var(--bg-primary); + border: 1px solid var(--border-color); + border-radius: 10px; + box-shadow: var(--shadow-md, 0 8px 24px rgba(15, 23, 42, 0.12)); +} + +.vulnerability-more-filters-popover[hidden] { + display: none !important; +} + +.vulnerability-more-filters-popover-title { + margin: 0 0 10px; + font-size: 0.8125rem; + font-weight: 600; + color: var(--text-secondary); +} + +.vulnerability-more-filters-popover-body { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 10px 12px; +} + +.vulnerability-more-filters-popover-body .vulnerability-filter-field--full { + grid-column: 1 / -1; +} + +.vulnerability-more-filters-popover-body .vulnerability-filter-field { + flex-direction: column; + align-items: stretch; + gap: 4px; +} + +.vulnerability-more-filters-popover-body .vulnerability-filter-field > span { + font-size: 0.75rem; + color: var(--text-secondary); +} + +.vulnerability-more-filters-popover-footer { + display: flex; + justify-content: flex-end; + gap: 8px; + margin-top: 12px; + padding-top: 10px; + border-top: 1px solid var(--border-color); +} + +@media (max-width: 520px) { + .vulnerability-more-filters-popover-body { + grid-template-columns: 1fr; + } + + .vulnerability-more-filters-popover { + right: auto; + left: 0; + } +} + .vulnerability-filter-field { display: flex; align-items: center; @@ -17061,6 +17172,10 @@ header { box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.12); } +.vulnerability-filter-clear-btn[hidden] { + display: none !important; +} + .vulnerability-filter-clear-btn { flex-shrink: 0; padding: 8px 12px; @@ -17078,69 +17193,7 @@ header { background: rgba(59, 130, 246, 0.06); } -/* tasks-filters 的 display:flex 会覆盖 [hidden],必须显式隐藏 */ -#vulnerability-advanced-filters[hidden] { - display: none !important; -} - -.vulnerability-filter-advanced-wrap { - margin-top: 6px; -} - -.vulnerability-filter-advanced-wrap.is-expanded { - margin-top: 10px; - padding-top: 10px; - border-top: 1px dashed var(--border-color); -} - -.vulnerability-filter-advanced { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 10px 14px; -} - -.vulnerability-filter-advanced .vulnerability-filter-field { - flex-direction: column; - align-items: stretch; - gap: 4px; -} - -.vulnerability-filter-advanced .vulnerability-filter-field > span { - max-width: none; - font-size: 0.75rem; -} - -.vulnerability-filter-advanced .vulnerability-filter-field input { - width: 100%; -} - -@media (max-width: 768px) { - .vulnerability-filter-advanced { - grid-template-columns: 1fr; - } -} - -.vulnerability-filter-advanced-toggle { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 4px 8px; - margin: 0 0 8px; - border: none; - background: transparent; - color: var(--text-secondary); - font-size: 0.8125rem; - cursor: pointer; - border-radius: 6px; - transition: color 0.15s ease, background 0.15s ease; -} - -.vulnerability-filter-advanced-toggle:hover { - color: var(--text-primary); - background: rgba(0, 0, 0, 0.04); -} - -/* 高级筛选生效数量:弱提示文字,避免实心蓝点过于抢眼 */ +/* 更多筛选生效数量:弱提示文字 */ .vulnerability-filter-advanced-badge { display: inline; margin-left: 2px; @@ -17155,30 +17208,23 @@ header { display: none !important; } -.vulnerability-filter-advanced-chevron { - display: inline-block; - width: 0; - height: 0; - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 5px solid currentColor; - transition: transform 0.2s ease; -} - -.vulnerability-filter-advanced-toggle[aria-expanded="true"] .vulnerability-filter-advanced-chevron { - transform: rotate(180deg); -} - .vulnerability-filter-chips { display: flex; flex-wrap: wrap; align-items: center; - gap: 6px; - margin-top: 10px; - padding-top: 10px; + gap: 6px 8px; + margin-top: 8px; + padding-top: 8px; border-top: 1px solid var(--border-color); } +.vulnerability-filter-chips-label { + flex-shrink: 0; + font-size: 0.75rem; + font-weight: 600; + color: var(--text-secondary); +} + .vulnerability-filter-chips-list { display: flex; flex-wrap: wrap; @@ -17222,8 +17268,13 @@ header { flex: 1 1 100%; } + .vulnerability-filter-actions { + width: 100%; + justify-content: flex-end; + } + .vulnerability-filter-clear-btn { - align-self: flex-end; + margin-left: auto; } } diff --git a/web/static/i18n/en-US.json b/web/static/i18n/en-US.json index 871a96dc..171426a6 100644 --- a/web/static/i18n/en-US.json +++ b/web/static/i18n/en-US.json @@ -1545,6 +1545,10 @@ "statClickAll": "View all (clear severity filter)", "statClickFilter": "Click to filter by this severity; click again to clear", "advancedFilters": "Advanced filters", + "moreFilters": "More filters", + "applyFilters": "Apply", + "clearAdvanced": "Clear", + "clearAll": "Reset all", "activeFilters": "Active filters", "chipRemove": "Remove", "filter": "Filter", @@ -1564,6 +1568,10 @@ "statusFixed": "Fixed", "statusFalsePositive": "False positive", "searchVulnId": "Search vuln ID", + "searchKeyword": "Search title, description, type, target…", + "searchKeywordShort": "Keyword", + "filterExactId": "Exact vuln ID", + "filterEnterHint": "Press Enter to filter", "filterConversation": "Filter by conversation", "loading": "Loading...", "loadListFailed": "Failed to load", diff --git a/web/static/i18n/zh-CN.json b/web/static/i18n/zh-CN.json index 2c00e1bb..c456c3f1 100644 --- a/web/static/i18n/zh-CN.json +++ b/web/static/i18n/zh-CN.json @@ -1534,6 +1534,10 @@ "statClickAll": "查看全部(清除严重度筛选)", "statClickFilter": "点击按此严重度筛选;再次点击清除", "advancedFilters": "高级筛选", + "moreFilters": "更多筛选", + "applyFilters": "应用", + "clearAdvanced": "清空", + "clearAll": "重置全部", "activeFilters": "已选条件", "chipRemove": "移除", "filter": "筛选", @@ -1552,7 +1556,11 @@ "statusConfirmed": "已确认", "statusFixed": "已修复", "statusFalsePositive": "误报", - "searchVulnId": "搜索漏洞ID", + "searchVulnId": "搜索漏洞 ID", + "searchKeyword": "搜索标题、描述、类型、目标…", + "searchKeywordShort": "关键词", + "filterExactId": "精确匹配漏洞 ID", + "filterEnterHint": "回车筛选", "filterConversation": "筛选特定会话", "loading": "加载中...", "loadListFailed": "加载失败", diff --git a/web/static/js/vulnerability.js b/web/static/js/vulnerability.js index 42c171ea..91e9007a 100644 --- a/web/static/js/vulnerability.js +++ b/web/static/js/vulnerability.js @@ -46,6 +46,7 @@ const getVulnerabilityPageSize = () => { let currentVulnerabilityId = null; let vulnerabilityFilters = { + q: '', id: '', conversation_id: '', task_id: '', @@ -65,11 +66,14 @@ const VULN_STAT_SEVERITIES = ['critical', 'high', 'medium', 'low', 'info']; let vulnerabilityStatCardsBound = false; let vulnerabilityFilterPanelBound = false; let vulnerabilityFilterOptionsCache = null; -const VULNERABILITY_ADVANCED_OPEN_KEY = 'vulnerabilityAdvancedFiltersOpen'; +let vulnerabilityMoreFiltersPopoverOpen = false; +let vulnerabilityFilterDebounceTimer = null; +const VULNERABILITY_FILTER_DEBOUNCE_MS = 400; const VULNERABILITY_DATALIST_MAX = 8; const VULNERABILITY_DATALIST_MIN_QUERY = 2; const VULN_FILTER_CHIP_FIELDS = [ + { key: 'q', labelKey: 'vulnerabilityPage.searchKeywordShort' }, { key: 'id', labelKey: 'vulnerabilityPage.vulnId' }, { key: 'status', labelKey: null, format: 'status' }, { key: 'severity', labelKey: null, format: 'severity' }, @@ -94,10 +98,12 @@ function syncVulnerabilityFiltersFromLocationHash() { const st = (params.get('status') || '').trim(); const convTag = (params.get('conversation_tag') || '').trim(); const taskTag = (params.get('task_tag') || '').trim(); - if (!vid && !cid && !tid && !sev && !st && !convTag && !taskTag) { + const q = (params.get('q') || params.get('search') || '').trim(); + if (!vid && !cid && !tid && !sev && !st && !convTag && !taskTag && !q) { return; } + vulnerabilityFilters.q = ''; vulnerabilityFilters.id = ''; vulnerabilityFilters.conversation_id = ''; vulnerabilityFilters.task_id = ''; @@ -105,14 +111,16 @@ function syncVulnerabilityFiltersFromLocationHash() { vulnerabilityFilters.task_tag = ''; vulnerabilityFilters.severity = ''; vulnerabilityFilters.status = ''; - const idEl = document.getElementById('vulnerability-id-filter'); + const searchEl = document.getElementById('vulnerability-search-filter'); + const exactIdEl = document.getElementById('vulnerability-exact-id-filter'); const convEl = document.getElementById('vulnerability-conversation-filter'); const taskEl = document.getElementById('vulnerability-task-filter'); const convTagEl = document.getElementById('vulnerability-conversation-tag-filter'); const taskTagEl = document.getElementById('vulnerability-task-tag-filter'); const sevEl = document.getElementById('vulnerability-severity-filter'); const stEl = document.getElementById('vulnerability-status-filter'); - if (idEl) idEl.value = ''; + if (searchEl) searchEl.value = ''; + if (exactIdEl) exactIdEl.value = ''; if (convEl) convEl.value = ''; if (taskEl) taskEl.value = ''; if (convTagEl) convTagEl.value = ''; @@ -120,9 +128,13 @@ function syncVulnerabilityFiltersFromLocationHash() { if (sevEl) sevEl.value = ''; if (stEl) stEl.value = ''; + if (q) { + vulnerabilityFilters.q = q; + if (searchEl) searchEl.value = q; + } if (vid) { vulnerabilityFilters.id = vid; - if (idEl) idEl.value = vid; + if (exactIdEl) exactIdEl.value = vid; } if (cid) { vulnerabilityFilters.conversation_id = cid; @@ -149,9 +161,6 @@ function syncVulnerabilityFiltersFromLocationHash() { if (stEl) stEl.value = st; } vulnerabilityPagination.currentPage = 1; - if (hasVulnerabilityAdvancedFiltersActive()) { - setVulnerabilityAdvancedFiltersOpen(true, false); - } syncVulnerabilityStatCardActiveState(); updateVulnerabilityFilterPanelState(); renderVulnerabilityFilterChips(); @@ -213,7 +222,8 @@ function applyVulnerabilitySeverityFilter(severity) { } function readVulnerabilityFiltersFromForm() { - vulnerabilityFilters.id = (document.getElementById('vulnerability-id-filter')?.value || '').trim(); + vulnerabilityFilters.q = (document.getElementById('vulnerability-search-filter')?.value || '').trim(); + vulnerabilityFilters.id = (document.getElementById('vulnerability-exact-id-filter')?.value || '').trim(); vulnerabilityFilters.conversation_id = (document.getElementById('vulnerability-conversation-filter')?.value || '').trim(); vulnerabilityFilters.task_id = (document.getElementById('vulnerability-task-filter')?.value || '').trim(); vulnerabilityFilters.conversation_tag = (document.getElementById('vulnerability-conversation-tag-filter')?.value || '').trim(); @@ -225,13 +235,13 @@ function readVulnerabilityFiltersFromForm() { function hasVulnerabilityAdvancedFiltersActive() { const f = vulnerabilityFilters; - return Boolean(f.conversation_id || f.task_id || f.conversation_tag || f.task_tag); + return Boolean(f.id || f.conversation_id || f.task_id || f.conversation_tag || f.task_tag); } function hasAnyVulnerabilityFilterActive() { const f = vulnerabilityFilters; return Boolean( - f.id || f.conversation_id || f.task_id || f.conversation_tag || f.task_tag || f.severity || f.status + f.q || f.id || f.conversation_id || f.task_id || f.conversation_tag || f.task_tag || f.severity || f.status ); } @@ -253,6 +263,7 @@ function updateVulnerabilityLocationHashFromFilters() { const params = new URLSearchParams(hashParts.length >= 2 ? hashParts.slice(1).join('?') : ''); const f = vulnerabilityFilters; const pairs = [ + ['q', f.q], ['id', f.id], ['conversation_id', f.conversation_id], ['task_id', f.task_id], @@ -279,17 +290,82 @@ function updateVulnerabilityLocationHashFromFilters() { } } -function toggleVulnerabilityAdvancedFilters(ev) { +function scheduleVulnerabilityFilterApply(immediate) { + if (vulnerabilityFilterDebounceTimer) { + clearTimeout(vulnerabilityFilterDebounceTimer); + vulnerabilityFilterDebounceTimer = null; + } + if (immediate) { + applyVulnerabilityFilters(); + return; + } + vulnerabilityFilterDebounceTimer = setTimeout(function () { + vulnerabilityFilterDebounceTimer = null; + applyVulnerabilityFilters(); + }, VULNERABILITY_FILTER_DEBOUNCE_MS); +} + +function syncVulnerabilityAdvancedFieldsFromFilters() { + const map = { + id: 'vulnerability-exact-id-filter', + conversation_id: 'vulnerability-conversation-filter', + task_id: 'vulnerability-task-filter', + conversation_tag: 'vulnerability-conversation-tag-filter', + task_tag: 'vulnerability-task-tag-filter' + }; + Object.keys(map).forEach(function (key) { + const el = document.getElementById(map[key]); + if (el) el.value = vulnerabilityFilters[key] || ''; + }); +} + +function setVulnerabilityMoreFiltersPopoverOpen(open) { + const btn = document.getElementById('vulnerability-more-filters-btn'); + const popover = document.getElementById('vulnerability-more-filters-popover'); + if (!btn || !popover) return; + vulnerabilityMoreFiltersPopoverOpen = open; + btn.setAttribute('aria-expanded', open ? 'true' : 'false'); + btn.classList.toggle('is-active', open); + popover.hidden = !open; +} + +function toggleVulnerabilityMoreFiltersPopover(ev) { if (ev) { ev.preventDefault(); ev.stopPropagation(); } - const toggleBtn = document.getElementById('vulnerability-advanced-toggle'); - if (!toggleBtn) return; - const expanded = toggleBtn.getAttribute('aria-expanded') === 'true'; - setVulnerabilityAdvancedFiltersOpen(!expanded, true); + const opening = !vulnerabilityMoreFiltersPopoverOpen; + if (opening) { + readVulnerabilityFiltersFromForm(); + syncVulnerabilityAdvancedFieldsFromFilters(); + } + setVulnerabilityMoreFiltersPopoverOpen(opening); +} + +function closeVulnerabilityMoreFiltersPopover(revertDraft) { + if (revertDraft) syncVulnerabilityAdvancedFieldsFromFilters(); + setVulnerabilityMoreFiltersPopoverOpen(false); +} + +function clearVulnerabilityAdvancedFilterFields() { + ['vulnerability-exact-id-filter', 'vulnerability-conversation-filter', 'vulnerability-task-filter', + 'vulnerability-conversation-tag-filter', 'vulnerability-task-tag-filter'].forEach(function (id) { + const el = document.getElementById(id); + if (el) el.value = ''; + }); +} + +function applyVulnerabilityMoreFiltersFromPopover() { + closeVulnerabilityMoreFiltersPopover(false); + scheduleVulnerabilityFilterApply(true); +} + +function onVulnerabilityFilterDocumentPointerDown(ev) { + if (!vulnerabilityMoreFiltersPopoverOpen) return; + const anchor = document.querySelector('.vulnerability-more-filters-anchor'); + if (anchor && anchor.contains(ev.target)) return; + closeVulnerabilityMoreFiltersPopover(true); } -window.toggleVulnerabilityAdvancedFilters = toggleVulnerabilityAdvancedFilters; function initVulnerabilityFilterPanel() { const panel = document.getElementById('vulnerability-filter-panel'); @@ -301,55 +377,69 @@ function initVulnerabilityFilterPanel() { } vulnerabilityFilterPanelBound = true; - let savedOpen = false; - try { - savedOpen = localStorage.getItem(VULNERABILITY_ADVANCED_OPEN_KEY) === 'true'; - } catch (e) { /* ignore */ } - setVulnerabilityAdvancedFiltersOpen(savedOpen, false); - const stEl = document.getElementById('vulnerability-status-filter'); - if (stEl) stEl.addEventListener('change', applyVulnerabilityFilters); + if (stEl) stEl.addEventListener('change', function () { scheduleVulnerabilityFilterApply(true); }); - const textIds = [ - 'vulnerability-id-filter', + const searchEl = document.getElementById('vulnerability-search-filter'); + if (searchEl) { + searchEl.addEventListener('input', function () { scheduleVulnerabilityFilterApply(false); }); + searchEl.addEventListener('keydown', function (ev) { + if (ev.key === 'Enter') { + ev.preventDefault(); + scheduleVulnerabilityFilterApply(true); + } + }); + searchEl.addEventListener('search', function () { + if (searchEl.value === '') scheduleVulnerabilityFilterApply(true); + }); + } + + const moreBtn = document.getElementById('vulnerability-more-filters-btn'); + if (moreBtn) moreBtn.addEventListener('click', toggleVulnerabilityMoreFiltersPopover); + + const applyBtn = document.getElementById('vulnerability-more-filters-apply'); + if (applyBtn) applyBtn.addEventListener('click', applyVulnerabilityMoreFiltersFromPopover); + + const resetBtn = document.getElementById('vulnerability-more-filters-reset'); + if (resetBtn) { + resetBtn.addEventListener('click', function () { + clearVulnerabilityAdvancedFilterFields(); + applyVulnerabilityMoreFiltersFromPopover(); + }); + } + + const advancedTextIds = [ + 'vulnerability-exact-id-filter', 'vulnerability-conversation-filter', 'vulnerability-task-filter', 'vulnerability-conversation-tag-filter', 'vulnerability-task-tag-filter' ]; - textIds.forEach(function (id) { + advancedTextIds.forEach(function (id) { const el = document.getElementById(id); if (!el) return; el.addEventListener('keydown', function (ev) { if (ev.key === 'Enter') { ev.preventDefault(); - applyVulnerabilityFilters(); + applyVulnerabilityMoreFiltersFromPopover(); } }); }); + document.addEventListener('mousedown', onVulnerabilityFilterDocumentPointerDown); + document.addEventListener('keydown', function (ev) { + if (ev.key === 'Escape' && vulnerabilityMoreFiltersPopoverOpen) { + closeVulnerabilityMoreFiltersPopover(true); + } + }); + bindVulnerabilityFilterTypeaheads(); } -function setVulnerabilityAdvancedFiltersOpen(open, persist) { - const toggleBtn = document.getElementById('vulnerability-advanced-toggle'); - const advanced = document.getElementById('vulnerability-advanced-filters'); - const wrap = document.querySelector('#vulnerability-filter-panel .vulnerability-filter-advanced-wrap'); - if (!toggleBtn || !advanced) return; - toggleBtn.setAttribute('aria-expanded', open ? 'true' : 'false'); - advanced.hidden = !open; - advanced.classList.toggle('is-open', open); - if (wrap) wrap.classList.toggle('is-expanded', open); - if (persist) { - try { - localStorage.setItem(VULNERABILITY_ADVANCED_OPEN_KEY, open ? 'true' : 'false'); - } catch (e) { /* ignore */ } - } -} - function countVulnerabilityAdvancedFiltersActive() { const f = vulnerabilityFilters; let n = 0; + if (f.id) n++; if (f.conversation_id) n++; if (f.task_id) n++; if (f.conversation_tag) n++; @@ -379,6 +469,8 @@ function updateVulnerabilityFilterPanelState() { readVulnerabilityFiltersFromForm(); panel.classList.toggle('is-filtered', hasAnyVulnerabilityFilterActive()); updateVulnerabilityAdvancedBadge(); + const clearBtn = document.getElementById('vulnerability-filter-clear-btn'); + if (clearBtn) clearBtn.hidden = !hasAnyVulnerabilityFilterActive(); } function formatVulnerabilityFilterChipValue(key, value) { @@ -431,7 +523,8 @@ function renderVulnerabilityFilterChips() { function removeVulnerabilityFilterByKey(key) { const map = { - id: 'vulnerability-id-filter', + q: 'vulnerability-search-filter', + id: 'vulnerability-exact-id-filter', conversation_id: 'vulnerability-conversation-filter', task_id: 'vulnerability-task-filter', conversation_tag: 'vulnerability-conversation-tag-filter', @@ -609,13 +702,7 @@ async function loadVulnerabilityStats() { throw new Error('apiFetch未定义'); } - const params = new URLSearchParams(); - if (vulnerabilityFilters.conversation_id) { - params.append('conversation_id', vulnerabilityFilters.conversation_id); - } - if (vulnerabilityFilters.task_id) { - params.append('task_id', vulnerabilityFilters.task_id); - } + const params = buildVulnerabilityFilterParams(); const response = await apiFetch(`/api/vulnerabilities/stats?${params.toString()}`); if (!response.ok) { @@ -689,31 +776,9 @@ async function loadVulnerabilities(page = null) { vulnerabilityPagination.currentPage = page; } - const params = new URLSearchParams(); + const params = buildVulnerabilityFilterParams(); params.append('page', vulnerabilityPagination.currentPage.toString()); params.append('limit', vulnerabilityPagination.pageSize.toString()); - - if (vulnerabilityFilters.id) { - params.append('id', vulnerabilityFilters.id); - } - if (vulnerabilityFilters.conversation_id) { - params.append('conversation_id', vulnerabilityFilters.conversation_id); - } - if (vulnerabilityFilters.task_id) { - params.append('task_id', vulnerabilityFilters.task_id); - } - if (vulnerabilityFilters.conversation_tag) { - params.append('conversation_tag', vulnerabilityFilters.conversation_tag); - } - if (vulnerabilityFilters.task_tag) { - params.append('task_tag', vulnerabilityFilters.task_tag); - } - if (vulnerabilityFilters.severity) { - params.append('severity', vulnerabilityFilters.severity); - } - if (vulnerabilityFilters.status) { - params.append('status', vulnerabilityFilters.status); - } const response = await apiFetch(`/api/vulnerabilities?${params.toString()}`); if (!response.ok) { @@ -1090,8 +1155,14 @@ function filterVulnerabilities() { // 清除筛选 function clearVulnerabilityFilters() { + closeVulnerabilityMoreFiltersPopover(false); + if (vulnerabilityFilterDebounceTimer) { + clearTimeout(vulnerabilityFilterDebounceTimer); + vulnerabilityFilterDebounceTimer = null; + } const fields = [ - 'vulnerability-id-filter', + 'vulnerability-search-filter', + 'vulnerability-exact-id-filter', 'vulnerability-conversation-filter', 'vulnerability-task-filter', 'vulnerability-conversation-tag-filter', @@ -1105,6 +1176,7 @@ function clearVulnerabilityFilters() { }); vulnerabilityFilters = { + q: '', id: '', conversation_id: '', task_id: '', @@ -1277,8 +1349,11 @@ function formatVulnerabilityAsMarkdown(vuln) { function buildVulnerabilityFilterParams() { const params = new URLSearchParams(); + if (vulnerabilityFilters.q) { + params.append('q', vulnerabilityFilters.q); + } const keys = ['id', 'conversation_id', 'task_id', 'conversation_tag', 'task_tag', 'severity', 'status']; - keys.forEach((k) => { + keys.forEach(function (k) { if (vulnerabilityFilters[k]) { params.append(k, vulnerabilityFilters[k]); } diff --git a/web/templates/index.html b/web/templates/index.html index 6d94bc83..5f69adc1 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -1446,10 +1446,14 @@
-
-
- - -