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
a48b2ac795
commit
d6284338c6
@ -3,6 +3,12 @@
|
|||||||
"title": "MCP Interactive Feedback System",
|
"title": "MCP Interactive Feedback System",
|
||||||
"subtitle": "AI Assistant Interactive Feedback Platform",
|
"subtitle": "AI Assistant Interactive Feedback Platform",
|
||||||
"projectDirectory": "Project Directory",
|
"projectDirectory": "Project Directory",
|
||||||
|
"clickToCopyPath": "Click to copy full path",
|
||||||
|
"clickToCopySessionId": "Click to copy full session ID",
|
||||||
|
"pathCopied": "Project path copied to clipboard",
|
||||||
|
"pathCopyFailed": "Failed to copy path",
|
||||||
|
"sessionIdCopied": "Session ID copied to clipboard",
|
||||||
|
"sessionIdCopyFailed": "Failed to copy session ID",
|
||||||
"updateFailed": "Failed to update content, please manually refresh the page to view new AI work summary"
|
"updateFailed": "Failed to update content, please manually refresh the page to view new AI work summary"
|
||||||
},
|
},
|
||||||
"tabs": {
|
"tabs": {
|
||||||
|
@ -3,6 +3,12 @@
|
|||||||
"title": "MCP 交互反馈系统",
|
"title": "MCP 交互反馈系统",
|
||||||
"subtitle": "AI 助手交互反馈平台",
|
"subtitle": "AI 助手交互反馈平台",
|
||||||
"projectDirectory": "项目目录",
|
"projectDirectory": "项目目录",
|
||||||
|
"clickToCopyPath": "点击复制完整路径",
|
||||||
|
"clickToCopySessionId": "点击复制完整会话ID",
|
||||||
|
"pathCopied": "项目路径已复制到剪贴板",
|
||||||
|
"pathCopyFailed": "复制路径失败",
|
||||||
|
"sessionIdCopied": "会话ID已复制到剪贴板",
|
||||||
|
"sessionIdCopyFailed": "复制会话ID失败",
|
||||||
"updateFailed": "更新内容失败,请手动刷新页面以查看新的 AI 工作摘要"
|
"updateFailed": "更新内容失败,请手动刷新页面以查看新的 AI 工作摘要"
|
||||||
},
|
},
|
||||||
"tabs": {
|
"tabs": {
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
"authorLink": "GitHub: Minidoracat",
|
"authorLink": "GitHub: Minidoracat",
|
||||||
"credits": "⭐ 如果這個專案對您有幫助,請在 GitHub 上給我們一個星星!\n\n本增強版本由 Minidoracat 開發和維護,大幅擴展了專案功能,新增了 Web UI 介面、圖片支援、多語言能力以及許多其他改進功能。\n\n同時感謝 sanshao85 的 mcp-feedback-collector 專案提供的 UI 設計靈感。\n\n開源協作讓技術變得更美好!",
|
"credits": "⭐ 如果這個專案對您有幫助,請在 GitHub 上給我們一個星星!\n\n本增強版本由 Minidoracat 開發和維護,大幅擴展了專案功能,新增了 Web UI 介面、圖片支援、多語言能力以及許多其他改進功能。\n\n同時感謝 sanshao85 的 mcp-feedback-collector 專案提供的 UI 設計靈感。\n\n開源協作讓技術變得更美好!",
|
||||||
"projectDirectory": "專案目錄",
|
"projectDirectory": "專案目錄",
|
||||||
|
"clickToCopyPath": "點擊複製完整路徑",
|
||||||
|
"clickToCopySessionId": "點擊複製完整會話ID",
|
||||||
|
"pathCopied": "專案路徑已複製到剪貼板",
|
||||||
|
"pathCopyFailed": "複製路徑失敗",
|
||||||
|
"sessionIdCopied": "會話ID已複製到剪貼板",
|
||||||
|
"sessionIdCopyFailed": "複製會話ID失敗",
|
||||||
"updateFailed": "更新內容失敗,請手動刷新頁面以查看新的 AI 工作摘要"
|
"updateFailed": "更新內容失敗,請手動刷新頁面以查看新的 AI 工作摘要"
|
||||||
},
|
},
|
||||||
"tabs": {
|
"tabs": {
|
||||||
|
@ -107,6 +107,170 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
flex: 2;
|
flex: 2;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 會話狀態資訊區域 */
|
||||||
|
.session-status-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-status-info .current-session-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-status-info .session-indicator {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-status-info .session-age {
|
||||||
|
font-size: 10px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
opacity: 0.8;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 會話ID顯示樣式 */
|
||||||
|
.session-id-display {
|
||||||
|
font-family: 'Consolas', 'Monaco', monospace;
|
||||||
|
color: var(--accent-color);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(0, 122, 204, 0.1);
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: all var(--transition-fast) ease;
|
||||||
|
position: relative;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-id-display:hover {
|
||||||
|
background: rgba(0, 122, 204, 0.2);
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
transform: scale(1.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-id-display:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 會話ID tooltip */
|
||||||
|
.session-id-display::after {
|
||||||
|
content: attr(data-full-id);
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
white-space: nowrap;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transition: all var(--transition-fast) ease;
|
||||||
|
z-index: 1000;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-id-display:hover::after {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 專案路徑顯示樣式 - 模仿會話ID顯示 */
|
||||||
|
.project-path-display {
|
||||||
|
font-family: 'Consolas', 'Monaco', monospace;
|
||||||
|
color: var(--accent-color);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(0, 122, 204, 0.1);
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: all var(--transition-fast) ease;
|
||||||
|
position: relative;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-path-display:hover {
|
||||||
|
background: rgba(0, 122, 204, 0.2);
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
transform: scale(1.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-path-display:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 專案路徑 tooltip */
|
||||||
|
.project-path-display::after {
|
||||||
|
content: attr(data-full-path);
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
white-space: nowrap;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transition: all var(--transition-fast) ease;
|
||||||
|
z-index: 1000;
|
||||||
|
margin-top: 4px;
|
||||||
|
max-width: 400px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-path-display:hover::after {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 專案路徑 tooltip 位置自動調整 */
|
||||||
|
.project-path-display.tooltip-up::after {
|
||||||
|
top: auto;
|
||||||
|
bottom: 100%;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-path-display.tooltip-left::after {
|
||||||
|
left: 0;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-path-display.tooltip-right::after {
|
||||||
|
left: auto;
|
||||||
|
right: 0;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 連線和狀態資訊組合容器 */
|
||||||
|
.connection-status-combined {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +278,7 @@
|
|||||||
.detailed-status-info {
|
.detailed-status-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
margin-left: 16px;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.websocket-metrics,
|
.websocket-metrics,
|
||||||
@ -680,9 +844,14 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.connection-status-combined {
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.detailed-status-info {
|
.detailed-status-info {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-top: 8px;
|
margin-top: 0;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
@ -161,6 +161,16 @@ class I18nManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 翻譯有 data-i18n-title 屬性的元素
|
||||||
|
const titleElements = document.querySelectorAll('[data-i18n-title]');
|
||||||
|
titleElements.forEach(element => {
|
||||||
|
const key = element.getAttribute('data-i18n-title');
|
||||||
|
const translation = this.t(key);
|
||||||
|
if (translation && translation !== key) {
|
||||||
|
element.title = translation;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 更新動態內容
|
// 更新動態內容
|
||||||
this.updateDynamicContent();
|
this.updateDynamicContent();
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
this.currentSessionData = null;
|
this.currentSessionData = null;
|
||||||
|
|
||||||
this.initializeElements();
|
this.initializeElements();
|
||||||
|
this.initializeProjectPathDisplay();
|
||||||
this.startActiveTimeTimer();
|
this.startActiveTimeTimer();
|
||||||
|
|
||||||
console.log('🎨 SessionUIRenderer 初始化完成');
|
console.log('🎨 SessionUIRenderer 初始化完成');
|
||||||
@ -55,6 +56,58 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化專案路徑顯示
|
||||||
|
*/
|
||||||
|
SessionUIRenderer.prototype.initializeProjectPathDisplay = function() {
|
||||||
|
console.log('🎨 初始化專案路徑顯示');
|
||||||
|
|
||||||
|
const projectPathElement = document.getElementById('projectPathDisplay');
|
||||||
|
console.log('🎨 初始化時找到專案路徑元素:', !!projectPathElement);
|
||||||
|
|
||||||
|
if (projectPathElement) {
|
||||||
|
const fullPath = projectPathElement.getAttribute('data-full-path');
|
||||||
|
console.log('🎨 初始化時的完整路徑:', fullPath);
|
||||||
|
|
||||||
|
if (fullPath) {
|
||||||
|
// 使用工具函數截斷路徑
|
||||||
|
const pathResult = window.MCPFeedback.Utils.truncatePathFromRight(fullPath, 2, 40);
|
||||||
|
console.log('🎨 初始化時路徑處理:', { fullPath, shortPath: pathResult.truncated });
|
||||||
|
|
||||||
|
// 更新顯示文字
|
||||||
|
DOMUtils.safeSetTextContent(projectPathElement, pathResult.truncated);
|
||||||
|
|
||||||
|
// 添加點擊複製功能
|
||||||
|
if (!projectPathElement.hasAttribute('data-copy-handler')) {
|
||||||
|
console.log('🎨 初始化時添加點擊複製功能');
|
||||||
|
projectPathElement.setAttribute('data-copy-handler', 'true');
|
||||||
|
projectPathElement.addEventListener('click', function() {
|
||||||
|
console.log('🎨 初始化的專案路徑被點擊');
|
||||||
|
const fullPath = this.getAttribute('data-full-path');
|
||||||
|
console.log('🎨 初始化時準備複製路徑:', fullPath);
|
||||||
|
|
||||||
|
if (fullPath) {
|
||||||
|
const successMessage = window.i18nManager ?
|
||||||
|
window.i18nManager.t('app.pathCopied', '專案路徑已複製到剪貼板') :
|
||||||
|
'專案路徑已複製到剪貼板';
|
||||||
|
const errorMessage = window.i18nManager ?
|
||||||
|
window.i18nManager.t('app.pathCopyFailed', '複製路徑失敗') :
|
||||||
|
'複製路徑失敗';
|
||||||
|
|
||||||
|
console.log('🎨 初始化時調用複製函數');
|
||||||
|
window.MCPFeedback.Utils.copyToClipboard(fullPath, successMessage, errorMessage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('🎨 初始化時點擊複製功能已存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加 tooltip 位置自動調整
|
||||||
|
this.adjustTooltipPosition(projectPathElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染當前會話
|
* 渲染當前會話
|
||||||
*/
|
*/
|
||||||
@ -145,6 +198,88 @@
|
|||||||
const projectLabel = window.i18nManager ? window.i18nManager.t('sessionManagement.project') : '專案';
|
const projectLabel = window.i18nManager ? window.i18nManager.t('sessionManagement.project') : '專案';
|
||||||
DOMUtils.safeSetTextContent(projectElement, projectLabel + ': ' + projectDir);
|
DOMUtils.safeSetTextContent(projectElement, projectLabel + ': ' + projectDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新頂部狀態列的專案路徑顯示
|
||||||
|
this.updateTopProjectPathDisplay(sessionData);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新頂部狀態列的專案路徑顯示
|
||||||
|
*/
|
||||||
|
SessionUIRenderer.prototype.updateTopProjectPathDisplay = function(sessionData) {
|
||||||
|
console.log('🎨 updateProjectPathDisplay 被調用:', sessionData);
|
||||||
|
|
||||||
|
const projectPathElement = document.getElementById('projectPathDisplay');
|
||||||
|
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 });
|
||||||
|
|
||||||
|
// 更新顯示文字
|
||||||
|
DOMUtils.safeSetTextContent(projectPathElement, pathResult.truncated);
|
||||||
|
|
||||||
|
// 更新完整路徑屬性
|
||||||
|
projectPathElement.setAttribute('data-full-path', fullPath);
|
||||||
|
|
||||||
|
// 添加點擊複製功能(如果還沒有)
|
||||||
|
if (!projectPathElement.hasAttribute('data-copy-handler')) {
|
||||||
|
console.log('🎨 添加點擊複製功能');
|
||||||
|
projectPathElement.setAttribute('data-copy-handler', 'true');
|
||||||
|
projectPathElement.addEventListener('click', function() {
|
||||||
|
console.log('🎨 專案路徑被點擊');
|
||||||
|
const fullPath = this.getAttribute('data-full-path');
|
||||||
|
console.log('🎨 準備複製路徑:', fullPath);
|
||||||
|
|
||||||
|
if (fullPath) {
|
||||||
|
const successMessage = window.i18nManager ?
|
||||||
|
window.i18nManager.t('app.pathCopied', '專案路徑已複製到剪貼板') :
|
||||||
|
'專案路徑已複製到剪貼板';
|
||||||
|
const errorMessage = window.i18nManager ?
|
||||||
|
window.i18nManager.t('app.pathCopyFailed', '複製路徑失敗') :
|
||||||
|
'複製路徑失敗';
|
||||||
|
|
||||||
|
console.log('🎨 調用複製函數');
|
||||||
|
window.MCPFeedback.Utils.copyToClipboard(fullPath, successMessage, errorMessage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('🎨 點擊複製功能已存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加 tooltip 位置自動調整
|
||||||
|
this.adjustTooltipPosition(projectPathElement);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 調整 tooltip 位置以避免超出視窗邊界
|
||||||
|
*/
|
||||||
|
SessionUIRenderer.prototype.adjustTooltipPosition = function(element) {
|
||||||
|
if (!element) return;
|
||||||
|
|
||||||
|
// 移除之前的位置類別
|
||||||
|
element.classList.remove('tooltip-up', 'tooltip-left', 'tooltip-right');
|
||||||
|
|
||||||
|
// 獲取元素位置
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
const viewportWidth = window.innerWidth;
|
||||||
|
const viewportHeight = window.innerHeight;
|
||||||
|
|
||||||
|
// 檢查是否需要調整垂直位置
|
||||||
|
if (rect.bottom + 100 > viewportHeight) {
|
||||||
|
element.classList.add('tooltip-up');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 檢查是否需要調整水平位置
|
||||||
|
if (rect.left + 200 > viewportWidth) {
|
||||||
|
element.classList.add('tooltip-right');
|
||||||
|
} else if (rect.left < 200) {
|
||||||
|
element.classList.add('tooltip-left');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -168,10 +303,30 @@
|
|||||||
|
|
||||||
console.log('🎨 更新會話狀態列:', sessionData);
|
console.log('🎨 更新會話狀態列:', sessionData);
|
||||||
|
|
||||||
// 更新當前會話 ID - 顯示完整 session ID
|
// 更新當前會話 ID - 顯示縮短版本,完整ID存在data-full-id中
|
||||||
const currentSessionElement = document.getElementById('currentSessionId');
|
const currentSessionElement = document.getElementById('currentSessionId');
|
||||||
if (currentSessionElement && sessionData.session_id) {
|
if (currentSessionElement && sessionData.session_id) {
|
||||||
DOMUtils.safeSetTextContent(currentSessionElement, sessionData.session_id);
|
const shortId = sessionData.session_id.substring(0, 8) + '...';
|
||||||
|
DOMUtils.safeSetTextContent(currentSessionElement, shortId);
|
||||||
|
currentSessionElement.setAttribute('data-full-id', sessionData.session_id);
|
||||||
|
|
||||||
|
// 添加點擊複製功能(如果還沒有)
|
||||||
|
if (!currentSessionElement.hasAttribute('data-copy-handler')) {
|
||||||
|
currentSessionElement.setAttribute('data-copy-handler', 'true');
|
||||||
|
currentSessionElement.addEventListener('click', function() {
|
||||||
|
const fullId = this.getAttribute('data-full-id');
|
||||||
|
if (fullId) {
|
||||||
|
const successMessage = window.i18nManager ?
|
||||||
|
window.i18nManager.t('app.sessionIdCopied', '會話ID已複製到剪貼板') :
|
||||||
|
'會話ID已複製到剪貼板';
|
||||||
|
const errorMessage = window.i18nManager ?
|
||||||
|
window.i18nManager.t('app.sessionIdCopyFailed', '複製會話ID失敗') :
|
||||||
|
'複製會話ID失敗';
|
||||||
|
|
||||||
|
window.MCPFeedback.Utils.copyToClipboard(fullId, successMessage, errorMessage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 立即更新活躍時間(定時器會持續更新)
|
// 立即更新活躍時間(定時器會持續更新)
|
||||||
|
@ -121,6 +121,125 @@
|
|||||||
return document.querySelector(selector) !== null;
|
return document.querySelector(selector) !== null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 從右側截斷路徑,保留最後幾個目錄層級
|
||||||
|
* @param {string} path - 完整路徑
|
||||||
|
* @param {number} maxLevels - 保留的最大目錄層級數(默認2)
|
||||||
|
* @param {number} maxLength - 最大顯示長度(默認40)
|
||||||
|
* @returns {object} 包含 truncated(截斷後的路徑)和 isTruncated(是否被截斷)
|
||||||
|
*/
|
||||||
|
truncatePathFromRight: function(path, maxLevels, maxLength) {
|
||||||
|
maxLevels = maxLevels || 2;
|
||||||
|
maxLength = maxLength || 40;
|
||||||
|
|
||||||
|
if (!path || typeof path !== 'string') {
|
||||||
|
return { truncated: path || '', isTruncated: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果路徑長度小於最大長度,直接返回
|
||||||
|
if (path.length <= maxLength) {
|
||||||
|
return { truncated: path, isTruncated: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 統一路徑分隔符為反斜線(Windows風格)
|
||||||
|
const normalizedPath = path.replace(/\//g, '\\');
|
||||||
|
|
||||||
|
// 分割路徑
|
||||||
|
const parts = normalizedPath.split('\\').filter(part => part.length > 0);
|
||||||
|
|
||||||
|
if (parts.length <= maxLevels) {
|
||||||
|
return { truncated: normalizedPath, isTruncated: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取最後幾個層級
|
||||||
|
const lastParts = parts.slice(-maxLevels);
|
||||||
|
const truncatedPath = '...' + '\\' + lastParts.join('\\');
|
||||||
|
|
||||||
|
return {
|
||||||
|
truncated: truncatedPath,
|
||||||
|
isTruncated: true
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 複製文字到剪貼板(統一的複製功能)
|
||||||
|
* @param {string} text - 要複製的文字
|
||||||
|
* @param {string} successMessage - 成功提示訊息
|
||||||
|
* @param {string} errorMessage - 錯誤提示訊息
|
||||||
|
* @returns {Promise<boolean>} 複製是否成功
|
||||||
|
*/
|
||||||
|
copyToClipboard: function(text, successMessage, errorMessage) {
|
||||||
|
successMessage = successMessage || '已複製到剪貼板';
|
||||||
|
errorMessage = errorMessage || '複製失敗';
|
||||||
|
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
|
// 使用現代 Clipboard API
|
||||||
|
navigator.clipboard.writeText(text).then(function() {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
window.MCPFeedback.Utils.showMessage(successMessage, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_SUCCESS);
|
||||||
|
}
|
||||||
|
resolve(true);
|
||||||
|
}).catch(function(err) {
|
||||||
|
console.error('Clipboard API 複製失敗:', err);
|
||||||
|
// 回退到舊方法
|
||||||
|
const success = window.MCPFeedback.Utils.fallbackCopyToClipboard(text);
|
||||||
|
if (success) {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
window.MCPFeedback.Utils.showMessage(successMessage, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_SUCCESS);
|
||||||
|
}
|
||||||
|
resolve(true);
|
||||||
|
} else {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
window.MCPFeedback.Utils.showMessage(errorMessage, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_ERROR);
|
||||||
|
}
|
||||||
|
resolve(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 直接使用回退方法
|
||||||
|
const success = window.MCPFeedback.Utils.fallbackCopyToClipboard(text);
|
||||||
|
if (success) {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
window.MCPFeedback.Utils.showMessage(successMessage, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_SUCCESS);
|
||||||
|
}
|
||||||
|
resolve(true);
|
||||||
|
} else {
|
||||||
|
if (window.MCPFeedback && window.MCPFeedback.Utils && window.MCPFeedback.Utils.showMessage) {
|
||||||
|
window.MCPFeedback.Utils.showMessage(errorMessage, window.MCPFeedback.Utils.CONSTANTS.MESSAGE_ERROR);
|
||||||
|
}
|
||||||
|
resolve(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回退的複製到剪貼板方法
|
||||||
|
* @param {string} text - 要複製的文字
|
||||||
|
* @returns {boolean} 複製是否成功
|
||||||
|
*/
|
||||||
|
fallbackCopyToClipboard: function(text) {
|
||||||
|
try {
|
||||||
|
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();
|
||||||
|
|
||||||
|
const successful = document.execCommand('copy');
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
|
||||||
|
return successful;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('回退複製方法失敗:', err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 安全的元素查詢
|
* 安全的元素查詢
|
||||||
* @param {string} selector - CSS 選擇器
|
* @param {string} selector - CSS 選擇器
|
||||||
|
@ -398,12 +398,32 @@
|
|||||||
<h1 data-i18n="app.title">MCP Feedback Enhanced</h1>
|
<h1 data-i18n="app.title">MCP Feedback Enhanced</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="project-info">
|
<div class="project-info">
|
||||||
<span data-i18n="app.projectDirectory">專案目錄</span>: {{ project_directory }}
|
📂 <span data-i18n="app.projectDirectory">專案目錄</span>:
|
||||||
|
<span id="projectPathDisplay" class="project-path-display"
|
||||||
|
data-full-path="{{ project_directory }}"
|
||||||
|
data-i18n-title="app.clickToCopyPath"
|
||||||
|
title="點擊複製完整路徑">{{ project_directory }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 中間:連線狀態資訊 -->
|
<!-- 中間:連線狀態資訊 -->
|
||||||
<div class="connection-status-group">
|
<div class="connection-status-group">
|
||||||
|
<!-- 左側:會話狀態資訊 -->
|
||||||
|
<div class="session-status-info">
|
||||||
|
<div class="current-session-info">
|
||||||
|
<span class="session-indicator">
|
||||||
|
📋 <span data-i18n="sessionManagement.currentSession">當前會話</span>:
|
||||||
|
<span id="currentSessionId" class="session-id-display"
|
||||||
|
data-full-id="{{ session_id if session_id else 'loading' }}"
|
||||||
|
data-i18n-title="app.clickToCopySessionId"
|
||||||
|
title="點擊複製完整會話ID">{{ session_id[:8] if session_id else 'loading' }}...</span>
|
||||||
|
</span>
|
||||||
|
<span class="session-age">
|
||||||
|
<span data-i18n="sessionManagement.activeTime">活躍時間</span>: <span id="sessionAge">--</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 倒數計時器顯示 -->
|
<!-- 倒數計時器顯示 -->
|
||||||
<div id="countdownDisplay" class="countdown-display" style="display: none;">
|
<div id="countdownDisplay" class="countdown-display" style="display: none;">
|
||||||
<span class="countdown-label" data-i18n="autoSubmit.countdownLabel">提交倒數</span>
|
<span class="countdown-label" data-i18n="autoSubmit.countdownLabel">提交倒數</span>
|
||||||
@ -424,21 +444,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 連線詳細資訊 -->
|
<!-- 連線和狀態資訊組合 -->
|
||||||
<div class="connection-details">
|
<div class="connection-status-combined">
|
||||||
<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 class="connection-details">
|
||||||
</div>
|
<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 class="detailed-status-info">
|
|
||||||
<div class="websocket-metrics">
|
|
||||||
<span class="metric"><span data-i18n="connectionMonitor.metrics.messages">訊息</span>: <span id="messageCount">0</span></span>
|
|
||||||
<span class="metric"><span data-i18n="connectionMonitor.metrics.latencyMs">延遲</span>: <span id="latencyDisplay">--ms</span></span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="session-metrics">
|
|
||||||
<span class="metric"><span data-i18n="connectionMonitor.metrics.sessions">會話</span>: <span id="sessionCount">1</span></span>
|
<!-- 詳細狀態資訊 -->
|
||||||
<span class="metric"><span data-i18n="connectionMonitor.statusText">狀態</span>: <span id="sessionStatusText" data-i18n="connectionMonitor.waiting">等待中</span></span>
|
<div class="detailed-status-info">
|
||||||
|
<div class="websocket-metrics">
|
||||||
|
<span class="metric"><span data-i18n="connectionMonitor.metrics.messages">訊息</span>: <span id="messageCount">0</span></span>
|
||||||
|
<span class="metric"><span data-i18n="connectionMonitor.metrics.latencyMs">延遲</span>: <span id="latencyDisplay">--ms</span></span>
|
||||||
|
</div>
|
||||||
|
<div class="session-metrics">
|
||||||
|
<span class="metric"><span data-i18n="connectionMonitor.metrics.sessions">會話</span>: <span id="sessionCount">1</span></span>
|
||||||
|
<span class="metric"><span data-i18n="connectionMonitor.statusText">狀態</span>: <span id="sessionStatusText" data-i18n="connectionMonitor.waiting">等待中</span></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -530,20 +553,6 @@
|
|||||||
|
|
||||||
<!-- ===== 右側主要內容區域 ===== -->
|
<!-- ===== 右側主要內容區域 ===== -->
|
||||||
<div class="main-content-area" style="flex: 1; min-width: 0;">
|
<div class="main-content-area" style="flex: 1; min-width: 0;">
|
||||||
<!-- 會話狀態條 -->
|
|
||||||
<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 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 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;" data-i18n="sessionManagement.switchSession">
|
|
||||||
切換會話
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 分頁導航 -->
|
<!-- 分頁導航 -->
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
|
288
tests/helpers/manual_tooltip_test.html
Normal file
288
tests/helpers/manual_tooltip_test.html
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-TW">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Tooltip 方向測試</title>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg-primary: #1e1e1e;
|
||||||
|
--bg-secondary: #2d2d30;
|
||||||
|
--text-primary: #cccccc;
|
||||||
|
--text-secondary: #969696;
|
||||||
|
--accent-color: #007acc;
|
||||||
|
--border-color: #464647;
|
||||||
|
--transition-fast: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-section {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
padding: 20px;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-header {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
padding: 12px 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 會話ID顯示樣式 */
|
||||||
|
.session-id-display {
|
||||||
|
font-family: 'Consolas', 'Monaco', monospace;
|
||||||
|
color: var(--accent-color);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(0, 122, 204, 0.1);
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: all var(--transition-fast) ease;
|
||||||
|
position: relative;
|
||||||
|
font-weight: 500;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-id-display:hover {
|
||||||
|
background: rgba(0, 122, 204, 0.2);
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
transform: scale(1.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-id-display:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 會話ID tooltip - 向下顯示 */
|
||||||
|
.session-id-display::after {
|
||||||
|
content: attr(data-full-id);
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
white-space: nowrap;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transition: all var(--transition-fast) ease;
|
||||||
|
z-index: 1000;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-id-display:hover::after {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 對比:向上顯示的tooltip */
|
||||||
|
.session-id-display-up {
|
||||||
|
font-family: 'Consolas', 'Monaco', monospace;
|
||||||
|
color: var(--accent-color);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(0, 122, 204, 0.1);
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: all var(--transition-fast) ease;
|
||||||
|
position: relative;
|
||||||
|
font-weight: 500;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-id-display-up:hover {
|
||||||
|
background: rgba(0, 122, 204, 0.2);
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
transform: scale(1.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-id-display-up::after {
|
||||||
|
content: attr(data-full-id);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
white-space: nowrap;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transition: all var(--transition-fast) ease;
|
||||||
|
z-index: 1000;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.session-id-display-up:hover::after {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-item {
|
||||||
|
margin: 20px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-message {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(76, 175, 80, 0.2);
|
||||||
|
color: #4caf50;
|
||||||
|
border: 1px solid #4caf50;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="test-container">
|
||||||
|
<h1>Tooltip 方向測試</h1>
|
||||||
|
|
||||||
|
<!-- 頂部測試 - 模擬實際使用場景 -->
|
||||||
|
<div class="test-header">
|
||||||
|
<span>📋 當前會話:
|
||||||
|
<span class="session-id-display"
|
||||||
|
data-full-id="6a674dda-1b98-4f86-824b-afdfd8c581f2"
|
||||||
|
title="點擊複製完整會話ID">6a674dda...</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="test-section">
|
||||||
|
<h3>測試說明</h3>
|
||||||
|
<div class="description">
|
||||||
|
以下是不同位置的tooltip顯示測試。將滑鼠懸停在會話ID上查看tooltip的顯示方向。
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="test-item">
|
||||||
|
<span class="test-label">✅ 新版本 - 向下顯示 (推薦)</span>
|
||||||
|
<span class="session-id-display"
|
||||||
|
data-full-id="6a674dda-1b98-4f86-824b-afdfd8c581f2">6a674dda...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="test-item">
|
||||||
|
<span class="test-label">❌ 舊版本 - 向上顯示 (會超出畫面)</span>
|
||||||
|
<span class="session-id-display-up"
|
||||||
|
data-full-id="6a674dda-1b98-4f86-824b-afdfd8c581f2">6a674dda...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="status-message">
|
||||||
|
✅ 新版本的tooltip向下顯示,確保在頁面頂部也能完整看到完整的會話ID
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="test-section">
|
||||||
|
<h3>實際應用場景</h3>
|
||||||
|
<div class="description">
|
||||||
|
在實際應用中,會話ID位於頁面頂部的連線狀態欄中。向下顯示tooltip可以確保用戶始終能看到完整的會話ID,而不會被瀏覽器視窗邊界截斷。
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: center; margin-top: 20px;">
|
||||||
|
<span style="color: var(--text-secondary);">
|
||||||
|
💡 提示:將滑鼠懸停在上方頂部區域的會話ID上測試實際效果
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 添加點擊複製功能
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const sessionIdElements = document.querySelectorAll('.session-id-display, .session-id-display-up');
|
||||||
|
|
||||||
|
sessionIdElements.forEach(function(element) {
|
||||||
|
element.addEventListener('click', function() {
|
||||||
|
const fullId = this.getAttribute('data-full-id');
|
||||||
|
|
||||||
|
if (navigator.clipboard) {
|
||||||
|
navigator.clipboard.writeText(fullId).then(function() {
|
||||||
|
showMessage('會話ID已複製到剪貼板: ' + fullId);
|
||||||
|
}).catch(function(err) {
|
||||||
|
console.error('複製失敗:', err);
|
||||||
|
fallbackCopy(fullId);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fallbackCopy(fullId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function fallbackCopy(text) {
|
||||||
|
const textArea = document.createElement('textarea');
|
||||||
|
textArea.value = text;
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
showMessage('會話ID已複製到剪貼板: ' + text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMessage(message) {
|
||||||
|
// 創建臨時消息提示
|
||||||
|
const messageEl = document.createElement('div');
|
||||||
|
messageEl.textContent = message;
|
||||||
|
messageEl.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
background: rgba(76, 175, 80, 0.9);
|
||||||
|
color: white;
|
||||||
|
padding: 12px 20px;
|
||||||
|
border-radius: 6px;
|
||||||
|
z-index: 10000;
|
||||||
|
font-size: 14px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(messageEl);
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
messageEl.style.opacity = '0';
|
||||||
|
messageEl.style.transition = 'opacity 0.3s ease';
|
||||||
|
setTimeout(function() {
|
||||||
|
document.body.removeChild(messageEl);
|
||||||
|
}, 300);
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user