mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-25 04:12:31 +02:00
Add files via upload
This commit is contained in:
+134
-83
@@ -16990,8 +16990,8 @@ header {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.vulnerability-controls {
|
.vulnerability-controls {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 12px;
|
||||||
padding: 10px 12px;
|
padding: 8px 10px;
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@@ -17016,6 +17016,117 @@ header {
|
|||||||
min-width: 0;
|
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 {
|
.vulnerability-filter-field {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -17061,6 +17172,10 @@ header {
|
|||||||
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.12);
|
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vulnerability-filter-clear-btn[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.vulnerability-filter-clear-btn {
|
.vulnerability-filter-clear-btn {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
@@ -17078,69 +17193,7 @@ header {
|
|||||||
background: rgba(59, 130, 246, 0.06);
|
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 {
|
.vulnerability-filter-advanced-badge {
|
||||||
display: inline;
|
display: inline;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
@@ -17155,30 +17208,23 @@ header {
|
|||||||
display: none !important;
|
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 {
|
.vulnerability-filter-chips {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px 8px;
|
||||||
margin-top: 10px;
|
margin-top: 8px;
|
||||||
padding-top: 10px;
|
padding-top: 8px;
|
||||||
border-top: 1px solid var(--border-color);
|
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 {
|
.vulnerability-filter-chips-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@@ -17222,8 +17268,13 @@ header {
|
|||||||
flex: 1 1 100%;
|
flex: 1 1 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vulnerability-filter-actions {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
.vulnerability-filter-clear-btn {
|
.vulnerability-filter-clear-btn {
|
||||||
align-self: flex-end;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1545,6 +1545,10 @@
|
|||||||
"statClickAll": "View all (clear severity filter)",
|
"statClickAll": "View all (clear severity filter)",
|
||||||
"statClickFilter": "Click to filter by this severity; click again to clear",
|
"statClickFilter": "Click to filter by this severity; click again to clear",
|
||||||
"advancedFilters": "Advanced filters",
|
"advancedFilters": "Advanced filters",
|
||||||
|
"moreFilters": "More filters",
|
||||||
|
"applyFilters": "Apply",
|
||||||
|
"clearAdvanced": "Clear",
|
||||||
|
"clearAll": "Reset all",
|
||||||
"activeFilters": "Active filters",
|
"activeFilters": "Active filters",
|
||||||
"chipRemove": "Remove",
|
"chipRemove": "Remove",
|
||||||
"filter": "Filter",
|
"filter": "Filter",
|
||||||
@@ -1564,6 +1568,10 @@
|
|||||||
"statusFixed": "Fixed",
|
"statusFixed": "Fixed",
|
||||||
"statusFalsePositive": "False positive",
|
"statusFalsePositive": "False positive",
|
||||||
"searchVulnId": "Search vuln ID",
|
"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",
|
"filterConversation": "Filter by conversation",
|
||||||
"loading": "Loading...",
|
"loading": "Loading...",
|
||||||
"loadListFailed": "Failed to load",
|
"loadListFailed": "Failed to load",
|
||||||
|
|||||||
@@ -1534,6 +1534,10 @@
|
|||||||
"statClickAll": "查看全部(清除严重度筛选)",
|
"statClickAll": "查看全部(清除严重度筛选)",
|
||||||
"statClickFilter": "点击按此严重度筛选;再次点击清除",
|
"statClickFilter": "点击按此严重度筛选;再次点击清除",
|
||||||
"advancedFilters": "高级筛选",
|
"advancedFilters": "高级筛选",
|
||||||
|
"moreFilters": "更多筛选",
|
||||||
|
"applyFilters": "应用",
|
||||||
|
"clearAdvanced": "清空",
|
||||||
|
"clearAll": "重置全部",
|
||||||
"activeFilters": "已选条件",
|
"activeFilters": "已选条件",
|
||||||
"chipRemove": "移除",
|
"chipRemove": "移除",
|
||||||
"filter": "筛选",
|
"filter": "筛选",
|
||||||
@@ -1552,7 +1556,11 @@
|
|||||||
"statusConfirmed": "已确认",
|
"statusConfirmed": "已确认",
|
||||||
"statusFixed": "已修复",
|
"statusFixed": "已修复",
|
||||||
"statusFalsePositive": "误报",
|
"statusFalsePositive": "误报",
|
||||||
"searchVulnId": "搜索漏洞ID",
|
"searchVulnId": "搜索漏洞 ID",
|
||||||
|
"searchKeyword": "搜索标题、描述、类型、目标…",
|
||||||
|
"searchKeywordShort": "关键词",
|
||||||
|
"filterExactId": "精确匹配漏洞 ID",
|
||||||
|
"filterEnterHint": "回车筛选",
|
||||||
"filterConversation": "筛选特定会话",
|
"filterConversation": "筛选特定会话",
|
||||||
"loading": "加载中...",
|
"loading": "加载中...",
|
||||||
"loadListFailed": "加载失败",
|
"loadListFailed": "加载失败",
|
||||||
|
|||||||
+152
-77
@@ -46,6 +46,7 @@ const getVulnerabilityPageSize = () => {
|
|||||||
|
|
||||||
let currentVulnerabilityId = null;
|
let currentVulnerabilityId = null;
|
||||||
let vulnerabilityFilters = {
|
let vulnerabilityFilters = {
|
||||||
|
q: '',
|
||||||
id: '',
|
id: '',
|
||||||
conversation_id: '',
|
conversation_id: '',
|
||||||
task_id: '',
|
task_id: '',
|
||||||
@@ -65,11 +66,14 @@ const VULN_STAT_SEVERITIES = ['critical', 'high', 'medium', 'low', 'info'];
|
|||||||
let vulnerabilityStatCardsBound = false;
|
let vulnerabilityStatCardsBound = false;
|
||||||
let vulnerabilityFilterPanelBound = false;
|
let vulnerabilityFilterPanelBound = false;
|
||||||
let vulnerabilityFilterOptionsCache = null;
|
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_MAX = 8;
|
||||||
const VULNERABILITY_DATALIST_MIN_QUERY = 2;
|
const VULNERABILITY_DATALIST_MIN_QUERY = 2;
|
||||||
|
|
||||||
const VULN_FILTER_CHIP_FIELDS = [
|
const VULN_FILTER_CHIP_FIELDS = [
|
||||||
|
{ key: 'q', labelKey: 'vulnerabilityPage.searchKeywordShort' },
|
||||||
{ key: 'id', labelKey: 'vulnerabilityPage.vulnId' },
|
{ key: 'id', labelKey: 'vulnerabilityPage.vulnId' },
|
||||||
{ key: 'status', labelKey: null, format: 'status' },
|
{ key: 'status', labelKey: null, format: 'status' },
|
||||||
{ key: 'severity', labelKey: null, format: 'severity' },
|
{ key: 'severity', labelKey: null, format: 'severity' },
|
||||||
@@ -94,10 +98,12 @@ function syncVulnerabilityFiltersFromLocationHash() {
|
|||||||
const st = (params.get('status') || '').trim();
|
const st = (params.get('status') || '').trim();
|
||||||
const convTag = (params.get('conversation_tag') || '').trim();
|
const convTag = (params.get('conversation_tag') || '').trim();
|
||||||
const taskTag = (params.get('task_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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vulnerabilityFilters.q = '';
|
||||||
vulnerabilityFilters.id = '';
|
vulnerabilityFilters.id = '';
|
||||||
vulnerabilityFilters.conversation_id = '';
|
vulnerabilityFilters.conversation_id = '';
|
||||||
vulnerabilityFilters.task_id = '';
|
vulnerabilityFilters.task_id = '';
|
||||||
@@ -105,14 +111,16 @@ function syncVulnerabilityFiltersFromLocationHash() {
|
|||||||
vulnerabilityFilters.task_tag = '';
|
vulnerabilityFilters.task_tag = '';
|
||||||
vulnerabilityFilters.severity = '';
|
vulnerabilityFilters.severity = '';
|
||||||
vulnerabilityFilters.status = '';
|
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 convEl = document.getElementById('vulnerability-conversation-filter');
|
||||||
const taskEl = document.getElementById('vulnerability-task-filter');
|
const taskEl = document.getElementById('vulnerability-task-filter');
|
||||||
const convTagEl = document.getElementById('vulnerability-conversation-tag-filter');
|
const convTagEl = document.getElementById('vulnerability-conversation-tag-filter');
|
||||||
const taskTagEl = document.getElementById('vulnerability-task-tag-filter');
|
const taskTagEl = document.getElementById('vulnerability-task-tag-filter');
|
||||||
const sevEl = document.getElementById('vulnerability-severity-filter');
|
const sevEl = document.getElementById('vulnerability-severity-filter');
|
||||||
const stEl = document.getElementById('vulnerability-status-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 (convEl) convEl.value = '';
|
||||||
if (taskEl) taskEl.value = '';
|
if (taskEl) taskEl.value = '';
|
||||||
if (convTagEl) convTagEl.value = '';
|
if (convTagEl) convTagEl.value = '';
|
||||||
@@ -120,9 +128,13 @@ function syncVulnerabilityFiltersFromLocationHash() {
|
|||||||
if (sevEl) sevEl.value = '';
|
if (sevEl) sevEl.value = '';
|
||||||
if (stEl) stEl.value = '';
|
if (stEl) stEl.value = '';
|
||||||
|
|
||||||
|
if (q) {
|
||||||
|
vulnerabilityFilters.q = q;
|
||||||
|
if (searchEl) searchEl.value = q;
|
||||||
|
}
|
||||||
if (vid) {
|
if (vid) {
|
||||||
vulnerabilityFilters.id = vid;
|
vulnerabilityFilters.id = vid;
|
||||||
if (idEl) idEl.value = vid;
|
if (exactIdEl) exactIdEl.value = vid;
|
||||||
}
|
}
|
||||||
if (cid) {
|
if (cid) {
|
||||||
vulnerabilityFilters.conversation_id = cid;
|
vulnerabilityFilters.conversation_id = cid;
|
||||||
@@ -149,9 +161,6 @@ function syncVulnerabilityFiltersFromLocationHash() {
|
|||||||
if (stEl) stEl.value = st;
|
if (stEl) stEl.value = st;
|
||||||
}
|
}
|
||||||
vulnerabilityPagination.currentPage = 1;
|
vulnerabilityPagination.currentPage = 1;
|
||||||
if (hasVulnerabilityAdvancedFiltersActive()) {
|
|
||||||
setVulnerabilityAdvancedFiltersOpen(true, false);
|
|
||||||
}
|
|
||||||
syncVulnerabilityStatCardActiveState();
|
syncVulnerabilityStatCardActiveState();
|
||||||
updateVulnerabilityFilterPanelState();
|
updateVulnerabilityFilterPanelState();
|
||||||
renderVulnerabilityFilterChips();
|
renderVulnerabilityFilterChips();
|
||||||
@@ -213,7 +222,8 @@ function applyVulnerabilitySeverityFilter(severity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function readVulnerabilityFiltersFromForm() {
|
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.conversation_id = (document.getElementById('vulnerability-conversation-filter')?.value || '').trim();
|
||||||
vulnerabilityFilters.task_id = (document.getElementById('vulnerability-task-filter')?.value || '').trim();
|
vulnerabilityFilters.task_id = (document.getElementById('vulnerability-task-filter')?.value || '').trim();
|
||||||
vulnerabilityFilters.conversation_tag = (document.getElementById('vulnerability-conversation-tag-filter')?.value || '').trim();
|
vulnerabilityFilters.conversation_tag = (document.getElementById('vulnerability-conversation-tag-filter')?.value || '').trim();
|
||||||
@@ -225,13 +235,13 @@ function readVulnerabilityFiltersFromForm() {
|
|||||||
|
|
||||||
function hasVulnerabilityAdvancedFiltersActive() {
|
function hasVulnerabilityAdvancedFiltersActive() {
|
||||||
const f = vulnerabilityFilters;
|
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() {
|
function hasAnyVulnerabilityFilterActive() {
|
||||||
const f = vulnerabilityFilters;
|
const f = vulnerabilityFilters;
|
||||||
return Boolean(
|
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 params = new URLSearchParams(hashParts.length >= 2 ? hashParts.slice(1).join('?') : '');
|
||||||
const f = vulnerabilityFilters;
|
const f = vulnerabilityFilters;
|
||||||
const pairs = [
|
const pairs = [
|
||||||
|
['q', f.q],
|
||||||
['id', f.id],
|
['id', f.id],
|
||||||
['conversation_id', f.conversation_id],
|
['conversation_id', f.conversation_id],
|
||||||
['task_id', f.task_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) {
|
if (ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
}
|
}
|
||||||
const toggleBtn = document.getElementById('vulnerability-advanced-toggle');
|
const opening = !vulnerabilityMoreFiltersPopoverOpen;
|
||||||
if (!toggleBtn) return;
|
if (opening) {
|
||||||
const expanded = toggleBtn.getAttribute('aria-expanded') === 'true';
|
readVulnerabilityFiltersFromForm();
|
||||||
setVulnerabilityAdvancedFiltersOpen(!expanded, true);
|
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() {
|
function initVulnerabilityFilterPanel() {
|
||||||
const panel = document.getElementById('vulnerability-filter-panel');
|
const panel = document.getElementById('vulnerability-filter-panel');
|
||||||
@@ -301,55 +377,69 @@ function initVulnerabilityFilterPanel() {
|
|||||||
}
|
}
|
||||||
vulnerabilityFilterPanelBound = true;
|
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');
|
const stEl = document.getElementById('vulnerability-status-filter');
|
||||||
if (stEl) stEl.addEventListener('change', applyVulnerabilityFilters);
|
if (stEl) stEl.addEventListener('change', function () { scheduleVulnerabilityFilterApply(true); });
|
||||||
|
|
||||||
const textIds = [
|
const searchEl = document.getElementById('vulnerability-search-filter');
|
||||||
'vulnerability-id-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-conversation-filter',
|
||||||
'vulnerability-task-filter',
|
'vulnerability-task-filter',
|
||||||
'vulnerability-conversation-tag-filter',
|
'vulnerability-conversation-tag-filter',
|
||||||
'vulnerability-task-tag-filter'
|
'vulnerability-task-tag-filter'
|
||||||
];
|
];
|
||||||
textIds.forEach(function (id) {
|
advancedTextIds.forEach(function (id) {
|
||||||
const el = document.getElementById(id);
|
const el = document.getElementById(id);
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
el.addEventListener('keydown', function (ev) {
|
el.addEventListener('keydown', function (ev) {
|
||||||
if (ev.key === 'Enter') {
|
if (ev.key === 'Enter') {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
applyVulnerabilityFilters();
|
applyVulnerabilityMoreFiltersFromPopover();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.addEventListener('mousedown', onVulnerabilityFilterDocumentPointerDown);
|
||||||
|
document.addEventListener('keydown', function (ev) {
|
||||||
|
if (ev.key === 'Escape' && vulnerabilityMoreFiltersPopoverOpen) {
|
||||||
|
closeVulnerabilityMoreFiltersPopover(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
bindVulnerabilityFilterTypeaheads();
|
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() {
|
function countVulnerabilityAdvancedFiltersActive() {
|
||||||
const f = vulnerabilityFilters;
|
const f = vulnerabilityFilters;
|
||||||
let n = 0;
|
let n = 0;
|
||||||
|
if (f.id) n++;
|
||||||
if (f.conversation_id) n++;
|
if (f.conversation_id) n++;
|
||||||
if (f.task_id) n++;
|
if (f.task_id) n++;
|
||||||
if (f.conversation_tag) n++;
|
if (f.conversation_tag) n++;
|
||||||
@@ -379,6 +469,8 @@ function updateVulnerabilityFilterPanelState() {
|
|||||||
readVulnerabilityFiltersFromForm();
|
readVulnerabilityFiltersFromForm();
|
||||||
panel.classList.toggle('is-filtered', hasAnyVulnerabilityFilterActive());
|
panel.classList.toggle('is-filtered', hasAnyVulnerabilityFilterActive());
|
||||||
updateVulnerabilityAdvancedBadge();
|
updateVulnerabilityAdvancedBadge();
|
||||||
|
const clearBtn = document.getElementById('vulnerability-filter-clear-btn');
|
||||||
|
if (clearBtn) clearBtn.hidden = !hasAnyVulnerabilityFilterActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatVulnerabilityFilterChipValue(key, value) {
|
function formatVulnerabilityFilterChipValue(key, value) {
|
||||||
@@ -431,7 +523,8 @@ function renderVulnerabilityFilterChips() {
|
|||||||
|
|
||||||
function removeVulnerabilityFilterByKey(key) {
|
function removeVulnerabilityFilterByKey(key) {
|
||||||
const map = {
|
const map = {
|
||||||
id: 'vulnerability-id-filter',
|
q: 'vulnerability-search-filter',
|
||||||
|
id: 'vulnerability-exact-id-filter',
|
||||||
conversation_id: 'vulnerability-conversation-filter',
|
conversation_id: 'vulnerability-conversation-filter',
|
||||||
task_id: 'vulnerability-task-filter',
|
task_id: 'vulnerability-task-filter',
|
||||||
conversation_tag: 'vulnerability-conversation-tag-filter',
|
conversation_tag: 'vulnerability-conversation-tag-filter',
|
||||||
@@ -609,13 +702,7 @@ async function loadVulnerabilityStats() {
|
|||||||
throw new Error('apiFetch未定义');
|
throw new Error('apiFetch未定义');
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = new URLSearchParams();
|
const params = buildVulnerabilityFilterParams();
|
||||||
if (vulnerabilityFilters.conversation_id) {
|
|
||||||
params.append('conversation_id', vulnerabilityFilters.conversation_id);
|
|
||||||
}
|
|
||||||
if (vulnerabilityFilters.task_id) {
|
|
||||||
params.append('task_id', vulnerabilityFilters.task_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await apiFetch(`/api/vulnerabilities/stats?${params.toString()}`);
|
const response = await apiFetch(`/api/vulnerabilities/stats?${params.toString()}`);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -689,31 +776,9 @@ async function loadVulnerabilities(page = null) {
|
|||||||
vulnerabilityPagination.currentPage = page;
|
vulnerabilityPagination.currentPage = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = new URLSearchParams();
|
const params = buildVulnerabilityFilterParams();
|
||||||
params.append('page', vulnerabilityPagination.currentPage.toString());
|
params.append('page', vulnerabilityPagination.currentPage.toString());
|
||||||
params.append('limit', vulnerabilityPagination.pageSize.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()}`);
|
const response = await apiFetch(`/api/vulnerabilities?${params.toString()}`);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -1090,8 +1155,14 @@ function filterVulnerabilities() {
|
|||||||
|
|
||||||
// 清除筛选
|
// 清除筛选
|
||||||
function clearVulnerabilityFilters() {
|
function clearVulnerabilityFilters() {
|
||||||
|
closeVulnerabilityMoreFiltersPopover(false);
|
||||||
|
if (vulnerabilityFilterDebounceTimer) {
|
||||||
|
clearTimeout(vulnerabilityFilterDebounceTimer);
|
||||||
|
vulnerabilityFilterDebounceTimer = null;
|
||||||
|
}
|
||||||
const fields = [
|
const fields = [
|
||||||
'vulnerability-id-filter',
|
'vulnerability-search-filter',
|
||||||
|
'vulnerability-exact-id-filter',
|
||||||
'vulnerability-conversation-filter',
|
'vulnerability-conversation-filter',
|
||||||
'vulnerability-task-filter',
|
'vulnerability-task-filter',
|
||||||
'vulnerability-conversation-tag-filter',
|
'vulnerability-conversation-tag-filter',
|
||||||
@@ -1105,6 +1176,7 @@ function clearVulnerabilityFilters() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
vulnerabilityFilters = {
|
vulnerabilityFilters = {
|
||||||
|
q: '',
|
||||||
id: '',
|
id: '',
|
||||||
conversation_id: '',
|
conversation_id: '',
|
||||||
task_id: '',
|
task_id: '',
|
||||||
@@ -1277,8 +1349,11 @@ function formatVulnerabilityAsMarkdown(vuln) {
|
|||||||
|
|
||||||
function buildVulnerabilityFilterParams() {
|
function buildVulnerabilityFilterParams() {
|
||||||
const params = new URLSearchParams();
|
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'];
|
const keys = ['id', 'conversation_id', 'task_id', 'conversation_tag', 'task_tag', 'severity', 'status'];
|
||||||
keys.forEach((k) => {
|
keys.forEach(function (k) {
|
||||||
if (vulnerabilityFilters[k]) {
|
if (vulnerabilityFilters[k]) {
|
||||||
params.append(k, vulnerabilityFilters[k]);
|
params.append(k, vulnerabilityFilters[k]);
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-32
@@ -1446,10 +1446,14 @@
|
|||||||
<div class="vulnerability-controls" id="vulnerability-filter-panel">
|
<div class="vulnerability-controls" id="vulnerability-filter-panel">
|
||||||
<div class="vulnerability-filter-toolbar">
|
<div class="vulnerability-filter-toolbar">
|
||||||
<div class="vulnerability-filter-primary">
|
<div class="vulnerability-filter-primary">
|
||||||
<label class="vulnerability-filter-field vulnerability-filter-field--grow">
|
<label class="vulnerability-filter-field vulnerability-filter-field--grow vulnerability-search-wrap">
|
||||||
<span class="sr-only" data-i18n="vulnerabilityPage.vulnId">漏洞ID</span>
|
<span class="sr-only" data-i18n="vulnerabilityPage.searchKeyword">关键词搜索</span>
|
||||||
<input type="search" id="vulnerability-id-filter" autocomplete="off"
|
<svg class="vulnerability-search-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
|
||||||
data-i18n="vulnerabilityPage.searchVulnId" data-i18n-attr="placeholder" placeholder="搜索漏洞 ID,回车筛选" />
|
<circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"/>
|
||||||
|
<path d="M20 20L16 16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
<input type="search" id="vulnerability-search-filter" autocomplete="off"
|
||||||
|
data-i18n="vulnerabilityPage.searchKeyword" data-i18n-attr="placeholder" placeholder="搜索标题、描述、类型、目标…" />
|
||||||
</label>
|
</label>
|
||||||
<label class="vulnerability-filter-field vulnerability-filter-field--status">
|
<label class="vulnerability-filter-field vulnerability-filter-field--status">
|
||||||
<span class="sr-only" data-i18n="vulnerabilityPage.status">状态</span>
|
<span class="sr-only" data-i18n="vulnerabilityPage.status">状态</span>
|
||||||
@@ -1461,7 +1465,52 @@
|
|||||||
<option value="false_positive" data-i18n="vulnerabilityPage.statusFalsePositive">误报</option>
|
<option value="false_positive" data-i18n="vulnerabilityPage.statusFalsePositive">误报</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<button type="button" class="vulnerability-filter-clear-btn" onclick="clearVulnerabilityFilters()" data-i18n="vulnerabilityPage.clear">清除</button>
|
<div class="vulnerability-filter-actions">
|
||||||
|
<div class="vulnerability-more-filters-anchor">
|
||||||
|
<button type="button" class="btn-secondary vulnerability-more-filters-btn" id="vulnerability-more-filters-btn"
|
||||||
|
aria-expanded="false" aria-haspopup="dialog" aria-controls="vulnerability-more-filters-popover">
|
||||||
|
<span data-i18n="vulnerabilityPage.moreFilters">更多筛选</span>
|
||||||
|
<span class="vulnerability-filter-advanced-badge" id="vulnerability-advanced-badge" hidden></span>
|
||||||
|
</button>
|
||||||
|
<div class="vulnerability-more-filters-popover" id="vulnerability-more-filters-popover" hidden role="dialog"
|
||||||
|
aria-labelledby="vulnerability-more-filters-title">
|
||||||
|
<p class="vulnerability-more-filters-popover-title" id="vulnerability-more-filters-title" data-i18n="vulnerabilityPage.moreFilters">更多筛选</p>
|
||||||
|
<div class="vulnerability-more-filters-popover-body">
|
||||||
|
<label class="vulnerability-filter-field vulnerability-filter-field--full">
|
||||||
|
<span data-i18n="vulnerabilityPage.vulnId">漏洞 ID</span>
|
||||||
|
<input type="text" id="vulnerability-exact-id-filter"
|
||||||
|
data-i18n="vulnerabilityPage.filterExactId" data-i18n-attr="placeholder" placeholder="精确匹配漏洞 ID" />
|
||||||
|
</label>
|
||||||
|
<label class="vulnerability-filter-field">
|
||||||
|
<span data-i18n="vulnerabilityPage.conversationId">会话 ID</span>
|
||||||
|
<input type="text" id="vulnerability-conversation-filter" list="vulnerability-conversation-suggestions"
|
||||||
|
data-i18n="vulnerabilityPage.filterConversation" data-i18n-attr="placeholder" placeholder="筛选特定会话" />
|
||||||
|
</label>
|
||||||
|
<label class="vulnerability-filter-field">
|
||||||
|
<span data-i18n="vulnerabilityPage.taskOrQueueId">任务 / 队列 ID</span>
|
||||||
|
<input type="text" id="vulnerability-task-filter" list="vulnerability-task-suggestions"
|
||||||
|
data-i18n="vulnerabilityPage.filterTaskOrQueue" data-i18n-attr="placeholder" placeholder="筛选任务或队列 ID" />
|
||||||
|
</label>
|
||||||
|
<label class="vulnerability-filter-field">
|
||||||
|
<span data-i18n="vulnerabilityPage.conversationTag">对话标签</span>
|
||||||
|
<input type="text" id="vulnerability-conversation-tag-filter" list="vulnerability-conversation-tag-suggestions"
|
||||||
|
data-i18n="vulnerabilityPage.filterConversationTag" data-i18n-attr="placeholder" placeholder="筛选对话标签" />
|
||||||
|
</label>
|
||||||
|
<label class="vulnerability-filter-field">
|
||||||
|
<span data-i18n="vulnerabilityPage.taskTag">任务标签</span>
|
||||||
|
<input type="text" id="vulnerability-task-tag-filter" list="vulnerability-task-tag-suggestions"
|
||||||
|
data-i18n="vulnerabilityPage.filterTaskTag" data-i18n-attr="placeholder" placeholder="筛选任务标签" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="vulnerability-more-filters-popover-footer">
|
||||||
|
<button type="button" class="btn-secondary" id="vulnerability-more-filters-reset" data-i18n="vulnerabilityPage.clearAdvanced">清空</button>
|
||||||
|
<button type="button" class="btn-primary" id="vulnerability-more-filters-apply" data-i18n="vulnerabilityPage.applyFilters">应用</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="vulnerability-filter-clear-btn" id="vulnerability-filter-clear-btn"
|
||||||
|
onclick="clearVulnerabilityFilters()" hidden data-i18n="vulnerabilityPage.clearAll">重置全部</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<select id="vulnerability-severity-filter" class="vulnerability-severity-sync" hidden aria-hidden="true" tabindex="-1">
|
<select id="vulnerability-severity-filter" class="vulnerability-severity-sync" hidden aria-hidden="true" tabindex="-1">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
@@ -1472,34 +1521,8 @@
|
|||||||
<option value="info">info</option>
|
<option value="info">info</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="vulnerability-filter-advanced-wrap">
|
|
||||||
<button type="button" class="vulnerability-filter-advanced-toggle" id="vulnerability-advanced-toggle"
|
|
||||||
aria-expanded="false" aria-controls="vulnerability-advanced-filters"
|
|
||||||
onclick="toggleVulnerabilityAdvancedFilters(event)">
|
|
||||||
<span class="vulnerability-filter-advanced-chevron" aria-hidden="true"></span>
|
|
||||||
<span data-i18n="vulnerabilityPage.advancedFilters">高级筛选</span>
|
|
||||||
<span class="vulnerability-filter-advanced-badge" id="vulnerability-advanced-badge" hidden></span>
|
|
||||||
</button>
|
|
||||||
<div class="vulnerability-filter-advanced" id="vulnerability-advanced-filters" hidden>
|
|
||||||
<label class="vulnerability-filter-field">
|
|
||||||
<span data-i18n="vulnerabilityPage.conversationId">会话 ID</span>
|
|
||||||
<input type="text" id="vulnerability-conversation-filter" list="vulnerability-conversation-suggestions" placeholder="回车筛选" />
|
|
||||||
</label>
|
|
||||||
<label class="vulnerability-filter-field">
|
|
||||||
<span data-i18n="vulnerabilityPage.taskOrQueueId">任务 / 队列 ID</span>
|
|
||||||
<input type="text" id="vulnerability-task-filter" list="vulnerability-task-suggestions" placeholder="回车筛选" />
|
|
||||||
</label>
|
|
||||||
<label class="vulnerability-filter-field">
|
|
||||||
<span data-i18n="vulnerabilityPage.conversationTag">对话标签</span>
|
|
||||||
<input type="text" id="vulnerability-conversation-tag-filter" list="vulnerability-conversation-tag-suggestions" placeholder="回车筛选" />
|
|
||||||
</label>
|
|
||||||
<label class="vulnerability-filter-field">
|
|
||||||
<span data-i18n="vulnerabilityPage.taskTag">任务标签</span>
|
|
||||||
<input type="text" id="vulnerability-task-tag-filter" list="vulnerability-task-tag-suggestions" placeholder="回车筛选" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="vulnerability-filter-chips" id="vulnerability-filter-chips" hidden>
|
<div class="vulnerability-filter-chips" id="vulnerability-filter-chips" hidden>
|
||||||
|
<span class="vulnerability-filter-chips-label" data-i18n="vulnerabilityPage.activeFilters">已选条件</span>
|
||||||
<div class="vulnerability-filter-chips-list" id="vulnerability-filter-chips-list" role="list"></div>
|
<div class="vulnerability-filter-chips-list" id="vulnerability-filter-chips-list" role="list"></div>
|
||||||
</div>
|
</div>
|
||||||
<datalist id="vulnerability-conversation-suggestions"></datalist>
|
<datalist id="vulnerability-conversation-suggestions"></datalist>
|
||||||
|
|||||||
Reference in New Issue
Block a user