From 76afe5f433cc8b84d44aa8552fc11d835d4b4a5e Mon Sep 17 00:00:00 2001
From: ZF sun <34314687@qq.com>
Date: Sat, 16 May 2026 11:08:46 +0800
Subject: [PATCH] =?UTF-8?q?feat(ai-chat):=20=E6=94=AF=E6=8C=81=E9=95=BF?=
=?UTF-8?q?=E6=8C=89=E5=A4=8D=E5=88=B6=E6=B6=88=E6=81=AF=E5=86=85=E5=AE=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages_tool/ai-chat/ai-chat-message.vue | 150 ++++++++++++++++++++++++-
1 file changed, 145 insertions(+), 5 deletions(-)
diff --git a/pages_tool/ai-chat/ai-chat-message.vue b/pages_tool/ai-chat/ai-chat-message.vue
index 41dc5e9..a62a8ce 100644
--- a/pages_tool/ai-chat/ai-chat-message.vue
+++ b/pages_tool/ai-chat/ai-chat-message.vue
@@ -39,8 +39,13 @@
{{ formatTime(message.timestamp) }}
-
- {{ message.content }}
+
+ {{ message.content }}
@@ -63,7 +68,12 @@
智能助手
{{ formatTime(message.timestamp) }}
-
+
@@ -512,7 +522,11 @@ export default {
lastScrollTop: 0,
historyOffset: 0,
isFetchingHistory: false,
- keyboardHeight: 0
+ keyboardHeight: 0,
+
+ // 手动长按检测相关(touch 计时器)
+ _longPressTimer: null,
+ _longPressMessage: null
}
},
computed: {
@@ -1755,7 +1769,126 @@ _handleStreamError(msg) {
this.$emit('action-click', { action, message })
},
-
+
+ // 长按消息→直接复制
+ onMessageLongPress(message) {
+ // loading 消息不允许操作
+ if (message.type === 'loading') return
+
+ // #ifdef MP-WEIXIN
+ // 微信小程序:震动反馈提升手感(小米等 Android 设备也可用)
+ try {
+ wx.vibrateShort({ type: 'medium' })
+ } catch (e) { /* 不支持震动的设备忽略 */ }
+ // #endif
+
+ this.copyMessage(message)
+ },
+
+ // 手动长按检测(touch 事件方案,兼容所有平台)
+ // 在 H5 desktop 上用 @contextmenu 触发,
+ // 在 H5 mobile / 小米微信小程序等场景靠 touch 计时器兜底
+ onBubbleTouchStart(event, message) {
+ // 单指长按才触发,忽略多点触控
+ if (event.touches && event.touches.length > 1) return
+ this._longPressMessage = message
+ this._longPressTimer = setTimeout(() => {
+ this._longPressTimer = null
+ this.onMessageLongPress(message)
+ }, 500) // 和系统长按接近的 500ms
+ },
+ onBubbleTouchMove() {
+ // 手指移动(滚动列表)→ 取消长按
+ if (this._longPressTimer) {
+ clearTimeout(this._longPressTimer)
+ this._longPressTimer = null
+ }
+ this._longPressMessage = null
+ },
+ onBubbleTouchEnd() {
+ // 手指提前松开 → 取消长按
+ if (this._longPressTimer) {
+ clearTimeout(this._longPressTimer)
+ this._longPressTimer = null
+ }
+ this._longPressMessage = null
+ },
+
+ // 复制消息内容到剪贴板(兼容 H5 / 微信小程序)
+ copyMessage(message) {
+ let copyText = message.content || ''
+ if (!copyText && message.type === 'text') {
+ copyText = message.content || ''
+ }
+ if (!copyText) {
+ uni.showToast({ title: '无可复制的内容', icon: 'none' })
+ return
+ }
+
+ // #ifdef H5
+ // H5:检测是否有局部文本被选中,有则复制选区文本,无则复制全文
+ const selection = window.getSelection()
+ const selectedText = selection && selection.toString().trim()
+ const finalText = selectedText || copyText
+
+ // H5 优先使用 Clipboard API,降级使用 document.execCommand
+ try {
+ if (navigator.clipboard && navigator.clipboard.writeText) {
+ navigator.clipboard.writeText(finalText).then(() => {
+ uni.showToast({ title: selectedText ? '已复制选中内容' : '已复制', icon: 'success' })
+ }).catch(() => {
+ this._fallbackCopyH5(finalText)
+ })
+ } else {
+ this._fallbackCopyH5(finalText)
+ }
+ } catch (e) {
+ this._fallbackCopyH5(finalText)
+ }
+ // #endif
+
+ // #ifdef MP-WEIXIN
+ // 微信小程序专用(含小米等 Android 兼容)
+ console.log('[AI Chat] 开始复制, 内容长度:', copyText.length, '内容前50字:', copyText.substring(0, 50))
+ uni.setClipboardData({
+ data: copyText,
+ success: () => {
+ console.log('[AI Chat] 复制成功')
+ uni.showToast({ title: '已复制', icon: 'success' })
+ },
+ fail: (err) => {
+ console.error('[AI Chat] 复制失败, 详细错误:', JSON.stringify(err))
+ console.error('[AI Chat] 复制失败 errMsg:', err.errMsg || err.message || '无错误消息')
+ uni.showToast({ title: '复制失败: ' + (err.errMsg || '未知错误'), icon: 'none', duration: 3000 })
+ }
+ })
+ // #endif
+ },
+
+ // H5 降级复制方案(document.execCommand + textarea)
+ _fallbackCopyH5(text) {
+ try {
+ const textarea = document.createElement('textarea')
+ textarea.value = text
+ textarea.style.position = 'fixed'
+ textarea.style.left = '-9999px'
+ textarea.style.top = '-9999px'
+ textarea.style.opacity = '0'
+ document.body.appendChild(textarea)
+ textarea.select()
+ textarea.setSelectionRange(0, text.length)
+ const success = document.execCommand('copy')
+ document.body.removeChild(textarea)
+ if (success) {
+ uni.showToast({ title: '已复制', icon: 'success' })
+ } else {
+ uni.showToast({ title: '复制失败', icon: 'none' })
+ }
+ } catch (e) {
+ uni.showToast({ title: '复制失败', icon: 'none' })
+ }
+ },
+
// 重试消息
async retryMessage(message) {
// 找到对应的用户消息
@@ -4066,5 +4199,12 @@ $radius-lg: 36rpx;
}
}
}
+
+ // H5 下允许 rich-text 内容文本选择(鼠标拖选复制)
+ .text-content,
+ .markdown-body {
+ user-select: text;
+ -webkit-user-select: text;
+ }
}