更新翻譯文件,將「合併模式」更名為「工作區」,並調整相關描述;新增自動刷新功能的界面元素及樣式,提升使用者體驗與界面一致性。

This commit is contained in:
Minidoracat 2025-06-07 04:22:24 +08:00
parent b9d781f147
commit 568f7d986c
8 changed files with 448 additions and 111 deletions

View File

@ -10,7 +10,7 @@
"commands": "⚡ Commands",
"command": "⚡ Commands",
"settings": "⚙️ Settings",
"combined": "📝 Combined Mode",
"combined": "📝 Workspace",
"about": " About"
},
"feedback": {
@ -73,7 +73,7 @@
"history": "Command History"
},
"combined": {
"description": "Combined mode: AI summary and feedback input are on the same page for easy comparison.",
"description": "AI summary and feedback input are on the same page for easy comparison.",
"summaryTitle": "📋 AI Work Summary",
"feedbackTitle": "💬 Provide Feedback"
},
@ -86,12 +86,10 @@
"interface": "Interface Settings",
"layoutMode": "Interface Layout Mode",
"layoutModeDesc": "Select how AI summary and feedback input are displayed",
"separateMode": "Separate Mode",
"separateModeDesc": "AI summary and feedback are in separate tabs",
"combinedVertical": "Combined Mode (Vertical Layout)",
"combinedVerticalDesc": "AI summary on top, feedback input below, both on the same page",
"combinedHorizontal": "Combined Mode (Horizontal Layout)",
"combinedHorizontalDesc": "AI summary on left, feedback input on right, expanding summary viewing area",
"combinedVertical": "Vertical Layout",
"combinedVerticalDesc": "AI summary on top, feedback input below, suitable for standard screens",
"combinedHorizontal": "Horizontal Layout",
"combinedHorizontalDesc": "AI summary on left, feedback input on right, suitable for widescreen displays",
"autoClose": "Auto Close Page",
"autoCloseDesc": "Automatically close page after submitting feedback",
"theme": "Theme",
@ -172,6 +170,15 @@
"timeoutDescription": "Due to prolonged inactivity, the session has timed out. The interface will automatically close in 3 seconds.",
"closing": "Closing..."
},
"autoRefresh": {
"enable": "Auto Detect",
"seconds": "seconds",
"disabled": "Disabled",
"enabled": "Detecting",
"checking": "Checking",
"detected": "Detected",
"error": "Failed"
},
"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!",

View File

@ -10,7 +10,7 @@
"commands": "⚡ 命令",
"command": "⚡ 命令",
"settings": "⚙️ 设置",
"combined": "📝 合并模式",
"combined": "📝 工作区",
"about": " 关于"
},
"feedback": {
@ -73,7 +73,7 @@
"history": "命令历史"
},
"combined": {
"description": "合并模式:AI 摘要和反馈输入在同一页面中,方便对照查看。",
"description": "AI 摘要和反馈输入在同一页面中,方便对照查看。",
"summaryTitle": "📋 AI 工作摘要",
"feedbackTitle": "💬 提供反馈"
},
@ -86,12 +86,10 @@
"interface": "界面设定",
"layoutMode": "界面布局模式",
"layoutModeDesc": "选择 AI 摘要和反馈输入的显示方式",
"separateMode": "分离模式",
"separateModeDesc": "AI 摘要和反馈分别在不同页签",
"combinedVertical": "合并模式(垂直布局)",
"combinedVerticalDesc": "AI 摘要在上,反馈输入在下,摘要和反馈在同一页面",
"combinedHorizontal": "合并模式(水平布局)",
"combinedHorizontalDesc": "AI 摘要在左,反馈输入在右,增大摘要可视区域",
"combinedVertical": "垂直布局",
"combinedVerticalDesc": "AI 摘要在上,反馈输入在下,适合标准屏幕使用",
"combinedHorizontal": "水平布局",
"combinedHorizontalDesc": "AI 摘要在左,反馈输入在右,适合宽屏幕使用",
"autoClose": "自动关闭页面",
"autoCloseDesc": "提交回馈后自动关闭页面",
"theme": "主题",
@ -172,6 +170,15 @@
"timeoutDescription": "由于长时间无响应,会话已超时。界面将在 3 秒后自动关闭。",
"closing": "正在关闭..."
},
"autoRefresh": {
"enable": "自动检测",
"seconds": "秒",
"disabled": "停用",
"enabled": "检测中",
"checking": "检查中",
"detected": "已检测",
"error": "失败"
},
"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请测试这些功能并提供反馈",

