From eabfed09c9e0e0fa5a68089d1d16f93a0c2ddbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AC=E6=98=8E?= <83812544+Ed1s0nZ@users.noreply.github.com> Date: Sun, 31 May 2026 13:33:32 +0800 Subject: [PATCH] Add files via upload --- web/static/css/style.css | 94 ++++++++++++++++++++++++++++---------- web/static/i18n/en-US.json | 3 ++ web/static/i18n/zh-CN.json | 3 ++ web/static/js/projects.js | 63 +++++++++++++++++++++++-- web/templates/index.html | 55 ++++++++++++++++++++-- 5 files changed, 186 insertions(+), 32 deletions(-) diff --git a/web/static/css/style.css b/web/static/css/style.css index b06b9077..cba50243 100644 --- a/web/static/css/style.css +++ b/web/static/css/style.css @@ -21258,10 +21258,11 @@ button.chat-files-dropdown-item:hover:not(:disabled) { border-radius: 14px; box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06); overflow: hidden; - min-height: 420px; + min-height: 0; align-self: stretch; } .projects-detail-header { + flex-shrink: 0; display: flex; align-items: flex-start; justify-content: space-between; @@ -21349,6 +21350,7 @@ button.chat-files-dropdown-item:hover:not(:disabled) { padding: 12px 24px; background: #f8fafc; border-bottom: 1px solid #eef2f7; + flex-shrink: 0; } .projects-tab { padding: 8px 16px; @@ -21594,40 +21596,86 @@ button.chat-files-dropdown-item:hover:not(:disabled) { overflow: hidden; background: #fff; } -#project-panel-facts { +#project-panel-facts, +#project-panel-conversations, +#project-panel-vulns { display: flex; flex-direction: column; overflow: hidden; + min-height: 0; } -#project-panel-facts .projects-fact-toolbar { +#project-panel-facts .projects-fact-toolbar, +#project-panel-vulns .projects-fact-toolbar, +#project-panel-conversations .projects-panel-toolbar { flex: 0 0 auto; } -#project-panel-facts .projects-table-wrap { +#project-panel-facts .projects-table-wrap, +#project-panel-conversations .projects-table-wrap, +#project-panel-vulns .projects-table-wrap { flex: 1 1 auto; min-height: 0; - max-height: 100%; - overflow: hidden; -} -#project-panel-facts .projects-table-wrap .data-table--projects { - width: 100%; - height: 100%; - table-layout: fixed; - border-spacing: 0; -} -#project-panel-facts .projects-table-wrap .data-table--projects thead, -#project-panel-facts .projects-table-wrap .data-table--projects tbody tr { - display: table; - width: 100%; - table-layout: fixed; -} -#project-panel-facts .projects-table-wrap .data-table--projects tbody { - display: block; - height: calc(100% - 42px); - overflow-y: auto; overflow-x: hidden; + overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; } +#project-panel-facts .projects-table-wrap .data-table--projects thead th, +#project-panel-conversations .projects-table-wrap .data-table--projects thead th, +#project-panel-vulns .projects-table-wrap .data-table--projects thead th { + position: sticky; + top: 0; + z-index: 2; + box-shadow: 0 1px 0 var(--border-color, #e2e8f0); +} +.projects-panel-toolbar--hint { + margin-bottom: 14px; + padding: 0; + background: transparent; + border: none; + border-radius: 0; +} +.projects-panel-toolbar--hint .projects-fact-toolbar-hint { + margin: 0; +} +#project-panel-conversations .data-table--projects th:nth-child(1), +#project-panel-conversations .data-table--projects td:nth-child(1) { + width: 48%; +} +#project-panel-conversations .data-table--projects th:nth-child(2), +#project-panel-conversations .data-table--projects td:nth-child(2) { + width: 22%; +} +#project-panel-conversations .data-table--projects th:nth-child(3), +#project-panel-conversations .data-table--projects td:nth-child(3) { + width: 30%; +} +.projects-vuln-toolbar-top { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; + flex-wrap: wrap; +} +.projects-vuln-toolbar-top .projects-fact-toolbar-hint { + flex: 1 1 240px; + margin: 0; +} +#project-panel-vulns .data-table--projects th:nth-child(1), +#project-panel-vulns .data-table--projects td:nth-child(1) { + width: 46%; +} +#project-panel-vulns .data-table--projects th:nth-child(2), +#project-panel-vulns .data-table--projects td:nth-child(2) { + width: 14%; +} +#project-panel-vulns .data-table--projects th:nth-child(3), +#project-panel-vulns .data-table--projects td:nth-child(3) { + width: 14%; +} +#project-panel-vulns .data-table--projects th:nth-child(4), +#project-panel-vulns .data-table--projects td:nth-child(4) { + width: 26%; +} .projects-table-wrap .data-table--projects { min-width: 0; table-layout: fixed; diff --git a/web/static/i18n/en-US.json b/web/static/i18n/en-US.json index 0511cb64..02e79684 100644 --- a/web/static/i18n/en-US.json +++ b/web/static/i18n/en-US.json @@ -258,6 +258,9 @@ "boundConversationsHint": "Conversations bound to this project; click to open", "titleLabel": "Title", "projectVulnSummaryHint": "Vulnerability summary under this project", + "searchVulnsSr": "Search vulnerabilities", + "searchVulnsPlaceholder": "Search title, description, type, target…", + "noMatchingVulns": "No matching vulnerabilities, try adjusting filters", "viewInVulnerabilityManagement": "View in vulnerability management", "severity": "Severity", "status": "Status", diff --git a/web/static/i18n/zh-CN.json b/web/static/i18n/zh-CN.json index 8a1981f7..f78c47d9 100644 --- a/web/static/i18n/zh-CN.json +++ b/web/static/i18n/zh-CN.json @@ -247,6 +247,9 @@ "boundConversationsHint": "绑定到本项目的对话;点击可打开会话", "titleLabel": "标题", "projectVulnSummaryHint": "本项目下记录的漏洞汇总", + "searchVulnsSr": "搜索漏洞", + "searchVulnsPlaceholder": "搜索标题、描述、类型、目标…", + "noMatchingVulns": "无匹配漏洞,请调整筛选条件", "viewInVulnerabilityManagement": "在漏洞管理中查看", "severity": "严重度", "status": "状态", diff --git a/web/static/js/projects.js b/web/static/js/projects.js index 4f3a703e..f19117d8 100644 --- a/web/static/js/projects.js +++ b/web/static/js/projects.js @@ -336,6 +336,50 @@ function formatSeverityBadge(severity) { return `${escapeHtml(severity || '—')}`; } +function formatVulnStatusBadge(status) { + const s = (status || 'open').toLowerCase(); + const labelMap = { + open: 'vulnerabilityPage.statusOpen', + confirmed: 'vulnerabilityPage.statusConfirmed', + fixed: 'vulnerabilityPage.statusFixed', + false_positive: 'vulnerabilityPage.statusFalsePositive', + }; + const label = labelMap[s] ? tp(labelMap[s]) : status || '—'; + const cls = ['open', 'confirmed', 'fixed', 'false_positive'].includes(s) ? s : 'open'; + return `${escapeHtml(label)}`; +} + +let _projectVulnsFilterDebounce = null; + +function buildProjectVulnsQueryParams() { + const params = new URLSearchParams(); + params.set('project_id', currentProjectId); + params.set('limit', '200'); + const search = document.getElementById('project-vulns-search')?.value?.trim(); + const severity = document.getElementById('project-vulns-filter-severity')?.value?.trim(); + const status = document.getElementById('project-vulns-filter-status')?.value?.trim(); + if (search) params.set('q', search); + if (severity) params.set('severity', severity); + if (status) params.set('status', status); + return params; +} + +function projectVulnsHasActiveFilter() { + return !!( + document.getElementById('project-vulns-search')?.value?.trim() || + document.getElementById('project-vulns-filter-severity')?.value || + document.getElementById('project-vulns-filter-status')?.value + ); +} + +function debouncedLoadProjectVulnerabilities() { + if (_projectVulnsFilterDebounce) clearTimeout(_projectVulnsFilterDebounce); + _projectVulnsFilterDebounce = setTimeout(() => { + _projectVulnsFilterDebounce = null; + loadProjectVulnerabilities(); + }, 280); +} + function getProjectsListFilter() { return (document.getElementById('projects-list-search')?.value || '').trim().toLowerCase(); } @@ -417,10 +461,16 @@ async function selectProject(id) { const catEl = document.getElementById('project-facts-filter-category'); const confEl = document.getElementById('project-facts-filter-confidence'); const sparseEl = document.getElementById('project-facts-filter-sparse'); + const vulnSearchEl = document.getElementById('project-vulns-search'); + const vulnSevEl = document.getElementById('project-vulns-filter-severity'); + const vulnStatusEl = document.getElementById('project-vulns-filter-status'); if (searchEl) searchEl.value = ''; if (catEl) catEl.value = ''; if (confEl) confEl.value = ''; if (sparseEl) sparseEl.checked = false; + if (vulnSearchEl) vulnSearchEl.value = ''; + if (vulnSevEl) vulnSevEl.value = ''; + if (vulnStatusEl) vulnStatusEl.value = ''; renderProjectsSidebar(); updateProjectsDetailVisibility(); try { @@ -846,15 +896,18 @@ async function loadProjectVulnerabilities() { const tbody = document.getElementById('project-vulns-tbody'); if (!tbody || !currentProjectId) return; tbody.innerHTML = `