mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-06-05 22:06:41 +02:00
Add files via upload
This commit is contained in:
@@ -12771,6 +12771,16 @@ tr.mcp-stats-tool-row[data-tool-name]:focus-visible {
|
||||
}
|
||||
|
||||
/* 漏洞管理页面样式 */
|
||||
.page-header-actions .btn-secondary.btn-delete {
|
||||
color: var(--error-color, #dc3545);
|
||||
}
|
||||
|
||||
.page-header-actions .btn-secondary.btn-delete:hover {
|
||||
color: #c82333;
|
||||
border-color: rgba(220, 53, 69, 0.35);
|
||||
background: rgba(220, 53, 69, 0.06);
|
||||
}
|
||||
|
||||
.vulnerability-dashboard {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
@@ -1787,6 +1787,12 @@
|
||||
"loadListFailed": "Failed to load",
|
||||
"noRecords": "No vulnerability records",
|
||||
"batchExport": "Batch export",
|
||||
"batchDelete": "Batch delete",
|
||||
"batchDeleteNoResults": "No vulnerabilities match the current filters to delete",
|
||||
"batchDeleteConfirm": "Delete {{count}} vulnerability record(s) matching the current filters? This cannot be undone.",
|
||||
"batchDeleteConfirmAll": "No filters are set. This will delete all {{count}} vulnerability record(s). This cannot be undone. Continue?",
|
||||
"batchDeleteSuccess": "Successfully deleted {{count}} vulnerability record(s)",
|
||||
"batchDeleteFailed": "Batch delete failed",
|
||||
"downloadMarkdownTitle": "Download Markdown",
|
||||
"exportNoResults": "No vulnerabilities match the current filters",
|
||||
"exportStarted": "Started downloading {{count}} file(s)",
|
||||
|
||||
@@ -1776,6 +1776,12 @@
|
||||
"loadListFailed": "加载失败",
|
||||
"noRecords": "暂无漏洞记录",
|
||||
"batchExport": "批量导出",
|
||||
"batchDelete": "批量删除",
|
||||
"batchDeleteNoResults": "当前筛选条件下没有可删除的漏洞",
|
||||
"batchDeleteConfirm": "确定要删除当前筛选条件下的 {{count}} 条漏洞吗?此操作不可恢复。",
|
||||
"batchDeleteConfirmAll": "未设置筛选条件,将删除全部 {{count}} 条漏洞。此操作不可恢复,确定继续?",
|
||||
"batchDeleteSuccess": "成功删除 {{count}} 条漏洞",
|
||||
"batchDeleteFailed": "批量删除失败",
|
||||
"downloadMarkdownTitle": "下载 Markdown",
|
||||
"exportNoResults": "当前筛选条件下无可导出漏洞",
|
||||
"exportStarted": "已开始下载 {{count}} 份报告",
|
||||
|
||||
@@ -720,7 +720,7 @@ async function loadVulnerabilityStats() {
|
||||
throw new Error('apiFetch未定义');
|
||||
}
|
||||
|
||||
const params = buildVulnerabilityFilterParams();
|
||||
const params = buildVulnerabilityDashboardStatsParams();
|
||||
|
||||
const response = await apiFetch(`/api/vulnerabilities/stats?${params.toString()}`);
|
||||
if (!response.ok) {
|
||||
@@ -1531,6 +1531,13 @@ function buildVulnerabilityFilterParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
/** 看板统计:保留项目/关键词等筛选,但不带严重度(卡片本身用于切换严重度筛选) */
|
||||
function buildVulnerabilityDashboardStatsParams() {
|
||||
const params = buildVulnerabilityFilterParams();
|
||||
params.delete('severity');
|
||||
return params;
|
||||
}
|
||||
|
||||
function triggerTextDownload(fileName, content) {
|
||||
const blob = new Blob([content], { type: 'text/markdown;charset=utf-8' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
@@ -1543,6 +1550,53 @@ function triggerTextDownload(fileName, content) {
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
function hasActiveVulnerabilityFilters() {
|
||||
const keys = ['q', 'id', 'project_id', 'conversation_id', 'task_id', 'conversation_tag', 'task_tag', 'severity', 'status'];
|
||||
return keys.some(function (k) {
|
||||
return Boolean(vulnerabilityFilters[k]);
|
||||
});
|
||||
}
|
||||
|
||||
async function batchDeleteVulnerabilityReports() {
|
||||
try {
|
||||
const params = buildVulnerabilityFilterParams();
|
||||
const statsResponse = await apiFetch(`/api/vulnerabilities/stats?${params.toString()}`);
|
||||
if (!statsResponse.ok) {
|
||||
throw new Error(vulnT('vulnerabilityPage.deleteFailed'));
|
||||
}
|
||||
const stats = await statsResponse.json();
|
||||
const count = stats.total || 0;
|
||||
if (count <= 0) {
|
||||
alert(vulnT('vulnerabilityPage.batchDeleteNoResults'));
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmKey = hasActiveVulnerabilityFilters()
|
||||
? 'vulnerabilityPage.batchDeleteConfirm'
|
||||
: 'vulnerabilityPage.batchDeleteConfirmAll';
|
||||
if (!confirm(vulnT(confirmKey, { count: count }))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await apiFetch(`/api/vulnerabilities/batch?${params.toString()}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
if (!response.ok) {
|
||||
const error = await response.json().catch(() => ({ error: vulnT('vulnerabilityPage.deleteFailed') }));
|
||||
throw new Error(error.error || vulnT('vulnerabilityPage.deleteFailed'));
|
||||
}
|
||||
const data = await response.json();
|
||||
const deleted = data.deleted || 0;
|
||||
alert(vulnT('vulnerabilityPage.batchDeleteSuccess', { count: deleted }));
|
||||
vulnerabilityPagination.currentPage = 1;
|
||||
loadVulnerabilityStats();
|
||||
loadVulnerabilities();
|
||||
} catch (error) {
|
||||
console.error('批量删除漏洞失败:', error);
|
||||
alert(vulnT('vulnerabilityPage.batchDeleteFailed') + ': ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function exportVulnerabilityReports() {
|
||||
try {
|
||||
const params = buildVulnerabilityFilterParams();
|
||||
|
||||
@@ -1714,6 +1714,7 @@
|
||||
<h2 data-i18n="vulnerability.title">漏洞管理</h2>
|
||||
<div class="page-header-actions">
|
||||
<button class="btn-secondary" onclick="exportVulnerabilityReports()" data-i18n="vulnerabilityPage.batchExport">批量导出</button>
|
||||
<button class="btn-secondary btn-delete" onclick="batchDeleteVulnerabilityReports()" data-i18n="vulnerabilityPage.batchDelete">批量删除</button>
|
||||
<button class="btn-secondary" onclick="refreshVulnerabilities()" data-i18n="common.refresh">刷新</button>
|
||||
<button class="btn-primary" onclick="showAddVulnerabilityModal()" data-i18n="vulnerability.addVuln">添加漏洞</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user