View File

@ -10,7 +10,7 @@
"commands": "⚡ 命令",
"command": "⚡ 命令",
"settings": "⚙️ 設定",
"combined": "📝 合併模式",
"combined": "📝 工作區",
"about": " 關於"
},
"feedback": {
@ -73,7 +73,7 @@
"history": "命令歷史"
},
"combined": {
"description": "合併模式:AI 摘要和回饋輸入在同一頁面中,方便對照查看。",
"description": "AI 摘要和回饋輸入在同一頁面中,方便對照查看。",
"summaryTitle": "📋 AI 工作摘要",
"feedbackTitle": "💬 提供回饋"
},
@ -86,12 +86,10 @@
"interface": "介面設定",
"layoutMode": "界面佈局模式",
"layoutModeDesc": "選擇 AI 摘要和回饋輸入的顯示方式",
"separateMode": "分離模式",
"separateModeDesc": "AI 摘要和回饋分別在不同頁籤",
"combinedVertical": "合併模式(垂直布局)",
"combinedVerticalDesc": "AI 摘要在上,回饋輸入在下,摘要和回饋在同一頁面",
"combinedHorizontal": "合併模式(水平布局)",
"combinedHorizontalDesc": "AI 摘要在左,回饋輸入在右,增大摘要可視區域",
"combinedVertical": "垂直佈局",
"combinedVerticalDesc": "AI 摘要在上,回饋輸入在下,適合標準螢幕使用",
"combinedHorizontal": "水平佈局",
"combinedHorizontalDesc": "AI 摘要在左,回饋輸入在右,適合寬螢幕使用",
"autoClose": "自動關閉頁面",
"autoCloseDesc": "提交回饋後自動關閉頁面",
"theme": "主題",
@ -172,6 +170,15 @@
"timeoutDescription": "由於長時間無回應,會話已超時。介面將在 3 秒後自動關閉。",
"closing": "正在關閉..."
},
"autoRefresh": {
"enable": "自動檢測",
"seconds": "秒",
"disabled": "停用",
"enabled": "檢測中",
"checking": "檢查中",
"detected": "已檢測",
"error": "失敗"
},
"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請測試這些功能並提供回饋",

View File

@ -33,15 +33,15 @@ def load_user_layout_settings() -> str:
if settings_file.exists():
with open(settings_file, 'r', encoding='utf-8') as f:
settings = json.load(f)
layout_mode = settings.get('layoutMode', 'separate')
layout_mode = settings.get('layoutMode', 'combined-vertical')
debug_log(f"從設定檔案載入佈局模式: {layout_mode}")
return layout_mode
else:
debug_log("設定檔案不存在,使用預設佈局模式: separate")
return 'separate'
debug_log("設定檔案不存在,使用預設佈局模式: combined-vertical")
return 'combined-vertical'
except Exception as e:
debug_log(f"載入佈局設定失敗: {e},使用預設佈局模式: separate")
return 'separate'
debug_log(f"載入佈局設定失敗: {e},使用預設佈局模式: combined-vertical")
return 'combined-vertical'
def setup_routes(manager: 'WebUIManager'):

View File

