mirror of
https://github.com/Minidoracat/mcp-feedback-enhanced.git
synced 2025-07-27 02:22:26 +08:00
🎨 大幅簡化UI
This commit is contained in:
parent
5f9eb6a42e
commit
7b6b177031
@ -47,7 +47,10 @@
|
||||
"processingFeedback": "Processing, please wait",
|
||||
"connectingMessage": "WebSocket connecting, feedback will be submitted automatically when connection is ready...",
|
||||
"invalidState": "Current state does not allow submission",
|
||||
"sendFailed": "Send failed, please retry"
|
||||
"sendFailed": "Send failed, please retry",
|
||||
"noContent": "No content to copy",
|
||||
"copySuccess": "Content copied to clipboard",
|
||||
"copyFailed": "Failed to copy"
|
||||
},
|
||||
"summary": {
|
||||
"title": "📋 AI Work Summary",
|
||||
@ -321,7 +324,11 @@
|
||||
"latencyMs": "Latency",
|
||||
"sessions": "Sessions",
|
||||
"reconnects": "Reconnects"
|
||||
}
|
||||
},
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"stats": {
|
||||
"detailedStats": "Detailed Statistics"
|
||||
},
|
||||
|
||||
"dynamic": {
|
||||
@ -380,6 +387,7 @@
|
||||
},
|
||||
"about": {
|
||||
"title": "ℹ️ About",
|
||||
"description": "A powerful MCP server that provides human-in-the-loop feedback functionality for AI-assisted development tools. Features a Web UI interface with rich capabilities including image upload, command execution, and multi-language support.",
|
||||
"appInfo": "Application Information",
|
||||
"version": "Version",
|
||||
"projectLinks": "Project Links",
|
||||
|
@ -47,7 +47,10 @@
|
||||
"processingFeedback": "正在处理中,请稍候",
|
||||
"connectingMessage": "WebSocket 连接中,反馈将在连接就绪后自动提交...",
|
||||
"invalidState": "当前状态不允许提交",
|
||||
"sendFailed": "发送失败,请重试"
|
||||
"sendFailed": "发送失败,请重试",
|
||||
"noContent": "没有可复制的内容",
|
||||
"copySuccess": "内容已复制到剪贴板",
|
||||
"copyFailed": "复制失败"
|
||||
},
|
||||
"summary": {
|
||||
"title": "📋 AI 工作摘要",
|
||||
@ -380,6 +383,7 @@
|
||||
},
|
||||
"about": {
|
||||
"title": "ℹ️ 关于",
|
||||
"description": "一个强大的 MCP 服务器,为 AI 辅助开发工具提供人在回路的互动反馈功能。支持 Web UI 界面,并具备图片上传、命令执行、多语言等丰富功能。",
|
||||
"appInfo": "应用程序信息",
|
||||
"version": "版本",
|
||||
"projectLinks": "项目链接",
|
||||
@ -463,5 +467,8 @@
|
||||
"testPlaying": "正在播放测试音效",
|
||||
"audioNotFound": "找不到选择的音效"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"detailedStats": "详细统计信息"
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,10 @@
|
||||
"processingFeedback": "正在處理中,請稍候",
|
||||
"connectingMessage": "WebSocket 連接中,回饋將在連接就緒後自動提交...",
|
||||
"invalidState": "當前狀態不允許提交",
|
||||
"sendFailed": "發送失敗,請重試"
|
||||
"sendFailed": "發送失敗,請重試",
|
||||
"noContent": "沒有可複製的內容",
|
||||
"copySuccess": "內容已複製到剪貼板",
|
||||
"copyFailed": "複製失敗"
|
||||
},
|
||||
"summary": {
|
||||
"title": "📋 AI 工作摘要",
|
||||
@ -385,6 +388,7 @@
|
||||
},
|
||||
"about": {
|
||||
"title": "ℹ️ 關於",
|
||||
"description": "一個強大的 MCP 伺服器,為 AI 輔助開發工具提供人在回路的互動回饋功能。支援 Web UI 介面,並具備圖片上傳、命令執行、多語言等豐富功能。",
|
||||
"appInfo": "應用程式資訊",
|
||||
"version": "版本",
|
||||
"projectLinks": "專案連結",
|
||||
@ -468,5 +472,8 @@
|
||||
"testPlaying": "正在播放測試音效",
|
||||
"audioNotFound": "找不到選擇的音效"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"detailedStats": "詳細統計資訊"
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,86 @@
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
/* 緊湊版頂部欄 */
|
||||
.connection-monitor-bar.compact {
|
||||
padding: 4px 12px;
|
||||
gap: 0;
|
||||
font-size: 12px;
|
||||
height: 32px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
/* 緊湊版元素樣式 */
|
||||
.app-title-compact {
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.info-separator {
|
||||
margin: 0 6px;
|
||||
color: var(--text-secondary);
|
||||
opacity: 0.4;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.project-info-compact,
|
||||
.session-info-compact,
|
||||
.countdown-display-compact,
|
||||
.connection-status-compact {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
white-space: nowrap;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.project-info-compact .project-path-display {
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.session-info-compact .session-id-display {
|
||||
font-size: 11px;
|
||||
padding: 1px 4px;
|
||||
}
|
||||
|
||||
.countdown-display-compact {
|
||||
color: var(--warning-color);
|
||||
}
|
||||
|
||||
.countdown-display-compact .countdown-timer {
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.connection-status-compact {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.connection-status-compact .status-dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.connection-status-compact.connected {
|
||||
color: var(--status-connected);
|
||||
}
|
||||
|
||||
.connection-status-compact.disconnected {
|
||||
color: var(--status-disconnected);
|
||||
}
|
||||
|
||||
.connection-status-compact.connecting {
|
||||
color: var(--status-connecting);
|
||||
}
|
||||
|
||||
/* 應用資訊區域 */
|
||||
.app-info-section {
|
||||
display: flex;
|
||||
@ -648,42 +728,37 @@
|
||||
|
||||
/* ===== 響應式設計 ===== */
|
||||
@media (max-width: 768px) {
|
||||
.connection-monitor-bar {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
/* 緊湊版頂部欄在移動設備上的調整 */
|
||||
.connection-monitor-bar.compact {
|
||||
padding: 4px 10px;
|
||||
font-size: 11px;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.app-info-section {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
/* 隱藏專案路徑以節省空間 */
|
||||
.project-info-compact {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.app-title {
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
/* 隱藏相關的分隔符 */
|
||||
.project-info-compact + .info-separator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.app-title h1 {
|
||||
font-size: 16px;
|
||||
/* 調整標題字體 */
|
||||
.app-title-compact {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.connection-status-group {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
/* 減少分隔符間距 */
|
||||
.info-separator {
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.connection-status-combined {
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.detailed-status-info {
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
/* 確保倒數計時器始終可見 */
|
||||
.countdown-display-compact {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 會話管理頁籤響應式調整 */
|
||||
@ -697,6 +772,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 超小螢幕調整 */
|
||||
@media (max-width: 480px) {
|
||||
/* 隱藏會話 ID */
|
||||
.session-info-compact {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 隱藏相關的分隔符 */
|
||||
.session-info-compact + .info-separator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 保留核心資訊:標題、倒數計時器、連線狀態 */
|
||||
.connection-monitor-bar.compact {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.connection-status-compact {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 載入狀態 ===== */
|
||||
.loading-skeleton {
|
||||
background: linear-gradient(90deg,
|
||||
@ -1204,3 +1301,32 @@
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 響應式設計 - 緊湊版頂部欄 */
|
||||
@media (max-width: 768px) {
|
||||
/* 小螢幕隱藏專案路徑 */
|
||||
.connection-monitor-bar.compact .project-info-compact {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 隱藏相鄰的分隔符 */
|
||||
.connection-monitor-bar.compact .project-info-compact + .info-separator {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
/* 極小螢幕只顯示最關鍵資訊 */
|
||||
.connection-monitor-bar.compact .session-info-compact {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.connection-monitor-bar.compact .session-info-compact + .info-separator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 調整標題字體大小 */
|
||||
.app-title-compact {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +98,114 @@
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* ===== 可折疊統計面板 ===== */
|
||||
.stats-panel-floating {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: var(--bg-secondary);
|
||||
border-top: 1px solid var(--border-color);
|
||||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
|
||||
z-index: 100;
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
/* 收起狀態 */
|
||||
.stats-panel-floating.collapsed {
|
||||
transform: translateY(calc(100% - 40px));
|
||||
}
|
||||
|
||||
/* 統計面板頭部 */
|
||||
.stats-panel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
background: var(--bg-tertiary);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.stats-panel-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.stats-toggle-icon {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.stats-panel-floating.collapsed .stats-toggle-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* 統計面板內容 */
|
||||
.stats-panel-content {
|
||||
padding: 16px 20px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 16px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* 統計項目 */
|
||||
.stats-item-detailed {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding: 12px;
|
||||
background: var(--bg-primary);
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.stats-item-label {
|
||||
font-size: 11px;
|
||||
color: var(--text-secondary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.stats-item-value {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--accent-color);
|
||||
font-family: 'Consolas', 'Monaco', monospace;
|
||||
}
|
||||
|
||||
|
||||
/* 動畫效能優化 */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.stats-panel-floating {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.stats-toggle-icon {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* 響應式設計 */
|
||||
@media (max-width: 768px) {
|
||||
.stats-panel-content {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.stats-item-detailed {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.tooltip:hover::after {
|
||||
opacity: 1;
|
||||
}
|
||||
@ -371,7 +479,7 @@ body {
|
||||
.container {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
padding: 12px;
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
min-height: 100vh;
|
||||
@ -950,7 +1058,7 @@ body {
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
min-height: 0; /* 允許內容自然收縮 */
|
||||
padding: 20px;
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
transition: all 0.6s cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||
background: var(--bg-primary);
|
||||
@ -968,7 +1076,7 @@ body {
|
||||
/* 分頁樣式 */
|
||||
.tabs {
|
||||
border-bottom: 2px solid var(--border-color);
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.tab-buttons {
|
||||
@ -980,7 +1088,7 @@ body {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--text-secondary);
|
||||
padding: 12px 20px;
|
||||
padding: 10px 16px;
|
||||
cursor: pointer;
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: all 0.3s ease;
|
||||
|
@ -314,6 +314,15 @@
|
||||
});
|
||||
}
|
||||
|
||||
// 複製用戶內容按鈕
|
||||
const copyUserFeedback = window.MCPFeedback.Utils.safeQuerySelector('#copyUserFeedback');
|
||||
if (copyUserFeedback) {
|
||||
copyUserFeedback.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
self.copyUserFeedback();
|
||||
});
|
||||
}
|
||||
|
||||
// 快捷鍵
|
||||
document.addEventListener('keydown', function(e) {
|
||||
// Ctrl+Enter 提交回饋
|
||||
@ -1058,8 +1067,14 @@
|
||||
});
|
||||
|
||||
if (success) {
|
||||
// 清空表單
|
||||
this.clearFeedback();
|
||||
// 重置表單狀態但保留文字內容
|
||||
if (this.uiManager) {
|
||||
this.uiManager.resetFeedbackForm(false); // false 表示不清空文字
|
||||
}
|
||||
// 只清空圖片
|
||||
if (this.imageHandler) {
|
||||
this.imageHandler.clearImages();
|
||||
}
|
||||
console.log('📤 回饋已發送,等待服務器確認...');
|
||||
} else {
|
||||
throw new Error('WebSocket 發送失敗');
|
||||
@ -1121,9 +1136,9 @@
|
||||
FeedbackApp.prototype.clearFeedback = function() {
|
||||
console.log('🧹 清空回饋內容...');
|
||||
|
||||
// 使用 UI 管理器重置表單
|
||||
// 使用 UI 管理器重置表單,並清空文字
|
||||
if (this.uiManager) {
|
||||
this.uiManager.resetFeedbackForm();
|
||||
this.uiManager.resetFeedbackForm(true); // 傳入 true 表示要清空文字
|
||||
}
|
||||
|
||||
// 清空圖片數據
|
||||
@ -1134,6 +1149,57 @@
|
||||
console.log('✅ 回饋內容清空完成');
|
||||
};
|
||||
|
||||
/**
|
||||
* 複製用戶回饋內容
|
||||
*/
|
||||
FeedbackApp.prototype.copyUserFeedback = function() {
|
||||
console.log('📋 複製用戶回饋內容...');
|
||||
|
||||
const feedbackInput = window.MCPFeedback.Utils.safeQuerySelector('#combinedFeedbackText');
|
||||
if (!feedbackInput || !feedbackInput.value.trim()) {
|
||||
window.MCPFeedback.Utils.showMessage(
|
||||
window.i18nManager ? window.i18nManager.t('feedback.noContent') : '沒有可複製的內容',
|
||||
window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const textContent = feedbackInput.value;
|
||||
|
||||
// 複製到剪貼板
|
||||
navigator.clipboard.writeText(textContent)
|
||||
.then(function() {
|
||||
console.log('✅ 內容已複製到剪貼板');
|
||||
window.MCPFeedback.Utils.showMessage(
|
||||
window.i18nManager ? window.i18nManager.t('feedback.copySuccess') : '內容已複製到剪貼板',
|
||||
window.MCPFeedback.Utils.CONSTANTS.MESSAGE_SUCCESS
|
||||
);
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.error('❌ 複製失敗:', err);
|
||||
// 降級方案:使用舊的複製方法
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = textContent;
|
||||
textarea.style.position = 'fixed';
|
||||
textarea.style.left = '-999999px';
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
window.MCPFeedback.Utils.showMessage(
|
||||
window.i18nManager ? window.i18nManager.t('feedback.copySuccess') : '內容已複製到剪貼板',
|
||||
window.MCPFeedback.Utils.CONSTANTS.MESSAGE_SUCCESS
|
||||
);
|
||||
} catch (error) {
|
||||
window.MCPFeedback.Utils.showMessage(
|
||||
window.i18nManager ? window.i18nManager.t('feedback.copyFailed') : '複製失敗',
|
||||
window.MCPFeedback.Utils.CONSTANTS.MESSAGE_ERROR
|
||||
);
|
||||
}
|
||||
document.body.removeChild(textarea);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消回饋
|
||||
*/
|
||||
@ -1298,7 +1364,7 @@
|
||||
if (self.uiManager) {
|
||||
// console.log('🔧 準備更新 AI 摘要內容,summary 長度:', sessionData.summary ? sessionData.summary.length : 'undefined');
|
||||
self.uiManager.updateAISummaryContent(sessionData.summary);
|
||||
self.uiManager.resetFeedbackForm();
|
||||
self.uiManager.resetFeedbackForm(false); // 不清空文字內容
|
||||
self.uiManager.updateStatusIndicator();
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,36 @@
|
||||
indicator.className = 'connection-indicator ' + status;
|
||||
}
|
||||
|
||||
// 更新精簡的頂部狀態指示器(現在是緊湊版)
|
||||
const minimalIndicator = document.getElementById('connectionStatusMinimal');
|
||||
if (minimalIndicator) {
|
||||
minimalIndicator.className = 'connection-status-compact ' + status;
|
||||
const statusText = minimalIndicator.querySelector('.status-text');
|
||||
if (statusText) {
|
||||
let statusKey = '';
|
||||
switch (status) {
|
||||
case 'connected':
|
||||
statusKey = 'connectionMonitor.connected';
|
||||
break;
|
||||
case 'connecting':
|
||||
statusKey = 'connectionMonitor.connecting';
|
||||
break;
|
||||
case 'disconnected':
|
||||
statusKey = 'connectionMonitor.disconnected';
|
||||
break;
|
||||
case 'reconnecting':
|
||||
statusKey = 'connectionMonitor.reconnecting';
|
||||
break;
|
||||
default:
|
||||
statusKey = 'connectionMonitor.unknown';
|
||||
}
|
||||
statusText.setAttribute('data-i18n', statusKey);
|
||||
if (window.i18nManager) {
|
||||
statusText.textContent = window.i18nManager.t(statusKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 處理特殊狀態
|
||||
switch (status) {
|
||||
case 'connected':
|
||||
@ -282,15 +312,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 更新統計面板中的延遲顯示
|
||||
const statsLatency = document.getElementById('statsLatency');
|
||||
if (statsLatency) {
|
||||
statsLatency.textContent = this.currentLatency > 0 ? this.currentLatency + 'ms' : '--ms';
|
||||
}
|
||||
|
||||
// 更新連線時間
|
||||
if (this.connectionTimeDisplay && this.connectionStartTime) {
|
||||
let connectionTimeStr = '--:--';
|
||||
if (this.connectionStartTime) {
|
||||
const duration = Math.floor((Date.now() - this.connectionStartTime) / 1000);
|
||||
const minutes = Math.floor(duration / 60);
|
||||
const seconds = duration % 60;
|
||||
connectionTimeStr = String(minutes).padStart(2, '0') + ':' + String(seconds).padStart(2, '0');
|
||||
}
|
||||
|
||||
if (this.connectionTimeDisplay) {
|
||||
const connectionTimeLabel = window.i18nManager ? window.i18nManager.t('connectionMonitor.connectionTime') : '連線時間';
|
||||
this.connectionTimeDisplay.textContent = connectionTimeLabel + ': ' +
|
||||
String(minutes).padStart(2, '0') + ':' +
|
||||
String(seconds).padStart(2, '0');
|
||||
this.connectionTimeDisplay.textContent = connectionTimeLabel + ': ' + connectionTimeStr;
|
||||
}
|
||||
|
||||
// 更新統計面板中的連線時間
|
||||
const statsConnectionTime = document.getElementById('statsConnectionTime');
|
||||
if (statsConnectionTime) {
|
||||
statsConnectionTime.textContent = connectionTimeStr;
|
||||
}
|
||||
|
||||
// 更新重連次數
|
||||
@ -300,10 +345,35 @@
|
||||
this.reconnectCountDisplay.textContent = reconnectLabel + ': ' + this.reconnectCount + ' ' + timesLabel;
|
||||
}
|
||||
|
||||
// 更新統計面板中的重連次數
|
||||
const statsReconnectCount = document.getElementById('statsReconnectCount');
|
||||
if (statsReconnectCount) {
|
||||
statsReconnectCount.textContent = this.reconnectCount.toString();
|
||||
}
|
||||
|
||||
// 更新訊息計數
|
||||
if (this.messageCountDisplay) {
|
||||
this.messageCountDisplay.textContent = this.messageCount;
|
||||
}
|
||||
|
||||
// 更新統計面板中的訊息計數
|
||||
const statsMessageCount = document.getElementById('statsMessageCount');
|
||||
if (statsMessageCount) {
|
||||
statsMessageCount.textContent = this.messageCount.toString();
|
||||
}
|
||||
|
||||
// 更新統計面板中的會話數和狀態
|
||||
const sessionCount = document.getElementById('sessionCount');
|
||||
const statsSessionCount = document.getElementById('statsSessionCount');
|
||||
if (sessionCount && statsSessionCount) {
|
||||
statsSessionCount.textContent = sessionCount.textContent;
|
||||
}
|
||||
|
||||
const sessionStatusText = document.getElementById('sessionStatusText');
|
||||
const statsSessionStatus = document.getElementById('statsSessionStatus');
|
||||
if (sessionStatusText && statsSessionStatus) {
|
||||
statsSessionStatus.textContent = sessionStatusText.textContent;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -482,14 +482,18 @@
|
||||
|
||||
/**
|
||||
* 重置回饋表單
|
||||
* @param {boolean} clearText - 是否清空文字內容,預設為 false
|
||||
*/
|
||||
UIManager.prototype.resetFeedbackForm = function() {
|
||||
UIManager.prototype.resetFeedbackForm = function(clearText) {
|
||||
console.log('🔄 重置回饋表單...');
|
||||
|
||||
// 清空回饋輸入
|
||||
// 根據參數決定是否清空回饋輸入
|
||||
const feedbackInput = Utils.safeQuerySelector('#combinedFeedbackText');
|
||||
if (feedbackInput) {
|
||||
if (clearText === true) {
|
||||
feedbackInput.value = '';
|
||||
console.log('📝 已清空文字內容');
|
||||
}
|
||||
feedbackInput.disabled = false;
|
||||
}
|
||||
|
||||
|
@ -396,85 +396,51 @@
|
||||
</style>
|
||||
</head>
|
||||
<body class="layout-{{ layout_mode }}">
|
||||
<!-- ===== 頂部連線監控狀態列 ===== -->
|
||||
<div class="connection-monitor-bar">
|
||||
<!-- 左側:應用標題和專案資訊 -->
|
||||
<div class="app-info-section">
|
||||
<div class="app-title">
|
||||
<h1 data-i18n="app.title">MCP Feedback Enhanced</h1>
|
||||
<!-- ===== 頂部連線監控狀態列(緊湊版) ===== -->
|
||||
<div class="connection-monitor-bar compact">
|
||||
<!-- 標題 -->
|
||||
<div class="app-title-compact">
|
||||
<span data-i18n="app.title">MCP Feedback</span>
|
||||
</div>
|
||||
<div class="project-info">
|
||||
📂 <span data-i18n="app.projectDirectory">專案目錄</span>:
|
||||
|
||||
<!-- 分隔符 -->
|
||||
<span class="info-separator">·</span>
|
||||
|
||||
<!-- 專案路徑 -->
|
||||
<div class="project-info-compact">
|
||||
<span>📂</span>
|
||||
<span id="projectPathDisplay" class="project-path-display"
|
||||
data-full-path="{{ project_directory }}"
|
||||
data-i18n-title="app.clickToCopyPath"
|
||||
title="點擊複製完整路徑">{{ project_directory }}</span>
|
||||
</div>
|
||||
title="點擊複製完整路徑">{{ project_directory[-30:] if project_directory|length > 30 else project_directory }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 中間:連線狀態資訊 -->
|
||||
<div class="connection-status-group">
|
||||
<!-- 左側:會話狀態資訊 -->
|
||||
<div class="session-status-info">
|
||||
<div class="current-session-info">
|
||||
<span class="session-indicator">
|
||||
📋 <span data-i18n="sessionManagement.currentSession">當前會話</span>:
|
||||
<!-- 分隔符 -->
|
||||
<span class="info-separator">·</span>
|
||||
|
||||
<!-- 會話 ID -->
|
||||
<div class="session-info-compact">
|
||||
<span>📋</span>
|
||||
<span id="currentSessionId" class="session-id-display"
|
||||
data-full-id="{{ session_id if session_id else 'loading' }}"
|
||||
data-i18n-title="app.clickToCopySessionId"
|
||||
title="點擊複製完整會話ID">{{ session_id[:8] if session_id else 'loading' }}...</span>
|
||||
</span>
|
||||
<span class="session-age">
|
||||
<span data-i18n="sessionManagement.activeTime">活躍時間</span>: <span id="sessionAge">--</span>
|
||||
</span>
|
||||
</div>
|
||||
title="點擊複製完整會話ID">{{ session_id[:6] if session_id else '--' }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 倒數計時器顯示 -->
|
||||
<div id="countdownDisplay" class="countdown-display" style="display: none;">
|
||||
<span class="countdown-label" data-i18n="autoSubmit.countdownLabel">提交倒數</span>
|
||||
<!-- 倒數計時器(條件顯示) -->
|
||||
<div id="countdownDisplay" class="countdown-display-compact" style="display: none;">
|
||||
<span class="info-separator">·</span>
|
||||
<span>⏱️</span>
|
||||
<span id="countdownTimer" class="countdown-timer">--:--</span>
|
||||
</div>
|
||||
|
||||
<!-- 主要連線狀態 -->
|
||||
<div class="connection-indicator connecting" id="mainConnectionStatus">
|
||||
<div class="status-icon pulse"></div>
|
||||
<span class="status-text" data-i18n="connectionMonitor.connecting">連接中...</span>
|
||||
<div class="connection-quality">
|
||||
<div class="latency-indicator"><span data-i18n="connectionMonitor.latency">延遲</span>: --ms</div>
|
||||
<div class="signal-strength">
|
||||
<div class="signal-bar"></div>
|
||||
<div class="signal-bar"></div>
|
||||
<div class="signal-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分隔符 -->
|
||||
<span class="info-separator">·</span>
|
||||
|
||||
<!-- 連線和狀態資訊組合 -->
|
||||
<div class="connection-status-combined">
|
||||
<!-- 連線詳細資訊 -->
|
||||
<div class="connection-details">
|
||||
<span class="connection-time"><span data-i18n="connectionMonitor.connectionTime">連線時間</span>: --:--</span>
|
||||
<span class="reconnect-count"><span data-i18n="connectionMonitor.reconnectCount">重連</span>: 0 <span data-i18n="connectionMonitor.times">次</span></span>
|
||||
</div>
|
||||
|
||||
<!-- 詳細狀態資訊 -->
|
||||
<div class="detailed-status-info">
|
||||
<div class="websocket-metrics">
|
||||
<span class="metric"><span data-i18n="connectionMonitor.metrics.messages">訊息</span>: <span id="messageCount">0</span></span>
|
||||
<span class="metric"><span data-i18n="connectionMonitor.metrics.latencyMs">延遲</span>: <span id="latencyDisplay">--ms</span></span>
|
||||
</div>
|
||||
<div class="session-metrics">
|
||||
<span class="metric"><span data-i18n="connectionMonitor.metrics.sessions">會話</span>: <span id="sessionCount">1</span></span>
|
||||
<span class="metric"><span data-i18n="connectionMonitor.statusText">狀態</span>: <span id="sessionStatusText" data-i18n="connectionMonitor.waiting">等待中</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右側:快速操作 -->
|
||||
<div class="quick-actions">
|
||||
<!-- 保留空間以保持佈局平衡 -->
|
||||
<!-- 連線狀態 -->
|
||||
<div class="connection-status-compact" id="connectionStatusMinimal">
|
||||
<span class="status-dot"></span>
|
||||
<span class="status-text" data-i18n="connectionMonitor.connected">已連線</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -517,10 +483,6 @@
|
||||
|
||||
<!-- ===== AI 摘要分頁 ===== -->
|
||||
<div id="tab-summary" class="tab-content">
|
||||
<div class="section-description" data-i18n="summary.description">
|
||||
以下是 AI 助手完成的工作摘要,請仔細查看並提供您的回饋意見。
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<div id="summaryContent" class="text-input" style="min-height: 300px; cursor: text; padding: 12px; line-height: 1.6; word-wrap: break-word; overflow-wrap: break-word;" data-dynamic-content="aiSummary">
|
||||
{{ summary }}
|
||||
@ -579,29 +541,9 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 等待回饋狀態指示器 -->
|
||||
{% set id = "combinedFeedbackStatusIndicator" %}
|
||||
{% set status = "waiting" %}
|
||||
{% set icon = "⏳" %}
|
||||
{% set title = "等待回饋" %}
|
||||
{% set message = "請提供您的回饋意見" %}
|
||||
{% include 'components/status-indicator.html' %}
|
||||
|
||||
<div class="input-group">
|
||||
<label class="input-label" data-i18n="feedback.textLabel">文字回饋</label>
|
||||
|
||||
<!-- 提示詞按鈕 -->
|
||||
<div class="prompt-input-buttons" id="combinedPromptButtons">
|
||||
<button type="button" class="prompt-input-btn select-prompt-btn" data-container-index="1">
|
||||
<span>📝</span>
|
||||
<span class="button-text" data-i18n="prompts.buttons.selectPrompt">Templates</span>
|
||||
</button>
|
||||
<button type="button" class="prompt-input-btn last-prompt-btn" data-container-index="1">
|
||||
<span>🔄</span>
|
||||
<span class="button-text" data-i18n="prompts.buttons.useLastPrompt">Last Used</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
id="combinedFeedbackText"
|
||||
class="text-input"
|
||||
@ -613,6 +555,22 @@
|
||||
• 按 Ctrl+V/Cmd+V 可直接貼上剪貼板圖片"
|
||||
style="min-height: 150px;"
|
||||
></textarea>
|
||||
|
||||
<!-- 提示詞按鈕 - 移至輸入框下方 -->
|
||||
<div class="prompt-input-buttons" id="combinedPromptButtons" style="margin-top: 8px;">
|
||||
<button type="button" class="prompt-input-btn select-prompt-btn" data-container-index="1">
|
||||
<span>📝</span>
|
||||
<span class="button-text" data-i18n="prompts.buttons.selectPrompt">Templates</span>
|
||||
</button>
|
||||
<button type="button" class="prompt-input-btn last-prompt-btn" data-container-index="1">
|
||||
<span>🔄</span>
|
||||
<span class="button-text" data-i18n="prompts.buttons.useLastPrompt">Last Used</span>
|
||||
</button>
|
||||
<button type="button" class="prompt-input-btn copy-user-content-btn" id="copyUserFeedback">
|
||||
<span>📋</span>
|
||||
<span class="button-text" data-i18n="sessionManagement.copyUserContent">複製用戶內容</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 圖片上傳組件 -->
|
||||
@ -998,7 +956,6 @@
|
||||
<div class="setting-item" style="border-bottom: none; padding-bottom: 16px;">
|
||||
<div class="setting-info">
|
||||
<div class="setting-description" data-i18n="about.description" style="color: var(--text-secondary); font-size: 13px; line-height: 1.5;">
|
||||
一個強大的 MCP 伺服器,為 AI 輔助開發工具提供人在回路的互動回饋功能。支援 Web UI 介面,並具備圖片上傳、命令執行、多語言等豐富功能。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1203,5 +1160,53 @@
|
||||
initializeApp();
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- 可折疊統計面板 -->
|
||||
<div class="stats-panel-floating collapsed" id="statsPanel">
|
||||
<div class="stats-panel-header" onclick="toggleStatsPanel()">
|
||||
<div class="stats-panel-title">
|
||||
<span>📊</span>
|
||||
<span data-i18n="stats.detailedStats">詳細統計資訊</span>
|
||||
</div>
|
||||
<span class="stats-toggle-icon">▲</span>
|
||||
</div>
|
||||
<div class="stats-panel-content">
|
||||
<!-- 連線資訊 -->
|
||||
<div class="stats-item-detailed">
|
||||
<span class="stats-item-label" data-i18n="connectionMonitor.connectionTime">連線時間</span>
|
||||
<span class="stats-item-value" id="statsConnectionTime">--:--</span>
|
||||
</div>
|
||||
<div class="stats-item-detailed">
|
||||
<span class="stats-item-label" data-i18n="connectionMonitor.reconnectCount">重連次數</span>
|
||||
<span class="stats-item-value" id="statsReconnectCount">0</span>
|
||||
</div>
|
||||
<!-- WebSocket 統計 -->
|
||||
<div class="stats-item-detailed">
|
||||
<span class="stats-item-label" data-i18n="connectionMonitor.metrics.messages">訊息數</span>
|
||||
<span class="stats-item-value" id="statsMessageCount">0</span>
|
||||
</div>
|
||||
<div class="stats-item-detailed">
|
||||
<span class="stats-item-label" data-i18n="connectionMonitor.metrics.latencyMs">延遲</span>
|
||||
<span class="stats-item-value" id="statsLatency">--ms</span>
|
||||
</div>
|
||||
<!-- 會話統計 -->
|
||||
<div class="stats-item-detailed">
|
||||
<span class="stats-item-label" data-i18n="connectionMonitor.metrics.sessions">會話數</span>
|
||||
<span class="stats-item-value" id="statsSessionCount">1</span>
|
||||
</div>
|
||||
<div class="stats-item-detailed">
|
||||
<span class="stats-item-label" data-i18n="connectionMonitor.statusText">狀態</span>
|
||||
<span class="stats-item-value" id="statsSessionStatus" data-i18n="connectionMonitor.waiting">等待中</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 統計面板切換功能
|
||||
function toggleStatsPanel() {
|
||||
const panel = document.getElementById('statsPanel');
|
||||
panel.classList.toggle('collapsed');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
x
Reference in New Issue
Block a user