mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-03-31 16:20:28 +02:00
Add files via upload
This commit is contained in:
@@ -449,8 +449,8 @@ header {
|
||||
|
||||
.message.system .message-content {
|
||||
max-width: 90%;
|
||||
align-items: center;
|
||||
margin: 0 auto;
|
||||
align-items: stretch;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.message-bubble {
|
||||
@@ -611,7 +611,7 @@ header {
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--text-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
text-align: center;
|
||||
text-align: left;
|
||||
font-size: 0.875rem;
|
||||
padding: 10px 16px;
|
||||
width: 100%;
|
||||
@@ -1148,42 +1148,135 @@ header {
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
margin-bottom: 24px;
|
||||
margin-bottom: 20px;
|
||||
background: var(--bg-primary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 14px;
|
||||
padding: 20px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.detail-section:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.detail-section-overview {
|
||||
background: linear-gradient(135deg, rgba(0, 102, 255, 0.07), rgba(0, 102, 255, 0.02));
|
||||
border-color: rgba(0, 102, 255, 0.2);
|
||||
}
|
||||
|
||||
.detail-section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.detail-section h3 {
|
||||
margin: 0;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
font-size: 0.9375rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.detail-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.detail-info-grid .detail-item {
|
||||
background: var(--bg-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 12px;
|
||||
padding: 12px 14px;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
margin-bottom: 10px;
|
||||
padding: 8px 0;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.detail-item strong {
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
font-size: 0.875rem;
|
||||
min-width: 80px;
|
||||
font-weight: 600;
|
||||
font-size: 0.75rem;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.detail-item span {
|
||||
color: var(--text-primary);
|
||||
font-size: 0.875rem;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.mono-text {
|
||||
font-family: 'SF Mono', 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.status-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4px 12px;
|
||||
border-radius: 999px;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--text-secondary);
|
||||
border: 1px solid transparent;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.status-chip.status-running {
|
||||
background: rgba(0, 102, 255, 0.12);
|
||||
color: var(--accent-color);
|
||||
border-color: rgba(0, 102, 255, 0.3);
|
||||
}
|
||||
|
||||
.status-chip.status-completed {
|
||||
background: rgba(40, 167, 69, 0.12);
|
||||
color: var(--success-color);
|
||||
border-color: rgba(40, 167, 69, 0.3);
|
||||
}
|
||||
|
||||
.status-chip.status-failed {
|
||||
background: rgba(220, 53, 69, 0.12);
|
||||
color: var(--error-color);
|
||||
border-color: rgba(220, 53, 69, 0.3);
|
||||
}
|
||||
|
||||
.status-chip.status-pending,
|
||||
.status-chip.status-unknown {
|
||||
background: rgba(255, 193, 7, 0.12);
|
||||
color: #b8860b;
|
||||
border-color: rgba(255, 193, 7, 0.3);
|
||||
}
|
||||
|
||||
.detail-code-card {
|
||||
background: var(--bg-secondary);
|
||||
border: 1px dashed rgba(0, 0, 0, 0.06);
|
||||
border-radius: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.detail-code-card .code-block {
|
||||
margin: 0;
|
||||
max-height: 360px;
|
||||
}
|
||||
|
||||
.detail-error-wrapper {
|
||||
border-color: rgba(220, 53, 69, 0.4);
|
||||
background: rgba(220, 53, 69, 0.05);
|
||||
}
|
||||
|
||||
.code-block {
|
||||
@@ -1208,6 +1301,24 @@ header {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
padding: 6px 14px;
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
color: var(--accent-color);
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-ghost:hover {
|
||||
background: rgba(0, 102, 255, 0.08);
|
||||
border-color: rgba(0, 102, 255, 0.2);
|
||||
color: var(--accent-hover);
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
|
||||
@@ -829,8 +829,13 @@ async function showMCPDetail(executionId) {
|
||||
// 填充模态框内容
|
||||
document.getElementById('detail-tool-name').textContent = exec.toolName || 'Unknown';
|
||||
document.getElementById('detail-execution-id').textContent = exec.id || 'N/A';
|
||||
document.getElementById('detail-status').textContent = getStatusText(exec.status);
|
||||
document.getElementById('detail-time').textContent = new Date(exec.startTime).toLocaleString('zh-CN');
|
||||
const statusEl = document.getElementById('detail-status');
|
||||
const normalizedStatus = (exec.status || 'unknown').toLowerCase();
|
||||
statusEl.textContent = getStatusText(exec.status);
|
||||
statusEl.className = `status-chip status-${normalizedStatus}`;
|
||||
document.getElementById('detail-time').textContent = exec.startTime
|
||||
? new Date(exec.startTime).toLocaleString('zh-CN')
|
||||
: '—';
|
||||
|
||||
// 请求参数
|
||||
const requestData = {
|
||||
@@ -874,6 +879,75 @@ function closeMCPDetail() {
|
||||
document.getElementById('mcp-detail-modal').style.display = 'none';
|
||||
}
|
||||
|
||||
// 复制详情面板中的内容
|
||||
function copyDetailBlock(elementId, triggerBtn = null) {
|
||||
const target = document.getElementById(elementId);
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
const text = target.textContent || '';
|
||||
if (!text.trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const originalLabel = triggerBtn ? (triggerBtn.dataset.originalLabel || triggerBtn.textContent.trim()) : '';
|
||||
if (triggerBtn && !triggerBtn.dataset.originalLabel) {
|
||||
triggerBtn.dataset.originalLabel = originalLabel;
|
||||
}
|
||||
|
||||
const showCopiedState = () => {
|
||||
if (!triggerBtn) {
|
||||
return;
|
||||
}
|
||||
triggerBtn.textContent = '已复制';
|
||||
triggerBtn.disabled = true;
|
||||
setTimeout(() => {
|
||||
triggerBtn.disabled = false;
|
||||
triggerBtn.textContent = triggerBtn.dataset.originalLabel || originalLabel || '复制';
|
||||
}, 1200);
|
||||
};
|
||||
|
||||
const fallbackCopy = (value) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = value;
|
||||
textarea.style.position = 'fixed';
|
||||
textarea.style.opacity = '0';
|
||||
document.body.appendChild(textarea);
|
||||
textarea.focus();
|
||||
textarea.select();
|
||||
try {
|
||||
const successful = document.execCommand('copy');
|
||||
document.body.removeChild(textarea);
|
||||
if (successful) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error('execCommand failed'));
|
||||
}
|
||||
} catch (err) {
|
||||
document.body.removeChild(textarea);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const copyPromise = (navigator.clipboard && typeof navigator.clipboard.writeText === 'function')
|
||||
? navigator.clipboard.writeText(text)
|
||||
: fallbackCopy(text);
|
||||
|
||||
copyPromise
|
||||
.then(() => {
|
||||
showCopiedState();
|
||||
})
|
||||
.catch(() => {
|
||||
if (triggerBtn) {
|
||||
triggerBtn.disabled = false;
|
||||
triggerBtn.textContent = triggerBtn.dataset.originalLabel || originalLabel || '复制';
|
||||
}
|
||||
alert('复制失败,请手动选择文本复制。');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 开始新对话
|
||||
function startNewConversation() {
|
||||
|
||||
@@ -237,32 +237,55 @@
|
||||
<span class="modal-close" onclick="closeMCPDetail()">×</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="detail-section">
|
||||
<h3>执行信息</h3>
|
||||
<div class="detail-item">
|
||||
<strong>工具:</strong> <span id="detail-tool-name"></span>
|
||||
<div class="detail-section detail-section-overview">
|
||||
<div class="detail-section-header">
|
||||
<h3>执行信息</h3>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<strong>状态:</strong> <span id="detail-status"></span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<strong>时间:</strong> <span id="detail-time"></span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<strong>ID:</strong> <span id="detail-execution-id" style="font-family: monospace; font-size: 0.8125rem; color: var(--text-secondary);"></span>
|
||||
<div class="detail-info-grid">
|
||||
<div class="detail-item">
|
||||
<strong>工具</strong>
|
||||
<span id="detail-tool-name"></span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<strong>状态</strong>
|
||||
<span id="detail-status" class="status-chip status-unknown"></span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<strong>时间</strong>
|
||||
<span id="detail-time"></span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<strong>执行 ID</strong>
|
||||
<span id="detail-execution-id" class="mono-text"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section">
|
||||
<h3>请求参数</h3>
|
||||
<pre id="detail-request" class="code-block"></pre>
|
||||
<div class="detail-section-header">
|
||||
<h3>请求参数</h3>
|
||||
<button class="btn-ghost" type="button" onclick="copyDetailBlock('detail-request', this)">复制 JSON</button>
|
||||
</div>
|
||||
<div class="detail-code-card">
|
||||
<pre id="detail-request" class="code-block"></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section">
|
||||
<h3>响应结果</h3>
|
||||
<pre id="detail-response" class="code-block"></pre>
|
||||
<div class="detail-section-header">
|
||||
<h3>响应结果</h3>
|
||||
<button class="btn-ghost" type="button" onclick="copyDetailBlock('detail-response', this)">复制内容</button>
|
||||
</div>
|
||||
<div class="detail-code-card">
|
||||
<pre id="detail-response" class="code-block"></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section" id="detail-error-section" style="display: none;">
|
||||
<h3>错误信息</h3>
|
||||
<pre id="detail-error" class="code-block error"></pre>
|
||||
<div class="detail-section detail-error-wrapper" id="detail-error-section" style="display: none;">
|
||||
<div class="detail-section-header">
|
||||
<h3>错误信息</h3>
|
||||
<button class="btn-ghost" type="button" onclick="copyDetailBlock('detail-error', this)">复制错误</button>
|
||||
</div>
|
||||
<div class="detail-code-card">
|
||||
<pre id="detail-error" class="code-block error"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user