From 48c0232f5737d129a392bdd7d2a9fcf87557f4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AC=E6=98=8E?= <83812544+Ed1s0nZ@users.noreply.github.com> Date: Tue, 25 Nov 2025 21:24:03 +0800 Subject: [PATCH] Add files via upload --- web/static/css/style.css | 145 ++++++++++++++++++++++++++++++++++----- web/static/js/chat.js | 78 ++++++++++++++++++++- web/templates/index.html | 61 +++++++++++----- 3 files changed, 246 insertions(+), 38 deletions(-) diff --git a/web/static/css/style.css b/web/static/css/style.css index a64879bc..f80d2a57 100644 --- a/web/static/css/style.css +++ b/web/static/css/style.css @@ -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; diff --git a/web/static/js/chat.js b/web/static/js/chat.js index d9d3b860..ee4cc9ab 100644 --- a/web/static/js/chat.js +++ b/web/static/js/chat.js @@ -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() { diff --git a/web/templates/index.html b/web/templates/index.html index 4c3b7008..e5462d07 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -237,32 +237,55 @@ ×