@ -1265,4 +1265,128 @@ body {
.compatibility-hint-btn:hover {
background: #f57c00;
}
/* 自動刷新控制項樣式 */
.section-header-with-controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
/* AI 工作摘要標題樣式 */
h3.combined-section-title {
font-size: 16px;
font-weight: 600;
color: var(--text-primary);
margin: 0;
}
.auto-refresh-controls {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
background: var(--bg-tertiary);
border: 1px solid var(--border-color);
border-radius: 6px;
padding: 6px 10px;
transition: all 0.3s ease;
}
.auto-refresh-controls:hover {
border-color: var(--accent-color);
background: var(--surface-color);
}
.auto-refresh-toggle {
display: flex;
align-items: center;
gap: 4px;
cursor: pointer;
user-select: none;
}
.auto-refresh-toggle input[type="checkbox"] {
appearance: none;
width: 14px;
height: 14px;
border: 1px solid var(--border-color);
border-radius: 2px;
background: var(--bg-primary);
cursor: pointer;
transition: all 0.3s ease;
position: relative;
}
.auto-refresh-toggle input[type="checkbox"]:checked {
background: var(--accent-color);
border-color: var(--accent-color);
}
.auto-refresh-toggle input[type="checkbox"]:checked::after {
content: '✓';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 9px;
font-weight: bold;
}
.toggle-label {
color: var(--text-primary);
font-size: 14px;
font-weight: 500;
white-space: nowrap;
}
.auto-refresh-interval {
display: flex;
align-items: center;
gap: 2px;
}
.auto-refresh-interval input[type="number"] {
width: 50px;
background: var(--bg-primary);
color: var(--text-primary);
border: 1px solid var(--border-color);
border-radius: 3px;
padding: 4px 6px;
font-size: 13px;
text-align: center;
}
.auto-refresh-interval input[type="number"]:focus {
outline: none;
border-color: var(--accent-color);
}
.interval-unit {
color: var(--text-secondary);
font-size: 14px;
white-space: nowrap;
}
.auto-refresh-status {
display: flex;
align-items: center;
gap: 3px;
padding: 1px 4px;
background: var(--bg-primary);
border-radius: 3px;
border: 1px solid var(--border-color);
}
.auto-refresh-status .status-indicator {
font-size: 13px;
}
.auto-refresh-status .status-text {
color: var(--text-secondary);
font-size: 14px;
white-space: nowrap;
}

View File

@ -185,11 +185,17 @@ class FeedbackApp {
// 設定
this.autoClose = false;
this.layoutMode = 'separate';
this.layoutMode = 'combined-vertical';
// 語言設定
this.currentLanguage = 'zh-TW';
// 自動刷新設定
this.autoRefreshEnabled = false;
this.autoRefreshInterval = 5; // 默認5秒
this.autoRefreshTimer = null;
this.lastKnownSessionId = null;
this.init();
}
@ -223,6 +229,9 @@ class FeedbackApp {
// 確保狀態指示器使用正確的翻譯(在國際化系統載入後)
this.updateStatusIndicators();
// 初始化自動刷新功能
this.initAutoRefresh();
// 設置頁面關閉時的清理
window.addEventListener('beforeunload', () => {
if (this.tabManager) {
@ -231,6 +240,9 @@ class FeedbackApp {
if (this.heartbeatInterval) {
clearInterval(this.heartbeatInterval);
}
if (this.autoRefreshTimer) {
clearInterval(this.autoRefreshTimer);
}
});
console.log('MCP Feedback Enhanced 應用程式初始化完成');
@ -259,6 +271,12 @@ class FeedbackApp {
this.commandOutput = document.getElementById('commandOutput');
this.runCommandBtn = document.getElementById('runCommandBtn');
// 自動刷新相關元素
this.autoRefreshCheckbox = document.getElementById('autoRefreshEnabled');
this.autoRefreshIntervalInput = document.getElementById('autoRefreshInterval');
this.refreshStatusIndicator = document.getElementById('refreshStatusIndicator');
this.refreshStatusText = document.getElementById('refreshStatusText');
// 動態初始化圖片相關元素
this.initImageElements();
}
@ -1016,7 +1034,7 @@ class FeedbackApp {
if (event.code !== 1000 && this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
const delay = Math.min(3000 * this.reconnectAttempts, 15000); // 最大延遲15秒
console.log(`${delay/1000}秒後嘗試重連... (第${this.reconnectAttempts}次)`);
console.log(`${delay / 1000}秒後嘗試重連... (第${this.reconnectAttempts}次)`);
setTimeout(() => {
console.log(`🔄 開始重連 WebSocket... (第${this.reconnectAttempts}次)`);
this.setupWebSocket();
@ -1410,9 +1428,9 @@ class FeedbackApp {
word-wrap: break-word;
`;
messageDiv.textContent = message;
document.body.appendChild(messageDiv);
// 3秒後自動移除
setTimeout(() => {
if (messageDiv.parentNode) {
@ -1450,12 +1468,12 @@ class FeedbackApp {
async loadFeedbackInterface(sessionInfo) {
if (!this.mainContainer) return;
this.sessionInfo = sessionInfo;
// 載入完整的回饋界面
this.mainContainer.innerHTML = await this.generateFeedbackHTML(sessionInfo);
// 重新設置事件監聽器
this.setupFeedbackEventListeners();
}
@ -1801,6 +1819,8 @@ class FeedbackApp {
this.currentLanguage = settings.language || 'zh-TW';
this.imageSizeLimit = settings.imageSizeLimit || 0;
this.enableBase64Detail = settings.enableBase64Detail || false;
this.autoRefreshEnabled = settings.autoRefreshEnabled || false;
this.autoRefreshInterval = settings.autoRefreshInterval || 5;
// 處理 activeTab 設定
if (settings.activeTab) {
@ -1846,6 +1866,8 @@ class FeedbackApp {
language: this.currentLanguage,
imageSizeLimit: this.imageSizeLimit,
enableBase64Detail: this.enableBase64Detail,
autoRefreshEnabled: this.autoRefreshEnabled,
autoRefreshInterval: this.autoRefreshInterval,
activeTab: this.currentTab
};
@ -1904,6 +1926,15 @@ class FeedbackApp {
if (this.enableBase64DetailCheckbox) {
this.enableBase64DetailCheckbox.checked = this.enableBase64Detail;
}
// 應用自動刷新設定
if (this.autoRefreshCheckbox) {
this.autoRefreshCheckbox.checked = this.autoRefreshEnabled;
}
if (this.autoRefreshIntervalInput) {
this.autoRefreshIntervalInput.value = this.autoRefreshInterval;
}
}
applyLayoutMode() {
@ -1927,18 +1958,11 @@ class FeedbackApp {
// 同步合併佈局和分頁中的內容
this.syncCombinedLayoutContent();
// 如果是合併模式,確保內容同步
if (this.layoutMode.startsWith('combined')) {
this.setupCombinedModeSync();
// 如果當前頁籤不是合併模式,則切換到合併模式頁籤
if (this.currentTab !== 'combined') {
this.currentTab = 'combined';
}
} else {
// 分離模式時,如果當前頁籤是合併模式,則切換到回饋頁籤
if (this.currentTab === 'combined') {
this.currentTab = 'feedback';
}
// 確保合併模式內容同步
this.setupCombinedModeSync();
// 如果當前頁籤不是合併模式,則切換到合併模式頁籤
if (this.currentTab !== 'combined') {
this.currentTab = 'combined';
}
}
@ -1947,17 +1971,10 @@ class FeedbackApp {
const feedbackTab = document.querySelector('.tab-button[data-tab="feedback"]');
const summaryTab = document.querySelector('.tab-button[data-tab="summary"]');
if (this.layoutMode.startsWith('combined')) {
// 合併模式顯示合併模式頁籤隱藏回饋和AI摘要頁籤
if (combinedTab) combinedTab.style.display = 'inline-block';
if (feedbackTab) feedbackTab.style.display = 'none';
if (summaryTab) summaryTab.style.display = 'none';
} else {
// 分離模式隱藏合併模式頁籤顯示回饋和AI摘要頁籤
if (combinedTab) combinedTab.style.display = 'none';
if (feedbackTab) feedbackTab.style.display = 'inline-block';
if (summaryTab) summaryTab.style.display = 'inline-block';
}
// 只使用合併模式顯示合併模式頁籤隱藏回饋和AI摘要頁籤
if (combinedTab) combinedTab.style.display = 'inline-block';
if (feedbackTab) feedbackTab.style.display = 'none';
if (summaryTab) summaryTab.style.display = 'none';
}
syncCombinedLayoutContent() {
@ -2012,27 +2029,6 @@ class FeedbackApp {
}
setupCombinedModeSync() {
// 設置文字輸入的雙向同步
const feedbackText = document.getElementById('feedbackText');
const combinedFeedbackText = document.getElementById('combinedFeedbackText');
if (feedbackText && combinedFeedbackText) {
// 移除舊的事件監聽器(如果存在)
feedbackText.removeEventListener('input', this.syncToCombinetText);
combinedFeedbackText.removeEventListener('input', this.syncToSeparateText);
// 添加新的事件監聽器
this.syncToCombinetText = (e) => {
combinedFeedbackText.value = e.target.value;
};
this.syncToSeparateText = (e) => {
feedbackText.value = e.target.value;
};
feedbackText.addEventListener('input', this.syncToCombinetText);
combinedFeedbackText.addEventListener('input', this.syncToSeparateText);
}
// 設置圖片設定的同步
this.setupImageSettingsSync();
@ -2111,11 +2107,13 @@ class FeedbackApp {
resetSettings() {
localStorage.removeItem('mcp-feedback-settings');
this.layoutMode = 'separate';
this.layoutMode = 'combined-vertical';
this.autoClose = false;
this.currentLanguage = 'zh-TW';
this.imageSizeLimit = 0;
this.enableBase64Detail = false;
this.autoRefreshEnabled = false;
this.autoRefreshInterval = 5;
this.applySettings();
this.saveSettings();
}
@ -2169,6 +2167,197 @@ class FeedbackApp {
// 不需要手動複製updateStatusIndicator() 會處理所有狀態指示器
}
/**
* 初始化自動刷新功能
*/
initAutoRefresh() {
console.log('🔄 初始化自動刷新功能...');
// 檢查必要元素是否存在
if (!this.autoRefreshCheckbox || !this.autoRefreshIntervalInput) {
console.warn('⚠️ 自動刷新元素不存在,跳過初始化');
return;
}
// 設置開關事件監聽器
this.autoRefreshCheckbox.addEventListener('change', (e) => {
this.autoRefreshEnabled = e.target.checked;
this.handleAutoRefreshToggle();
this.saveSettings();
});
// 設置間隔輸入事件監聽器
this.autoRefreshIntervalInput.addEventListener('change', (e) => {
const newInterval = parseInt(e.target.value);
if (newInterval >= 5 && newInterval <= 300) {
this.autoRefreshInterval = newInterval;
this.saveSettings();
// 如果自動刷新已啟用,重新啟動定時器
if (this.autoRefreshEnabled) {
this.stopAutoRefresh();
this.startAutoRefresh();
}
}
});
// 從設定中恢復狀態
this.autoRefreshCheckbox.checked = this.autoRefreshEnabled;
this.autoRefreshIntervalInput.value = this.autoRefreshInterval;
// 延遲更新狀態指示器,確保 i18n 已完全載入
setTimeout(() => {
this.updateAutoRefreshStatus();
}, 100);
console.log('✅ 自動刷新功能初始化完成');
}
/**
* 處理自動刷新開關切換
*/
handleAutoRefreshToggle() {
if (this.autoRefreshEnabled) {
this.startAutoRefresh();
} else {
this.stopAutoRefresh();
}
this.updateAutoRefreshStatus();
}
/**
* 啟動自動刷新
*/
startAutoRefresh() {
if (this.autoRefreshTimer) {
clearInterval(this.autoRefreshTimer);
}
// 記錄當前會話 ID
this.lastKnownSessionId = this.currentSessionId;
this.autoRefreshTimer = setInterval(() => {
this.checkForSessionUpdate();
}, this.autoRefreshInterval * 1000);
console.log(`🔄 自動刷新已啟動,間隔: ${this.autoRefreshInterval}`);
}
/**
* 停止自動刷新
*/
stopAutoRefresh() {
if (this.autoRefreshTimer) {
clearInterval(this.autoRefreshTimer);
this.autoRefreshTimer = null;
}
console.log('⏸️ 自動刷新已停止');
}
/**
* 檢查會話更新
*/
async checkForSessionUpdate() {
try {
this.updateAutoRefreshStatus('checking');
const response = await fetch('/api/current-session');
if (!response.ok) {
throw new Error(`API 請求失敗: ${response.status}`);
}
const sessionData = await response.json();
// 檢查會話 ID 是否變化
if (sessionData.session_id && sessionData.session_id !== this.lastKnownSessionId) {
console.log(`🔄 檢測到新會話: ${this.lastKnownSessionId} -> ${sessionData.session_id}`);
// 更新記錄的會話 ID
this.lastKnownSessionId = sessionData.session_id;
this.currentSessionId = sessionData.session_id;
// 觸發局部刷新
await this.updatePageContentPartially();
this.updateAutoRefreshStatus('detected');
// 短暫顯示檢測成功狀態,然後恢復為檢測中
setTimeout(() => {
if (this.autoRefreshEnabled) {
this.updateAutoRefreshStatus('enabled');
}
}, 2000);
} else {
this.updateAutoRefreshStatus('enabled');
}
} catch (error) {
console.error('❌ 自動刷新檢測失敗:', error);
this.updateAutoRefreshStatus('error');
// 短暫顯示錯誤狀態,然後恢復
setTimeout(() => {
if (this.autoRefreshEnabled) {
this.updateAutoRefreshStatus('enabled');
}
}, 3000);
}
}
/**
* 更新自動刷新狀態指示器
*/
updateAutoRefreshStatus(status = null) {
console.log(`🔧 updateAutoRefreshStatus 被調用status: ${status}`);
console.log(`🔧 refreshStatusIndicator: ${this.refreshStatusIndicator ? 'found' : 'null'}`);
console.log(`🔧 refreshStatusText: ${this.refreshStatusText ? 'found' : 'null'}`);
if (!this.refreshStatusIndicator || !this.refreshStatusText) {
console.log(`⚠️ 自動檢測狀態元素未找到,跳過更新`);
return;
}
let indicator = '⏸️';
let textKey = 'autoRefresh.disabled';
if (status === null) {
status = this.autoRefreshEnabled ? 'enabled' : 'disabled';
}
switch (status) {
case 'enabled':
indicator = '🔄';
textKey = 'autoRefresh.enabled';
break;
case 'checking':
indicator = '🔍';
textKey = 'autoRefresh.checking';
break;
case 'detected':
indicator = '✅';
textKey = 'autoRefresh.detected';
break;
case 'error':
indicator = '❌';
textKey = 'autoRefresh.error';
break;
case 'disabled':
default:
indicator = '⏸️';
textKey = 'autoRefresh.disabled';
break;
}
this.refreshStatusIndicator.textContent = indicator;
// 使用多語系翻譯
const translatedText = window.i18nManager.t(textKey);
console.log(`🔄 自動檢測狀態翻譯: ${textKey} -> ${translatedText} (語言: ${window.i18nManager.currentLanguage})`);
this.refreshStatusText.textContent = translatedText;
}
}

View File

@ -178,6 +178,10 @@ class I18nManager {
if (window.feedbackApp) {
window.feedbackApp.updateUIState();
window.feedbackApp.updateStatusIndicator();
// 更新自動檢測狀態文字
if (window.feedbackApp.updateAutoRefreshStatus) {
window.feedbackApp.updateAutoRefreshStatus();
}
}
}

View File

@ -23,18 +23,8 @@
/* 頁面特定的佈局模式樣式 */
/* 佈局模式樣式 */
/* 預設分離模式 - 顯示回饋和AI摘要頁籤隱藏合併模式頁籤 */
body.layout-separate .tab-button[data-tab="combined"] {
display: none;
}
body.layout-separate .tab-button[data-tab="feedback"],
body.layout-separate .tab-button[data-tab="summary"] {
display: inline-block;
}
/* 合併模式 - 顯示合併模式頁籤隱藏回饋和AI摘要頁籤 */
/* 佈局模式樣式 - 工作區模式 */
/* 工作區模式 - 顯示工作區頁籤隱藏回饋和AI摘要頁籤 */
body.layout-combined-vertical .tab-button[data-tab="combined"],
body.layout-combined-horizontal .tab-button[data-tab="combined"] {
display: inline-block;
@ -62,7 +52,7 @@
/* 合併模式分頁的水平佈局樣式 */
/* 工作區分頁的水平佈局樣式 */
#tab-combined.active.combined-horizontal .combined-content {
display: flex !important;
flex-direction: row !important;
@ -99,7 +89,7 @@
min-height: 200px;
}
/* 合併模式分頁的垂直佈局樣式 */
/* 工作區分頁的垂直佈局樣式 */
#tab-combined.active.combined-vertical .combined-content {
display: flex !important;
flex-direction: column !important;
@ -144,7 +134,7 @@
flex: 1;
}
/* 合併模式基礎樣式 */
/* 工作區基礎樣式 */
.combined-section {
background: var(--bg-tertiary);
border: 1px solid var(--border-color);
@ -395,9 +385,9 @@
<!-- 分頁導航 -->
<div class="tabs">
<div class="tab-buttons">
<!-- 合併模式分頁 - 移到最左邊第一個 -->
<!-- 工作區分頁 - 移到最左邊第一個 -->
<button class="tab-button hidden" data-tab="combined" data-i18n="tabs.combined">
📝 合併模式
📝 工作區
</button>
<button class="tab-button active" data-tab="feedback" data-i18n="tabs.feedback">
💬 回饋
@ -499,16 +489,32 @@
</div>
</div>
<!-- 合併模式分頁 - 移動到此位置 -->
<!-- 工作區分頁 - 移動到此位置 -->
<div id="tab-combined" class="tab-content">
<div class="section-description" style="margin-bottom: 12px; padding: 8px 12px; font-size: 13px;" data-i18n="combined.description">
合併模式:AI 摘要和回饋輸入在同一頁面中,方便對照查看。
AI 摘要和回饋輸入在同一頁面中,方便對照查看。
</div>
<div class="combined-content">
<!-- AI 摘要區域 -->
<div class="combined-section">
<h3 class="combined-section-title" data-i18n="combined.summaryTitle">📋 AI 工作摘要</h3>
<div class="section-header-with-controls">
<h3 class="combined-section-title" data-i18n="combined.summaryTitle">📋 AI 工作摘要</h3>
<div class="auto-refresh-controls">
<label class="auto-refresh-toggle">
<input type="checkbox" id="autoRefreshEnabled" />
<span class="toggle-label" data-i18n="autoRefresh.enable"></span>
</label>
<div class="auto-refresh-interval">
<input type="number" id="autoRefreshInterval" min="5" max="300" value="5" />
<span class="interval-unit" data-i18n="autoRefresh.seconds"></span>
</div>
<div class="auto-refresh-status" id="autoRefreshStatus">
<span class="status-indicator" id="refreshStatusIndicator">⏸️</span>
<span class="status-text" id="refreshStatusText" data-i18n="autoRefresh.disabled"></span>
</div>
</div>
</div>
<div class="combined-summary">
<div id="combinedSummaryContent" class="text-input" style="min-height: 200px; white-space: pre-wrap !important; cursor: text; padding: 12px; line-height: 1.6; word-wrap: break-word; overflow-wrap: break-word;" data-dynamic-content="aiSummary">{{ summary }}</div>
</div>
@ -570,23 +576,16 @@
</div>
<div class="layout-mode-selector">
<div class="layout-option">
<input type="radio" id="separateMode" name="layoutMode" value="separate" checked>
<label for="separateMode">
<div class="layout-option-title" data-i18n="settings.separateMode">分離模式</div>
<div class="layout-option-desc" data-i18n="settings.separateModeDesc">AI 摘要和回饋分別在不同頁籤</div>
</label>
</div>
<div class="layout-option">
<input type="radio" id="combinedVertical" name="layoutMode" value="combined-vertical">
<input type="radio" id="combinedVertical" name="layoutMode" value="combined-vertical" checked>
<label for="combinedVertical">
<div class="layout-option-title" data-i18n="settings.combinedVertical">合併模式(垂直布局</div>
<div class="layout-option-title" data-i18n="settings.combinedVertical">垂直布局</div>
<div class="layout-option-desc" data-i18n="settings.combinedVerticalDesc">AI 摘要在上,回饋輸入在下,摘要和回饋在同一頁面</div>
</label>
</div>
<div class="layout-option">
<input type="radio" id="combinedHorizontal" name="layoutMode" value="combined-horizontal">
<label for="combinedHorizontal">
<div class="layout-option-title" data-i18n="settings.combinedHorizontal">合併模式(水平布局</div>
<div class="layout-option-title" data-i18n="settings.combinedHorizontal">水平布局</div>
<div class="layout-option-desc" data-i18n="settings.combinedHorizontalDesc">AI 摘要在左,回饋輸入在右,增大摘要可視區域</div>
</label>
</div>