Add files via upload

This commit is contained in:
公明
2026-07-13 18:56:52 +08:00
committed by GitHub
parent 597712a7b9
commit 68e3ead4d7
7 changed files with 365 additions and 0 deletions
+228
View File
@@ -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 {
+10
View File
@@ -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",
+10
View File
@@ -2093,6 +2093,16 @@
"errorGeneric": "操作失败,请稍后重试。"
},
"vulnerabilityPage": {
"alertTitle": "机器人漏洞提醒",
"alertDescription": "按严重级别将新发现的漏洞推送至当前账号绑定的机器人。",
"alertHint": "发现符合级别的新漏洞后,通过已绑定机器人账号推送。",
"alertConfiguredNotBound": "{{platforms}}已启用,但当前 Web 账号尚未绑定对应的接收身份。",
"alertNoBinding": "尚未启用并绑定支持主动推送的机器人。设置仍会保存。",
"alertBindAction": "绑定接收账号",
"alertMinimum": "最低级别",
"alertEnabled": "启用提醒",
"alertSaved": "漏洞提醒设置已保存",
"alertSaveFailed": "保存漏洞提醒设置失败",
"statTotal": "总漏洞数",
"statClickAll": "查看全部(清除严重度筛选)",
"statClickFilter": "点击按此严重度筛选;再次点击清除",
+6
View File
@@ -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) {
+3
View File
@@ -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);
}
+75
View File
@@ -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;