diff --git a/dashboard/src/views/ChatPage.vue b/dashboard/src/views/ChatPage.vue index 4995babfc..1aa8bb9e0 100644 --- a/dashboard/src/views/ChatPage.vue +++ b/dashboard/src/views/ChatPage.vue @@ -80,7 +80,7 @@

{{ getCurrentConversation.title || tm('conversation.newConversation') - }}

+ }}
{{ formatDate(getCurrentConversation.updated_at) }}
@@ -175,8 +175,17 @@ -
-
+
+
+
+
+
+ +
@@ -340,6 +349,11 @@ export default { sidebarHoverExpanded: false, sidebarHoverDelay: 100, // 悬停延迟,单位毫秒 pendingCid: null, // Store pending conversation ID for route handling + + // 复制成功提示 + copySuccessMessage: null, + copySuccessTimeout: null, + copiedMessages: new Set(), // 存储已复制的消息索引 } }, @@ -1000,7 +1014,6 @@ export default { // 复制代码到剪贴板 copyCodeToClipboard(code) { navigator.clipboard.writeText(code).then(() => { - // 可以添加一个简单的提示 console.log('代码已复制到剪贴板'); }).catch(err => { console.error('复制失败:', err); @@ -1019,6 +1032,54 @@ export default { }); }, + // 复制bot消息到剪贴板 + copyBotMessage(message, messageIndex) { + // 移除HTML标签,获取纯文本 + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = message; + const plainText = tempDiv.textContent || tempDiv.innerText || message; + + navigator.clipboard.writeText(plainText).then(() => { + console.log('消息已复制到剪贴板'); + this.showCopySuccess(messageIndex); + }).catch(err => { + console.error('复制失败:', err); + // 如果现代API失败,使用传统方法 + const textArea = document.createElement('textarea'); + textArea.value = plainText; + document.body.appendChild(textArea); + textArea.select(); + try { + document.execCommand('copy'); + console.log('消息已复制到剪贴板 (fallback)'); + this.showCopySuccess(messageIndex); + } catch (fallbackErr) { + console.error('复制失败 (fallback):', fallbackErr); + } + document.body.removeChild(textArea); + }); + }, + + // 显示复制成功提示 + showCopySuccess(messageIndex) { + this.copiedMessages.add(messageIndex); + + // 2秒后移除成功状态 + setTimeout(() => { + this.copiedMessages.delete(messageIndex); + }, 2000); + }, + + // 获取复制按钮图标 + getCopyIcon(messageIndex) { + return this.copiedMessages.has(messageIndex) ? 'mdi-check' : 'mdi-content-copy'; + }, + + // 检查是否为复制成功状态 + isCopySuccess(messageIndex) { + return this.copiedMessages.has(messageIndex); + }, + // 获取复制图标SVG getCopyIconSvg() { return ''; @@ -1368,6 +1429,47 @@ export default { gap: 12px; } +.bot-message-content { + display: flex; + flex-direction: column; + align-items: flex-start; + max-width: 80%; + position: relative; +} + +.message-actions { + display: flex; + gap: 4px; + opacity: 0; + transition: opacity 0.2s ease; + margin-left: 8px; +} + +.bot-message:hover .message-actions { + opacity: 1; +} + +.copy-message-btn { + opacity: 0.6; + transition: all 0.2s ease; + color: var(--v-theme-secondary); +} + +.copy-message-btn:hover { + opacity: 1; + background-color: rgba(103, 58, 183, 0.1); +} + +.copy-message-btn.copy-success { + color: #4caf50; + opacity: 1; +} + +.copy-message-btn.copy-success:hover { + color: #4caf50; + background-color: rgba(76, 175, 80, 0.1); +} + .message-bubble { padding: 8px 16px; border-radius: 12px; @@ -1727,6 +1829,5 @@ export default { width: 100%; padding-right: 32px; flex-shrink: 0; - /* 防止header被压缩 */ } \ No newline at end of file