🐛 修復 Copilot 審查問題並完善會話歷史 i18n 支援

- 修復 fallbackCopyTextToClipboard 函數定義順序錯誤
  - 修復會話歷史區塊語言切換不生效問題
  - 修復 renderHistory 函數名稱錯誤
  - 添加複製按鈕的多語言支援
  - 優化調試日誌管理,添加 DEBUG_MODE 控制
  - 統一程式碼註釋為繁體中文
This commit is contained in:
Minidoracat 2025-06-27 11:47:11 +08:00
parent 788d7b61cc
commit de6838c79c
7 changed files with 220 additions and 173 deletions

View File

@ -238,7 +238,10 @@
"summary": "Summary",
"noSummary": "No summary available",
"unknown": "Unknown"
}
},
"copySessionContent": "Copy Session Content",
"copyUserContent": "Copy User Content",
"exportSession": "Export This Session"
},
"sessionHistory": {
"management": {

View File

@ -238,7 +238,10 @@
"summary": "总结",
"noSummary": "暂无总结",
"unknown": "未知"
}
},
"copySessionContent": "复制会话内容",
"copyUserContent": "复制用户内容",
"exportSession": "导出此会话"
},
"sessionHistory": {
"management": {

View File

@ -243,7 +243,10 @@
"noSummary": "暫無摘要",
"unknown": "未知"
},
"noSummary": "無摘要"
"noSummary": "無摘要",
"copySessionContent": "複製會話內容",
"copyUserContent": "複製用戶內容",
"exportSession": "匯出此會話"
},
"sessionHistory": {
"management": {

View File

@ -227,6 +227,11 @@ class I18nManager {
const stats = window.feedbackApp.sessionManager.dataManager.getStats();
window.feedbackApp.sessionManager.uiRenderer.renderStats(stats);
console.log('🌐 已更新統計資訊的語言顯示');
// 重新渲染會話歷史以更新所有動態創建的元素
const sessionHistory = window.feedbackApp.sessionManager.dataManager.getSessionHistory();
window.feedbackApp.sessionManager.uiRenderer.renderSessionHistory(sessionHistory);
console.log('🌐 已更新會話歷史的語言顯示');
}
}

View File

@ -31,7 +31,7 @@
this.currentModal = null;
this.keydownHandler = null;
console.log('🔍 SessionDetailsModal 初始化完成');
// console.log('🔍 SessionDetailsModal 初始化完成');
}
/**
@ -43,7 +43,7 @@
return;
}
console.log('🔍 顯示會話詳情:', sessionData.session_id);
// console.log('🔍 顯示會話詳情:', sessionData.session_id);
// 存储当前会话数据,供复制功能使用
this.currentSessionData = sessionData;
@ -62,7 +62,7 @@
* 格式化會話詳情
*/
SessionDetailsModal.prototype.formatSessionDetails = function(sessionData) {
console.log('🔍 格式化會話詳情:', sessionData);
// console.log('🔍 格式化會話詳情:', sessionData);
// 處理會話 ID - 顯示完整 session ID
const sessionId = sessionData.session_id || '未知';
@ -171,7 +171,7 @@
<span class="detail-label">${i18n ? i18n.t('sessionManagement.aiSummary') : 'AI 摘要'}:</span>
<div class="detail-value summary">
<div class="summary-actions">
<button class="btn-copy-summary" title="复制源码" aria-label="复制源码">📋</button>
<button class="btn-copy-summary" title="複製摘要" aria-label="複製摘要">📋</button>
</div>
<div class="summary-content">${this.renderMarkdownSafely(details.summary)}</div>
</div>
@ -254,7 +254,7 @@
<span class="message-index">#${index + 1}</span>
<span class="message-time">${timestamp}</span>
<span class="message-method">${submissionMethod}</span>
<button class="btn-copy-message" title="复制消息内容" aria-label="复制消息内容" data-message-content="${this.escapeHtml(message.content)}">📋</button>
<button class="btn-copy-message" title="複製消息內容" aria-label="複製消息內容" data-message-content="${this.escapeHtml(message.content)}">📋</button>
</div>
${contentHtml}
</div>
@ -346,7 +346,7 @@
if (!this.currentModal) return;
// 彈窗已經通過 CSS 動畫自動顯示,無需額外處理
console.log('🔍 會話詳情彈窗已顯示');
// console.log('🔍 會話詳情彈窗已顯示');
};
/**
@ -395,9 +395,9 @@
if (!content) return '';
try {
// 查 marked 和 DOMPurify 是否可用
// 查 marked 和 DOMPurify 是否可用
if (typeof window.marked === 'undefined' || typeof window.DOMPurify === 'undefined') {
console.warn('⚠️ Markdown 库未载入,使用纯文字显示');
console.warn('⚠️ Markdown 庫未載入,使用純文字顯示');
return this.escapeHtml(content);
}
@ -413,29 +413,16 @@
return cleanHtml;
} catch (error) {
console.error('❌ Markdown 渲染失:', error);
console.error('❌ Markdown 渲染失:', error);
return this.escapeHtml(content);
}
};
/**
* 复制摘要内容到剪贴板
* 傳統複製文字到剪貼板的方法
*/
SessionDetailsModal.prototype.copySummaryToClipboard = function() {
const self = this; // 定义 self 变量
try {
// 获取原始摘要内容Markdown 源码)
const summaryContent = this.currentSessionData && this.currentSessionData.summary ?
this.currentSessionData.summary : '';
if (!summaryContent) {
console.warn('⚠️ 没有摘要内容可复制');
return;
}
// 传统复制方法
const fallbackCopyTextToClipboard = function(text) {
SessionDetailsModal.prototype.fallbackCopyTextToClipboard = function(text, successMessage) {
const self = this;
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
@ -448,121 +435,109 @@
try {
const successful = document.execCommand('copy');
if (successful) {
console.log('✅ 摘要内容已复制到剪贴板(传统方法)');
self.showToast('✅ 摘要已复制到剪贴板', 'success');
// console.log('✅ 內容已複製到剪貼板(傳統方法)');
self.showToast(successMessage, 'success');
} else {
console.error('❌ 复制失败(传统方法)');
self.showToast('❌ 复制失败,请手动复制', 'error');
console.error('❌ 複製失敗(傳統方法)');
self.showToast('❌ 複製失敗,請手動複製', 'error');
}
} catch (err) {
console.error('❌ 复制失败:', err);
self.showToast('❌ 复制失败,请手动复制', 'error');
console.error('❌ 複製失敗:', err);
self.showToast('❌ 複製失敗,請手動複製', 'error');
} finally {
document.body.removeChild(textArea);
}
};
// 使用现代 Clipboard API
/**
* 複製摘要內容到剪貼板
*/
SessionDetailsModal.prototype.copySummaryToClipboard = function() {
const self = this;
try {
// 獲取原始摘要內容Markdown 原始碼)
const summaryContent = this.currentSessionData && this.currentSessionData.summary ?
this.currentSessionData.summary : '';
if (!summaryContent) {
console.warn('⚠️ 沒有摘要內容可複製');
return;
}
// 使用現代 Clipboard API
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(summaryContent).then(function() {
console.log('✅ 摘要内容已复制到剪贴板');
self.showToast('✅ 摘要已复制到剪贴板', 'success');
// console.log('✅ 摘要內容已複製到剪貼板');
self.showToast('✅ 摘要已複製到剪貼板', 'success');
}).catch(function(err) {
console.error('❌ 复制失败:', err);
// 降级到传统方法
fallbackCopyTextToClipboard(summaryContent);
console.error('❌ 複製失敗:', err);
// 降級到傳統方法
self.fallbackCopyTextToClipboard(summaryContent, '✅ 摘要已複製到剪貼板');
});
} else {
// 降级到传统方法
fallbackCopyTextToClipboard(summaryContent);
// 降級到傳統方法
this.fallbackCopyTextToClipboard(summaryContent, '✅ 摘要已複製到剪貼板');
}
} catch (error) {
console.error('❌ 复制摘要时发生错误:', error);
this.showToast('❌ 复制失败,请手动复制', 'error');
console.error('❌ 複製摘要時發生錯誤:', error);
this.showToast('❌ 複製失敗,請手動複製', 'error');
}
};
/**
* 复制用户消息内容到剪贴
* 複製用戶消息內容到剪貼
*/
SessionDetailsModal.prototype.copyMessageToClipboard = function(messageContent) {
if (!messageContent) {
console.warn('⚠️ 没有消息内容可复制');
console.warn('⚠️ 沒有消息內容可複製');
return;
}
const self = this;
try {
// 使用代 Clipboard API
// 使用代 Clipboard API
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(messageContent).then(function() {
console.log('✅ 用户消息已复制到剪贴板');
self.showToast('✅ 消息已复制到剪贴板', 'success');
// console.log('✅ 用戶消息已複製到剪貼板');
self.showToast('✅ 消息已複製到剪貼板', 'success');
}).catch(function(err) {
console.error('❌ 复制失败:', err);
// 降级到传统方法
fallbackCopyTextToClipboard(messageContent);
console.error('❌ 複製失敗:', err);
// 降級到傳統方法
self.fallbackCopyTextToClipboard(messageContent, '✅ 消息已複製到剪貼板');
});
} else {
// 降级到传统方法
fallbackCopyTextToClipboard(messageContent);
// 降級到傳統方法
this.fallbackCopyTextToClipboard(messageContent, '✅ 消息已複製到剪貼板');
}
// 传统复制方法
const fallbackCopyTextToClipboard = function(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
textArea.style.top = '-999999px';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand('copy');
if (successful) {
console.log('✅ 用户消息已复制到剪贴板(传统方法)');
self.showToast('✅ 消息已复制到剪贴板', 'success');
} else {
console.error('❌ 复制失败(传统方法)');
self.showToast('❌ 复制失败,请手动复制', 'error');
}
} catch (err) {
console.error('❌ 复制失败:', err);
self.showToast('❌ 复制失败,请手动复制', 'error');
} finally {
document.body.removeChild(textArea);
}
};
} catch (error) {
console.error('❌ 复制用户消息时发生错误:', error);
this.showToast('❌ 复制失败,请手动复制', 'error');
console.error('❌ 複製用戶消息時發生錯誤:', error);
this.showToast('❌ 複製失敗,請手動複製', 'error');
}
};
/**
* 示提示消息
* 顯示提示消息
*/
SessionDetailsModal.prototype.showToast = function(message, type) {
// 建提示元素
// 創建提示元素
const toast = document.createElement('div');
toast.className = 'copy-toast copy-toast-' + type;
toast.textContent = message;
// 添加到窗中
// 添加到彈窗中
if (this.currentModal) {
this.currentModal.appendChild(toast);
// 显示动画
// 顯示動畫
setTimeout(function() {
toast.classList.add('show');
}, 10);
// 自动隐
// 自動隱藏
setTimeout(function() {
toast.classList.remove('show');
setTimeout(function() {
@ -608,12 +583,12 @@
*/
SessionDetailsModal.prototype.cleanup = function() {
this.forceCloseAll();
console.log('🔍 SessionDetailsModal 清理完成');
// console.log('🔍 SessionDetailsModal 清理完成');
};
// 將 SessionDetailsModal 加入命名空間
window.MCPFeedback.Session.DetailsModal = SessionDetailsModal;
console.log('✅ SessionDetailsModal 模組載入完成');
// console.log('✅ SessionDetailsModal 模組載入完成');
})();

View File

@ -21,6 +21,9 @@
console;
const StatusUtils = window.MCPFeedback.Utils.Status;
// 調試模式標誌 - 生產環境應設為 false
const DEBUG_MODE = false;
/**
* 會話 UI 渲染器
*/
@ -80,31 +83,31 @@
* 初始化專案路徑顯示
*/
SessionUIRenderer.prototype.initializeProjectPathDisplay = function() {
console.log('🎨 初始化專案路徑顯示');
if (DEBUG_MODE) console.log('🎨 初始化專案路徑顯示');
const projectPathElement = document.getElementById('projectPathDisplay');
console.log('🎨 初始化時找到專案路徑元素:', !!projectPathElement);
if (DEBUG_MODE) console.log('🎨 初始化時找到專案路徑元素:', !!projectPathElement);
if (projectPathElement) {
const fullPath = projectPathElement.getAttribute('data-full-path');
console.log('🎨 初始化時的完整路徑:', fullPath);
if (DEBUG_MODE) console.log('🎨 初始化時的完整路徑:', fullPath);
if (fullPath) {
// 使用工具函數截斷路徑
const pathResult = window.MCPFeedback.Utils.truncatePathFromRight(fullPath, 2, 40);
console.log('🎨 初始化時路徑處理:', { fullPath, shortPath: pathResult.truncated });
if (DEBUG_MODE) console.log('🎨 初始化時路徑處理:', { fullPath, shortPath: pathResult.truncated });
// 更新顯示文字
DOMUtils.safeSetTextContent(projectPathElement, pathResult.truncated);
// 添加點擊複製功能
if (!projectPathElement.hasAttribute('data-copy-handler')) {
console.log('🎨 初始化時添加點擊複製功能');
if (DEBUG_MODE) console.log('🎨 初始化時添加點擊複製功能');
projectPathElement.setAttribute('data-copy-handler', 'true');
projectPathElement.addEventListener('click', function() {
console.log('🎨 初始化的專案路徑被點擊');
if (DEBUG_MODE) console.log('🎨 初始化的專案路徑被點擊');
const fullPath = this.getAttribute('data-full-path');
console.log('🎨 初始化時準備複製路徑:', fullPath);
if (DEBUG_MODE) console.log('🎨 初始化時準備複製路徑:', fullPath);
if (fullPath) {
const successMessage = window.i18nManager ?
@ -114,12 +117,12 @@
window.i18nManager.t('app.pathCopyFailed', '複製路徑失敗') :
'複製路徑失敗';
console.log('🎨 初始化時調用複製函數');
if (DEBUG_MODE) console.log('🎨 初始化時調用複製函數');
window.MCPFeedback.Utils.copyToClipboard(fullPath, successMessage, errorMessage);
}
});
} else {
console.log('🎨 初始化時點擊複製功能已存在');
if (DEBUG_MODE) console.log('🎨 初始化時點擊複製功能已存在');
}
// 添加 tooltip 位置自動調整
@ -168,7 +171,7 @@
* 執行實際的當前會話渲染
*/
SessionUIRenderer.prototype._performCurrentSessionRender = function(sessionData, isNewSession) {
console.log('🎨 渲染當前會話:', sessionData);
if (DEBUG_MODE) console.log('🎨 渲染當前會話:', sessionData);
// 更新快取
this.lastRenderedData.currentSessionId = sessionData.session_id;
@ -176,7 +179,7 @@
// 如果是新會話,重置活躍時間定時器
if (isNewSession) {
console.log('🎨 檢測到新會話,重置活躍時間定時器');
if (DEBUG_MODE) console.log('🎨 檢測到新會話,重置活躍時間定時器');
this.resetActiveTimeTimer();
}
@ -258,17 +261,17 @@
* 更新頂部狀態列的專案路徑顯示
*/
SessionUIRenderer.prototype.updateTopProjectPathDisplay = function(sessionData) {
console.log('🎨 updateProjectPathDisplay 被調用:', sessionData);
if (DEBUG_MODE) console.log('🎨 updateProjectPathDisplay 被調用:', sessionData);
const projectPathElement = document.getElementById('projectPathDisplay');
console.log('🎨 找到專案路徑元素:', !!projectPathElement);
if (DEBUG_MODE) console.log('🎨 找到專案路徑元素:', !!projectPathElement);
if (projectPathElement && sessionData.project_directory) {
const fullPath = sessionData.project_directory;
// 使用工具函數截斷路徑
const pathResult = window.MCPFeedback.Utils.truncatePathFromRight(fullPath, 2, 40);
console.log('🎨 路徑處理:', { fullPath, shortPath: pathResult.truncated });
if (DEBUG_MODE) console.log('🎨 路徑處理:', { fullPath, shortPath: pathResult.truncated });
// 更新顯示文字
DOMUtils.safeSetTextContent(projectPathElement, pathResult.truncated);
@ -278,12 +281,12 @@
// 添加點擊複製功能(如果還沒有)
if (!projectPathElement.hasAttribute('data-copy-handler')) {
console.log('🎨 添加點擊複製功能');
if (DEBUG_MODE) console.log('🎨 添加點擊複製功能');
projectPathElement.setAttribute('data-copy-handler', 'true');
projectPathElement.addEventListener('click', function() {
console.log('🎨 專案路徑被點擊');
if (DEBUG_MODE) console.log('🎨 專案路徑被點擊');
const fullPath = this.getAttribute('data-full-path');
console.log('🎨 準備複製路徑:', fullPath);
if (DEBUG_MODE) console.log('🎨 準備複製路徑:', fullPath);
if (fullPath) {
const successMessage = window.i18nManager ?
@ -293,12 +296,12 @@
window.i18nManager.t('app.pathCopyFailed', '複製路徑失敗') :
'複製路徑失敗';
console.log('🎨 調用複製函數');
if (DEBUG_MODE) console.log('🎨 調用複製函數');
window.MCPFeedback.Utils.copyToClipboard(fullPath, successMessage, errorMessage);
}
});
} else {
console.log('🎨 點擊複製功能已存在');
if (DEBUG_MODE) console.log('🎨 點擊複製功能已存在');
}
// 添加 tooltip 位置自動調整
@ -352,7 +355,7 @@
SessionUIRenderer.prototype.updateSessionStatusBar = function(sessionData) {
if (!sessionData) return;
console.log('🎨 更新會話狀態列:', sessionData);
if (DEBUG_MODE) console.log('🎨 更新會話狀態列:', sessionData);
// 更新當前會話 ID - 顯示縮短版本完整ID存在data-full-id中
const currentSessionElement = document.getElementById('currentSessionId');
@ -413,7 +416,7 @@
* 執行實際的會話歷史渲染
*/
SessionUIRenderer.prototype._performHistoryRender = function(sessionHistory) {
console.log('🎨 渲染會話歷史:', sessionHistory.length, '個會話');
if (DEBUG_MODE) console.log('🎨 渲染會話歷史:', sessionHistory.length, '個會話');
// 更新快取
this.lastRenderedData.historyLength = sessionHistory.length;
@ -477,23 +480,39 @@
SessionUIRenderer.prototype.createSessionHeader = function(sessionData) {
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: sessionIdLabel + ': ' + (sessionData.session_id || '').substring(0, 8) + '...'
// 會話 ID 容器
const sessionIdContainer = DOMUtils.createElement('div', {
className: 'session-id'
});
// 會話 ID 標籤
const sessionIdLabel = DOMUtils.createElement('span', {
attributes: {
'data-i18n': 'sessionManagement.sessionId'
},
textContent: window.i18nManager ? window.i18nManager.t('sessionManagement.sessionId') : '會話 ID'
});
// 會話 ID 值
const sessionIdValue = DOMUtils.createElement('span', {
textContent: ': ' + (sessionData.session_id || '').substring(0, 8) + '...'
});
sessionIdContainer.appendChild(sessionIdLabel);
sessionIdContainer.appendChild(sessionIdValue);
// 狀態徽章
const statusContainer = DOMUtils.createElement('div', { className: 'session-status' });
const statusText = StatusUtils.getStatusText(sessionData.status);
// 添加調試信息
if (DEBUG_MODE) {
console.log('🎨 會話狀態調試:', {
sessionId: sessionData.session_id ? sessionData.session_id.substring(0, 8) + '...' : 'unknown',
rawStatus: sessionData.status,
displayText: statusText
});
}
const statusBadge = DOMUtils.createElement('span', {
className: 'status-badge ' + (sessionData.status || 'waiting'),
@ -501,7 +520,7 @@
});
statusContainer.appendChild(statusBadge);
header.appendChild(sessionId);
header.appendChild(sessionIdContainer);
header.appendChild(statusContainer);
return header;
@ -513,31 +532,57 @@
SessionUIRenderer.prototype.createSessionInfo = function(sessionData, isHistory) {
const info = DOMUtils.createElement('div', { className: 'session-info' });
// 時間資訊
// 時間資訊容器
const timeContainer = DOMUtils.createElement('div', {
className: 'session-time'
});
// 時間標籤
const timeLabelKey = isHistory ? 'sessionManagement.createdTime' : 'sessionManagement.createdTime';
const timeLabel = DOMUtils.createElement('span', {
attributes: {
'data-i18n': timeLabelKey
},
textContent: window.i18nManager ? window.i18nManager.t(timeLabelKey) : '建立時間'
});
// 時間值
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: timeLabel + ': ' + timeText
const timeValue = DOMUtils.createElement('span', {
textContent: ': ' + timeText
});
info.appendChild(timeElement);
timeContainer.appendChild(timeLabel);
timeContainer.appendChild(timeValue);
info.appendChild(timeContainer);
// 歷史會話顯示持續時間
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: durationLabel + ': ' + duration
// 持續時間容器
const durationContainer = DOMUtils.createElement('div', {
className: 'session-duration'
});
info.appendChild(durationElement);
// 持續時間標籤
const durationLabel = DOMUtils.createElement('span', {
attributes: {
'data-i18n': 'sessionManagement.sessionDetails.duration'
},
textContent: window.i18nManager ? window.i18nManager.t('sessionManagement.sessionDetails.duration') : '持續時間'
});
// 持續時間值
const durationValue = DOMUtils.createElement('span', {
textContent: ': ' + duration
});
durationContainer.appendChild(durationLabel);
durationContainer.appendChild(durationValue);
info.appendChild(durationContainer);
}
return info;
@ -564,13 +609,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 viewButton = DOMUtils.createElement('button', {
className: 'btn-small',
textContent: buttonText
attributes: {
'data-i18n': 'sessionManagement.viewDetails'
},
textContent: window.i18nManager ? window.i18nManager.t('sessionManagement.viewDetails') : '詳細資訊'
});
// 添加查看詳情點擊事件
@ -586,7 +631,10 @@
if (isHistory) {
const exportButton = DOMUtils.createElement('button', {
className: 'btn-small btn-export',
textContent: window.i18nManager ? window.i18nManager.t('sessionHistory.management.exportSingle') : '匯出',
attributes: {
'data-i18n': 'sessionHistory.management.exportSingle'
},
textContent: window.i18nManager ? window.i18nManager.t('sessionHistory.management.exportSingle') : '匯出此會話',
style: 'margin-left: 4px; font-size: 11px; padding: 2px 6px;'
});
@ -695,7 +743,7 @@
self.updateActiveTime();
}, 1000);
console.log('🎨 活躍時間定時器已啟動');
if (DEBUG_MODE) console.log('🎨 活躍時間定時器已啟動');
};
/**
@ -705,7 +753,7 @@
if (this.activeTimeTimer) {
clearInterval(this.activeTimeTimer);
this.activeTimeTimer = null;
console.log('🎨 活躍時間定時器已停止');
if (DEBUG_MODE) console.log('🎨 活躍時間定時器已停止');
}
};
@ -758,12 +806,12 @@
currentSessionId: null
};
console.log('🎨 SessionUIRenderer 清理完成');
if (DEBUG_MODE) console.log('🎨 SessionUIRenderer 清理完成');
};
// 將 SessionUIRenderer 加入命名空間
window.MCPFeedback.Session.UIRenderer = SessionUIRenderer;
console.log('✅ SessionUIRenderer 模組載入完成');
if (DEBUG_MODE) console.log('✅ SessionUIRenderer 模組載入完成');
})();

View File

@ -657,8 +657,18 @@
</div>
<div class="session-actions">
<button class="btn-small" id="viewSessionDetails" data-i18n="sessionManagement.viewDetails">詳細資訊</button>
<button class="btn-small btn-primary" id="copyCurrentSessionContent" title="复制当前会话内容">📋 复制会话内容</button>
<button class="btn-small btn-secondary" id="copyCurrentUserContent" title="复制当前用户发送的内容">📝 复制用户内容</button>
<button class="btn-small btn-primary" id="copyCurrentSessionContent"
data-i18n="sessionManagement.copySessionContent"
data-i18n-title="sessionManagement.copySessionContent"
aria-label="複製會話內容">
📋 <span data-i18n="sessionManagement.copySessionContent">複製會話內容</span>
</button>
<button class="btn-small btn-secondary" id="copyCurrentUserContent"
data-i18n="sessionManagement.copyUserContent"
data-i18n-title="sessionManagement.copyUserContent"
aria-label="複製用戶內容">
📝 <span data-i18n="sessionManagement.copyUserContent">複製用戶內容</span>
</button>
</div>
</div>
</div>