mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-05 10:28:45 +02:00
Add files via upload
This commit is contained in:
@@ -1371,7 +1371,6 @@
|
|||||||
Modal
|
Modal
|
||||||
============================================================================ */
|
============================================================================ */
|
||||||
|
|
||||||
/* Toast 须高于模态遮罩 (10050),避免被 backdrop-filter 模糊 */
|
|
||||||
#c2-toast-container {
|
#c2-toast-container {
|
||||||
z-index: 10100 !important;
|
z-index: 10100 !important;
|
||||||
}
|
}
|
||||||
@@ -1379,9 +1378,7 @@
|
|||||||
.c2-modal-overlay {
|
.c2-modal-overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0; left: 0; right: 0; bottom: 0;
|
top: 0; left: 0; right: 0; bottom: 0;
|
||||||
background: rgba(15, 23, 42, 0.5);
|
background: rgba(15, 23, 42, 0.52);
|
||||||
backdrop-filter: blur(8px);
|
|
||||||
-webkit-backdrop-filter: blur(8px);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -1404,7 +1401,8 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
box-shadow: var(--c2-shadow-lg);
|
box-shadow: var(--c2-shadow-lg);
|
||||||
border: 1px solid var(--c2-border);
|
border: 1px solid var(--c2-border);
|
||||||
animation: c2-slide-up 0.2s ease-out;
|
animation: c2-slide-up 0.18s ease-out;
|
||||||
|
contain: layout style paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes c2-slide-up {
|
@keyframes c2-slide-up {
|
||||||
|
|||||||
@@ -3326,9 +3326,9 @@ header {
|
|||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
background-color: rgba(15, 23, 42, 0.52);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
animation: fadeIn 0.2s ease-in;
|
animation: fadeIn 0.15s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content {
|
.modal-content {
|
||||||
@@ -3343,8 +3343,9 @@ header {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
box-shadow: var(--shadow-lg);
|
box-shadow: var(--shadow-lg);
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
animation: slideDown 0.3s ease-out;
|
animation: slideDown 0.18s ease-out;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
contain: layout style paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slideDown {
|
@keyframes slideDown {
|
||||||
@@ -19374,6 +19375,8 @@ tr.mcp-stats-tool-row[data-tool-name]:focus-visible {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.role-selection-item-main:hover {
|
.role-selection-item-main:hover {
|
||||||
@@ -19436,6 +19439,10 @@ tr.mcp-stats-tool-row[data-tool-name]:focus-visible {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
transition: color 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
transition: color 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
.role-selection-item-main.selected .role-selection-item-name-main {
|
.role-selection-item-main.selected .role-selection-item-name-main {
|
||||||
@@ -19443,6 +19450,10 @@ tr.mcp-stats-tool-row[data-tool-name]:focus-visible {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.role-selection-item-main.selected .role-selection-item-content-main {
|
||||||
|
padding-right: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.role-selection-item-description-main {
|
.role-selection-item-description-main {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
color: #666666;
|
color: #666666;
|
||||||
@@ -23777,10 +23788,8 @@ button.chat-files-dropdown-item:hover:not(:disabled) {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 24px 16px;
|
padding: 24px 16px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
background: rgba(15, 23, 42, 0.45);
|
background: rgba(15, 23, 42, 0.52);
|
||||||
backdrop-filter: blur(4px);
|
animation: projectsOverlayIn 0.15s ease-out;
|
||||||
-webkit-backdrop-filter: blur(4px);
|
|
||||||
animation: projectsOverlayIn 0.2s ease-out;
|
|
||||||
}
|
}
|
||||||
@keyframes projectsOverlayIn {
|
@keyframes projectsOverlayIn {
|
||||||
from { opacity: 0; }
|
from { opacity: 0; }
|
||||||
@@ -23798,7 +23807,8 @@ button.chat-files-dropdown-item:hover:not(:disabled) {
|
|||||||
0 24px 48px rgba(15, 23, 42, 0.18),
|
0 24px 48px rgba(15, 23, 42, 0.18),
|
||||||
0 0 0 1px rgba(15, 23, 42, 0.06);
|
0 0 0 1px rgba(15, 23, 42, 0.06);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
animation: projectsDialogIn 0.25s cubic-bezier(0.22, 1, 0.36, 1);
|
animation: projectsDialogIn 0.18s cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
contain: layout style paint;
|
||||||
}
|
}
|
||||||
.projects-modal-dialog--wide {
|
.projects-modal-dialog--wide {
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
@@ -23859,6 +23869,13 @@ button.chat-files-dropdown-item:hover:not(:disabled) {
|
|||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
transition: border-color 0.15s, box-shadow 0.15s;
|
transition: border-color 0.15s, box-shadow 0.15s;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
#project-modal-name {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
.projects-modal-body .form-input:focus {
|
.projects-modal-body .form-input:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -23882,7 +23899,8 @@ button.chat-files-dropdown-item:hover:not(:disabled) {
|
|||||||
.projects-modal-footer .btn-primary {
|
.projects-modal-footer .btn-primary {
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
}
|
}
|
||||||
body.projects-modal-open {
|
body.projects-modal-open,
|
||||||
|
body.app-modal-open {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.fact-detail-prev-wrap {
|
.fact-detail-prev-wrap {
|
||||||
@@ -24030,8 +24048,11 @@ body.projects-modal-open {
|
|||||||
/* 对话区项目选择器(与角色/代理模式共用 role-selector-*) */
|
/* 对话区项目选择器(与角色/代理模式共用 role-selector-*) */
|
||||||
.project-selector-wrapper .role-selector-text {
|
.project-selector-wrapper .role-selector-text {
|
||||||
max-width: 108px;
|
max-width: 108px;
|
||||||
|
min-width: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.chat-project-panel {
|
.chat-project-panel {
|
||||||
width: 280px;
|
width: 280px;
|
||||||
@@ -24051,6 +24072,7 @@ body.projects-modal-open {
|
|||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
.chat-project-panel .role-selection-item-main {
|
.chat-project-panel .role-selection-item-main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
+20
-17
@@ -105,45 +105,48 @@ function showAddMarkdownAgentModal() {
|
|||||||
document.getElementById('agent-md-bind-role').value = '';
|
document.getElementById('agent-md-bind-role').value = '';
|
||||||
document.getElementById('agent-md-max-iter').value = '0';
|
document.getElementById('agent-md-max-iter').value = '0';
|
||||||
document.getElementById('agent-md-instruction').value = '';
|
document.getElementById('agent-md-instruction').value = '';
|
||||||
if (modal) modal.style.display = 'flex';
|
openAppModal('agent-md-modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function editMarkdownAgent(filename) {
|
async function editMarkdownAgent(filename) {
|
||||||
if (!filename) return;
|
if (!filename) return;
|
||||||
const modal = document.getElementById('agent-md-modal');
|
|
||||||
const title = document.getElementById('agent-md-modal-title');
|
const title = document.getElementById('agent-md-modal-title');
|
||||||
const row = document.getElementById('agent-md-filename-row');
|
const row = document.getElementById('agent-md-filename-row');
|
||||||
markdownAgentsEditingFilename = null;
|
markdownAgentsEditingFilename = null;
|
||||||
markdownAgentsEditingIsOrchestrator = false;
|
markdownAgentsEditingIsOrchestrator = false;
|
||||||
if (title) title.textContent = _agentsT('agentsPage.editTitle');
|
if (title) title.textContent = _agentsT('agentsPage.editTitle');
|
||||||
if (row) row.style.display = 'none';
|
if (row) row.style.display = 'none';
|
||||||
|
document.getElementById('agent-md-instruction').value = '';
|
||||||
|
openAppModal('agent-md-modal', { focus: false });
|
||||||
try {
|
try {
|
||||||
const r = await apiFetch('/api/multi-agent/markdown-agents/' + encodeURIComponent(filename));
|
const r = await apiFetch('/api/multi-agent/markdown-agents/' + encodeURIComponent(filename));
|
||||||
const data = await r.json();
|
const data = await r.json();
|
||||||
if (!r.ok) throw new Error(data.error || r.statusText);
|
if (!r.ok) throw new Error(data.error || r.statusText);
|
||||||
markdownAgentsEditingFilename = data.filename || filename;
|
markdownAgentsEditingFilename = data.filename || filename;
|
||||||
markdownAgentsEditingIsOrchestrator = !!data.is_orchestrator;
|
markdownAgentsEditingIsOrchestrator = !!data.is_orchestrator;
|
||||||
document.getElementById('agent-md-filename-current').value = data.filename || filename;
|
deferModalContent(function () {
|
||||||
document.getElementById('agent-md-filename').value = data.filename || filename;
|
document.getElementById('agent-md-filename-current').value = data.filename || filename;
|
||||||
document.getElementById('agent-md-filename').disabled = true;
|
document.getElementById('agent-md-filename').value = data.filename || filename;
|
||||||
var roleEl2 = document.getElementById('agent-md-role');
|
document.getElementById('agent-md-filename').disabled = true;
|
||||||
if (roleEl2) roleEl2.value = data.is_orchestrator ? 'orchestrator' : 'sub';
|
var roleEl2 = document.getElementById('agent-md-role');
|
||||||
document.getElementById('agent-md-id').value = data.id || '';
|
if (roleEl2) roleEl2.value = data.is_orchestrator ? 'orchestrator' : 'sub';
|
||||||
document.getElementById('agent-md-name').value = data.name || '';
|
document.getElementById('agent-md-id').value = data.id || '';
|
||||||
document.getElementById('agent-md-description').value = data.description || '';
|
document.getElementById('agent-md-name').value = data.name || '';
|
||||||
document.getElementById('agent-md-tools').value = Array.isArray(data.tools) ? data.tools.join(', ') : '';
|
document.getElementById('agent-md-description').value = data.description || '';
|
||||||
document.getElementById('agent-md-bind-role').value = data.bind_role || '';
|
document.getElementById('agent-md-tools').value = Array.isArray(data.tools) ? data.tools.join(', ') : '';
|
||||||
document.getElementById('agent-md-max-iter').value = String(data.max_iterations != null ? data.max_iterations : 0);
|
document.getElementById('agent-md-bind-role').value = data.bind_role || '';
|
||||||
document.getElementById('agent-md-instruction').value = data.instruction || '';
|
document.getElementById('agent-md-max-iter').value = String(data.max_iterations != null ? data.max_iterations : 0);
|
||||||
if (modal) modal.style.display = 'flex';
|
document.getElementById('agent-md-instruction').value = data.instruction || '';
|
||||||
|
document.getElementById('agent-md-name')?.focus();
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
closeMarkdownAgentModal();
|
||||||
showNotification(_agentsT('agentsPage.loadOneFailed') + ': ' + e.message, 'error');
|
showNotification(_agentsT('agentsPage.loadOneFailed') + ': ' + e.message, 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeMarkdownAgentModal() {
|
function closeMarkdownAgentModal() {
|
||||||
const modal = document.getElementById('agent-md-modal');
|
closeAppModal('agent-md-modal');
|
||||||
if (modal) modal.style.display = 'none';
|
|
||||||
markdownAgentsEditingFilename = null;
|
markdownAgentsEditingFilename = null;
|
||||||
markdownAgentsEditingIsOrchestrator = false;
|
markdownAgentsEditingIsOrchestrator = false;
|
||||||
}
|
}
|
||||||
|
|||||||
+38
-33
@@ -533,56 +533,61 @@ async function exportAuditLogsCsv() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeAuditDetailModal() {
|
function closeAuditDetailModal() {
|
||||||
|
closeAppModal('audit-detail-modal');
|
||||||
const el = document.getElementById('audit-detail-modal');
|
const el = document.getElementById('audit-detail-modal');
|
||||||
if (el) el.remove();
|
if (el) el.remove();
|
||||||
|
syncAppModalBodyLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function showAuditLogDetail(id) {
|
async function showAuditLogDetail(id) {
|
||||||
if (!id || typeof apiFetch !== 'function') return;
|
if (!id || typeof apiFetch !== 'function') return;
|
||||||
const esc = typeof escapeHtml === 'function' ? escapeHtml : function (s) { return String(s || ''); };
|
const esc = typeof escapeHtml === 'function' ? escapeHtml : function (s) { return String(s || ''); };
|
||||||
try {
|
try {
|
||||||
|
closeAuditDetailModal();
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.id = 'audit-detail-modal';
|
||||||
|
overlay.className = 'modal';
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
openAppModal(overlay, { focus: false });
|
||||||
const r = await apiFetch('/api/audit/logs/' + encodeURIComponent(id));
|
const r = await apiFetch('/api/audit/logs/' + encodeURIComponent(id));
|
||||||
if (!r.ok) throw new Error('not found');
|
if (!r.ok) throw new Error('not found');
|
||||||
const data = await r.json();
|
const data = await r.json();
|
||||||
const log = data.log || {};
|
const log = data.log || {};
|
||||||
const detail = log.detail ? JSON.stringify(log.detail, null, 2) : '';
|
const detail = log.detail ? JSON.stringify(log.detail, null, 2) : '';
|
||||||
closeAuditDetailModal();
|
|
||||||
const overlay = document.createElement('div');
|
|
||||||
overlay.id = 'audit-detail-modal';
|
|
||||||
overlay.className = 'modal';
|
|
||||||
overlay.style.display = 'block';
|
|
||||||
const catAction = esc(auditCategoryLabel(log.category || '')) + ' / ' + esc(auditActionLabel(log.action || ''));
|
const catAction = esc(auditCategoryLabel(log.category || '')) + ' / ' + esc(auditActionLabel(log.action || ''));
|
||||||
overlay.innerHTML =
|
deferModalContent(function () {
|
||||||
'<div class="modal-content" style="max-width: 720px;">' +
|
overlay.innerHTML =
|
||||||
'<div class="modal-header">' +
|
'<div class="modal-content" style="max-width: 720px;">' +
|
||||||
'<h2>' + esc(auditT('settingsAudit.detailTitle', null, '审计详情')) + '</h2>' +
|
'<div class="modal-header">' +
|
||||||
'<span class="modal-close" onclick="closeAuditDetailModal()">×</span>' +
|
'<h2>' + esc(auditT('settingsAudit.detailTitle', null, '审计详情')) + '</h2>' +
|
||||||
'</div>' +
|
'<span class="modal-close" onclick="closeAuditDetailModal()">×</span>' +
|
||||||
'<div class="modal-body audit-detail-body">' +
|
'</div>' +
|
||||||
'<p><strong>' + esc(auditT('settingsAudit.detailTime', null, '时间')) + ':</strong> ' + esc(formatAuditTime(log.createdAt)) + '</p>' +
|
'<div class="modal-body audit-detail-body">' +
|
||||||
'<p><strong>' + esc(auditT('settingsAudit.detailCategory', null, '类别')) + ':</strong> ' + catAction + '</p>' +
|
'<p><strong>' + esc(auditT('settingsAudit.detailTime', null, '时间')) + ':</strong> ' + esc(formatAuditTime(log.createdAt)) + '</p>' +
|
||||||
'<p><strong>' + esc(auditT('settingsAudit.detailResult', null, '结果')) + ':</strong> ' + esc(log.result || '') + '</p>' +
|
'<p><strong>' + esc(auditT('settingsAudit.detailCategory', null, '类别')) + ':</strong> ' + catAction + '</p>' +
|
||||||
'<p><strong>' + esc(auditT('settingsAudit.detailMessage', null, '说明')) + ':</strong> ' + esc(log.message || '') + '</p>' +
|
'<p><strong>' + esc(auditT('settingsAudit.detailResult', null, '结果')) + ':</strong> ' + esc(log.result || '') + '</p>' +
|
||||||
(log.clientIp ? '<p><strong>IP:</strong> ' + esc(log.clientIp) + '</p>' : '') +
|
'<p><strong>' + esc(auditT('settingsAudit.detailMessage', null, '说明')) + ':</strong> ' + esc(log.message || '') + '</p>' +
|
||||||
(log.sessionHint ? '<p><strong>' + esc(auditT('settingsAudit.detailSession', null, '会话')) + ':</strong> ' + esc(log.sessionHint) + '</p>' : '') +
|
(log.clientIp ? '<p><strong>IP:</strong> ' + esc(log.clientIp) + '</p>' : '') +
|
||||||
(log.userAgent ? '<p><strong>UA:</strong> ' + esc(log.userAgent) + '</p>' : '') +
|
(log.sessionHint ? '<p><strong>' + esc(auditT('settingsAudit.detailSession', null, '会话')) + ':</strong> ' + esc(log.sessionHint) + '</p>' : '') +
|
||||||
auditResourceMeta(log) +
|
(log.userAgent ? '<p><strong>UA:</strong> ' + esc(log.userAgent) + '</p>' : '') +
|
||||||
(detail ? '<pre class="audit-detail-pre">' + esc(detail) + '</pre>' : '') +
|
auditResourceMeta(log) +
|
||||||
'</div>' +
|
(detail ? '<pre class="audit-detail-pre">' + esc(detail) + '</pre>' : '') +
|
||||||
'<div class="modal-footer"><button type="button" class="btn-secondary" onclick="closeAuditDetailModal()">' +
|
'</div>' +
|
||||||
esc(auditT('common.close', null, '关闭')) + '</button></div>' +
|
'<div class="modal-footer"><button type="button" class="btn-secondary" onclick="closeAuditDetailModal()">' +
|
||||||
'</div>';
|
esc(auditT('common.close', null, '关闭')) + '</button></div>' +
|
||||||
document.body.appendChild(overlay);
|
'</div>';
|
||||||
const chatBtn = overlay.querySelector('.audit-open-chat-btn');
|
const chatBtn = overlay.querySelector('.audit-open-chat-btn');
|
||||||
if (chatBtn) {
|
if (chatBtn) {
|
||||||
chatBtn.addEventListener('click', function () {
|
chatBtn.addEventListener('click', function () {
|
||||||
auditOpenConversationChat(chatBtn.getAttribute('data-conversation-id'));
|
auditOpenConversationChat(chatBtn.getAttribute('data-conversation-id'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
overlay.addEventListener('click', function (ev) {
|
||||||
|
if (ev.target === overlay) closeAuditDetailModal();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
overlay.addEventListener('click', function (ev) {
|
|
||||||
if (ev.target === overlay) closeAuditDetailModal();
|
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
closeAuditDetailModal();
|
||||||
if (typeof showToast === 'function') {
|
if (typeof showToast === 'function') {
|
||||||
showToast(e.message || String(e), 'error');
|
showToast(e.message || String(e), 'error');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ function showLoginOverlay(message = '') {
|
|||||||
if (!overlay) {
|
if (!overlay) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
overlay.style.display = 'flex';
|
openAppModal('login-overlay', { focus: false });
|
||||||
if (errorBox) {
|
if (errorBox) {
|
||||||
if (message) {
|
if (message) {
|
||||||
errorBox.textContent = message;
|
errorBox.textContent = message;
|
||||||
@@ -82,7 +82,7 @@ function showLoginOverlay(message = '') {
|
|||||||
errorBox.style.display = 'none';
|
errorBox.style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(function () {
|
||||||
if (passwordInput) {
|
if (passwordInput) {
|
||||||
passwordInput.focus();
|
passwordInput.focus();
|
||||||
}
|
}
|
||||||
@@ -93,9 +93,7 @@ function hideLoginOverlay() {
|
|||||||
const overlay = document.getElementById('login-overlay');
|
const overlay = document.getElementById('login-overlay');
|
||||||
const errorBox = document.getElementById('login-error');
|
const errorBox = document.getElementById('login-error');
|
||||||
const passwordInput = document.getElementById('login-password');
|
const passwordInput = document.getElementById('login-password');
|
||||||
if (overlay) {
|
closeAppModal('login-overlay');
|
||||||
overlay.style.display = 'none';
|
|
||||||
}
|
|
||||||
if (errorBox) {
|
if (errorBox) {
|
||||||
errorBox.textContent = '';
|
errorBox.textContent = '';
|
||||||
errorBox.style.display = 'none';
|
errorBox.style.display = 'none';
|
||||||
|
|||||||
+5
-5
@@ -478,7 +478,7 @@
|
|||||||
const content = document.getElementById('c2-modal-content');
|
const content = document.getElementById('c2-modal-content');
|
||||||
if (!content || !modal) return;
|
if (!content || !modal) return;
|
||||||
|
|
||||||
modal.style.display = 'flex';
|
openAppModal(modal);
|
||||||
content.innerHTML = `
|
content.innerHTML = `
|
||||||
<div class="c2-modal-header">
|
<div class="c2-modal-header">
|
||||||
<h3>${escapeHtml(c2t('c2.listeners.modalCreateTitle'))}</h3>
|
<h3>${escapeHtml(c2t('c2.listeners.modalCreateTitle'))}</h3>
|
||||||
@@ -635,7 +635,7 @@
|
|||||||
const content = document.getElementById('c2-modal-content');
|
const content = document.getElementById('c2-modal-content');
|
||||||
if (!content || !modal) return;
|
if (!content || !modal) return;
|
||||||
|
|
||||||
modal.style.display = 'flex';
|
openAppModal(modal);
|
||||||
content.innerHTML = `
|
content.innerHTML = `
|
||||||
<div class="c2-modal-header">
|
<div class="c2-modal-header">
|
||||||
<h3>${escapeHtml(c2t('c2.listeners.editTitle'))}</h3>
|
<h3>${escapeHtml(c2t('c2.listeners.editTitle'))}</h3>
|
||||||
@@ -2376,7 +2376,7 @@
|
|||||||
<button class="btn-secondary" onclick="C2.closeModal()">${escapeHtml(c2t('common.close'))}</button>
|
<button class="btn-secondary" onclick="C2.closeModal()">${escapeHtml(c2t('common.close'))}</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
modal.style.display = 'flex';
|
openAppModal(modal);
|
||||||
};
|
};
|
||||||
|
|
||||||
const local = C2.tasks.find(x => x.id === id);
|
const local = C2.tasks.find(x => x.id === id);
|
||||||
@@ -2920,7 +2920,7 @@
|
|||||||
<button class="btn-primary" onclick="C2.createProfile()">${escapeHtml(c2t('c2.profiles.submitCreate'))}</button>
|
<button class="btn-primary" onclick="C2.createProfile()">${escapeHtml(c2t('c2.profiles.submitCreate'))}</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
modal.style.display = 'flex';
|
openAppModal(modal);
|
||||||
};
|
};
|
||||||
|
|
||||||
C2.createProfile = function() {
|
C2.createProfile = function() {
|
||||||
@@ -2981,10 +2981,10 @@
|
|||||||
C2.closeModal = function() {
|
C2.closeModal = function() {
|
||||||
const modal = document.getElementById('c2-modal');
|
const modal = document.getElementById('c2-modal');
|
||||||
if (modal) {
|
if (modal) {
|
||||||
modal.style.display = 'none';
|
|
||||||
const modalBox = modal.querySelector('.c2-modal');
|
const modalBox = modal.querySelector('.c2-modal');
|
||||||
if (modalBox) modalBox.classList.remove('c2-modal--wide');
|
if (modalBox) modalBox.classList.remove('c2-modal--wide');
|
||||||
}
|
}
|
||||||
|
closeAppModal('c2-modal');
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
+12
-11
@@ -1002,7 +1002,7 @@ async function openChatFilesEdit(relativePath) {
|
|||||||
const modal = document.getElementById('chat-files-edit-modal');
|
const modal = document.getElementById('chat-files-edit-modal');
|
||||||
if (pathEl) pathEl.textContent = relativePath;
|
if (pathEl) pathEl.textContent = relativePath;
|
||||||
if (ta) ta.value = '';
|
if (ta) ta.value = '';
|
||||||
if (modal) modal.style.display = 'block';
|
openAppModal('chat-files-edit-modal', { focus: false });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await apiFetch('/api/chat-uploads/content?path=' + encodeURIComponent(relativePath));
|
const res = await apiFetch('/api/chat-uploads/content?path=' + encodeURIComponent(relativePath));
|
||||||
@@ -1017,16 +1017,19 @@ async function openChatFilesEdit(relativePath) {
|
|||||||
throw new Error(errText || res.status);
|
throw new Error(errText || res.status);
|
||||||
}
|
}
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
if (ta) ta.value = data.content != null ? String(data.content) : '';
|
const content = data.content != null ? String(data.content) : '';
|
||||||
|
deferModalContent(() => {
|
||||||
|
if (ta) ta.value = content;
|
||||||
|
ta?.focus();
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (modal) modal.style.display = 'none';
|
closeAppModal('chat-files-edit-modal');
|
||||||
alert(chatFilesAlertMessage(e && e.message));
|
alert(chatFilesAlertMessage(e && e.message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeChatFilesEditModal() {
|
function closeChatFilesEditModal() {
|
||||||
const modal = document.getElementById('chat-files-edit-modal');
|
closeAppModal('chat-files-edit-modal');
|
||||||
if (modal) modal.style.display = 'none';
|
|
||||||
chatFilesEditRelativePath = '';
|
chatFilesEditRelativePath = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1060,7 +1063,7 @@ function openChatFilesRename(relativePath, currentName) {
|
|||||||
input.value = currentName || '';
|
input.value = currentName || '';
|
||||||
input.select();
|
input.select();
|
||||||
}
|
}
|
||||||
if (modal) modal.style.display = 'flex';
|
if (modal) openAppModal(modal);
|
||||||
if (modal && typeof window.applyTranslations === 'function') {
|
if (modal && typeof window.applyTranslations === 'function') {
|
||||||
window.applyTranslations(modal);
|
window.applyTranslations(modal);
|
||||||
}
|
}
|
||||||
@@ -1068,8 +1071,7 @@ function openChatFilesRename(relativePath, currentName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeChatFilesRenameModal() {
|
function closeChatFilesRenameModal() {
|
||||||
const modal = document.getElementById('chat-files-rename-modal');
|
closeAppModal('chat-files-rename-modal');
|
||||||
if (modal) modal.style.display = 'none';
|
|
||||||
const hint = document.getElementById('chat-files-rename-path-hint');
|
const hint = document.getElementById('chat-files-rename-path-hint');
|
||||||
if (hint) hint.textContent = '';
|
if (hint) hint.textContent = '';
|
||||||
chatFilesRenameRelativePath = '';
|
chatFilesRenameRelativePath = '';
|
||||||
@@ -1106,7 +1108,7 @@ function openChatFilesMkdirModal() {
|
|||||||
const p = chatFilesBrowsePath.join('/');
|
const p = chatFilesBrowsePath.join('/');
|
||||||
if (hint) hint.textContent = p ? ('chat_uploads/' + p) : 'chat_uploads';
|
if (hint) hint.textContent = p ? ('chat_uploads/' + p) : 'chat_uploads';
|
||||||
if (input) input.value = '';
|
if (input) input.value = '';
|
||||||
if (modal) modal.style.display = 'flex';
|
if (modal) openAppModal(modal);
|
||||||
if (modal && typeof window.applyTranslations === 'function') {
|
if (modal && typeof window.applyTranslations === 'function') {
|
||||||
window.applyTranslations(modal);
|
window.applyTranslations(modal);
|
||||||
}
|
}
|
||||||
@@ -1116,8 +1118,7 @@ function openChatFilesMkdirModal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeChatFilesMkdirModal() {
|
function closeChatFilesMkdirModal() {
|
||||||
const modal = document.getElementById('chat-files-mkdir-modal');
|
closeAppModal('chat-files-mkdir-modal');
|
||||||
if (modal) modal.style.display = 'none';
|
|
||||||
const input = document.getElementById('chat-files-mkdir-input');
|
const input = document.getElementById('chat-files-mkdir-input');
|
||||||
if (input) input.value = '';
|
if (input) input.value = '';
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-49
@@ -2535,10 +2535,17 @@ async function batchUpdateButtonToolNames(buttonsContainer, executionIds) {
|
|||||||
// 显示MCP调用详情
|
// 显示MCP调用详情
|
||||||
async function showMCPDetail(executionId) {
|
async function showMCPDetail(executionId) {
|
||||||
try {
|
try {
|
||||||
|
openAppModal('mcp-detail-modal', { focus: false });
|
||||||
const response = await apiFetch(`/api/monitor/execution/${executionId}`);
|
const response = await apiFetch(`/api/monitor/execution/${executionId}`);
|
||||||
const exec = await response.json();
|
const exec = await response.json();
|
||||||
|
|
||||||
if (response.ok) {
|
if (!response.ok) {
|
||||||
|
closeMCPDetail();
|
||||||
|
alert((typeof window.t === 'function' ? window.t('mcpDetailModal.getDetailFailed') : '获取详情失败') + ': ' + (exec.error || (typeof window.t === 'function' ? window.t('mcpDetailModal.unknown') : '未知错误')));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deferModalContent(function () {
|
||||||
// 填充模态框内容
|
// 填充模态框内容
|
||||||
document.getElementById('detail-tool-name').textContent = exec.toolName || (typeof window.t === 'function' ? window.t('mcpDetailModal.unknown') : 'Unknown');
|
document.getElementById('detail-tool-name').textContent = exec.toolName || (typeof window.t === 'function' ? window.t('mcpDetailModal.unknown') : 'Unknown');
|
||||||
document.getElementById('detail-execution-id').textContent = exec.id || 'N/A';
|
document.getElementById('detail-execution-id').textContent = exec.id || 'N/A';
|
||||||
@@ -2645,20 +2652,16 @@ async function showMCPDetail(executionId) {
|
|||||||
delete abortBtn.dataset.execId;
|
delete abortBtn.dataset.execId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// 显示模态框
|
|
||||||
document.getElementById('mcp-detail-modal').style.display = 'block';
|
|
||||||
} else {
|
|
||||||
alert((typeof window.t === 'function' ? window.t('mcpDetailModal.getDetailFailed') : '获取详情失败') + ': ' + (exec.error || (typeof window.t === 'function' ? window.t('mcpDetailModal.unknown') : '未知错误')));
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
closeMCPDetail();
|
||||||
alert((typeof window.t === 'function' ? window.t('mcpDetailModal.getDetailFailed') : '获取详情失败') + ': ' + error.message);
|
alert((typeof window.t === 'function' ? window.t('mcpDetailModal.getDetailFailed') : '获取详情失败') + ': ' + error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭MCP详情模态框
|
// 关闭MCP详情模态框
|
||||||
function closeMCPDetail() {
|
function closeMCPDetail() {
|
||||||
document.getElementById('mcp-detail-modal').style.display = 'none';
|
closeAppModal('mcp-detail-modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 从详情模态框触发:取消当前进行中的 MCP 工具调用 */
|
/** 从详情模态框触发:取消当前进行中的 MCP 工具调用 */
|
||||||
@@ -2682,18 +2685,12 @@ function openMcpToolAbortModal(executionId, options = {}) {
|
|||||||
if (ta) {
|
if (ta) {
|
||||||
ta.value = '';
|
ta.value = '';
|
||||||
}
|
}
|
||||||
const m = document.getElementById('mcp-tool-abort-modal');
|
openAppModal('mcp-tool-abort-modal');
|
||||||
if (m) {
|
|
||||||
m.style.display = 'block';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeMcpToolAbortModal() {
|
function closeMcpToolAbortModal() {
|
||||||
window.__mcpToolAbortContext = null;
|
window.__mcpToolAbortContext = null;
|
||||||
const m = document.getElementById('mcp-tool-abort-modal');
|
closeAppModal('mcp-tool-abort-modal');
|
||||||
if (m) {
|
|
||||||
m.style.display = 'none';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submitMcpToolAbortModal() {
|
async function submitMcpToolAbortModal() {
|
||||||
@@ -3125,7 +3122,7 @@ async function loadConversation(conversationId) {
|
|||||||
|
|
||||||
// 如果攻击链模态框打开且显示的不是当前对话,关闭它
|
// 如果攻击链模态框打开且显示的不是当前对话,关闭它
|
||||||
const attackChainModal = document.getElementById('attack-chain-modal');
|
const attackChainModal = document.getElementById('attack-chain-modal');
|
||||||
if (attackChainModal && attackChainModal.style.display === 'block') {
|
if (attackChainModal && isAppModalOpen('attack-chain-modal')) {
|
||||||
if (currentAttackChainConversationId !== conversationId) {
|
if (currentAttackChainConversationId !== conversationId) {
|
||||||
closeAttackChainModal();
|
closeAttackChainModal();
|
||||||
}
|
}
|
||||||
@@ -3415,7 +3412,7 @@ async function deleteConversation(conversationId, skipConfirm = false) {
|
|||||||
|
|
||||||
// 批量管理弹窗打开时,同步刷新弹窗内列表
|
// 批量管理弹窗打开时,同步刷新弹窗内列表
|
||||||
const batchModal = document.getElementById('batch-manage-modal');
|
const batchModal = document.getElementById('batch-manage-modal');
|
||||||
if (batchModal && batchModal.style.display === 'flex') {
|
if (batchModal && isAppModalOpen('batch-manage-modal')) {
|
||||||
allConversationsForBatch = allConversationsForBatch.filter(c => c.id !== conversationId);
|
allConversationsForBatch = allConversationsForBatch.filter(c => c.id !== conversationId);
|
||||||
updateBatchManageTitle(allConversationsForBatch.length);
|
updateBatchManageTitle(allConversationsForBatch.length);
|
||||||
const searchInput = document.getElementById('batch-search-input');
|
const searchInput = document.getElementById('batch-search-input');
|
||||||
@@ -3522,7 +3519,7 @@ async function showAttackChain(conversationId) {
|
|||||||
if (isAttackChainLoading(conversationId) && currentAttackChainConversationId === conversationId) {
|
if (isAttackChainLoading(conversationId) && currentAttackChainConversationId === conversationId) {
|
||||||
// 如果模态框已经打开且显示的是同一个对话,不重复打开
|
// 如果模态框已经打开且显示的是同一个对话,不重复打开
|
||||||
const modal = document.getElementById('attack-chain-modal');
|
const modal = document.getElementById('attack-chain-modal');
|
||||||
if (modal && modal.style.display === 'block') {
|
if (modal && isAppModalOpen('attack-chain-modal')) {
|
||||||
console.log('攻击链正在加载中,模态框已打开');
|
console.log('攻击链正在加载中,模态框已打开');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3535,8 +3532,7 @@ async function showAttackChain(conversationId) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
modal.style.display = 'block';
|
openAppModal('attack-chain-modal', { focus: false });
|
||||||
// 打开时立即按当前语言刷新统计(避免红框内仍显示硬编码中文)
|
|
||||||
updateAttackChainStats({ nodes: [], edges: [] });
|
updateAttackChainStats({ nodes: [], edges: [] });
|
||||||
|
|
||||||
// 清空容器
|
// 清空容器
|
||||||
@@ -4668,10 +4664,7 @@ function closeNodeDetails() {
|
|||||||
|
|
||||||
// 关闭攻击链模态框
|
// 关闭攻击链模态框
|
||||||
function closeAttackChainModal() {
|
function closeAttackChainModal() {
|
||||||
const modal = document.getElementById('attack-chain-modal');
|
closeAppModal('attack-chain-modal');
|
||||||
if (modal) {
|
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭节点详情
|
// 关闭节点详情
|
||||||
closeNodeDetails();
|
closeNodeDetails();
|
||||||
@@ -7214,19 +7207,14 @@ async function showBatchManageModal() {
|
|||||||
updateBatchManageTitle(allConversationsForBatch.length);
|
updateBatchManageTitle(allConversationsForBatch.length);
|
||||||
|
|
||||||
renderBatchConversations();
|
renderBatchConversations();
|
||||||
if (modal) {
|
openAppModal('batch-manage-modal');
|
||||||
modal.style.display = 'flex';
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载对话列表失败:', error);
|
console.error('加载对话列表失败:', error);
|
||||||
// 错误时使用空数组,不显示错误提示(更友好的用户体验)
|
// 错误时使用空数组,不显示错误提示(更友好的用户体验)
|
||||||
allConversationsForBatch = [];
|
allConversationsForBatch = [];
|
||||||
const modal = document.getElementById('batch-manage-modal');
|
|
||||||
updateBatchManageTitle(0);
|
updateBatchManageTitle(0);
|
||||||
if (modal) {
|
renderBatchConversations();
|
||||||
renderBatchConversations();
|
openAppModal('batch-manage-modal');
|
||||||
modal.style.display = 'flex';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7381,10 +7369,7 @@ async function deleteSelectedConversations() {
|
|||||||
|
|
||||||
// 关闭批量管理模态框
|
// 关闭批量管理模态框
|
||||||
function closeBatchManageModal() {
|
function closeBatchManageModal() {
|
||||||
const modal = document.getElementById('batch-manage-modal');
|
closeAppModal('batch-manage-modal');
|
||||||
if (modal) {
|
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
const selectAll = document.getElementById('batch-select-all');
|
const selectAll = document.getElementById('batch-select-all');
|
||||||
if (selectAll) {
|
if (selectAll) {
|
||||||
selectAll.checked = false;
|
selectAll.checked = false;
|
||||||
@@ -7424,8 +7409,7 @@ function refreshChatPanelI18n() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const mcpModal = document.getElementById('mcp-detail-modal');
|
if (isAppModalOpen('mcp-detail-modal')) {
|
||||||
if (mcpModal && mcpModal.style.display === 'block') {
|
|
||||||
const detailTimeEl = document.getElementById('detail-time');
|
const detailTimeEl = document.getElementById('detail-time');
|
||||||
if (detailTimeEl && detailTimeEl.dataset.detailTimeIso) {
|
if (detailTimeEl && detailTimeEl.dataset.detailTimeIso) {
|
||||||
try {
|
try {
|
||||||
@@ -7447,7 +7431,7 @@ document.addEventListener('languagechange', function () {
|
|||||||
refreshSystemReadyMessageBubbles();
|
refreshSystemReadyMessageBubbles();
|
||||||
refreshChatPanelI18n();
|
refreshChatPanelI18n();
|
||||||
const modal = document.getElementById('batch-manage-modal');
|
const modal = document.getElementById('batch-manage-modal');
|
||||||
if (modal && modal.style.display === 'flex') {
|
if (isAppModalOpen('batch-manage-modal')) {
|
||||||
updateBatchManageTitle(allConversationsForBatch.length);
|
updateBatchManageTitle(allConversationsForBatch.length);
|
||||||
}
|
}
|
||||||
// 侧边栏最近对话等列表的时间戳会随语言变化(24h/12h 等),重新拉列表以统一格式
|
// 侧边栏最近对话等列表的时间戳会随语言变化(24h/12h 等),重新拉列表以统一格式
|
||||||
@@ -7482,20 +7466,14 @@ function showCreateGroupModal(andMoveConversation = false) {
|
|||||||
iconPicker.style.display = 'none';
|
iconPicker.style.display = 'none';
|
||||||
}
|
}
|
||||||
if (modal) {
|
if (modal) {
|
||||||
modal.style.display = 'flex';
|
openAppModal('create-group-modal', { focusEl: input });
|
||||||
modal.dataset.moveConversation = andMoveConversation ? 'true' : 'false';
|
modal.dataset.moveConversation = andMoveConversation ? 'true' : 'false';
|
||||||
if (input) {
|
|
||||||
setTimeout(() => input.focus(), 100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭创建分组模态框
|
// 关闭创建分组模态框
|
||||||
function closeCreateGroupModal() {
|
function closeCreateGroupModal() {
|
||||||
const modal = document.getElementById('create-group-modal');
|
closeAppModal('create-group-modal');
|
||||||
if (modal) {
|
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
const input = document.getElementById('create-group-name-input');
|
const input = document.getElementById('create-group-name-input');
|
||||||
if (input) {
|
if (input) {
|
||||||
input.value = '';
|
input.value = '';
|
||||||
|
|||||||
@@ -344,7 +344,9 @@ function showFofaParseModal(nlText, parsed) {
|
|||||||
const modal = document.createElement('div');
|
const modal = document.createElement('div');
|
||||||
modal.id = 'fofa-parse-modal';
|
modal.id = 'fofa-parse-modal';
|
||||||
modal.className = 'modal';
|
modal.className = 'modal';
|
||||||
modal.style.display = 'block';
|
document.body.appendChild(modal);
|
||||||
|
openAppModal(modal, { focus: false });
|
||||||
|
deferModalContent(function () {
|
||||||
modal.innerHTML = `
|
modal.innerHTML = `
|
||||||
<div class="modal-content" style="max-width: 900px;">
|
<div class="modal-content" style="max-width: 900px;">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
@@ -384,24 +386,24 @@ function showFofaParseModal(nlText, parsed) {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.appendChild(modal);
|
|
||||||
|
|
||||||
const queryTextarea = document.getElementById('fofa-parse-query');
|
const queryTextarea = document.getElementById('fofa-parse-query');
|
||||||
if (queryTextarea) {
|
if (queryTextarea) {
|
||||||
queryTextarea.value = (parsed?.query || '').trim();
|
queryTextarea.value = (parsed?.query || '').trim();
|
||||||
setTimeout(() => {
|
queryTextarea.focus();
|
||||||
try { queryTextarea.focus(); } catch (e) { /* ignore */ }
|
|
||||||
}, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const close = () => modal.remove();
|
const close = function () {
|
||||||
modal.addEventListener('click', (e) => {
|
closeAppModal(modal);
|
||||||
|
modal.remove();
|
||||||
|
syncAppModalBodyLock();
|
||||||
|
};
|
||||||
|
modal.addEventListener('click', function (e) {
|
||||||
if (e.target === modal) close();
|
if (e.target === modal) close();
|
||||||
});
|
});
|
||||||
document.getElementById('fofa-parse-modal-close')?.addEventListener('click', close);
|
document.getElementById('fofa-parse-modal-close')?.addEventListener('click', close);
|
||||||
document.getElementById('fofa-parse-cancel')?.addEventListener('click', close);
|
document.getElementById('fofa-parse-cancel')?.addEventListener('click', close);
|
||||||
|
|
||||||
const applyToQuery = (run) => {
|
const applyToQuery = function (run) {
|
||||||
const els = getFofaFormElements();
|
const els = getFofaFormElements();
|
||||||
const q = (queryTextarea?.value || '').trim();
|
const q = (queryTextarea?.value || '').trim();
|
||||||
if (!q) {
|
if (!q) {
|
||||||
@@ -435,6 +437,7 @@ function showFofaParseModal(nlText, parsed) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
document.addEventListener('keydown', onKey);
|
document.addEventListener('keydown', onKey);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setFofaMeta(text) {
|
function setFofaMeta(text) {
|
||||||
@@ -1091,8 +1094,13 @@ function showCellDetailModal(field, fullText) {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.appendChild(modal);
|
document.body.appendChild(modal);
|
||||||
|
openAppModal(modal);
|
||||||
|
|
||||||
const close = () => modal.remove();
|
const close = function () {
|
||||||
|
closeAppModal(modal);
|
||||||
|
modal.remove();
|
||||||
|
syncAppModalBodyLock();
|
||||||
|
};
|
||||||
modal.addEventListener('click', (e) => {
|
modal.addEventListener('click', (e) => {
|
||||||
if (e.target === modal) close();
|
if (e.target === modal) close();
|
||||||
});
|
});
|
||||||
|
|||||||
+24
-20
@@ -905,25 +905,32 @@ function showAddKnowledgeItemModal() {
|
|||||||
document.getElementById('knowledge-item-category').value = '';
|
document.getElementById('knowledge-item-category').value = '';
|
||||||
document.getElementById('knowledge-item-title').value = '';
|
document.getElementById('knowledge-item-title').value = '';
|
||||||
document.getElementById('knowledge-item-content').value = '';
|
document.getElementById('knowledge-item-content').value = '';
|
||||||
document.getElementById('knowledge-item-modal').style.display = 'block';
|
openAppModal('knowledge-item-modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑知识项
|
// 编辑知识项
|
||||||
async function editKnowledgeItem(id) {
|
async function editKnowledgeItem(id) {
|
||||||
try {
|
try {
|
||||||
|
currentEditingItemId = id;
|
||||||
|
document.getElementById('knowledge-item-modal-title').textContent = '编辑知识';
|
||||||
|
document.getElementById('knowledge-item-category').value = '';
|
||||||
|
document.getElementById('knowledge-item-title').value = '';
|
||||||
|
document.getElementById('knowledge-item-content').value = '';
|
||||||
|
openAppModal('knowledge-item-modal', { focus: false });
|
||||||
const response = await apiFetch(`/api/knowledge/items/${id}`);
|
const response = await apiFetch(`/api/knowledge/items/${id}`);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('获取知识项失败');
|
throw new Error('获取知识项失败');
|
||||||
}
|
}
|
||||||
const item = await response.json();
|
const item = await response.json();
|
||||||
|
deferModalContent(() => {
|
||||||
currentEditingItemId = id;
|
document.getElementById('knowledge-item-category').value = item.category;
|
||||||
document.getElementById('knowledge-item-modal-title').textContent = '编辑知识';
|
document.getElementById('knowledge-item-title').value = item.title;
|
||||||
document.getElementById('knowledge-item-category').value = item.category;
|
document.getElementById('knowledge-item-content').value = item.content;
|
||||||
document.getElementById('knowledge-item-title').value = item.title;
|
document.getElementById('knowledge-item-title')?.focus();
|
||||||
document.getElementById('knowledge-item-content').value = item.content;
|
});
|
||||||
document.getElementById('knowledge-item-modal').style.display = 'block';
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
closeAppModal('knowledge-item-modal');
|
||||||
|
currentEditingItemId = null;
|
||||||
console.error('编辑知识项失败:', error);
|
console.error('编辑知识项失败:', error);
|
||||||
showNotification('编辑知识项失败: ' + error.message, 'error');
|
showNotification('编辑知识项失败: ' + error.message, 'error');
|
||||||
}
|
}
|
||||||
@@ -1232,10 +1239,7 @@ function updateKnowledgeStatsAfterDelete() {
|
|||||||
|
|
||||||
// 关闭知识项模态框
|
// 关闭知识项模态框
|
||||||
function closeKnowledgeItemModal() {
|
function closeKnowledgeItemModal() {
|
||||||
const modal = document.getElementById('knowledge-item-modal');
|
closeAppModal('knowledge-item-modal');
|
||||||
if (modal) {
|
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置编辑状态
|
// 重置编辑状态
|
||||||
currentEditingItemId = null;
|
currentEditingItemId = null;
|
||||||
@@ -1786,8 +1790,11 @@ function showRetrievalLogDetailsModal(log, retrievedItems) {
|
|||||||
document.body.appendChild(modal);
|
document.body.appendChild(modal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 填充内容
|
|
||||||
const content = document.getElementById('retrieval-log-details-content');
|
const content = document.getElementById('retrieval-log-details-content');
|
||||||
|
if (content) content.innerHTML = '<p style="color:#64748b;margin:0;">…</p>';
|
||||||
|
openAppModal(modal, { focus: false });
|
||||||
|
|
||||||
|
deferModalContent(() => {
|
||||||
const timeAgo = getTimeAgo(log.createdAt);
|
const timeAgo = getTimeAgo(log.createdAt);
|
||||||
const fullTime = formatTime(log.createdAt);
|
const fullTime = formatTime(log.createdAt);
|
||||||
|
|
||||||
@@ -1880,16 +1887,12 @@ function showRetrievalLogDetailsModal(log, retrievedItems) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
});
|
||||||
modal.style.display = 'block';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭检索日志详情模态框
|
// 关闭检索日志详情模态框
|
||||||
function closeRetrievalLogDetailsModal() {
|
function closeRetrievalLogDetailsModal() {
|
||||||
const modal = document.getElementById('retrieval-log-details-modal');
|
closeAppModal('retrieval-log-details-modal');
|
||||||
if (modal) {
|
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击模态框外部关闭
|
// 点击模态框外部关闭
|
||||||
@@ -2118,7 +2121,8 @@ function showToastNotification(message, type = 'info') {
|
|||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
line-height: 1.45;
|
line-height: 1.45;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
backdrop-filter: blur(8px);
|
backdrop-filter: none;
|
||||||
|
-webkit-backdrop-filter: none;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
toast.innerHTML = `
|
toast.innerHTML = `
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* 统一弹窗:先显示遮罩、下一帧再填大段内容,避免与 backdrop 绘制抢主线程。
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
const BODY_LOCK = 'app-modal-open';
|
||||||
|
const LEGACY_BODY_LOCK = 'projects-modal-open';
|
||||||
|
const OVERLAY_SELECTOR =
|
||||||
|
'.projects-modal-overlay, .c2-modal-overlay, .modal, .info-collect-cell-modal, #login-overlay';
|
||||||
|
|
||||||
|
const FLEX_MODAL_IDS = new Set([
|
||||||
|
'role-modal',
|
||||||
|
'skill-modal',
|
||||||
|
'agent-md-modal',
|
||||||
|
'batch-manage-modal',
|
||||||
|
'create-group-modal',
|
||||||
|
'login-overlay',
|
||||||
|
]);
|
||||||
|
|
||||||
|
function resolveEl(idOrEl) {
|
||||||
|
if (!idOrEl) return null;
|
||||||
|
return typeof idOrEl === 'string' ? document.getElementById(idOrEl) : idOrEl;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isElVisible(el) {
|
||||||
|
if (!el) return false;
|
||||||
|
const s = window.getComputedStyle(el);
|
||||||
|
return s.display !== 'none' && s.visibility !== 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultDisplay(el) {
|
||||||
|
if (el.classList.contains('projects-modal-overlay') || el.classList.contains('c2-modal-overlay')) {
|
||||||
|
return 'flex';
|
||||||
|
}
|
||||||
|
if (el.classList.contains('info-collect-cell-modal')) {
|
||||||
|
return 'flex';
|
||||||
|
}
|
||||||
|
if (FLEX_MODAL_IDS.has(el.id)) {
|
||||||
|
return 'flex';
|
||||||
|
}
|
||||||
|
return 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncBodyLock() {
|
||||||
|
const anyOpen = Array.from(document.querySelectorAll(OVERLAY_SELECTOR)).some(isElVisible);
|
||||||
|
document.body.classList.toggle(BODY_LOCK, anyOpen);
|
||||||
|
const projectsOpen = Array.from(document.querySelectorAll('.projects-modal-overlay')).some(isElVisible);
|
||||||
|
document.body.classList.toggle(LEGACY_BODY_LOCK, projectsOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openAppModal(idOrEl, opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
const el = resolveEl(idOrEl);
|
||||||
|
if (!el) return null;
|
||||||
|
el.style.display = opts.display || defaultDisplay(el);
|
||||||
|
syncBodyLock();
|
||||||
|
if (opts.focus === false) return el;
|
||||||
|
const sel =
|
||||||
|
opts.focusSelector ||
|
||||||
|
'input.form-input, textarea.form-input, select.form-input, input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled])';
|
||||||
|
const focusTarget = opts.focusEl || el.querySelector(sel);
|
||||||
|
if (focusTarget) {
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
focusTarget.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeAppModal(idOrEl) {
|
||||||
|
const el = resolveEl(idOrEl);
|
||||||
|
if (el) el.style.display = 'none';
|
||||||
|
syncBodyLock();
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isAppModalOpen(idOrEl) {
|
||||||
|
return isElVisible(resolveEl(idOrEl));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 双 rAF:等遮罩绘制完成后再写入大段 DOM / 表单 */
|
||||||
|
function deferModalContent(fn) {
|
||||||
|
requestAnimationFrame(function () {
|
||||||
|
requestAnimationFrame(fn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.openAppModal = openAppModal;
|
||||||
|
window.closeAppModal = closeAppModal;
|
||||||
|
window.isAppModalOpen = isAppModalOpen;
|
||||||
|
window.deferModalContent = deferModalContent;
|
||||||
|
window.syncAppModalBodyLock = syncBodyLock;
|
||||||
|
})();
|
||||||
@@ -944,18 +944,12 @@ function openUserInterruptModal(progressId, conversationId) {
|
|||||||
if (ta) {
|
if (ta) {
|
||||||
ta.value = '';
|
ta.value = '';
|
||||||
}
|
}
|
||||||
const m = document.getElementById('user-interrupt-modal');
|
openAppModal('user-interrupt-modal');
|
||||||
if (m) {
|
|
||||||
m.style.display = 'block';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeUserInterruptModal() {
|
function closeUserInterruptModal() {
|
||||||
userInterruptModalPending = null;
|
userInterruptModalPending = null;
|
||||||
const m = document.getElementById('user-interrupt-modal');
|
closeAppModal('user-interrupt-modal');
|
||||||
if (m) {
|
|
||||||
m.style.display = 'none';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submitUserInterruptContinue() {
|
async function submitUserInterruptContinue() {
|
||||||
|
|||||||
+70
-65
@@ -12,6 +12,7 @@ let _projectsFetchPromise = null;
|
|||||||
|
|
||||||
const PROJECT_ACTIVE_KEY = 'cyberstrike.activeProjectId';
|
const PROJECT_ACTIVE_KEY = 'cyberstrike.activeProjectId';
|
||||||
const PROJECT_DESCRIPTION_MAX_LENGTH = 4000;
|
const PROJECT_DESCRIPTION_MAX_LENGTH = 4000;
|
||||||
|
const PROJECT_NAME_MAX_LENGTH = 200;
|
||||||
|
|
||||||
function tp(key, opts) {
|
function tp(key, opts) {
|
||||||
if (typeof window.t === 'function') return window.t(key, opts);
|
if (typeof window.t === 'function') return window.t(key, opts);
|
||||||
@@ -878,38 +879,52 @@ let _factDetailFact = null;
|
|||||||
let _projectFactsFilterDebounce = null;
|
let _projectFactsFilterDebounce = null;
|
||||||
|
|
||||||
async function viewProjectFactBody(factKey) {
|
async function viewProjectFactBody(factKey) {
|
||||||
const res = await apiFetch(`/api/projects/${currentProjectId}/facts?fact_key=${encodeURIComponent(factKey)}`);
|
document.getElementById('fact-detail-title').textContent = factKey;
|
||||||
if (!res.ok) return alert(tp('common.loadFailed'));
|
document.getElementById('fact-detail-meta').textContent = '…';
|
||||||
const f = await res.json();
|
document.getElementById('fact-detail-body').textContent = '';
|
||||||
_factDetailKey = f.fact_key;
|
|
||||||
_factDetailFact = f;
|
|
||||||
document.getElementById('fact-detail-title').textContent = `[${f.fact_key}]`;
|
|
||||||
const metaParts = [
|
|
||||||
tpFmt('projects.factMetaCategory', `Category: ${f.category}`, { value: f.category }),
|
|
||||||
tpFmt('projects.factMetaConfidence', `Confidence: ${f.confidence}`, { value: f.confidence }),
|
|
||||||
tpFmt('projects.factMetaUpdated', `Updated: ${formatProjectTime(f.updated_at, f.created_at)}`, {
|
|
||||||
time: formatProjectTime(f.updated_at, f.created_at),
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
if (f.related_vulnerability_id) metaParts.push(tpFmt('projects.factMetaRelatedVuln', `Related vulnerability: ${f.related_vulnerability_id}`, { value: f.related_vulnerability_id }));
|
|
||||||
if (f.source_conversation_id) metaParts.push(tpFmt('projects.factMetaSourceConversation', `Source conversation: ${f.source_conversation_id}`, { value: f.source_conversation_id }));
|
|
||||||
document.getElementById('fact-detail-meta').textContent = metaParts.join(' · ');
|
|
||||||
document.getElementById('fact-detail-body').textContent = f.body || tp('projects.emptyBody');
|
|
||||||
const warnEl = document.getElementById('fact-detail-sparse-warn');
|
const warnEl = document.getElementById('fact-detail-sparse-warn');
|
||||||
if (warnEl) {
|
if (warnEl) {
|
||||||
if (isSparseFactBody(f.category, f.fact_key, f.body)) {
|
warnEl.hidden = true;
|
||||||
warnEl.hidden = false;
|
warnEl.textContent = '';
|
||||||
warnEl.textContent = tp('projects.factSparseWarn');
|
|
||||||
} else {
|
|
||||||
warnEl.hidden = true;
|
|
||||||
warnEl.textContent = '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const linkBtn = document.getElementById('fact-detail-link-vuln-btn');
|
const linkBtn = document.getElementById('fact-detail-link-vuln-btn');
|
||||||
const createBtn = document.getElementById('fact-detail-create-vuln-btn');
|
const createBtn = document.getElementById('fact-detail-create-vuln-btn');
|
||||||
if (linkBtn) linkBtn.hidden = false;
|
if (linkBtn) linkBtn.hidden = true;
|
||||||
if (createBtn) createBtn.hidden = false;
|
if (createBtn) createBtn.hidden = true;
|
||||||
openProjectsOverlay('fact-detail-modal');
|
openProjectsOverlay('fact-detail-modal', { focus: false });
|
||||||
|
const res = await apiFetch(`/api/projects/${currentProjectId}/facts?fact_key=${encodeURIComponent(factKey)}`);
|
||||||
|
if (!res.ok) {
|
||||||
|
closeFactDetailModal();
|
||||||
|
return alert(tp('common.loadFailed'));
|
||||||
|
}
|
||||||
|
const f = await res.json();
|
||||||
|
_factDetailKey = f.fact_key;
|
||||||
|
_factDetailFact = f;
|
||||||
|
deferModalContent(() => {
|
||||||
|
document.getElementById('fact-detail-title').textContent = `[${f.fact_key}]`;
|
||||||
|
const metaParts = [
|
||||||
|
tpFmt('projects.factMetaCategory', `Category: ${f.category}`, { value: f.category }),
|
||||||
|
tpFmt('projects.factMetaConfidence', `Confidence: ${f.confidence}`, { value: f.confidence }),
|
||||||
|
tpFmt('projects.factMetaUpdated', `Updated: ${formatProjectTime(f.updated_at, f.created_at)}`, {
|
||||||
|
time: formatProjectTime(f.updated_at, f.created_at),
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
if (f.related_vulnerability_id) metaParts.push(tpFmt('projects.factMetaRelatedVuln', `Related vulnerability: ${f.related_vulnerability_id}`, { value: f.related_vulnerability_id }));
|
||||||
|
if (f.source_conversation_id) metaParts.push(tpFmt('projects.factMetaSourceConversation', `Source conversation: ${f.source_conversation_id}`, { value: f.source_conversation_id }));
|
||||||
|
document.getElementById('fact-detail-meta').textContent = metaParts.join(' · ');
|
||||||
|
document.getElementById('fact-detail-body').textContent = f.body || tp('projects.emptyBody');
|
||||||
|
if (warnEl) {
|
||||||
|
if (isSparseFactBody(f.category, f.fact_key, f.body)) {
|
||||||
|
warnEl.hidden = false;
|
||||||
|
warnEl.textContent = tp('projects.factSparseWarn');
|
||||||
|
} else {
|
||||||
|
warnEl.hidden = true;
|
||||||
|
warnEl.textContent = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (linkBtn) linkBtn.hidden = false;
|
||||||
|
if (createBtn) createBtn.hidden = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function editFactFromDetail() {
|
function editFactFromDetail() {
|
||||||
@@ -1164,41 +1179,16 @@ async function viewFactsForVulnerability(vulnId) {
|
|||||||
else loadProjectFacts();
|
else loadProjectFacts();
|
||||||
}
|
}
|
||||||
|
|
||||||
function openProjectsOverlay(id) {
|
function openProjectsOverlay(id, opts) {
|
||||||
const el = document.getElementById(id);
|
openAppModal(id, opts);
|
||||||
if (!el) return;
|
|
||||||
el.style.display = 'flex';
|
|
||||||
syncProjectsModalBodyLock();
|
|
||||||
const focusTarget = el.querySelector('input.form-input, textarea.form-input, select.form-input');
|
|
||||||
if (focusTarget) {
|
|
||||||
setTimeout(() => focusTarget.focus(), 80);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isProjectsOverlayVisible(id) {
|
function isProjectsOverlayVisible(id) {
|
||||||
const el = document.getElementById(id);
|
return isAppModalOpen(id);
|
||||||
if (!el) return false;
|
|
||||||
const style = window.getComputedStyle(el);
|
|
||||||
return style.display !== 'none' && style.visibility !== 'hidden';
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasVisibleProjectsOverlay() {
|
|
||||||
const overlays = document.querySelectorAll('.projects-modal-overlay');
|
|
||||||
return Array.from(overlays).some((el) => {
|
|
||||||
const style = window.getComputedStyle(el);
|
|
||||||
return style.display !== 'none' && style.visibility !== 'hidden';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function syncProjectsModalBodyLock() {
|
|
||||||
if (hasVisibleProjectsOverlay()) document.body.classList.add('projects-modal-open');
|
|
||||||
else document.body.classList.remove('projects-modal-open');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeProjectsOverlay(id) {
|
function closeProjectsOverlay(id) {
|
||||||
const el = document.getElementById(id);
|
closeAppModal(id);
|
||||||
if (el) el.style.display = 'none';
|
|
||||||
syncProjectsModalBodyLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showNewProjectModal() {
|
function showNewProjectModal() {
|
||||||
@@ -1222,6 +1212,11 @@ async function showEditProjectModal(projectId) {
|
|||||||
if (sub) sub.textContent = tp('projects.modalEditSubtitle');
|
if (sub) sub.textContent = tp('projects.modalEditSubtitle');
|
||||||
const submitBtn = document.getElementById('project-modal-submit-btn');
|
const submitBtn = document.getElementById('project-modal-submit-btn');
|
||||||
if (submitBtn) submitBtn.textContent = tp('projects.saveChanges');
|
if (submitBtn) submitBtn.textContent = tp('projects.saveChanges');
|
||||||
|
const nameEl = document.getElementById('project-modal-name');
|
||||||
|
const descEl = document.getElementById('project-modal-description');
|
||||||
|
if (nameEl) nameEl.value = '';
|
||||||
|
if (descEl) descEl.value = '';
|
||||||
|
openProjectsOverlay('project-modal', { focus: false });
|
||||||
let p = findProjectById(projectId);
|
let p = findProjectById(projectId);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
try {
|
try {
|
||||||
@@ -1229,15 +1224,19 @@ async function showEditProjectModal(projectId) {
|
|||||||
if (!res.ok) throw new Error(tp('projects.projectNotFound'));
|
if (!res.ok) throw new Error(tp('projects.projectNotFound'));
|
||||||
p = await res.json();
|
p = await res.json();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
closeProjectModal();
|
||||||
alert(e.message || tp('projects.projectNotFound'));
|
alert(e.message || tp('projects.projectNotFound'));
|
||||||
window._projectModalEditId = null;
|
window._projectModalEditId = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.getElementById('project-modal-name').value = p.name || '';
|
const name = (p.name || '').slice(0, PROJECT_NAME_MAX_LENGTH);
|
||||||
document.getElementById('project-modal-description').value = p.description || '';
|
const description = clampProjectDescription(p.description || '');
|
||||||
openProjectsOverlay('project-modal');
|
deferModalContent(() => {
|
||||||
setTimeout(() => document.getElementById('project-modal-name')?.focus(), 0);
|
if (nameEl) nameEl.value = name;
|
||||||
|
if (descEl) descEl.value = description;
|
||||||
|
nameEl?.focus();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 从对话区「选择项目」面板打开新建项目,创建成功后自动绑定当前对话 */
|
/** 从对话区「选择项目」面板打开新建项目,创建成功后自动绑定当前对话 */
|
||||||
@@ -1248,7 +1247,7 @@ function showNewProjectModalFromChat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function saveProjectModal() {
|
async function saveProjectModal() {
|
||||||
const name = document.getElementById('project-modal-name').value.trim();
|
const name = document.getElementById('project-modal-name').value.trim().slice(0, PROJECT_NAME_MAX_LENGTH);
|
||||||
if (!name) return alert(tp('projects.enterProjectName'));
|
if (!name) return alert(tp('projects.enterProjectName'));
|
||||||
const body = {
|
const body = {
|
||||||
name,
|
name,
|
||||||
@@ -1541,14 +1540,20 @@ function showAddFactModal() {
|
|||||||
|
|
||||||
async function showEditFactModal(factKey) {
|
async function showEditFactModal(factKey) {
|
||||||
if (!currentProjectId) return alert(tp('projects.selectProjectFirst'));
|
if (!currentProjectId) return alert(tp('projects.selectProjectFirst'));
|
||||||
|
resetFactModalForm();
|
||||||
|
openProjectsOverlay('fact-modal', { focus: false });
|
||||||
const res = await apiFetch(
|
const res = await apiFetch(
|
||||||
`/api/projects/${currentProjectId}/facts?fact_key=${encodeURIComponent(factKey)}`,
|
`/api/projects/${currentProjectId}/facts?fact_key=${encodeURIComponent(factKey)}`,
|
||||||
);
|
);
|
||||||
if (!res.ok) return alert(tp('projects.loadFactFailed'));
|
if (!res.ok) {
|
||||||
|
closeFactModal();
|
||||||
|
return alert(tp('projects.loadFactFailed'));
|
||||||
|
}
|
||||||
const f = await res.json();
|
const f = await res.json();
|
||||||
resetFactModalForm();
|
deferModalContent(() => {
|
||||||
fillFactModalForm(f);
|
fillFactModalForm(f);
|
||||||
openProjectsOverlay('fact-modal');
|
document.getElementById('fact-modal-key')?.focus();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeFactModal() {
|
function closeFactModal() {
|
||||||
|
|||||||
@@ -1112,7 +1112,7 @@ async function showAddRoleModal() {
|
|||||||
// 确保统计信息正确更新(显示0/108)
|
// 确保统计信息正确更新(显示0/108)
|
||||||
updateRoleToolsStats();
|
updateRoleToolsStats();
|
||||||
|
|
||||||
modal.style.display = 'flex';
|
openAppModal('role-modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑角色
|
// 编辑角色
|
||||||
@@ -1274,15 +1274,16 @@ async function editRole(roleName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modal.style.display = 'flex';
|
openAppModal('role-modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭角色模态框
|
// 关闭角色模态框
|
||||||
function closeRoleModal() {
|
function closeRoleModal() {
|
||||||
const modal = document.getElementById('role-modal');
|
closeAppModal('role-modal');
|
||||||
if (modal) {
|
}
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
function closeRoleSelectModal() {
|
||||||
|
closeAppModal('role-select-modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取所有选中的工具(包括未在MCP管理中启用的工具)
|
// 获取所有选中的工具(包括未在MCP管理中启用的工具)
|
||||||
@@ -1634,6 +1635,7 @@ if (typeof window !== 'undefined') {
|
|||||||
window.getCurrentRole = getCurrentRole;
|
window.getCurrentRole = getCurrentRole;
|
||||||
window.toggleRoleSelectionPanel = toggleRoleSelectionPanel;
|
window.toggleRoleSelectionPanel = toggleRoleSelectionPanel;
|
||||||
window.closeRoleSelectionPanel = closeRoleSelectionPanel;
|
window.closeRoleSelectionPanel = closeRoleSelectionPanel;
|
||||||
|
window.closeRoleSelectModal = closeRoleSelectModal;
|
||||||
window.filterRoleToolsByStatus = filterRoleToolsByStatus;
|
window.filterRoleToolsByStatus = filterRoleToolsByStatus;
|
||||||
window.currentSelectedRole = getCurrentRole();
|
window.currentSelectedRole = getCurrentRole();
|
||||||
|
|
||||||
|
|||||||
+14
-19
@@ -2096,47 +2096,42 @@ function showAddExternalMCPModal() {
|
|||||||
document.getElementById('external-mcp-json-error').style.display = 'none';
|
document.getElementById('external-mcp-json-error').style.display = 'none';
|
||||||
document.getElementById('external-mcp-json-error').textContent = '';
|
document.getElementById('external-mcp-json-error').textContent = '';
|
||||||
document.getElementById('external-mcp-json').classList.remove('error');
|
document.getElementById('external-mcp-json').classList.remove('error');
|
||||||
document.getElementById('external-mcp-modal').style.display = 'block';
|
openAppModal('external-mcp-modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭外部MCP模态框
|
// 关闭外部MCP模态框
|
||||||
function closeExternalMCPModal() {
|
function closeExternalMCPModal() {
|
||||||
document.getElementById('external-mcp-modal').style.display = 'none';
|
closeAppModal('external-mcp-modal');
|
||||||
currentEditingMCPName = null;
|
currentEditingMCPName = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑外部MCP
|
// 编辑外部MCP
|
||||||
async function editExternalMCP(name) {
|
async function editExternalMCP(name) {
|
||||||
try {
|
try {
|
||||||
|
currentEditingMCPName = name;
|
||||||
|
document.getElementById('external-mcp-modal-title').textContent = (typeof window.t === 'function' ? window.t('mcp.editExternalMCP') : '编辑外部MCP');
|
||||||
|
document.getElementById('external-mcp-json').value = '';
|
||||||
|
document.getElementById('external-mcp-json-error').style.display = 'none';
|
||||||
|
document.getElementById('external-mcp-json-error').textContent = '';
|
||||||
|
document.getElementById('external-mcp-json').classList.remove('error');
|
||||||
|
openAppModal('external-mcp-modal', { focus: false });
|
||||||
const response = await apiFetch(`/api/external-mcp/${encodeURIComponent(name)}`);
|
const response = await apiFetch(`/api/external-mcp/${encodeURIComponent(name)}`);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(typeof window.t === 'function' ? window.t('mcp.getConfigFailed') : '获取外部MCP配置失败');
|
throw new Error(typeof window.t === 'function' ? window.t('mcp.getConfigFailed') : '获取外部MCP配置失败');
|
||||||
}
|
}
|
||||||
|
|
||||||
const server = await response.json();
|
const server = await response.json();
|
||||||
currentEditingMCPName = name;
|
|
||||||
|
|
||||||
document.getElementById('external-mcp-modal-title').textContent = (typeof window.t === 'function' ? window.t('mcp.editExternalMCP') : '编辑外部MCP');
|
|
||||||
|
|
||||||
// 将配置转换为对象格式(key为名称)
|
|
||||||
const config = { ...server.config };
|
const config = { ...server.config };
|
||||||
// 移除tool_count、external_mcp_enable等前端字段,但保留enabled/disabled用于向后兼容
|
|
||||||
delete config.tool_count;
|
delete config.tool_count;
|
||||||
delete config.external_mcp_enable;
|
delete config.external_mcp_enable;
|
||||||
|
|
||||||
// 包装成对象格式:{ "name": { config } }
|
|
||||||
const configObj = {};
|
const configObj = {};
|
||||||
configObj[name] = config;
|
configObj[name] = config;
|
||||||
|
|
||||||
// 格式化JSON
|
|
||||||
const jsonStr = JSON.stringify(configObj, null, 2);
|
const jsonStr = JSON.stringify(configObj, null, 2);
|
||||||
document.getElementById('external-mcp-json').value = jsonStr;
|
deferModalContent(() => {
|
||||||
document.getElementById('external-mcp-json-error').style.display = 'none';
|
document.getElementById('external-mcp-json').value = jsonStr;
|
||||||
document.getElementById('external-mcp-json-error').textContent = '';
|
document.getElementById('external-mcp-json')?.focus();
|
||||||
document.getElementById('external-mcp-json').classList.remove('error');
|
});
|
||||||
|
|
||||||
document.getElementById('external-mcp-modal').style.display = 'block';
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
closeExternalMCPModal();
|
||||||
console.error('编辑外部MCP失败:', error);
|
console.error('编辑外部MCP失败:', error);
|
||||||
alert((typeof window.t === 'function' ? window.t('mcp.operationFailed') : '编辑失败') + ': ' + error.message);
|
alert((typeof window.t === 'function' ? window.t('mcp.operationFailed') : '编辑失败') + ': ' + error.message);
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-40
@@ -40,7 +40,7 @@ function shouldSkipSkillsAutoRefresh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const modal = document.getElementById('skill-modal');
|
const modal = document.getElementById('skill-modal');
|
||||||
if (modal && modal.style.display === 'flex') {
|
if (modal && isAppModalOpen('skill-modal')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,7 +465,7 @@ function showAddSkillModal() {
|
|||||||
const addTa = document.getElementById('skill-content-add');
|
const addTa = document.getElementById('skill-content-add');
|
||||||
if (addTa) addTa.value = '';
|
if (addTa) addTa.value = '';
|
||||||
|
|
||||||
modal.style.display = 'flex';
|
openAppModal('skill-modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
function skillPackagePathDepth(path) {
|
function skillPackagePathDepth(path) {
|
||||||
@@ -555,6 +555,22 @@ async function selectSkillPackageFile(skillId, path, opts) {
|
|||||||
// 编辑skill
|
// 编辑skill
|
||||||
async function editSkill(skillId) {
|
async function editSkill(skillId) {
|
||||||
wireSkillModalOnce();
|
wireSkillModalOnce();
|
||||||
|
const modal = document.getElementById('skill-modal');
|
||||||
|
if (!modal) return;
|
||||||
|
skillModalAddMode = false;
|
||||||
|
skillFileDirty = false;
|
||||||
|
skillActivePath = 'SKILL.md';
|
||||||
|
const pkg = document.getElementById('skill-package-editor');
|
||||||
|
const addEd = document.getElementById('skill-add-editor');
|
||||||
|
if (pkg) pkg.style.display = 'block';
|
||||||
|
if (addEd) addEd.style.display = 'none';
|
||||||
|
document.getElementById('skill-modal-title').textContent = _t('skills.editSkill');
|
||||||
|
document.getElementById('skill-name').value = '';
|
||||||
|
document.getElementById('skill-name').disabled = true;
|
||||||
|
document.getElementById('skill-description').value = '';
|
||||||
|
const ta = document.getElementById('skill-content');
|
||||||
|
if (ta) ta.value = '';
|
||||||
|
openAppModal('skill-modal', { focus: false });
|
||||||
try {
|
try {
|
||||||
const [detailRes, filesRes] = await Promise.all([
|
const [detailRes, filesRes] = await Promise.all([
|
||||||
apiFetch(`/api/skills/${encodeURIComponent(skillId)}?depth=full`),
|
apiFetch(`/api/skills/${encodeURIComponent(skillId)}?depth=full`),
|
||||||
@@ -565,39 +581,24 @@ async function editSkill(skillId) {
|
|||||||
}
|
}
|
||||||
const data = await detailRes.json();
|
const data = await detailRes.json();
|
||||||
const skill = data.skill;
|
const skill = data.skill;
|
||||||
|
let files = [];
|
||||||
const modal = document.getElementById('skill-modal');
|
|
||||||
if (!modal) return;
|
|
||||||
|
|
||||||
skillModalAddMode = false;
|
|
||||||
skillFileDirty = false;
|
|
||||||
skillActivePath = 'SKILL.md';
|
|
||||||
const pkg = document.getElementById('skill-package-editor');
|
|
||||||
const addEd = document.getElementById('skill-add-editor');
|
|
||||||
if (pkg) pkg.style.display = 'block';
|
|
||||||
if (addEd) addEd.style.display = 'none';
|
|
||||||
|
|
||||||
document.getElementById('skill-modal-title').textContent = _t('skills.editSkill');
|
|
||||||
document.getElementById('skill-name').value = skill.id || skillId;
|
|
||||||
document.getElementById('skill-name').disabled = true;
|
|
||||||
document.getElementById('skill-description').value = skill.description || '';
|
|
||||||
|
|
||||||
if (filesRes.ok) {
|
if (filesRes.ok) {
|
||||||
const fd = await filesRes.json();
|
const fd = await filesRes.json();
|
||||||
skillPackageFiles = fd.files || [];
|
files = fd.files || [];
|
||||||
} else {
|
|
||||||
skillPackageFiles = [];
|
|
||||||
}
|
}
|
||||||
renderSkillPackageTree();
|
|
||||||
|
|
||||||
const ta = document.getElementById('skill-content');
|
|
||||||
if (ta) ta.value = skill.content || '';
|
|
||||||
const hint = document.getElementById('skill-body-hint-edit');
|
|
||||||
if (hint) hint.style.display = 'block';
|
|
||||||
|
|
||||||
currentEditingSkillName = skillId;
|
currentEditingSkillName = skillId;
|
||||||
modal.style.display = 'flex';
|
deferModalContent(() => {
|
||||||
|
document.getElementById('skill-name').value = skill.id || skillId;
|
||||||
|
document.getElementById('skill-description').value = skill.description || '';
|
||||||
|
skillPackageFiles = files;
|
||||||
|
renderSkillPackageTree();
|
||||||
|
if (ta) ta.value = skill.content || '';
|
||||||
|
const hint = document.getElementById('skill-body-hint-edit');
|
||||||
|
if (hint) hint.style.display = 'block';
|
||||||
|
document.getElementById('skill-name')?.focus();
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
closeSkillModal();
|
||||||
console.error('加载skill详情失败:', error);
|
console.error('加载skill详情失败:', error);
|
||||||
showNotification(_t('skills.loadDetailFailed') + ': ' + error.message, 'error');
|
showNotification(_t('skills.loadDetailFailed') + ': ' + error.message, 'error');
|
||||||
}
|
}
|
||||||
@@ -659,7 +660,7 @@ async function viewSkill(skillId) {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
document.body.appendChild(modal);
|
document.body.appendChild(modal);
|
||||||
modal.style.display = 'flex';
|
openAppModal(modal);
|
||||||
|
|
||||||
const close = () => closeSkillViewModal();
|
const close = () => closeSkillViewModal();
|
||||||
modal.querySelectorAll('[data-skill-view-close]').forEach(el => el.addEventListener('click', close));
|
modal.querySelectorAll('[data-skill-view-close]').forEach(el => el.addEventListener('click', close));
|
||||||
@@ -691,23 +692,22 @@ async function viewSkill(skillId) {
|
|||||||
|
|
||||||
// 关闭查看模态框
|
// 关闭查看模态框
|
||||||
function closeSkillViewModal() {
|
function closeSkillViewModal() {
|
||||||
|
closeAppModal('skill-view-modal');
|
||||||
const modal = document.getElementById('skill-view-modal');
|
const modal = document.getElementById('skill-view-modal');
|
||||||
if (modal) {
|
if (modal) {
|
||||||
modal.remove();
|
modal.remove();
|
||||||
|
syncAppModalBodyLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭skill模态框
|
// 关闭skill模态框
|
||||||
function closeSkillModal() {
|
function closeSkillModal() {
|
||||||
const modal = document.getElementById('skill-modal');
|
closeAppModal('skill-modal');
|
||||||
if (modal) {
|
currentEditingSkillName = null;
|
||||||
modal.style.display = 'none';
|
skillModalAddMode = true;
|
||||||
currentEditingSkillName = null;
|
skillFileDirty = false;
|
||||||
skillModalAddMode = true;
|
skillPackageFiles = [];
|
||||||
skillFileDirty = false;
|
skillActivePath = 'SKILL.md';
|
||||||
skillPackageFiles = [];
|
|
||||||
skillActivePath = 'SKILL.md';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存skill
|
// 保存skill
|
||||||
|
|||||||
+18
-25
@@ -914,18 +914,14 @@ async function showBatchImportModal() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
await refreshBatchProjectSelectOptions();
|
await refreshBatchProjectSelectOptions();
|
||||||
|
|
||||||
modal.style.display = 'block';
|
openAppModal('batch-import-modal', { focusEl: input });
|
||||||
input.focus();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭新建任务模态框
|
// 关闭新建任务模态框
|
||||||
function closeBatchImportModal() {
|
function closeBatchImportModal() {
|
||||||
const modal = document.getElementById('batch-import-modal');
|
closeAppModal('batch-import-modal');
|
||||||
if (modal) {
|
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleBatchScheduleModeChange() {
|
function handleBatchScheduleModeChange() {
|
||||||
@@ -1350,7 +1346,13 @@ async function showBatchQueueDetail(queueId) {
|
|||||||
const addTaskBtn = document.getElementById('batch-queue-add-task-btn');
|
const addTaskBtn = document.getElementById('batch-queue-add-task-btn');
|
||||||
|
|
||||||
if (!modal || !content) return;
|
if (!modal || !content) return;
|
||||||
|
|
||||||
|
const alreadyOpen = isAppModalOpen('batch-queue-detail-modal');
|
||||||
|
if (!alreadyOpen) {
|
||||||
|
if (content) content.innerHTML = '<p style="color:#64748b;margin:0;">…</p>';
|
||||||
|
openAppModal('batch-queue-detail-modal', { focus: false });
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 加载角色列表(如果还未加载)
|
// 加载角色列表(如果还未加载)
|
||||||
let loadedRoles = [];
|
let loadedRoles = [];
|
||||||
@@ -1459,6 +1461,7 @@ async function showBatchQueueDetail(queueId) {
|
|||||||
const sameQueueAsBefore = prevDetailFor === queue.id;
|
const sameQueueAsBefore = prevDetailFor === queue.id;
|
||||||
const savedTechDetailsOpen = sameQueueAsBefore && !!(prevTechDetails && prevTechDetails.open);
|
const savedTechDetailsOpen = sameQueueAsBefore && !!(prevTechDetails && prevTechDetails.open);
|
||||||
|
|
||||||
|
deferModalContent(function () {
|
||||||
content.innerHTML = `
|
content.innerHTML = `
|
||||||
<div class="batch-queue-detail-layout" data-bq-detail-for="${escapeHtml(queue.id)}">
|
<div class="batch-queue-detail-layout" data-bq-detail-for="${escapeHtml(queue.id)}">
|
||||||
<section class="batch-queue-detail-hero">
|
<section class="batch-queue-detail-hero">
|
||||||
@@ -1529,8 +1532,7 @@ async function showBatchQueueDetail(queueId) {
|
|||||||
if (newTechDetails && savedTechDetailsOpen) {
|
if (newTechDetails && savedTechDetailsOpen) {
|
||||||
newTechDetails.open = true;
|
newTechDetails.open = true;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
modal.style.display = 'block';
|
|
||||||
|
|
||||||
// 仅运行中定时拉取详情;其它状态应停止,避免 innerHTML 重绘把 <details> 等 UI 打回默认态
|
// 仅运行中定时拉取详情;其它状态应停止,避免 innerHTML 重绘把 <details> 等 UI 打回默认态
|
||||||
if (queue.status === 'running') {
|
if (queue.status === 'running') {
|
||||||
@@ -1540,6 +1542,7 @@ async function showBatchQueueDetail(queueId) {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取队列详情失败:', error);
|
console.error('获取队列详情失败:', error);
|
||||||
|
closeBatchQueueDetailModal();
|
||||||
alert(_t('tasks.getQueueDetailFailed') + ': ' + error.message);
|
alert(_t('tasks.getQueueDetailFailed') + ': ' + error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1708,10 +1711,7 @@ async function deleteBatchQueueFromList(queueId) {
|
|||||||
|
|
||||||
// 关闭批量任务队列详情模态框
|
// 关闭批量任务队列详情模态框
|
||||||
function closeBatchQueueDetailModal() {
|
function closeBatchQueueDetailModal() {
|
||||||
const modal = document.getElementById('batch-queue-detail-modal');
|
closeAppModal('batch-queue-detail-modal');
|
||||||
if (modal) {
|
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
batchQueuesState.currentQueueId = null;
|
batchQueuesState.currentQueueId = null;
|
||||||
stopBatchQueueRefresh();
|
stopBatchQueueRefresh();
|
||||||
}
|
}
|
||||||
@@ -1730,7 +1730,7 @@ function startBatchQueueRefresh(queueId) {
|
|||||||
content.querySelector('.bq-inline-edit-controls') ||
|
content.querySelector('.bq-inline-edit-controls') ||
|
||||||
content.querySelector('.batch-task-inline-edit')
|
content.querySelector('.batch-task-inline-edit')
|
||||||
);
|
);
|
||||||
if ((addModal && addModal.style.display === 'block') || hasInlineEdit) {
|
if ((addModal && isAppModalOpen('add-batch-task-modal')) || hasInlineEdit) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (batchQueuesState._bqDetailRefreshing) {
|
if (batchQueuesState._bqDetailRefreshing) {
|
||||||
@@ -1891,12 +1891,7 @@ function showAddBatchTaskModal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
messageInput.value = '';
|
messageInput.value = '';
|
||||||
modal.style.display = 'block';
|
openAppModal('add-batch-task-modal', { focusEl: messageInput });
|
||||||
|
|
||||||
// 聚焦到输入框
|
|
||||||
setTimeout(() => {
|
|
||||||
messageInput.focus();
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// 清理旧的事件监听器
|
// 清理旧的事件监听器
|
||||||
if (showAddBatchTaskModal._escHandler) {
|
if (showAddBatchTaskModal._escHandler) {
|
||||||
@@ -1940,9 +1935,7 @@ function closeAddBatchTaskModal() {
|
|||||||
}
|
}
|
||||||
const modal = document.getElementById('add-batch-task-modal');
|
const modal = document.getElementById('add-batch-task-modal');
|
||||||
const messageInput = document.getElementById('add-task-message');
|
const messageInput = document.getElementById('add-task-message');
|
||||||
if (modal) {
|
closeAppModal('add-batch-task-modal');
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
if (messageInput) {
|
if (messageInput) {
|
||||||
messageInput.value = '';
|
messageInput.value = '';
|
||||||
}
|
}
|
||||||
@@ -2462,7 +2455,7 @@ document.addEventListener('languagechange', function () {
|
|||||||
const detailModal = document.getElementById('batch-queue-detail-modal');
|
const detailModal = document.getElementById('batch-queue-detail-modal');
|
||||||
if (
|
if (
|
||||||
detailModal &&
|
detailModal &&
|
||||||
detailModal.style.display === 'block' &&
|
isAppModalOpen('batch-queue-detail-modal') &&
|
||||||
batchQueuesState.currentQueueId
|
batchQueuesState.currentQueueId
|
||||||
) {
|
) {
|
||||||
showBatchQueueDetail(batchQueuesState.currentQueueId);
|
showBatchQueueDetail(batchQueuesState.currentQueueId);
|
||||||
|
|||||||
@@ -1090,37 +1090,36 @@ async function showAddVulnerabilityModal() {
|
|||||||
document.getElementById('vulnerability-impact').value = '';
|
document.getElementById('vulnerability-impact').value = '';
|
||||||
document.getElementById('vulnerability-recommendation').value = '';
|
document.getElementById('vulnerability-recommendation').value = '';
|
||||||
|
|
||||||
document.getElementById('vulnerability-modal').style.display = 'block';
|
openAppModal('vulnerability-modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑漏洞
|
// 编辑漏洞
|
||||||
async function editVulnerability(id) {
|
async function editVulnerability(id) {
|
||||||
try {
|
try {
|
||||||
const response = await apiFetch(`/api/vulnerabilities/${id}`);
|
|
||||||
if (!response.ok) throw new Error(vulnT('vulnerabilityPage.fetchFailed'));
|
|
||||||
|
|
||||||
const vuln = await response.json();
|
|
||||||
currentVulnerabilityId = id;
|
currentVulnerabilityId = id;
|
||||||
document.getElementById('vulnerability-modal-title').textContent = vulnT('vulnerability.editVuln');
|
document.getElementById('vulnerability-modal-title').textContent = vulnT('vulnerability.editVuln');
|
||||||
|
openAppModal('vulnerability-modal', { focus: false });
|
||||||
// 填充表单
|
const response = await apiFetch(`/api/vulnerabilities/${id}`);
|
||||||
document.getElementById('vulnerability-conversation-id').value = vuln.conversation_id || '';
|
if (!response.ok) throw new Error(vulnT('vulnerabilityPage.fetchFailed'));
|
||||||
document.getElementById('vulnerability-conversation-tag').value = vuln.conversation_tag || '';
|
const vuln = await response.json();
|
||||||
document.getElementById('vulnerability-task-tag').value = vuln.task_tag || '';
|
deferModalContent(async () => {
|
||||||
document.getElementById('vulnerability-title').value = vuln.title || '';
|
document.getElementById('vulnerability-conversation-id').value = vuln.conversation_id || '';
|
||||||
document.getElementById('vulnerability-description').value = vuln.description || '';
|
document.getElementById('vulnerability-conversation-tag').value = vuln.conversation_tag || '';
|
||||||
document.getElementById('vulnerability-severity').value = vuln.severity || '';
|
document.getElementById('vulnerability-task-tag').value = vuln.task_tag || '';
|
||||||
document.getElementById('vulnerability-status').value = vuln.status || 'open';
|
document.getElementById('vulnerability-title').value = vuln.title || '';
|
||||||
document.getElementById('vulnerability-type').value = vuln.type || '';
|
document.getElementById('vulnerability-description').value = vuln.description || '';
|
||||||
document.getElementById('vulnerability-target').value = vuln.target || '';
|
document.getElementById('vulnerability-severity').value = vuln.severity || '';
|
||||||
document.getElementById('vulnerability-proof').value = vuln.proof || '';
|
document.getElementById('vulnerability-status').value = vuln.status || 'open';
|
||||||
document.getElementById('vulnerability-impact').value = vuln.impact || '';
|
document.getElementById('vulnerability-type').value = vuln.type || '';
|
||||||
document.getElementById('vulnerability-recommendation').value = vuln.recommendation || '';
|
document.getElementById('vulnerability-target').value = vuln.target || '';
|
||||||
|
document.getElementById('vulnerability-proof').value = vuln.proof || '';
|
||||||
await populateVulnerabilityModalProjectSelect(vuln.project_id || '');
|
document.getElementById('vulnerability-impact').value = vuln.impact || '';
|
||||||
|
document.getElementById('vulnerability-recommendation').value = vuln.recommendation || '';
|
||||||
document.getElementById('vulnerability-modal').style.display = 'block';
|
await populateVulnerabilityModalProjectSelect(vuln.project_id || '');
|
||||||
|
document.getElementById('vulnerability-title')?.focus();
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
closeVulnerabilityModal();
|
||||||
console.error('加载漏洞失败:', error);
|
console.error('加载漏洞失败:', error);
|
||||||
alert(vulnT('vulnerability.loadFailed') + ': ' + error.message);
|
alert(vulnT('vulnerability.loadFailed') + ': ' + error.message);
|
||||||
}
|
}
|
||||||
@@ -1233,7 +1232,7 @@ async function deleteVulnerability(id) {
|
|||||||
|
|
||||||
// 关闭漏洞模态框
|
// 关闭漏洞模态框
|
||||||
function closeVulnerabilityModal() {
|
function closeVulnerabilityModal() {
|
||||||
document.getElementById('vulnerability-modal').style.display = 'none';
|
closeAppModal('vulnerability-modal');
|
||||||
currentVulnerabilityId = null;
|
currentVulnerabilityId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1749,7 +1748,7 @@ async function refreshVulnerabilityProjectFilter() {
|
|||||||
sel.innerHTML = html;
|
sel.innerHTML = html;
|
||||||
if (cur) sel.value = cur;
|
if (cur) sel.value = cur;
|
||||||
const modalSel = document.getElementById('vulnerability-project-id');
|
const modalSel = document.getElementById('vulnerability-project-id');
|
||||||
if (modalSel && document.getElementById('vulnerability-modal')?.style.display === 'block') {
|
if (modalSel && isAppModalOpen('vulnerability-modal')) {
|
||||||
const modalCur = modalSel.value || '';
|
const modalCur = modalSel.value || '';
|
||||||
modalSel.innerHTML = buildVulnerabilityProjectOptionsHtml(modalCur);
|
modalSel.innerHTML = buildVulnerabilityProjectOptionsHtml(modalCur);
|
||||||
modalSel.value = modalCur;
|
modalSel.value = modalCur;
|
||||||
|
|||||||
+27
-22
@@ -2301,10 +2301,14 @@ function selectWebshell(id, stateReady) {
|
|||||||
|
|
||||||
function setDbProfileModalVisible(visible, mode) {
|
function setDbProfileModalVisible(visible, mode) {
|
||||||
if (!dbProfileModalEl) return;
|
if (!dbProfileModalEl) return;
|
||||||
dbProfileModalEl.style.display = visible ? 'block' : 'none';
|
if (visible) {
|
||||||
if (dbProfileModalTitleEl) {
|
if (dbProfileModalTitleEl) {
|
||||||
if (mode === 'add') dbProfileModalTitleEl.textContent = wsT('webshell.dbAddProfile') || '新增连接';
|
if (mode === 'add') dbProfileModalTitleEl.textContent = wsT('webshell.dbAddProfile') || '新增连接';
|
||||||
else dbProfileModalTitleEl.textContent = wsT('webshell.editConnectionTitle') || '编辑连接';
|
else dbProfileModalTitleEl.textContent = wsT('webshell.editConnectionTitle') || '编辑连接';
|
||||||
|
}
|
||||||
|
openAppModal(dbProfileModalEl);
|
||||||
|
} else {
|
||||||
|
closeAppModal(dbProfileModalEl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4369,37 +4373,38 @@ function showAddWebshellModal() {
|
|||||||
var titleEl = document.getElementById('webshell-modal-title');
|
var titleEl = document.getElementById('webshell-modal-title');
|
||||||
if (titleEl) titleEl.textContent = wsT('webshell.addConnection');
|
if (titleEl) titleEl.textContent = wsT('webshell.addConnection');
|
||||||
var modal = document.getElementById('webshell-modal');
|
var modal = document.getElementById('webshell-modal');
|
||||||
if (modal) modal.style.display = 'block';
|
if (modal) openAppModal(modal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打开编辑连接弹窗(预填当前连接信息)
|
// 打开编辑连接弹窗(预填当前连接信息)
|
||||||
function showEditWebshellModal(connId) {
|
function showEditWebshellModal(connId) {
|
||||||
var conn = webshellConnections.find(function (c) { return c.id === connId; });
|
var conn = webshellConnections.find(function (c) { return c.id === connId; });
|
||||||
if (!conn) return;
|
if (!conn) return;
|
||||||
var editIdEl = document.getElementById('webshell-edit-id');
|
|
||||||
if (editIdEl) editIdEl.value = conn.id;
|
|
||||||
document.getElementById('webshell-url').value = conn.url || '';
|
|
||||||
document.getElementById('webshell-password').value = conn.password || '';
|
|
||||||
document.getElementById('webshell-type').value = conn.type || 'php';
|
|
||||||
document.getElementById('webshell-method').value = (conn.method || 'post').toLowerCase();
|
|
||||||
document.getElementById('webshell-cmd-param').value = conn.cmdParam || '';
|
|
||||||
var osEditEl = document.getElementById('webshell-os');
|
|
||||||
if (osEditEl) osEditEl.value = normalizeWebshellOS(conn.os);
|
|
||||||
var encEditEl = document.getElementById('webshell-encoding');
|
|
||||||
if (encEditEl) encEditEl.value = normalizeWebshellEncoding(conn.encoding);
|
|
||||||
document.getElementById('webshell-remark').value = conn.remark || '';
|
|
||||||
var titleEl = document.getElementById('webshell-modal-title');
|
var titleEl = document.getElementById('webshell-modal-title');
|
||||||
if (titleEl) titleEl.textContent = wsT('webshell.editConnectionTitle');
|
if (titleEl) titleEl.textContent = wsT('webshell.editConnectionTitle');
|
||||||
var modal = document.getElementById('webshell-modal');
|
openAppModal('webshell-modal', { focus: false });
|
||||||
if (modal) modal.style.display = 'block';
|
deferModalContent(function () {
|
||||||
|
var editIdEl = document.getElementById('webshell-edit-id');
|
||||||
|
if (editIdEl) editIdEl.value = conn.id;
|
||||||
|
document.getElementById('webshell-url').value = conn.url || '';
|
||||||
|
document.getElementById('webshell-password').value = conn.password || '';
|
||||||
|
document.getElementById('webshell-type').value = conn.type || 'php';
|
||||||
|
document.getElementById('webshell-method').value = (conn.method || 'post').toLowerCase();
|
||||||
|
document.getElementById('webshell-cmd-param').value = conn.cmdParam || '';
|
||||||
|
var osEditEl = document.getElementById('webshell-os');
|
||||||
|
if (osEditEl) osEditEl.value = normalizeWebshellOS(conn.os);
|
||||||
|
var encEditEl = document.getElementById('webshell-encoding');
|
||||||
|
if (encEditEl) encEditEl.value = normalizeWebshellEncoding(conn.encoding);
|
||||||
|
document.getElementById('webshell-remark').value = conn.remark || '';
|
||||||
|
document.getElementById('webshell-url')?.focus();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
function closeWebshellModal() {
|
function closeWebshellModal() {
|
||||||
var editIdEl = document.getElementById('webshell-edit-id');
|
var editIdEl = document.getElementById('webshell-edit-id');
|
||||||
if (editIdEl) editIdEl.value = '';
|
if (editIdEl) editIdEl.value = '';
|
||||||
var modal = document.getElementById('webshell-modal');
|
closeAppModal('webshell-modal');
|
||||||
if (modal) modal.style.display = 'none';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 语言切换时刷新 WebShell 页面内所有由 JS 生成的文案(不重建终端)
|
// 语言切换时刷新 WebShell 页面内所有由 JS 生成的文案(不重建终端)
|
||||||
@@ -4571,7 +4576,7 @@ function refreshWebshellUIOnLanguageChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var modal = document.getElementById('webshell-modal');
|
var modal = document.getElementById('webshell-modal');
|
||||||
if (modal && modal.style.display === 'block') {
|
if (modal && isAppModalOpen('webshell-modal')) {
|
||||||
var titleEl = document.getElementById('webshell-modal-title');
|
var titleEl = document.getElementById('webshell-modal-title');
|
||||||
var editIdEl = document.getElementById('webshell-edit-id');
|
var editIdEl = document.getElementById('webshell-edit-id');
|
||||||
if (titleEl) {
|
if (titleEl) {
|
||||||
|
|||||||
@@ -4172,7 +4172,7 @@
|
|||||||
<div class="projects-modal-body">
|
<div class="projects-modal-body">
|
||||||
<div class="projects-form-field">
|
<div class="projects-form-field">
|
||||||
<label for="project-modal-name" data-i18n="projects.projectName">项目名称 <span class="required">*</span></label>
|
<label for="project-modal-name" data-i18n="projects.projectName">项目名称 <span class="required">*</span></label>
|
||||||
<input type="text" id="project-modal-name" class="form-input" placeholder="例如:某客户 Web 渗透" autocomplete="off" data-i18n="projects.projectNamePlaceholder" data-i18n-attr="placeholder">
|
<input type="text" id="project-modal-name" class="form-input" maxlength="200" placeholder="例如:某客户 Web 渗透" autocomplete="off" data-i18n="projects.projectNamePlaceholder" data-i18n-attr="placeholder">
|
||||||
</div>
|
</div>
|
||||||
<div class="projects-form-field">
|
<div class="projects-form-field">
|
||||||
<label for="project-modal-description" data-i18n="projects.projectDescription">项目描述</label>
|
<label for="project-modal-description" data-i18n="projects.projectDescription">项目描述</label>
|
||||||
@@ -4290,6 +4290,7 @@
|
|||||||
<script src="/static/js/i18n.js"></script>
|
<script src="/static/js/i18n.js"></script>
|
||||||
<script src="/static/js/builtin-tools.js"></script>
|
<script src="/static/js/builtin-tools.js"></script>
|
||||||
<script src="/static/js/auth.js"></script>
|
<script src="/static/js/auth.js"></script>
|
||||||
|
<script src="/static/js/modal.js"></script>
|
||||||
<script src="/static/js/notifications.js"></script>
|
<script src="/static/js/notifications.js"></script>
|
||||||
<script src="/static/js/info-collect.js"></script>
|
<script src="/static/js/info-collect.js"></script>
|
||||||
<script src="/static/js/router.js"></script>
|
<script src="/static/js/router.js"></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user