mirror of
https://github.com/Minidoracat/mcp-feedback-enhanced.git
synced 2025-07-27 10:42:25 +08:00
✨ 補充多語系文本
This commit is contained in:
parent
01acf5ee62
commit
82a7473f85
@ -2,7 +2,8 @@
|
||||
"app": {
|
||||
"title": "MCP Interactive Feedback System",
|
||||
"subtitle": "AI Assistant Interactive Feedback Platform",
|
||||
"projectDirectory": "Project Directory"
|
||||
"projectDirectory": "Project Directory",
|
||||
"updateFailed": "Failed to update content, please manually refresh the page to view new AI work summary"
|
||||
},
|
||||
"tabs": {
|
||||
"feedback": "💬 Feedback",
|
||||
@ -32,7 +33,15 @@
|
||||
"submit": "Ctrl+Enter to submit (Cmd+Enter on Mac, numpad supported)",
|
||||
"clear": "Ctrl+Delete to clear (Cmd+Delete on Mac)",
|
||||
"paste": "Ctrl+V to paste images (Cmd+V on Mac)"
|
||||
}
|
||||
},
|
||||
"submitSuccess": "Feedback submitted successfully!",
|
||||
"submittedWaiting": "Feedback submitted, waiting for next MCP call...",
|
||||
"waitingForUser": "Waiting for user feedback...",
|
||||
"alreadySubmitted": "Feedback already submitted, please wait for next MCP call",
|
||||
"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"
|
||||
},
|
||||
"summary": {
|
||||
"title": "📋 AI Work Summary",
|
||||
@ -55,7 +64,11 @@
|
||||
"running": "Running...",
|
||||
"completed": "Completed",
|
||||
"error": "Execution Error",
|
||||
"history": "Command History"
|
||||
"history": "Command History",
|
||||
"notConnected": "WebSocket not connected, cannot execute command",
|
||||
"emptyCommand": "Please enter a command",
|
||||
"sendFailed": "Failed to send command",
|
||||
"executing": "Executing..."
|
||||
},
|
||||
"command": {
|
||||
"title": "⚡ Command Execution",
|
||||
@ -179,6 +192,69 @@
|
||||
"detected": "Detected",
|
||||
"error": "Failed"
|
||||
},
|
||||
"sessionManagement": {
|
||||
"title": "Session Management",
|
||||
"currentSession": "Current Session",
|
||||
"sessionHistory": "Session History",
|
||||
"statistics": "Statistics",
|
||||
"sessionId": "Session ID",
|
||||
"status": "Status",
|
||||
"activeTime": "Active Time",
|
||||
"switchSession": "Switch Session",
|
||||
"viewDetails": "View Details",
|
||||
"refresh": "Refresh",
|
||||
"noHistory": "No session history",
|
||||
"todaySessions": "Today's Sessions",
|
||||
"averageDuration": "Average Duration",
|
||||
"createdTime": "Created Time",
|
||||
"project": "Project",
|
||||
"aiSummary": "AI Summary",
|
||||
"noSummary": "No summary",
|
||||
"loading": "Loading...",
|
||||
"collapsePanel": "Collapse Panel",
|
||||
"expandPanel": "Expand Panel",
|
||||
"sessionPanel": "Session",
|
||||
"sessionDetails": {
|
||||
"title": "Session Details",
|
||||
"close": "Close",
|
||||
"duration": "Duration",
|
||||
"projectDirectory": "Project Directory",
|
||||
"summary": "Summary",
|
||||
"noSummary": "No summary available",
|
||||
"unknown": "Unknown"
|
||||
}
|
||||
},
|
||||
"connectionMonitor": {
|
||||
"connecting": "Connecting...",
|
||||
"connected": "Connected",
|
||||
"disconnected": "Disconnected",
|
||||
"reconnecting": "Reconnecting... (attempt {attempt})",
|
||||
"connectionFailed": "Connection failed",
|
||||
"connectionError": "Connection error",
|
||||
"noActiveSession": "No active session",
|
||||
"maxReconnectReached": "WebSocket connection failed, please refresh the page to retry",
|
||||
"latency": "Latency",
|
||||
"connectionTime": "Connection Time",
|
||||
"reconnectCount": "Reconnects",
|
||||
"messageCount": "Messages",
|
||||
"sessionCount": "Sessions",
|
||||
"statusText": "Status",
|
||||
"waiting": "Waiting",
|
||||
"times": "times",
|
||||
"quality": {
|
||||
"excellent": "Excellent",
|
||||
"good": "Good",
|
||||
"fair": "Fair",
|
||||
"poor": "Poor",
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"metrics": {
|
||||
"messages": "Messages",
|
||||
"latencyMs": "Latency",
|
||||
"sessions": "Sessions",
|
||||
"reconnects": "Reconnects"
|
||||
}
|
||||
},
|
||||
|
||||
"dynamic": {
|
||||
"aiSummary": "Test Web UI Functionality\n\n🎯 **Test Items:**\n- Web UI server startup and operation\n- WebSocket real-time communication\n- Feedback submission functionality\n- Image upload and preview\n- Command execution functionality\n- Smart Ctrl+V image pasting\n- Multi-language interface functionality\n\n📋 **Test Steps:**\n1. Test image upload (drag-drop, file selection, clipboard)\n2. Press Ctrl+V in text box to test smart pasting\n3. Try switching languages (Traditional Chinese/Simplified Chinese/English)\n4. Test command execution functionality\n5. Submit feedback and images\n\nPlease test these features and provide feedback!",
|
||||
|
@ -2,7 +2,8 @@
|
||||
"app": {
|
||||
"title": "MCP 交互反馈系统",
|
||||
"subtitle": "AI 助手交互反馈平台",
|
||||
"projectDirectory": "项目目录"
|
||||
"projectDirectory": "项目目录",
|
||||
"updateFailed": "更新内容失败,请手动刷新页面以查看新的 AI 工作摘要"
|
||||
},
|
||||
"tabs": {
|
||||
"feedback": "💬 反馈",
|
||||
@ -32,7 +33,15 @@
|
||||
"submit": "Ctrl+Enter 提交 (Mac 用 Cmd+Enter,支持数字键盘)",
|
||||
"clear": "Ctrl+Delete 清除 (Mac 用 Cmd+Delete)",
|
||||
"paste": "Ctrl+V 粘贴图片 (Mac 用 Cmd+V)"
|
||||
}
|
||||
},
|
||||
"submitSuccess": "反馈提交成功!",
|
||||
"submittedWaiting": "已送出反馈,等待下次 MCP 调用...",
|
||||
"waitingForUser": "等待用户反馈...",
|
||||
"alreadySubmitted": "反馈已提交,请等待下次 MCP 调用",
|
||||
"processingFeedback": "正在处理中,请稍候",
|
||||
"connectingMessage": "WebSocket 连接中,反馈将在连接就绪后自动提交...",
|
||||
"invalidState": "当前状态不允许提交",
|
||||
"sendFailed": "发送失败,请重试"
|
||||
},
|
||||
"summary": {
|
||||
"title": "📋 AI 工作摘要",
|
||||
@ -55,7 +64,11 @@
|
||||
"running": "执行中...",
|
||||
"completed": "执行完成",
|
||||
"error": "执行错误",
|
||||
"history": "命令历史"
|
||||
"history": "命令历史",
|
||||
"notConnected": "WebSocket 未连接,无法执行命令",
|
||||
"emptyCommand": "请输入命令",
|
||||
"sendFailed": "发送命令失败",
|
||||
"executing": "正在执行..."
|
||||
},
|
||||
"command": {
|
||||
"title": "⚡ 命令执行",
|
||||
@ -179,6 +192,69 @@
|
||||
"detected": "已检测",
|
||||
"error": "失败"
|
||||
},
|
||||
"sessionManagement": {
|
||||
"title": "会话管理",
|
||||
"currentSession": "当前会话",
|
||||
"sessionHistory": "会话历史",
|
||||
"statistics": "统计信息",
|
||||
"sessionId": "会话 ID",
|
||||
"status": "状态",
|
||||
"activeTime": "活跃时间",
|
||||
"switchSession": "切换会话",
|
||||
"viewDetails": "详细信息",
|
||||
"refresh": "重新整理",
|
||||
"noHistory": "暂无历史会话",
|
||||
"todaySessions": "今日会话",
|
||||
"averageDuration": "平均时长",
|
||||
"createdTime": "建立时间",
|
||||
"project": "项目",
|
||||
"aiSummary": "AI 总结",
|
||||
"noSummary": "无总结",
|
||||
"loading": "加载中...",
|
||||
"collapsePanel": "收合面板",
|
||||
"expandPanel": "展开面板",
|
||||
"sessionPanel": "会话",
|
||||
"sessionDetails": {
|
||||
"title": "会话详细信息",
|
||||
"close": "关闭",
|
||||
"duration": "持续时间",
|
||||
"projectDirectory": "项目目录",
|
||||
"summary": "总结",
|
||||
"noSummary": "暂无总结",
|
||||
"unknown": "未知"
|
||||
}
|
||||
},
|
||||
"connectionMonitor": {
|
||||
"connecting": "连接中...",
|
||||
"connected": "已连接",
|
||||
"disconnected": "已断线",
|
||||
"reconnecting": "重连中... (第{attempt}次)",
|
||||
"connectionFailed": "连接失败",
|
||||
"connectionError": "连接错误",
|
||||
"noActiveSession": "没有活跃会话",
|
||||
"maxReconnectReached": "WebSocket 连接失败,请刷新页面重试",
|
||||
"latency": "延迟",
|
||||
"connectionTime": "连线时间",
|
||||
"reconnectCount": "重连",
|
||||
"messageCount": "消息",
|
||||
"sessionCount": "会话",
|
||||
"statusText": "状态",
|
||||
"waiting": "等待中",
|
||||
"times": "次",
|
||||
"quality": {
|
||||
"excellent": "优秀",
|
||||
"good": "良好",
|
||||
"fair": "一般",
|
||||
"poor": "较差",
|
||||
"unknown": "未知"
|
||||
},
|
||||
"metrics": {
|
||||
"messages": "消息",
|
||||
"latencyMs": "延迟",
|
||||
"sessions": "会话",
|
||||
"reconnects": "重连"
|
||||
}
|
||||
},
|
||||
|
||||
"dynamic": {
|
||||
"aiSummary": "测试 Web UI 功能\n\n🎯 **功能测试项目:**\n- Web UI 服务器启动和运行\n- WebSocket 实时通讯\n- 反馈提交功能\n- 图片上传和预览\n- 命令执行功能\n- 智能 Ctrl+V 图片粘贴\n- 多语言界面功能\n\n📋 **测试步骤:**\n1. 测试图片上传(拖拽、选择文件、剪贴板)\n2. 在文本框内按 Ctrl+V 测试智能粘贴\n3. 尝试切换语言(繁中/简中/英文)\n4. 测试命令执行功能\n5. 提交反馈和图片\n\n请测试这些功能并提供反馈!",
|
||||
|
@ -7,7 +7,8 @@
|
||||
"author": "作者:Fábio Ferreira (原作者) / Minidoracat (增強版)",
|
||||
"authorLink": "GitHub: Minidoracat",
|
||||
"credits": "⭐ 如果這個專案對您有幫助,請在 GitHub 上給我們一個星星!\n\n本增強版本由 Minidoracat 開發和維護,大幅擴展了專案功能,新增了 Web UI 介面、圖片支援、多語言能力以及許多其他改進功能。\n\n同時感謝 sanshao85 的 mcp-feedback-collector 專案提供的 UI 設計靈感。\n\n開源協作讓技術變得更美好!",
|
||||
"projectDirectory": "專案目錄"
|
||||
"projectDirectory": "專案目錄",
|
||||
"updateFailed": "更新內容失敗,請手動刷新頁面以查看新的 AI 工作摘要"
|
||||
},
|
||||
"tabs": {
|
||||
"feedback": "💬 回饋",
|
||||
@ -37,7 +38,15 @@
|
||||
"submit": "Ctrl+Enter 提交 (Mac 用 Cmd+Enter,支援數字鍵盤)",
|
||||
"clear": "Ctrl+Delete 清除 (Mac 用 Cmd+Delete)",
|
||||
"paste": "Ctrl+V 貼上圖片 (Mac 用 Cmd+V)"
|
||||
}
|
||||
},
|
||||
"submitSuccess": "回饋提交成功!",
|
||||
"submittedWaiting": "已送出反饋,等待下次 MCP 調用...",
|
||||
"waitingForUser": "等待用戶回饋...",
|
||||
"alreadySubmitted": "回饋已提交,請等待下次 MCP 調用",
|
||||
"processingFeedback": "正在處理中,請稍候",
|
||||
"connectingMessage": "WebSocket 連接中,回饋將在連接就緒後自動提交...",
|
||||
"invalidState": "當前狀態不允許提交",
|
||||
"sendFailed": "發送失敗,請重試"
|
||||
},
|
||||
"summary": {
|
||||
"title": "📋 AI 工作摘要",
|
||||
@ -60,7 +69,11 @@
|
||||
"running": "執行中...",
|
||||
"completed": "執行完成",
|
||||
"error": "執行錯誤",
|
||||
"history": "命令歷史"
|
||||
"history": "命令歷史",
|
||||
"notConnected": "WebSocket 未連接,無法執行命令",
|
||||
"emptyCommand": "請輸入命令",
|
||||
"sendFailed": "發送命令失敗",
|
||||
"executing": "正在執行..."
|
||||
},
|
||||
"command": {
|
||||
"title": "⚡ 命令執行",
|
||||
@ -184,6 +197,69 @@
|
||||
"detected": "已檢測",
|
||||
"error": "失敗"
|
||||
},
|
||||
"sessionManagement": {
|
||||
"title": "會話管理",
|
||||
"currentSession": "當前會話",
|
||||
"sessionHistory": "會話歷史",
|
||||
"statistics": "統計資訊",
|
||||
"sessionId": "會話 ID",
|
||||
"status": "狀態",
|
||||
"activeTime": "活躍時間",
|
||||
"switchSession": "切換會話",
|
||||
"viewDetails": "詳細資訊",
|
||||
"refresh": "重新整理",
|
||||
"noHistory": "暫無歷史會話",
|
||||
"todaySessions": "今日會話",
|
||||
"averageDuration": "平均時長",
|
||||
"createdTime": "建立時間",
|
||||
"project": "專案",
|
||||
"aiSummary": "AI 摘要",
|
||||
"loading": "載入中...",
|
||||
"collapsePanel": "收合面板",
|
||||
"expandPanel": "展開面板",
|
||||
"sessionPanel": "會話",
|
||||
"sessionDetails": {
|
||||
"title": "會話詳細資訊",
|
||||
"close": "關閉",
|
||||
"duration": "持續時間",
|
||||
"projectDirectory": "專案目錄",
|
||||
"summary": "摘要",
|
||||
"noSummary": "暫無摘要",
|
||||
"unknown": "未知"
|
||||
},
|
||||
"noSummary": "無摘要"
|
||||
},
|
||||
"connectionMonitor": {
|
||||
"connecting": "連接中...",
|
||||
"connected": "已連接",
|
||||
"disconnected": "已斷線",
|
||||
"reconnecting": "重連中... (第{attempt}次)",
|
||||
"connectionFailed": "連接失敗",
|
||||
"connectionError": "連接錯誤",
|
||||
"noActiveSession": "沒有活躍會話",
|
||||
"maxReconnectReached": "WebSocket 連接失敗,請刷新頁面重試",
|
||||
"latency": "延遲",
|
||||
"connectionTime": "連線時間",
|
||||
"reconnectCount": "重連",
|
||||
"messageCount": "訊息",
|
||||
"sessionCount": "會話",
|
||||
"statusText": "狀態",
|
||||
"waiting": "等待中",
|
||||
"times": "次",
|
||||
"quality": {
|
||||
"excellent": "優秀",
|
||||
"good": "良好",
|
||||
"fair": "一般",
|
||||
"poor": "較差",
|
||||
"unknown": "未知"
|
||||
},
|
||||
"metrics": {
|
||||
"messages": "訊息",
|
||||
"latencyMs": "延遲",
|
||||
"sessions": "會話",
|
||||
"reconnects": "重連"
|
||||
}
|
||||
},
|
||||
|
||||
"dynamic": {
|
||||
"aiSummary": "測試 Web UI 功能\n\n🎯 **功能測試項目:**\n- Web UI 服務器啟動和運行\n- WebSocket 即時通訊\n- 回饋提交功能\n- 圖片上傳和預覽\n- 命令執行功能\n- 智能 Ctrl+V 圖片貼上\n- 多語言介面功能\n\n📋 **測試步驟:**\n1. 測試圖片上傳(拖拽、選擇檔案、剪貼簿)\n2. 在文字框內按 Ctrl+V 測試智能貼上\n3. 嘗試切換語言(繁中/簡中/英文)\n4. 測試命令執行功能\n5. 提交回饋和圖片\n\n請測試這些功能並提供回饋!",
|
||||
|
@ -434,10 +434,12 @@
|
||||
this.uiManager.setLastSubmissionTime(Date.now());
|
||||
|
||||
// 顯示成功訊息
|
||||
window.MCPFeedback.Utils.showMessage(data.message || '回饋提交成功!', window.MCPFeedback.Utils.CONSTANTS.MESSAGE_SUCCESS);
|
||||
const successMessage = window.i18nManager ? window.i18nManager.t('feedback.submitSuccess') : '回饋提交成功!';
|
||||
window.MCPFeedback.Utils.showMessage(data.message || successMessage, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_SUCCESS);
|
||||
|
||||
// 更新 AI 摘要區域顯示「已送出反饋」狀態
|
||||
this.updateSummaryStatus('已送出反饋,等待下次 MCP 調用...');
|
||||
const submittedMessage = window.i18nManager ? window.i18nManager.t('feedback.submittedWaiting') : '已送出反饋,等待下次 MCP 調用...';
|
||||
this.updateSummaryStatus(submittedMessage);
|
||||
|
||||
console.log('反饋已提交,頁面保持開啟狀態');
|
||||
};
|
||||
@ -562,7 +564,8 @@
|
||||
switch (statusInfo.status) {
|
||||
case 'feedback_submitted':
|
||||
this.uiManager.setFeedbackState(window.MCPFeedback.Utils.CONSTANTS.FEEDBACK_SUBMITTED, sessionId);
|
||||
this.updateSummaryStatus('已送出反饋,等待下次 MCP 調用...');
|
||||
const submittedMessage = window.i18nManager ? window.i18nManager.t('feedback.submittedWaiting') : '已送出反饋,等待下次 MCP 調用...';
|
||||
this.updateSummaryStatus(submittedMessage);
|
||||
break;
|
||||
|
||||
case 'active':
|
||||
@ -575,7 +578,8 @@
|
||||
}
|
||||
|
||||
if (statusInfo.status === 'waiting') {
|
||||
this.updateSummaryStatus('等待用戶回饋...');
|
||||
const waitingMessage = window.i18nManager ? window.i18nManager.t('feedback.waitingForUser') : '等待用戶回饋...';
|
||||
this.updateSummaryStatus(waitingMessage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -620,18 +624,22 @@
|
||||
const feedbackState = this.uiManager ? this.uiManager.getFeedbackState() : null;
|
||||
|
||||
if (feedbackState === window.MCPFeedback.Utils.CONSTANTS.FEEDBACK_SUBMITTED) {
|
||||
window.MCPFeedback.Utils.showMessage('回饋已提交,請等待下次 MCP 調用', window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING);
|
||||
const submittedWarning = window.i18nManager ? window.i18nManager.t('feedback.alreadySubmitted') : '回饋已提交,請等待下次 MCP 調用';
|
||||
window.MCPFeedback.Utils.showMessage(submittedWarning, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING);
|
||||
} else if (feedbackState === window.MCPFeedback.Utils.CONSTANTS.FEEDBACK_PROCESSING) {
|
||||
window.MCPFeedback.Utils.showMessage('正在處理中,請稍候', window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING);
|
||||
const processingWarning = window.i18nManager ? window.i18nManager.t('feedback.processingFeedback') : '正在處理中,請稍候';
|
||||
window.MCPFeedback.Utils.showMessage(processingWarning, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING);
|
||||
} else if (!this.webSocketManager || !this.webSocketManager.isReady()) {
|
||||
// 收集回饋數據,等待連接就緒後提交
|
||||
const feedbackData = this.collectFeedbackData();
|
||||
if (feedbackData) {
|
||||
this.pendingSubmission = feedbackData;
|
||||
window.MCPFeedback.Utils.showMessage('WebSocket 連接中,回饋將在連接就緒後自動提交...', window.MCPFeedback.Utils.CONSTANTS.MESSAGE_INFO);
|
||||
const connectingMessage = window.i18nManager ? window.i18nManager.t('feedback.connectingMessage') : 'WebSocket 連接中,回饋將在連接就緒後自動提交...';
|
||||
window.MCPFeedback.Utils.showMessage(connectingMessage, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_INFO);
|
||||
}
|
||||
} else {
|
||||
window.MCPFeedback.Utils.showMessage('當前狀態不允許提交: ' + feedbackState, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING);
|
||||
const invalidStateMessage = window.i18nManager ? window.i18nManager.t('feedback.invalidState') : '當前狀態不允許提交';
|
||||
window.MCPFeedback.Utils.showMessage(invalidStateMessage + ': ' + feedbackState, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING);
|
||||
}
|
||||
};
|
||||
|
||||
@ -698,7 +706,8 @@
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 發送回饋失敗:', error);
|
||||
window.MCPFeedback.Utils.showMessage('發送失敗,請重試', window.MCPFeedback.Utils.CONSTANTS.MESSAGE_ERROR);
|
||||
const sendFailedMessage = window.i18nManager ? window.i18nManager.t('feedback.sendFailed') : '發送失敗,請重試';
|
||||
window.MCPFeedback.Utils.showMessage(sendFailedMessage, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_ERROR);
|
||||
|
||||
// 恢復到等待狀態
|
||||
if (this.uiManager) {
|
||||
@ -742,12 +751,14 @@
|
||||
const command = commandInput ? commandInput.value.trim() : '';
|
||||
|
||||
if (!command) {
|
||||
this.appendCommandOutput('⚠️ 請輸入命令\n');
|
||||
const emptyCommandMessage = window.i18nManager ? window.i18nManager.t('commands.emptyCommand') : '請輸入命令';
|
||||
this.appendCommandOutput('⚠️ ' + emptyCommandMessage + '\n');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.webSocketManager || !this.webSocketManager.isConnected) {
|
||||
this.appendCommandOutput('❌ WebSocket 未連接,無法執行命令\n');
|
||||
const notConnectedMessage = window.i18nManager ? window.i18nManager.t('commands.notConnected') : 'WebSocket 未連接,無法執行命令';
|
||||
this.appendCommandOutput('❌ ' + notConnectedMessage + '\n');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -764,13 +775,16 @@
|
||||
if (success) {
|
||||
// 清空輸入框
|
||||
commandInput.value = '';
|
||||
this.appendCommandOutput('[正在執行...]\n');
|
||||
const executingMessage = window.i18nManager ? window.i18nManager.t('commands.executing') : '正在執行...';
|
||||
this.appendCommandOutput('[' + executingMessage + ']\n');
|
||||
} else {
|
||||
this.appendCommandOutput('❌ 發送命令失敗\n');
|
||||
const sendFailedMessage = window.i18nManager ? window.i18nManager.t('commands.sendFailed') : '發送命令失敗';
|
||||
this.appendCommandOutput('❌ ' + sendFailedMessage + '\n');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.appendCommandOutput('❌ 發送命令失敗: ' + error.message + '\n');
|
||||
const sendFailedMessage = window.i18nManager ? window.i18nManager.t('commands.sendFailed') : '發送命令失敗';
|
||||
this.appendCommandOutput('❌ ' + sendFailedMessage + ': ' + error.message + '\n');
|
||||
}
|
||||
};
|
||||
|
||||
@ -867,7 +881,8 @@
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('❌ 局部更新失敗:', error);
|
||||
window.MCPFeedback.Utils.showMessage('更新內容失敗,請手動刷新頁面以查看新的 AI 工作摘要', window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING);
|
||||
const updateFailedMessage = window.i18nManager ? window.i18nManager.t('app.updateFailed') : '更新內容失敗,請手動刷新頁面以查看新的 AI 工作摘要';
|
||||
window.MCPFeedback.Utils.showMessage(updateFailedMessage, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_WARNING);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -171,6 +171,12 @@ class I18nManager {
|
||||
// 只更新終端歡迎信息,不要覆蓋 AI 摘要
|
||||
this.updateTerminalWelcome();
|
||||
|
||||
// 更新會話管理相關的動態內容
|
||||
this.updateSessionManagementContent();
|
||||
|
||||
// 更新連線監控相關的動態內容
|
||||
this.updateConnectionMonitorContent();
|
||||
|
||||
// 更新應用程式中的動態狀態文字(使用新的模組化架構)
|
||||
if (window.feedbackApp && window.feedbackApp.isInitialized) {
|
||||
// 更新 UI 狀態
|
||||
@ -199,6 +205,52 @@ class I18nManager {
|
||||
}
|
||||
}
|
||||
|
||||
updateSessionManagementContent() {
|
||||
// 更新會話管理面板中的動態文字
|
||||
if (window.feedbackApp && window.feedbackApp.sessionManager) {
|
||||
// 觸發會話管理器重新渲染,這會使用最新的翻譯
|
||||
if (typeof window.feedbackApp.sessionManager.updateDisplay === 'function') {
|
||||
window.feedbackApp.sessionManager.updateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
// 更新狀態徽章文字
|
||||
const statusBadges = document.querySelectorAll('.status-badge');
|
||||
statusBadges.forEach(badge => {
|
||||
const statusClass = Array.from(badge.classList).find(cls =>
|
||||
['waiting', 'active', 'completed', 'error', 'connecting', 'connected', 'disconnected'].includes(cls)
|
||||
);
|
||||
if (statusClass && window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.Status) {
|
||||
badge.textContent = window.MCPFeedback.Utils.Status.getStatusText(statusClass);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateConnectionMonitorContent() {
|
||||
// 更新連線監控器中的動態文字
|
||||
if (window.feedbackApp && window.feedbackApp.connectionMonitor) {
|
||||
// 觸發連線監控器重新更新顯示
|
||||
if (typeof window.feedbackApp.connectionMonitor.updateDisplay === 'function') {
|
||||
window.feedbackApp.connectionMonitor.updateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
// 更新連線狀態文字
|
||||
const statusText = document.querySelector('.status-text');
|
||||
if (statusText && window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.Status) {
|
||||
// 從元素的類名或數據屬性中獲取狀態
|
||||
const indicator = statusText.closest('.connection-indicator');
|
||||
if (indicator) {
|
||||
const statusClass = Array.from(indicator.classList).find(cls =>
|
||||
['connecting', 'connected', 'disconnected', 'reconnecting'].includes(cls)
|
||||
);
|
||||
if (statusClass) {
|
||||
statusText.textContent = window.MCPFeedback.Utils.Status.getConnectionStatusText(statusClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setupLanguageSelectors() {
|
||||
// 舊版下拉選擇器(兼容性保留)
|
||||
const selector = document.getElementById('settingsLanguageSelect');
|
||||
|
@ -101,16 +101,19 @@
|
||||
*/
|
||||
ConnectionMonitor.prototype.updateConnectionStatus = function(status, message) {
|
||||
console.log('🔍 連線狀態更新:', status, message);
|
||||
|
||||
|
||||
// 更新狀態顯示
|
||||
if (this.statusText) {
|
||||
this.statusText.textContent = message || status;
|
||||
// 使用 i18n 翻譯或提供的訊息
|
||||
const displayText = message || (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.Status ?
|
||||
window.MCPFeedback.Utils.Status.getConnectionStatusText(status) : status);
|
||||
this.statusText.textContent = displayText;
|
||||
}
|
||||
|
||||
|
||||
// 更新狀態圖示
|
||||
if (this.statusIcon) {
|
||||
this.statusIcon.className = 'status-icon';
|
||||
|
||||
|
||||
switch (status) {
|
||||
case 'connecting':
|
||||
case 'reconnecting':
|
||||
@ -123,7 +126,7 @@
|
||||
this.statusIcon.classList.remove('pulse');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 更新連線指示器樣式
|
||||
const indicator = Utils.safeQuerySelector('.connection-indicator');
|
||||
if (indicator) {
|
||||
@ -263,10 +266,11 @@
|
||||
ConnectionMonitor.prototype.updateDisplay = function() {
|
||||
// 更新延遲顯示
|
||||
if (this.latencyDisplay) {
|
||||
const latencyLabel = window.i18nManager ? window.i18nManager.t('connectionMonitor.latency') : '延遲';
|
||||
if (this.currentLatency > 0) {
|
||||
this.latencyDisplay.textContent = '延遲: ' + this.currentLatency + 'ms';
|
||||
this.latencyDisplay.textContent = latencyLabel + ': ' + this.currentLatency + 'ms';
|
||||
} else {
|
||||
this.latencyDisplay.textContent = '延遲: --ms';
|
||||
this.latencyDisplay.textContent = latencyLabel + ': --ms';
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,14 +287,17 @@
|
||||
const duration = Math.floor((Date.now() - this.connectionStartTime) / 1000);
|
||||
const minutes = Math.floor(duration / 60);
|
||||
const seconds = duration % 60;
|
||||
this.connectionTimeDisplay.textContent = '連線時間: ' +
|
||||
String(minutes).padStart(2, '0') + ':' +
|
||||
const connectionTimeLabel = window.i18nManager ? window.i18nManager.t('connectionMonitor.connectionTime') : '連線時間';
|
||||
this.connectionTimeDisplay.textContent = connectionTimeLabel + ': ' +
|
||||
String(minutes).padStart(2, '0') + ':' +
|
||||
String(seconds).padStart(2, '0');
|
||||
}
|
||||
|
||||
// 更新重連次數
|
||||
if (this.reconnectCountDisplay) {
|
||||
this.reconnectCountDisplay.textContent = '重連: ' + this.reconnectCount + ' 次';
|
||||
const reconnectLabel = window.i18nManager ? window.i18nManager.t('connectionMonitor.reconnectCount') : '重連';
|
||||
const timesLabel = window.i18nManager ? window.i18nManager.t('connectionMonitor.times') : '次';
|
||||
this.reconnectCountDisplay.textContent = reconnectLabel + ': ' + this.reconnectCount + ' ' + timesLabel;
|
||||
}
|
||||
|
||||
// 更新訊息計數
|
||||
|
@ -96,8 +96,8 @@
|
||||
statusColor: statusColor,
|
||||
createdTime: createdTime,
|
||||
duration: duration,
|
||||
projectDirectory: sessionData.project_directory || '未知',
|
||||
summary: sessionData.summary || '暫無摘要'
|
||||
projectDirectory: sessionData.project_directory || (window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.unknown') : '未知'),
|
||||
summary: sessionData.summary || (window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.noSummary') : '暫無摘要')
|
||||
};
|
||||
};
|
||||
|
||||
@ -125,42 +125,48 @@
|
||||
* 創建彈窗 HTML
|
||||
*/
|
||||
SessionDetailsModal.prototype.createModalHTML = function(details) {
|
||||
const i18n = window.i18nManager;
|
||||
const title = i18n ? i18n.t('sessionManagement.sessionDetails.title') : '會話詳細資訊';
|
||||
const closeLabel = i18n ? i18n.t('sessionManagement.sessionDetails.close') : '關閉';
|
||||
const sessionIdLabel = i18n ? i18n.t('sessionManagement.sessionId') : '會話 ID';
|
||||
const statusLabel = i18n ? i18n.t('sessionManagement.status') : '狀態';
|
||||
|
||||
return `
|
||||
<div class="session-details-modal" id="sessionDetailsModal">
|
||||
<div class="modal-backdrop"></div>
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>會話詳細資訊</h3>
|
||||
<button class="modal-close" id="closeSessionDetails" aria-label="關閉">×</button>
|
||||
<h3>${title}</h3>
|
||||
<button class="modal-close" id="closeSessionDetails" aria-label="${closeLabel}">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">會話 ID:</span>
|
||||
<span class="detail-label">${sessionIdLabel}:</span>
|
||||
<span class="detail-value session-id" title="${details.sessionId}">${details.sessionId}</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">狀態:</span>
|
||||
<span class="detail-label">${statusLabel}:</span>
|
||||
<span class="detail-value" style="color: ${details.statusColor};">${details.status}</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">建立時間:</span>
|
||||
<span class="detail-label">${i18n ? i18n.t('sessionManagement.createdTime') : '建立時間'}:</span>
|
||||
<span class="detail-value">${details.createdTime}</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">持續時間:</span>
|
||||
<span class="detail-label">${i18n ? i18n.t('sessionManagement.sessionDetails.duration') : '持續時間'}:</span>
|
||||
<span class="detail-value">${details.duration}</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">專案目錄:</span>
|
||||
<span class="detail-label">${i18n ? i18n.t('sessionManagement.sessionDetails.projectDirectory') : '專案目錄'}:</span>
|
||||
<span class="detail-value project-path" title="${details.projectDirectory}">${details.projectDirectory}</span>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<span class="detail-label">AI 摘要:</span>
|
||||
<span class="detail-label">${i18n ? i18n.t('sessionManagement.aiSummary') : 'AI 摘要'}:</span>
|
||||
<div class="detail-value summary">${this.escapeHtml(details.summary)}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn-secondary" id="closeSessionDetailsBtn">關閉</button>
|
||||
<button class="btn-secondary" id="closeSessionDetailsBtn">${closeLabel}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -102,10 +102,11 @@
|
||||
SessionUIRenderer.prototype.updateSessionId = function(sessionData) {
|
||||
const sessionIdElement = this.currentSessionCard.querySelector('.session-id');
|
||||
if (sessionIdElement && sessionData.session_id) {
|
||||
const displayId = this.showFullSessionId ?
|
||||
sessionData.session_id :
|
||||
const displayId = this.showFullSessionId ?
|
||||
sessionData.session_id :
|
||||
sessionData.session_id.substring(0, 8) + '...';
|
||||
DOMUtils.safeSetTextContent(sessionIdElement, '會話 ID: ' + displayId);
|
||||
const sessionIdLabel = window.i18nManager ? window.i18nManager.t('sessionManagement.sessionId') : '會話 ID';
|
||||
DOMUtils.safeSetTextContent(sessionIdElement, sessionIdLabel + ': ' + displayId);
|
||||
}
|
||||
};
|
||||
|
||||
@ -130,7 +131,8 @@
|
||||
const timeElement = this.currentSessionCard.querySelector('.session-time');
|
||||
if (timeElement && sessionData.created_at) {
|
||||
const timeText = TimeUtils.formatTimestamp(sessionData.created_at, { format: 'time' });
|
||||
DOMUtils.safeSetTextContent(timeElement, '建立時間: ' + timeText);
|
||||
const createdTimeLabel = window.i18nManager ? window.i18nManager.t('sessionManagement.createdTime') : '建立時間';
|
||||
DOMUtils.safeSetTextContent(timeElement, createdTimeLabel + ': ' + timeText);
|
||||
}
|
||||
};
|
||||
|
||||
@ -141,7 +143,8 @@
|
||||
const projectElement = this.currentSessionCard.querySelector('.session-project');
|
||||
if (projectElement) {
|
||||
const projectDir = sessionData.project_directory || './';
|
||||
DOMUtils.safeSetTextContent(projectElement, '專案: ' + projectDir);
|
||||
const projectLabel = window.i18nManager ? window.i18nManager.t('sessionManagement.project') : '專案';
|
||||
DOMUtils.safeSetTextContent(projectElement, projectLabel + ': ' + projectDir);
|
||||
}
|
||||
};
|
||||
|
||||
@ -151,8 +154,10 @@
|
||||
SessionUIRenderer.prototype.updateSummary = function(sessionData) {
|
||||
const summaryElement = this.currentSessionCard.querySelector('.session-summary');
|
||||
if (summaryElement) {
|
||||
const summary = sessionData.summary || '無摘要';
|
||||
DOMUtils.safeSetTextContent(summaryElement, 'AI 摘要: ' + summary);
|
||||
const noSummaryText = window.i18nManager ? window.i18nManager.t('sessionManagement.noSummary') : '無摘要';
|
||||
const summary = sessionData.summary || noSummaryText;
|
||||
const summaryLabel = window.i18nManager ? window.i18nManager.t('sessionManagement.aiSummary') : 'AI 摘要';
|
||||
DOMUtils.safeSetTextContent(summaryElement, summaryLabel + ': ' + summary);
|
||||
}
|
||||
};
|
||||
|
||||
@ -205,9 +210,10 @@
|
||||
* 渲染空歷史狀態
|
||||
*/
|
||||
SessionUIRenderer.prototype.renderEmptyHistory = function() {
|
||||
const noHistoryText = window.i18nManager ? window.i18nManager.t('sessionManagement.noHistory') : '暫無歷史會話';
|
||||
const emptyElement = DOMUtils.createElement('div', {
|
||||
className: 'no-sessions',
|
||||
textContent: '暫無歷史會話'
|
||||
textContent: noHistoryText
|
||||
});
|
||||
this.historyList.appendChild(emptyElement);
|
||||
};
|
||||
@ -242,9 +248,10 @@
|
||||
const header = DOMUtils.createElement('div', { className: 'session-header' });
|
||||
|
||||
// 會話 ID
|
||||
const sessionIdLabel = window.i18nManager ? window.i18nManager.t('sessionManagement.sessionId') : '會話 ID';
|
||||
const sessionId = DOMUtils.createElement('div', {
|
||||
className: 'session-id',
|
||||
textContent: '會話 ID: ' + (sessionData.session_id || '').substring(0, 8) + '...'
|
||||
textContent: sessionIdLabel + ': ' + (sessionData.session_id || '').substring(0, 8) + '...'
|
||||
});
|
||||
|
||||
// 狀態徽章
|
||||
@ -268,13 +275,17 @@
|
||||
const info = DOMUtils.createElement('div', { className: 'session-info' });
|
||||
|
||||
// 時間資訊
|
||||
const timeText = sessionData.created_at ?
|
||||
TimeUtils.formatTimestamp(sessionData.created_at, { format: 'time' }) :
|
||||
const timeText = sessionData.created_at ?
|
||||
TimeUtils.formatTimestamp(sessionData.created_at, { format: 'time' }) :
|
||||
'--:--:--';
|
||||
|
||||
|
||||
const timeLabel = isHistory ?
|
||||
(window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.duration') : '完成時間') :
|
||||
(window.i18nManager ? window.i18nManager.t('sessionManagement.createdTime') : '建立時間');
|
||||
|
||||
const timeElement = DOMUtils.createElement('div', {
|
||||
className: 'session-time',
|
||||
textContent: (isHistory ? '完成時間' : '建立時間') + ': ' + timeText
|
||||
textContent: timeLabel + ': ' + timeText
|
||||
});
|
||||
|
||||
info.appendChild(timeElement);
|
||||
@ -282,9 +293,10 @@
|
||||
// 歷史會話顯示持續時間
|
||||
if (isHistory) {
|
||||
const duration = this.calculateDisplayDuration(sessionData);
|
||||
const durationLabel = window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.duration') : '持續時間';
|
||||
const durationElement = DOMUtils.createElement('div', {
|
||||
className: 'session-duration',
|
||||
textContent: '持續時間: ' + duration
|
||||
textContent: durationLabel + ': ' + duration
|
||||
});
|
||||
info.appendChild(durationElement);
|
||||
}
|
||||
@ -304,7 +316,7 @@
|
||||
} else if (sessionData.created_at) {
|
||||
return TimeUtils.estimateSessionDuration(sessionData);
|
||||
}
|
||||
return '未知';
|
||||
return window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.unknown') : '未知';
|
||||
};
|
||||
|
||||
/**
|
||||
@ -313,9 +325,13 @@
|
||||
SessionUIRenderer.prototype.createSessionActions = function(sessionData, isHistory) {
|
||||
const actions = DOMUtils.createElement('div', { className: 'session-actions' });
|
||||
|
||||
const buttonText = isHistory ?
|
||||
(window.i18nManager ? window.i18nManager.t('sessionManagement.viewDetails') : '查看') :
|
||||
(window.i18nManager ? window.i18nManager.t('sessionManagement.viewDetails') : '詳細資訊');
|
||||
|
||||
const button = DOMUtils.createElement('button', {
|
||||
className: 'btn-small',
|
||||
textContent: isHistory ? '查看' : '詳細資訊'
|
||||
textContent: buttonText
|
||||
});
|
||||
|
||||
// 添加點擊事件
|
||||
|
@ -321,8 +321,8 @@
|
||||
|
||||
default:
|
||||
icon = '⏳';
|
||||
title = '等待回饋';
|
||||
message = '請提供您的回饋意見';
|
||||
title = window.i18nManager ? window.i18nManager.t('status.waiting.title') : '等待回饋';
|
||||
message = window.i18nManager ? window.i18nManager.t('status.waiting.message') : '請提供您的回饋意見';
|
||||
status = 'waiting';
|
||||
}
|
||||
|
||||
@ -410,7 +410,8 @@
|
||||
|
||||
submitButtons.forEach(function(button) {
|
||||
button.disabled = false;
|
||||
button.textContent = button.getAttribute('data-original-text') || '提交回饋';
|
||||
const defaultText = window.i18nManager ? window.i18nManager.t('buttons.submit') : '提交回饋';
|
||||
button.textContent = button.getAttribute('data-original-text') || defaultText;
|
||||
});
|
||||
|
||||
console.log('✅ 回饋表單重置完成');
|
||||
|
@ -17,34 +17,79 @@
|
||||
*/
|
||||
const StatusUtils = {
|
||||
/**
|
||||
* 會話狀態映射
|
||||
* 獲取會話狀態文字(使用 i18n)
|
||||
*/
|
||||
SESSION_STATUS_MAP: {
|
||||
'waiting': '等待回饋',
|
||||
'waiting_for_feedback': '等待回饋',
|
||||
'active': '進行中',
|
||||
'feedback_submitted': '已提交回饋',
|
||||
'completed': '已完成',
|
||||
'timeout': '已逾時',
|
||||
'error': '錯誤',
|
||||
'expired': '已過期',
|
||||
'connecting': '連接中',
|
||||
'connected': '已連接',
|
||||
'disconnected': '已斷開',
|
||||
'processing': '處理中',
|
||||
'ready': '就緒',
|
||||
'closed': '已關閉'
|
||||
getSessionStatusText: function(status) {
|
||||
if (!window.i18nManager) {
|
||||
// 回退到硬編碼文字
|
||||
const fallbackMap = {
|
||||
'waiting': '等待回饋',
|
||||
'waiting_for_feedback': '等待回饋',
|
||||
'active': '進行中',
|
||||
'feedback_submitted': '已提交回饋',
|
||||
'completed': '已完成',
|
||||
'timeout': '已逾時',
|
||||
'error': '錯誤',
|
||||
'expired': '已過期',
|
||||
'connecting': '連接中',
|
||||
'connected': '已連接',
|
||||
'disconnected': '已斷開',
|
||||
'processing': '處理中',
|
||||
'ready': '就緒',
|
||||
'closed': '已關閉'
|
||||
};
|
||||
return fallbackMap[status] || status;
|
||||
}
|
||||
|
||||
// 使用 i18n 翻譯
|
||||
const i18nKeyMap = {
|
||||
'waiting': 'connectionMonitor.waiting',
|
||||
'waiting_for_feedback': 'connectionMonitor.waiting',
|
||||
'active': 'status.processing.title',
|
||||
'feedback_submitted': 'status.submitted.title',
|
||||
'completed': 'status.submitted.title',
|
||||
'timeout': 'session.timeout',
|
||||
'error': 'status.error',
|
||||
'expired': 'session.timeout',
|
||||
'connecting': 'connectionMonitor.connecting',
|
||||
'connected': 'connectionMonitor.connected',
|
||||
'disconnected': 'connectionMonitor.disconnected',
|
||||
'processing': 'status.processing.title',
|
||||
'ready': 'connectionMonitor.connected',
|
||||
'closed': 'connectionMonitor.disconnected'
|
||||
};
|
||||
|
||||
const i18nKey = i18nKeyMap[status];
|
||||
return i18nKey ? window.i18nManager.t(i18nKey) : status;
|
||||
},
|
||||
|
||||
/**
|
||||
* 連線狀態映射
|
||||
* 獲取連線狀態文字(使用 i18n)
|
||||
*/
|
||||
CONNECTION_STATUS_MAP: {
|
||||
'connecting': '連接中',
|
||||
'connected': '已連接',
|
||||
'disconnected': '已斷開',
|
||||
'reconnecting': '重連中',
|
||||
'error': '連接錯誤'
|
||||
getConnectionStatusText: function(status) {
|
||||
if (!window.i18nManager) {
|
||||
// 回退到硬編碼文字
|
||||
const fallbackMap = {
|
||||
'connecting': '連接中',
|
||||
'connected': '已連接',
|
||||
'disconnected': '已斷開',
|
||||
'reconnecting': '重連中',
|
||||
'error': '連接錯誤'
|
||||
};
|
||||
return fallbackMap[status] || status;
|
||||
}
|
||||
|
||||
// 使用 i18n 翻譯
|
||||
const i18nKeyMap = {
|
||||
'connecting': 'connectionMonitor.connecting',
|
||||
'connected': 'connectionMonitor.connected',
|
||||
'disconnected': 'connectionMonitor.disconnected',
|
||||
'reconnecting': 'connectionMonitor.reconnecting',
|
||||
'error': 'status.error'
|
||||
};
|
||||
|
||||
const i18nKey = i18nKeyMap[status];
|
||||
return i18nKey ? window.i18nManager.t(i18nKey) : status;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -69,21 +114,56 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* 連線品質等級
|
||||
* 獲取連線品質標籤(使用 i18n)
|
||||
*/
|
||||
CONNECTION_QUALITY_LEVELS: {
|
||||
'excellent': { threshold: 50, label: '優秀', color: '#4caf50' },
|
||||
'good': { threshold: 100, label: '良好', color: '#8bc34a' },
|
||||
'fair': { threshold: 200, label: '一般', color: '#ff9800' },
|
||||
'poor': { threshold: Infinity, label: '較差', color: '#f44336' }
|
||||
getConnectionQualityLabel: function(level) {
|
||||
if (!window.i18nManager) {
|
||||
// 回退到硬編碼文字
|
||||
const fallbackLabels = {
|
||||
'excellent': '優秀',
|
||||
'good': '良好',
|
||||
'fair': '一般',
|
||||
'poor': '較差',
|
||||
'unknown': '未知'
|
||||
};
|
||||
return fallbackLabels[level] || level;
|
||||
}
|
||||
|
||||
const i18nKey = `connectionMonitor.quality.${level}`;
|
||||
return window.i18nManager.t(i18nKey);
|
||||
},
|
||||
|
||||
/**
|
||||
* 獲取狀態文字
|
||||
* 連線品質等級
|
||||
*/
|
||||
CONNECTION_QUALITY_LEVELS: {
|
||||
'excellent': { threshold: 50, color: '#4caf50' },
|
||||
'good': { threshold: 100, color: '#8bc34a' },
|
||||
'fair': { threshold: 200, color: '#ff9800' },
|
||||
'poor': { threshold: Infinity, color: '#f44336' }
|
||||
},
|
||||
|
||||
/**
|
||||
* 獲取狀態文字(統一入口,優先使用新方法)
|
||||
*/
|
||||
getStatusText: function(status) {
|
||||
if (!status) return '未知';
|
||||
return this.SESSION_STATUS_MAP[status] || this.CONNECTION_STATUS_MAP[status] || status;
|
||||
if (!status) {
|
||||
return window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.unknown') : '未知';
|
||||
}
|
||||
|
||||
// 優先嘗試會話狀態
|
||||
const sessionText = this.getSessionStatusText(status);
|
||||
if (sessionText !== status) {
|
||||
return sessionText;
|
||||
}
|
||||
|
||||
// 然後嘗試連線狀態
|
||||
const connectionText = this.getConnectionStatusText(status);
|
||||
if (connectionText !== status) {
|
||||
return connectionText;
|
||||
}
|
||||
|
||||
return status;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -99,20 +179,28 @@
|
||||
*/
|
||||
calculateConnectionQuality: function(latency) {
|
||||
if (typeof latency !== 'number' || latency < 0) {
|
||||
return { level: 'unknown', label: '未知', color: '#757575' };
|
||||
return {
|
||||
level: 'unknown',
|
||||
label: this.getConnectionQualityLabel('unknown'),
|
||||
color: '#757575'
|
||||
};
|
||||
}
|
||||
|
||||
for (const [level, config] of Object.entries(this.CONNECTION_QUALITY_LEVELS)) {
|
||||
if (latency < config.threshold) {
|
||||
return {
|
||||
level: level,
|
||||
label: config.label,
|
||||
label: this.getConnectionQualityLabel(level),
|
||||
color: config.color
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { level: 'poor', label: '較差', color: '#f44336' };
|
||||
return {
|
||||
level: 'poor',
|
||||
label: this.getConnectionQualityLabel('poor'),
|
||||
color: '#f44336'
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -60,7 +60,8 @@
|
||||
const wsUrl = protocol + '//' + host + '/ws';
|
||||
|
||||
console.log('嘗試連接 WebSocket:', wsUrl);
|
||||
this.updateConnectionStatus('connecting', '連接中...');
|
||||
const connectingMessage = window.i18nManager ? window.i18nManager.t('connectionMonitor.connecting') : '連接中...';
|
||||
this.updateConnectionStatus('connecting', connectingMessage);
|
||||
|
||||
try {
|
||||
// 如果已有連接,先關閉
|
||||
@ -74,7 +75,8 @@
|
||||
|
||||
} catch (error) {
|
||||
console.error('WebSocket 連接失敗:', error);
|
||||
this.updateConnectionStatus('error', '連接失敗');
|
||||
const connectionFailedMessage = window.i18nManager ? window.i18nManager.t('connectionMonitor.connectionFailed') : '連接失敗';
|
||||
this.updateConnectionStatus('error', connectionFailedMessage);
|
||||
}
|
||||
};
|
||||
|
||||
@ -107,7 +109,8 @@
|
||||
WebSocketManager.prototype.handleOpen = function() {
|
||||
this.isConnected = true;
|
||||
this.connectionReady = false; // 等待連接確認
|
||||
this.updateConnectionStatus('connected', '已連接');
|
||||
const connectedMessage = window.i18nManager ? window.i18nManager.t('connectionMonitor.connected') : '已連接';
|
||||
this.updateConnectionStatus('connected', connectedMessage);
|
||||
console.log('WebSocket 連接已建立');
|
||||
|
||||
// 重置重連計數器和延遲
|
||||
@ -173,9 +176,11 @@
|
||||
|
||||
// 處理不同的關閉原因
|
||||
if (event.code === 4004) {
|
||||
this.updateConnectionStatus('disconnected', '沒有活躍會話');
|
||||
const noActiveSessionMessage = window.i18nManager ? window.i18nManager.t('connectionMonitor.noActiveSession') : '沒有活躍會話';
|
||||
this.updateConnectionStatus('disconnected', noActiveSessionMessage);
|
||||
} else {
|
||||
this.updateConnectionStatus('disconnected', '已斷開');
|
||||
const disconnectedMessage = window.i18nManager ? window.i18nManager.t('connectionMonitor.disconnected') : '已斷開';
|
||||
this.updateConnectionStatus('disconnected', disconnectedMessage);
|
||||
this.handleReconnection(event);
|
||||
}
|
||||
|
||||
@ -190,8 +195,9 @@
|
||||
*/
|
||||
WebSocketManager.prototype.handleError = function(error) {
|
||||
console.error('WebSocket 錯誤:', error);
|
||||
this.updateConnectionStatus('error', '連接錯誤');
|
||||
|
||||
const connectionErrorMessage = window.i18nManager ? window.i18nManager.t('connectionMonitor.connectionError') : '連接錯誤';
|
||||
this.updateConnectionStatus('error', connectionErrorMessage);
|
||||
|
||||
// 調用外部回調
|
||||
if (this.onError) {
|
||||
this.onError(error);
|
||||
@ -218,7 +224,9 @@
|
||||
console.log(this.reconnectDelay / 1000 + '秒後嘗試重連... (第' + this.reconnectAttempts + '次)');
|
||||
|
||||
// 更新狀態為重連中
|
||||
this.updateConnectionStatus('reconnecting', '重連中... (第' + this.reconnectAttempts + '次)');
|
||||
const reconnectingTemplate = window.i18nManager ? window.i18nManager.t('connectionMonitor.reconnecting') : '重連中... (第{attempt}次)';
|
||||
const reconnectingMessage = reconnectingTemplate.replace('{attempt}', this.reconnectAttempts);
|
||||
this.updateConnectionStatus('reconnecting', reconnectingMessage);
|
||||
|
||||
const self = this;
|
||||
setTimeout(function() {
|
||||
@ -227,7 +235,8 @@
|
||||
}, this.reconnectDelay);
|
||||
} else if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
||||
console.log('❌ 達到最大重連次數,停止重連');
|
||||
Utils.showMessage('WebSocket 連接失敗,請刷新頁面重試', Utils.CONSTANTS.MESSAGE_ERROR);
|
||||
const maxReconnectMessage = window.i18nManager ? window.i18nManager.t('connectionMonitor.maxReconnectReached') : 'WebSocket 連接失敗,請刷新頁面重試';
|
||||
Utils.showMessage(maxReconnectMessage, Utils.CONSTANTS.MESSAGE_ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -385,9 +385,9 @@
|
||||
<!-- 主要連線狀態 -->
|
||||
<div class="connection-indicator connecting" id="mainConnectionStatus">
|
||||
<div class="status-icon pulse"></div>
|
||||
<span class="status-text">連接中...</span>
|
||||
<span class="status-text" data-i18n="connectionMonitor.connecting">連接中...</span>
|
||||
<div class="connection-quality">
|
||||
<div class="latency-indicator">延遲: --ms</div>
|
||||
<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>
|
||||
@ -398,19 +398,19 @@
|
||||
|
||||
<!-- 連線詳細資訊 -->
|
||||
<div class="connection-details">
|
||||
<span class="connection-time">連線時間: --:--</span>
|
||||
<span class="reconnect-count">重連: 0 次</span>
|
||||
<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 id="messageCount">0</span></span>
|
||||
<span class="metric">延遲: <span id="latencyDisplay">--ms</span></span>
|
||||
<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 id="sessionCount">1</span></span>
|
||||
<span class="metric">狀態: <span id="sessionStatusText">等待中</span></span>
|
||||
<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>
|
||||
@ -430,9 +430,9 @@
|
||||
<div class="session-management-panel" id="sessionPanel">
|
||||
<!-- 面板標題 -->
|
||||
<div class="panel-header">
|
||||
<h3>會話管理</h3>
|
||||
<h3 data-i18n="sessionManagement.title">會話管理</h3>
|
||||
<div class="panel-controls">
|
||||
<button class="btn-icon" id="refreshSessions" title="重新整理">
|
||||
<button class="btn-icon" id="refreshSessions" data-i18n-title="sessionManagement.refresh" title="重新整理">
|
||||
🔄
|
||||
</button>
|
||||
</div>
|
||||
@ -441,44 +441,44 @@
|
||||
<div class="panel-content">
|
||||
<!-- 當前活躍會話 -->
|
||||
<div class="current-session-section">
|
||||
<h4>當前會話</h4>
|
||||
<h4 data-i18n="sessionManagement.currentSession">當前會話</h4>
|
||||
<div class="session-card active" id="currentSessionCard">
|
||||
<div class="session-header">
|
||||
<div class="session-id">會話 ID: {{ session_id[:8] if session_id else 'loading' }}...</div>
|
||||
<div class="session-id"><span data-i18n="sessionManagement.sessionId">會話 ID</span>: {{ session_id[:8] if session_id else 'loading' }}...</div>
|
||||
<div class="session-status">
|
||||
<span class="status-badge waiting">等待中</span>
|
||||
<span class="status-badge waiting" data-i18n="connectionMonitor.waiting">等待中</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="session-info">
|
||||
<div class="session-time">建立時間: --:--:--</div>
|
||||
<div class="session-project">專案: {{ project_directory }}</div>
|
||||
<div class="session-summary">AI 摘要: 載入中...</div>
|
||||
<div class="session-time"><span data-i18n="sessionManagement.createdTime">建立時間</span>: --:--:--</div>
|
||||
<div class="session-project"><span data-i18n="sessionManagement.project">專案</span>: {{ project_directory }}</div>
|
||||
<div class="session-summary"><span data-i18n="sessionManagement.aiSummary">AI 摘要</span>: <span data-i18n="sessionManagement.loading">載入中...</span></div>
|
||||
</div>
|
||||
<div class="session-actions">
|
||||
<button class="btn-small" id="viewSessionDetails">詳細資訊</button>
|
||||
<button class="btn-small" id="viewSessionDetails" data-i18n="sessionManagement.viewDetails">詳細資訊</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 會話歷史記錄 -->
|
||||
<div class="session-history-section">
|
||||
<h4>會話歷史</h4>
|
||||
<h4 data-i18n="sessionManagement.sessionHistory">會話歷史</h4>
|
||||
<div class="session-list" id="sessionHistoryList">
|
||||
<div class="no-sessions">暫無歷史會話</div>
|
||||
<div class="no-sessions" data-i18n="sessionManagement.noHistory">暫無歷史會話</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 會話統計 -->
|
||||
<div class="session-stats-section">
|
||||
<h4>統計資訊</h4>
|
||||
<h4 data-i18n="sessionManagement.statistics">統計資訊</h4>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-item">
|
||||
<div class="stat-value">0</div>
|
||||
<div class="stat-label">今日會話</div>
|
||||
<div class="stat-label" data-i18n="sessionManagement.todaySessions">今日會話</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-value">--</div>
|
||||
<div class="stat-label">平均時長</div>
|
||||
<div class="stat-label" data-i18n="sessionManagement.averageDuration">平均時長</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -486,7 +486,7 @@
|
||||
|
||||
<!-- 邊緣收合/展開按鈕 -->
|
||||
<div class="panel-edge-toggle" id="panelEdgeToggle">
|
||||
<button class="edge-toggle-btn" id="edgeToggleBtn" title="收合面板">
|
||||
<button class="edge-toggle-btn" id="edgeToggleBtn" data-i18n-title="sessionManagement.collapsePanel" title="收合面板">
|
||||
<span class="toggle-icon">◀</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -494,9 +494,9 @@
|
||||
|
||||
<!-- 收合狀態下的展開按鈕 -->
|
||||
<div class="collapsed-panel-toggle" id="collapsedPanelToggle" style="display: none;">
|
||||
<button class="collapsed-toggle-btn" id="collapsedToggleBtn" title="展開會話面板">
|
||||
<button class="collapsed-toggle-btn" id="collapsedToggleBtn" data-i18n-title="sessionManagement.expandPanel" title="展開會話面板">
|
||||
<span class="toggle-icon">▶</span>
|
||||
<span class="toggle-text">會話</span>
|
||||
<span class="toggle-text" data-i18n="sessionManagement.sessionPanel">會話</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -506,12 +506,12 @@
|
||||
<div class="session-status-bar" style="display: flex; justify-content: space-between; align-items: center; padding: 8px 16px; background: var(--bg-secondary); border-bottom: 1px solid var(--border-color); margin-bottom: 16px; border-radius: 6px;">
|
||||
<div class="current-session-info">
|
||||
<span class="session-indicator" style="display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-secondary);">
|
||||
📋 當前會話: <span id="currentSessionId" style="font-family: monospace; color: var(--accent-color);">{{ session_id[:8] if session_id else 'loading' }}...</span>
|
||||
📋 <span data-i18n="sessionManagement.currentSession">當前會話</span>: <span id="currentSessionId" style="font-family: monospace; color: var(--accent-color);">{{ session_id[:8] if session_id else 'loading' }}...</span>
|
||||
</span>
|
||||
<span class="session-age" style="margin-left: 16px; font-size: 12px; color: var(--text-secondary);">活躍時間: <span id="sessionAge">--</span></span>
|
||||
<span class="session-age" style="margin-left: 16px; font-size: 12px; color: var(--text-secondary);"><span data-i18n="sessionManagement.activeTime">活躍時間</span>: <span id="sessionAge">--</span></span>
|
||||
</div>
|
||||
<div class="session-controls">
|
||||
<button class="btn-link" id="switchSessionBtn" style="display: none; font-size: 12px; color: var(--accent-color); background: none; border: none; cursor: pointer;">
|
||||
<button class="btn-link" id="switchSessionBtn" style="display: none; font-size: 12px; color: var(--accent-color); background: none; border: none; cursor: pointer;" data-i18n="sessionManagement.switchSession">
|
||||
切換會話
|
||||
</button>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user