From 3d4aafa3dc18432cf0c28d5ce68de045943ed63b Mon Sep 17 00:00:00 2001 From: Minidoracat Date: Sat, 14 Jun 2025 10:37:25 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E6=8F=90=E4=BA=A4=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E8=AE=8A=E5=8B=95=E3=80=81=E6=9C=83=E8=A9=B1=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=B9=B3=E5=9D=87=E6=99=82=E9=95=B7=E8=AA=BF=E6=95=B4?= =?UTF-8?q?=E7=82=BA=E4=BB=8A=E6=97=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/locales/en/translation.json | 12 +++- .../web/locales/zh-CN/translation.json | 12 +++- .../web/locales/zh-TW/translation.json | 12 +++- .../web/static/css/styles.css | 39 ++++++++++++ .../web/static/js/app.js | 15 +---- .../web/static/js/i18n.js | 8 +++ .../js/modules/audio/audio-settings-ui.js | 28 ++++++--- .../modules/session/session-data-manager.js | 25 ++++---- .../js/modules/session/session-ui-renderer.js | 18 ++---- .../web/static/js/modules/ui-manager.js | 6 +- .../web/static/js/modules/utils/time-utils.js | 61 +++++++++++++++---- .../web/templates/feedback.html | 21 +++---- 12 files changed, 175 insertions(+), 82 deletions(-) diff --git a/src/mcp_feedback_enhanced/web/locales/en/translation.json b/src/mcp_feedback_enhanced/web/locales/en/translation.json index 70b4f49..b365da2 100644 --- a/src/mcp_feedback_enhanced/web/locales/en/translation.json +++ b/src/mcp_feedback_enhanced/web/locales/en/translation.json @@ -128,6 +128,15 @@ "light": "Light", "auto": "Auto" }, + "timeUnits": { + "seconds": "seconds", + "minutes": "minutes", + "hours": "hours", + "days": "days", + "ago": "ago", + "justNow": "just now", + "about": "about" + }, "status": { "connected": "Connected", "connecting": "Connecting...", @@ -205,7 +214,7 @@ "refresh": "Refresh", "noHistory": "No session history", "todaySessions": "Today's Sessions", - "averageDuration": "Average Duration", + "todayAverageDuration": "Today's Average Duration", "createdTime": "Created Time", "project": "Project", "aiSummary": "AI Summary", @@ -411,6 +420,7 @@ "title": "Audio Notification Settings", "description": "Configure audio notifications for session updates", "enabled": "Enable Audio Notifications", + "enabledDesc": "Play audio notifications when there are new session updates", "volume": "Volume", "selectAudio": "Select Audio", "testPlay": "Test Play", diff --git a/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json b/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json index 5c7d697..9dfd2f4 100644 --- a/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json +++ b/src/mcp_feedback_enhanced/web/locales/zh-CN/translation.json @@ -128,6 +128,15 @@ "light": "浅色", "auto": "自动" }, + "timeUnits": { + "seconds": "秒", + "minutes": "分钟", + "hours": "小时", + "days": "天", + "ago": "前", + "justNow": "刚刚", + "about": "约" + }, "status": { "connected": "已连接", "connecting": "连接中...", @@ -205,7 +214,7 @@ "refresh": "重新整理", "noHistory": "暂无历史会话", "todaySessions": "今日会话", - "averageDuration": "平均时长", + "todayAverageDuration": "今日平均时长", "createdTime": "建立时间", "project": "项目", "aiSummary": "AI 总结", @@ -411,6 +420,7 @@ "title": "音效通知设定", "description": "设定会话更新时的音效通知", "enabled": "启用音效通知", + "enabledDesc": "启用后将在有新会话更新时播放音效通知", "volume": "音量", "selectAudio": "选择音效", "testPlay": "测试播放", diff --git a/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json b/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json index 90d26f6..a31ff2a 100644 --- a/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json +++ b/src/mcp_feedback_enhanced/web/locales/zh-TW/translation.json @@ -133,6 +133,15 @@ "light": "淺色", "auto": "自動" }, + "timeUnits": { + "seconds": "秒", + "minutes": "分鐘", + "hours": "小時", + "days": "天", + "ago": "前", + "justNow": "剛剛", + "about": "約" + }, "status": { "connected": "已連線", "connecting": "連線中...", @@ -210,7 +219,7 @@ "refresh": "重新整理", "noHistory": "暫無歷史會話", "todaySessions": "今日會話", - "averageDuration": "平均時長", + "todayAverageDuration": "今日平均時長", "createdTime": "建立時間", "project": "專案", "aiSummary": "AI 摘要", @@ -416,6 +425,7 @@ "title": "音效通知設定", "description": "設定會話更新時的音效通知", "enabled": "啟用音效通知", + "enabledDesc": "啟用後將在有新會話更新時播放音效通知", "volume": "音量", "selectAudio": "選擇音效", "testPlay": "測試播放", diff --git a/src/mcp_feedback_enhanced/web/static/css/styles.css b/src/mcp_feedback_enhanced/web/static/css/styles.css index d7864f8..0d67c00 100644 --- a/src/mcp_feedback_enhanced/web/static/css/styles.css +++ b/src/mcp_feedback_enhanced/web/static/css/styles.css @@ -1331,6 +1331,45 @@ h3.combined-section-title { margin: 0; } +/* Combined 標籤頁頂部佈局 */ +.combined-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + padding: 8px 12px; + gap: 16px; +} + +.combined-header .section-description { + flex: 1; + font-size: 13px; + margin: 0; + padding: 0; +} + +/* Combined 標籤頁提交按鈕樣式 */ +.combined-submit-btn { + flex-shrink: 0; + padding: 8px 16px; + font-size: 13px; + white-space: nowrap; +} + +/* 響應式設計 - 小螢幕時垂直排列 */ +@media (max-width: 768px) { + .combined-header { + flex-direction: column; + align-items: flex-start; + gap: 12px; + } + + .combined-submit-btn { + align-self: flex-end; + width: auto; + } +} + /* Placeholder 文本換行修復 - 全局樣式 */ textarea::placeholder, #feedbackText::placeholder, diff --git a/src/mcp_feedback_enhanced/web/static/js/app.js b/src/mcp_feedback_enhanced/web/static/js/app.js index 851c9fd..e25ebcd 100644 --- a/src/mcp_feedback_enhanced/web/static/js/app.js +++ b/src/mcp_feedback_enhanced/web/static/js/app.js @@ -240,8 +240,7 @@ return new Promise(function(resolve) { // 提交按鈕事件 const submitButtons = [ - window.MCPFeedback.Utils.safeQuerySelector('#submitBtn'), - window.MCPFeedback.Utils.safeQuerySelector('#combinedSubmitBtn') + window.MCPFeedback.Utils.safeQuerySelector('#submitBtn') ].filter(function(btn) { return btn !== null; }); submitButtons.forEach(function(button) { @@ -250,17 +249,7 @@ }); }); - // 取消按鈕事件 - const cancelButtons = [ - window.MCPFeedback.Utils.safeQuerySelector('#cancelBtn'), - window.MCPFeedback.Utils.safeQuerySelector('#combinedCancelBtn') - ].filter(function(btn) { return btn !== null; }); - - cancelButtons.forEach(function(button) { - button.addEventListener('click', function() { - self.cancelFeedback(); - }); - }); + // 取消按鈕事件 - 已移除取消按鈕,保留 ESC 快捷鍵功能 // 命令執行事件 const runCommandBtn = window.MCPFeedback.Utils.safeQuerySelector('#runCommandBtn'); diff --git a/src/mcp_feedback_enhanced/web/static/js/i18n.js b/src/mcp_feedback_enhanced/web/static/js/i18n.js index f022ce5..40dc4e5 100644 --- a/src/mcp_feedback_enhanced/web/static/js/i18n.js +++ b/src/mcp_feedback_enhanced/web/static/js/i18n.js @@ -218,6 +218,14 @@ class I18nManager { if (typeof window.feedbackApp.sessionManager.updateDisplay === 'function') { window.feedbackApp.sessionManager.updateDisplay(); } + + // 重新渲染統計資訊以更新時間單位 + if (window.feedbackApp.sessionManager.dataManager && + window.feedbackApp.sessionManager.uiRenderer) { + const stats = window.feedbackApp.sessionManager.dataManager.getStats(); + window.feedbackApp.sessionManager.uiRenderer.renderStats(stats); + console.log('🌐 已更新統計資訊的語言顯示'); + } } // 更新狀態徽章文字 diff --git a/src/mcp_feedback_enhanced/web/static/js/modules/audio/audio-settings-ui.js b/src/mcp_feedback_enhanced/web/static/js/modules/audio/audio-settings-ui.js index e0da350..bc24e70 100644 --- a/src/mcp_feedback_enhanced/web/static/js/modules/audio/audio-settings-ui.js +++ b/src/mcp_feedback_enhanced/web/static/js/modules/audio/audio-settings-ui.js @@ -79,11 +79,18 @@
-
- +
+
+
啟用音效通知
+
+ 啟用後將在有新會話更新時播放音效通知 +
+
+
+ +
@@ -156,8 +163,9 @@ // 啟用開關事件 if (this.enabledToggle) { - this.enabledToggle.addEventListener('change', function(e) { - self.handleEnabledChange(e.target.checked); + this.enabledToggle.addEventListener('click', function() { + const newValue = !self.enabledToggle.classList.contains('active'); + self.handleEnabledChange(newValue); }); } @@ -219,7 +227,7 @@ console.error('❌ 設定啟用狀態失敗:', error); this.showError(error.message); // 恢復原狀態 - this.enabledToggle.checked = this.audioManager.getSettings().enabled; + this.enabledToggle.classList.toggle('active', this.audioManager.getSettings().enabled); } }; @@ -342,7 +350,7 @@ // 更新啟用狀態 if (this.enabledToggle) { - this.enabledToggle.checked = settings.enabled; + this.enabledToggle.classList.toggle('active', settings.enabled); } // 更新音量 @@ -496,7 +504,7 @@ * 更新控制項狀態 */ AudioSettingsUI.prototype.updateControlsState = function() { - const enabled = this.enabledToggle ? this.enabledToggle.checked : false; + const enabled = this.enabledToggle ? this.enabledToggle.classList.contains('active') : false; // 根據啟用狀態禁用/啟用控制項 const controls = [ diff --git a/src/mcp_feedback_enhanced/web/static/js/modules/session/session-data-manager.js b/src/mcp_feedback_enhanced/web/static/js/modules/session/session-data-manager.js index c0d5b32..fb53b1c 100644 --- a/src/mcp_feedback_enhanced/web/static/js/modules/session/session-data-manager.js +++ b/src/mcp_feedback_enhanced/web/static/js/modules/session/session-data-manager.js @@ -29,8 +29,7 @@ // 統計數據 this.sessionStats = { todayCount: 0, - averageDuration: 0, - totalSessions: 0 + averageDuration: 0 }; // localStorage 相關設定 @@ -453,21 +452,20 @@ SessionDataManager.prototype.updateStats = function() { // 計算今日會話數 const todayStart = TimeUtils.getTodayStartTimestamp(); - this.sessionStats.todayCount = this.sessionHistory.filter(function(session) { + const todaySessions = this.sessionHistory.filter(function(session) { return session.created_at && session.created_at >= todayStart; - }).length; + }); + this.sessionStats.todayCount = todaySessions.length; - // 計算平均持續時間 - const completedSessions = this.sessionHistory.filter(s => s.duration && s.duration > 0); - if (completedSessions.length > 0) { - const totalDuration = completedSessions.reduce((sum, s) => sum + s.duration, 0); - this.sessionStats.averageDuration = Math.round(totalDuration / completedSessions.length); + // 計算今日平均持續時間 + const todayCompletedSessions = todaySessions.filter(s => s.duration && s.duration > 0); + if (todayCompletedSessions.length > 0) { + const totalDuration = todayCompletedSessions.reduce((sum, s) => sum + s.duration, 0); + this.sessionStats.averageDuration = Math.round(totalDuration / todayCompletedSessions.length); } else { this.sessionStats.averageDuration = 0; } - this.sessionStats.totalSessions = this.sessionHistory.length; - // 觸發回調 if (this.onStatsChange) { this.onStatsChange(this.sessionStats); @@ -671,7 +669,7 @@ const self = this; const exportData = { exportedAt: new Date().toISOString(), - totalSessions: this.sessionHistory.length, + sessionCount: this.sessionHistory.length, sessions: this.sessionHistory.map(function(session) { const sessionData = { session_id: session.session_id, @@ -774,8 +772,7 @@ this.lastStatusUpdate = null; this.sessionStats = { todayCount: 0, - averageDuration: 0, - totalSessions: 0 + averageDuration: 0 }; console.log('📊 SessionDataManager 清理完成'); diff --git a/src/mcp_feedback_enhanced/web/static/js/modules/session/session-ui-renderer.js b/src/mcp_feedback_enhanced/web/static/js/modules/session/session-ui-renderer.js index a1a21f6..a6c9408 100644 --- a/src/mcp_feedback_enhanced/web/static/js/modules/session/session-ui-renderer.js +++ b/src/mcp_feedback_enhanced/web/static/js/modules/session/session-ui-renderer.js @@ -51,8 +51,7 @@ // 統計元素 this.statsElements = { todayCount: DOMUtils.safeQuerySelector('.stat-today-count'), - averageDuration: DOMUtils.safeQuerySelector('.stat-average-duration'), - totalSessions: DOMUtils.safeQuerySelector('.stat-total-sessions') + averageDuration: DOMUtils.safeQuerySelector('.stat-average-duration') }; }; @@ -371,8 +370,7 @@ console.log('🎨 渲染統計資訊:', stats); console.log('🎨 統計元素狀態:', { todayCount: !!this.statsElements.todayCount, - averageDuration: !!this.statsElements.averageDuration, - totalSessions: !!this.statsElements.totalSessions + averageDuration: !!this.statsElements.averageDuration }); // 更新今日會話數 @@ -383,22 +381,14 @@ console.warn('🎨 找不到今日會話數元素 (.stat-today-count)'); } - // 更新平均時長 + // 更新今日平均時長 if (this.statsElements.averageDuration) { const durationText = TimeUtils.formatDuration(stats.averageDuration); DOMUtils.safeSetTextContent(this.statsElements.averageDuration, durationText); - console.log('🎨 已更新平均時長:', durationText); + console.log('🎨 已更新今日平均時長:', durationText); } else { console.warn('🎨 找不到平均時長元素 (.stat-average-duration)'); } - - // 更新總會話數 - if (this.statsElements.totalSessions) { - DOMUtils.safeSetTextContent(this.statsElements.totalSessions, stats.totalSessions.toString()); - console.log('🎨 已更新總會話數:', stats.totalSessions); - } else { - console.warn('🎨 找不到總會話數元素 (.stat-total-sessions)'); - } }; /** diff --git a/src/mcp_feedback_enhanced/web/static/js/modules/ui-manager.js b/src/mcp_feedback_enhanced/web/static/js/modules/ui-manager.js index e929185..09f73bc 100644 --- a/src/mcp_feedback_enhanced/web/static/js/modules/ui-manager.js +++ b/src/mcp_feedback_enhanced/web/static/js/modules/ui-manager.js @@ -204,8 +204,7 @@ */ UIManager.prototype.updateSubmitButton = function() { const submitButtons = [ - Utils.safeQuerySelector('#submitBtn'), - Utils.safeQuerySelector('#combinedSubmitBtn') + Utils.safeQuerySelector('#submitBtn') ].filter(function(btn) { return btn !== null; }); const self = this; @@ -404,8 +403,7 @@ // 重新啟用提交按鈕 const submitButtons = [ - Utils.safeQuerySelector('#submitBtn'), - Utils.safeQuerySelector('#combinedSubmitBtn') + Utils.safeQuerySelector('#submitBtn') ].filter(function(btn) { return btn !== null; }); submitButtons.forEach(function(button) { diff --git a/src/mcp_feedback_enhanced/web/static/js/modules/utils/time-utils.js b/src/mcp_feedback_enhanced/web/static/js/modules/utils/time-utils.js index 728e573..195ada9 100644 --- a/src/mcp_feedback_enhanced/web/static/js/modules/utils/time-utils.js +++ b/src/mcp_feedback_enhanced/web/static/js/modules/utils/time-utils.js @@ -63,26 +63,55 @@ }, /** - * 格式化持續時間(秒) + * 格式化持續時間(秒)- 支援國際化 */ formatDuration: function(seconds) { - if (!seconds || seconds < 0) return '0秒'; + if (!seconds || seconds < 0) { + const secondsText = this.getTimeUnitText('seconds'); + return `0${secondsText}`; + } const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const remainingSeconds = Math.floor(seconds % 60); + const hoursText = this.getTimeUnitText('hours'); + const minutesText = this.getTimeUnitText('minutes'); + const secondsText = this.getTimeUnitText('seconds'); + if (hours > 0) { - return `${hours}小時${minutes > 0 ? minutes + '分鐘' : ''}`; + return `${hours}${hoursText}${minutes > 0 ? minutes + minutesText : ''}`; } else if (minutes > 0) { - return `${minutes}分鐘${remainingSeconds > 0 ? remainingSeconds + '秒' : ''}`; + return `${minutes}${minutesText}${remainingSeconds > 0 ? remainingSeconds + secondsText : ''}`; } else { - return `${remainingSeconds}秒`; + return `${remainingSeconds}${secondsText}`; } }, /** - * 格式化相對時間(多久之前) + * 獲取時間單位文字(支援國際化) + */ + getTimeUnitText: function(unit) { + if (window.i18nManager && typeof window.i18nManager.t === 'function') { + return window.i18nManager.t(`timeUnits.${unit}`, unit); + } + + // 回退到預設值(繁體中文) + const fallbackUnits = { + 'seconds': '秒', + 'minutes': '分鐘', + 'hours': '小時', + 'days': '天', + 'ago': '前', + 'justNow': '剛剛', + 'about': '約' + }; + + return fallbackUnits[unit] || unit; + }, + + /** + * 格式化相對時間(多久之前)- 支援國際化 */ formatRelativeTime: function(timestamp) { if (!timestamp) return '未知'; @@ -96,17 +125,23 @@ const now = Date.now() / 1000; const diff = now - normalizedTimestamp; + const minutesText = this.getTimeUnitText('minutes'); + const hoursText = this.getTimeUnitText('hours'); + const daysText = this.getTimeUnitText('days'); + const agoText = this.getTimeUnitText('ago'); + const justNowText = this.getTimeUnitText('justNow'); + if (diff < 60) { - return '剛剛'; + return justNowText; } else if (diff < 3600) { const minutes = Math.floor(diff / 60); - return `${minutes}分鐘前`; + return `${minutes}${minutesText}${agoText}`; } else if (diff < 86400) { const hours = Math.floor(diff / 3600); - return `${hours}小時前`; + return `${hours}${hoursText}${agoText}`; } else { const days = Math.floor(diff / 86400); - return `${days}天前`; + return `${days}${daysText}${agoText}`; } } catch (error) { console.warn('相對時間計算失敗:', timestamp, error); @@ -353,7 +388,7 @@ }, /** - * 估算會話持續時間(用於歷史會話) + * 估算會話持續時間(用於歷史會話)- 支援國際化 */ estimateSessionDuration: function(sessionData) { // 基礎時間 2 分鐘 @@ -377,7 +412,9 @@ // 限制在合理範圍內 estimatedMinutes = Math.max(1, Math.min(estimatedMinutes, 15)); - return `約 ${estimatedMinutes} 分鐘`; + const aboutText = this.getTimeUnitText('about'); + const minutesText = this.getTimeUnitText('minutes'); + return `${aboutText} ${estimatedMinutes} ${minutesText}`; }, /** diff --git a/src/mcp_feedback_enhanced/web/templates/feedback.html b/src/mcp_feedback_enhanced/web/templates/feedback.html index 7900cba..66ec327 100644 --- a/src/mcp_feedback_enhanced/web/templates/feedback.html +++ b/src/mcp_feedback_enhanced/web/templates/feedback.html @@ -481,7 +481,7 @@
--
-
平均時長
+
今日平均時長
@@ -642,8 +642,13 @@
-
- AI 摘要和回饋輸入在同一頁面中,方便對照查看。 +
+
+ AI 摘要和回饋輸入在同一頁面中,方便對照查看。 +
+
@@ -1078,15 +1083,7 @@
- -
- - -
+