mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-07-16 08:57:30 +02:00
Add files via upload
This commit is contained in:
@@ -490,6 +490,234 @@ html[data-theme="dark"] .main-sidebar {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.vulnerability-alert-settings {
|
||||
margin: 24px 0 4px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 10px;
|
||||
background: var(--bg-primary);
|
||||
box-shadow: 0 3px 12px rgba(15, 23, 42, 0.035);
|
||||
}
|
||||
|
||||
.vulnerability-alert-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
padding: 17px 20px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.vulnerability-alert-copy {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.vulnerability-alert-copy > div {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.vulnerability-alert-copy strong {
|
||||
display: block;
|
||||
color: var(--text-primary);
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 650;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.vulnerability-alert-copy > div > span {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.vulnerability-alert-icon {
|
||||
display: flex;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
flex: 0 0 34px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 9px;
|
||||
background: rgba(0, 102, 255, 0.09);
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.vulnerability-alert-controls {
|
||||
display: flex;
|
||||
min-height: 58px;
|
||||
align-items: center;
|
||||
gap: 22px;
|
||||
padding: 10px 20px;
|
||||
border-radius: 0 0 10px 10px;
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.vulnerability-alert-binding-row {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 7px 10px;
|
||||
padding-left: 22px;
|
||||
border-left: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.vulnerability-alert-binding-row > span {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.vulnerability-alert-binding-row > span.is-warning {
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
.vulnerability-alert-bind-button {
|
||||
padding: 2px 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--accent-color);
|
||||
font: inherit;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 650;
|
||||
line-height: 1.45;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vulnerability-alert-bind-button:hover {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
}
|
||||
|
||||
.vulnerability-alert-field {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.vulnerability-alert-field .settings-custom-select {
|
||||
width: 148px !important;
|
||||
min-width: 148px !important;
|
||||
}
|
||||
|
||||
.vulnerability-alert-field .settings-custom-select-trigger {
|
||||
min-height: 36px;
|
||||
padding: 7px 11px;
|
||||
border-radius: 7px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.vulnerability-alert-field .settings-custom-select-menu {
|
||||
min-width: 148px;
|
||||
}
|
||||
|
||||
.vulnerability-alert-switch {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
min-height: 36px;
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
cursor: pointer;
|
||||
color: var(--text-primary);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.vulnerability-alert-switch input {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.vulnerability-alert-switch-track {
|
||||
position: relative;
|
||||
width: 38px;
|
||||
height: 22px;
|
||||
flex: 0 0 38px;
|
||||
border-radius: 999px;
|
||||
background: #cbd5e1;
|
||||
transition: background-color 0.16s ease, box-shadow 0.16s ease;
|
||||
}
|
||||
|
||||
.vulnerability-alert-switch-track::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 3px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.22);
|
||||
transition: transform 0.16s ease;
|
||||
}
|
||||
|
||||
.vulnerability-alert-switch input:checked + .vulnerability-alert-switch-track {
|
||||
background: var(--accent-color);
|
||||
}
|
||||
|
||||
.vulnerability-alert-switch input:checked + .vulnerability-alert-switch-track::after {
|
||||
transform: translateX(16px);
|
||||
}
|
||||
|
||||
.vulnerability-alert-switch input:focus-visible + .vulnerability-alert-switch-track {
|
||||
box-shadow: 0 0 0 3px rgba(0, 102, 255, 0.16);
|
||||
}
|
||||
|
||||
.vulnerability-alert-switch input:disabled ~ span {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.vulnerability-alert-header {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.vulnerability-alert-controls {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 14px 16px;
|
||||
}
|
||||
|
||||
.vulnerability-alert-binding-row {
|
||||
width: 100%;
|
||||
padding-top: 12px;
|
||||
padding-left: 0;
|
||||
border-top: 1px solid var(--border-color);
|
||||
border-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.vulnerability-alert-settings {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.vulnerability-alert-header {
|
||||
padding: 15px 16px;
|
||||
}
|
||||
|
||||
.vulnerability-alert-switch-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.page-header-actions .btn-danger,
|
||||
.page-header-actions .btn-secondary,
|
||||
.page-header-actions .btn-primary {
|
||||
|
||||
@@ -2105,6 +2105,16 @@
|
||||
"errorGeneric": "Something went wrong. Please try again."
|
||||
},
|
||||
"vulnerabilityPage": {
|
||||
"alertTitle": "Robot vulnerability alerts",
|
||||
"alertDescription": "Push newly discovered vulnerabilities to robots bound to this account, filtered by severity.",
|
||||
"alertHint": "Send newly discovered vulnerabilities at or above this severity to your bound robot accounts.",
|
||||
"alertConfiguredNotBound": "{{platforms}} is enabled, but this Web account is not bound to a recipient identity.",
|
||||
"alertNoBinding": "No proactive robot is both enabled and bound. Your settings are still saved.",
|
||||
"alertBindAction": "Bind recipient account",
|
||||
"alertMinimum": "Minimum severity",
|
||||
"alertEnabled": "Enable alerts",
|
||||
"alertSaved": "Vulnerability alert settings saved",
|
||||
"alertSaveFailed": "Failed to save vulnerability alert settings",
|
||||
"statTotal": "Total",
|
||||
"statClickAll": "View all (clear severity filter)",
|
||||
"statClickFilter": "Click to filter by this severity; click again to clear",
|
||||
|
||||
@@ -2093,6 +2093,16 @@
|
||||
"errorGeneric": "操作失败,请稍后重试。"
|
||||
},
|
||||
"vulnerabilityPage": {
|
||||
"alertTitle": "机器人漏洞提醒",
|
||||
"alertDescription": "按严重级别将新发现的漏洞推送至当前账号绑定的机器人。",
|
||||
"alertHint": "发现符合级别的新漏洞后,通过已绑定机器人账号推送。",
|
||||
"alertConfiguredNotBound": "{{platforms}}已启用,但当前 Web 账号尚未绑定对应的接收身份。",
|
||||
"alertNoBinding": "尚未启用并绑定支持主动推送的机器人。设置仍会保存。",
|
||||
"alertBindAction": "绑定接收账号",
|
||||
"alertMinimum": "最低级别",
|
||||
"alertEnabled": "启用提醒",
|
||||
"alertSaved": "漏洞提醒设置已保存",
|
||||
"alertSaveFailed": "保存漏洞提醒设置失败",
|
||||
"statTotal": "总漏洞数",
|
||||
"statClickAll": "查看全部(清除严重度筛选)",
|
||||
"statClickFilter": "点击按此严重度筛选;再次点击清除",
|
||||
|
||||
@@ -711,6 +711,9 @@ async function openRobotAccountBinding() {
|
||||
|
||||
function closeRobotAccountBinding() {
|
||||
closeAppModal('robot-account-binding-modal');
|
||||
if (typeof window.loadVulnerabilityAlertSubscription === 'function') {
|
||||
window.loadVulnerabilityAlertSubscription();
|
||||
}
|
||||
}
|
||||
|
||||
async function generateRobotBindingCode() {
|
||||
@@ -859,6 +862,9 @@ async function loadRobotAccountBindings() {
|
||||
</div>
|
||||
<button type="button" class="btn-secondary btn-small robot-binding-unbind-btn" onclick="deleteRobotAccountBinding('${escapeHtml(binding.id || '')}')">解除绑定</button>
|
||||
</div>`).join('');
|
||||
if (typeof window.loadVulnerabilityAlertSubscription === 'function') {
|
||||
window.loadVulnerabilityAlertSubscription();
|
||||
}
|
||||
}
|
||||
|
||||
function formatRobotBindingTime(value) {
|
||||
|
||||
@@ -585,6 +585,9 @@ function switchSettingsSection(section) {
|
||||
activeContent.classList.add('active');
|
||||
initSettingsCustomSelects(activeContent);
|
||||
}
|
||||
if (section === 'robots' && typeof window.loadVulnerabilityAlertSubscription === 'function') {
|
||||
window.loadVulnerabilityAlertSubscription();
|
||||
}
|
||||
if (section === 'terminal' && typeof initTerminal === 'function') {
|
||||
setTimeout(initTerminal, 0);
|
||||
}
|
||||
|
||||
@@ -1856,6 +1856,79 @@ function refreshVulnerabilities() {
|
||||
loadVulnerabilities();
|
||||
}
|
||||
|
||||
async function loadVulnerabilityAlertSubscription() {
|
||||
const enabledEl = document.getElementById('vulnerability-alert-enabled');
|
||||
const severityEl = document.getElementById('vulnerability-alert-min-severity');
|
||||
if (!enabledEl || !severityEl || typeof apiFetch === 'undefined') return;
|
||||
try {
|
||||
const response = await apiFetch('/api/vulnerability-alerts/subscription');
|
||||
if (!response.ok) throw new Error(await response.text());
|
||||
const data = await response.json();
|
||||
const sub = data.subscription || {};
|
||||
enabledEl.checked = !!sub.enabled;
|
||||
severityEl.value = sub.min_severity || 'high';
|
||||
severityEl.disabled = false;
|
||||
if (typeof window.refreshSettingsCustomSelects === 'function') {
|
||||
window.refreshSettingsCustomSelects();
|
||||
}
|
||||
const hint = document.getElementById('vulnerability-alert-binding-hint');
|
||||
const bindButton = document.getElementById('vulnerability-alert-bind-button');
|
||||
if (hint && !data.delivery_ready) {
|
||||
const supportedTypes = [
|
||||
{ type: 'wecom', label: vulnT('settings.robots.wecom.title') },
|
||||
{ type: 'lark', label: vulnT('settings.robots.lark.title') },
|
||||
{ type: 'telegram', label: 'Telegram' },
|
||||
{ type: 'slack', label: 'Slack' },
|
||||
{ type: 'discord', label: 'Discord' }
|
||||
];
|
||||
const enabledPlatforms = supportedTypes.filter(function (item) {
|
||||
if (typeof getRobotStatus !== 'function') return false;
|
||||
const status = getRobotStatus(item.type);
|
||||
return status && status.state === 'enabled';
|
||||
}).map(function (item) { return item.label; });
|
||||
hint.textContent = enabledPlatforms.length
|
||||
? vulnT('vulnerabilityPage.alertConfiguredNotBound', { platforms: enabledPlatforms.join('、') })
|
||||
: vulnT('vulnerabilityPage.alertNoBinding');
|
||||
hint.classList.add('is-warning');
|
||||
if (bindButton) bindButton.hidden = false;
|
||||
} else if (hint) {
|
||||
hint.textContent = vulnT('vulnerabilityPage.alertHint');
|
||||
hint.classList.remove('is-warning');
|
||||
if (bindButton) bindButton.hidden = true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('加载漏洞提醒设置失败', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveVulnerabilityAlertSubscription() {
|
||||
const enabledEl = document.getElementById('vulnerability-alert-enabled');
|
||||
const severityEl = document.getElementById('vulnerability-alert-min-severity');
|
||||
if (!enabledEl || !severityEl) return;
|
||||
enabledEl.disabled = true;
|
||||
severityEl.disabled = true;
|
||||
if (typeof window.refreshSettingsCustomSelects === 'function') {
|
||||
window.refreshSettingsCustomSelects();
|
||||
}
|
||||
try {
|
||||
const response = await apiFetch('/api/vulnerability-alerts/subscription', {
|
||||
method: 'PUT', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ enabled: enabledEl.checked, min_severity: severityEl.value })
|
||||
});
|
||||
if (!response.ok) throw new Error(await response.text());
|
||||
if (typeof showNotification === 'function') showNotification(vulnT('vulnerabilityPage.alertSaved'), 'success');
|
||||
} catch (error) {
|
||||
if (typeof showNotification === 'function') showNotification(vulnT('vulnerabilityPage.alertSaveFailed'), 'error');
|
||||
await loadVulnerabilityAlertSubscription();
|
||||
} finally {
|
||||
enabledEl.disabled = false;
|
||||
severityEl.disabled = false;
|
||||
if (typeof window.refreshSettingsCustomSelects === 'function') {
|
||||
window.refreshSettingsCustomSelects();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 切换漏洞详情展开/折叠
|
||||
function toggleVulnerabilityDetails(id) {
|
||||
const content = document.getElementById(`content-${id}`);
|
||||
@@ -2415,3 +2488,5 @@ window.bindVulnerabilityProject = bindVulnerabilityProject;
|
||||
window.buildVulnerabilityProjectOptionsHtml = buildVulnerabilityProjectOptionsHtml;
|
||||
window.changeVulnerabilityStatus = changeVulnerabilityStatus;
|
||||
window.openVulnerabilityConversation = openVulnerabilityConversation;
|
||||
window.loadVulnerabilityAlertSubscription = loadVulnerabilityAlertSubscription;
|
||||
window.saveVulnerabilityAlertSubscription = saveVulnerabilityAlertSubscription;
|
||||
|
||||
Reference in New Issue
Block a user