diff --git a/main/manager-mobile/src/pages/chat-history/detail.vue b/main/manager-mobile/src/pages/chat-history/detail.vue index 4d8f91e7..c3d399d5 100644 --- a/main/manager-mobile/src/pages/chat-history/detail.vue +++ b/main/manager-mobile/src/pages/chat-history/detail.vue @@ -13,9 +13,9 @@ import type { ChatMessage, UserMessageContent } from '@/api/chat-history/types' import { onLoad, onUnload } from '@dcloudio/uni-app' import { computed, ref } from 'vue' import { getAudioId, getChatHistory } from '@/api/chat-history/chat-history' -import { getEnvBaseUrl } from '@/utils' -import { toast } from '@/utils/toast' import { t } from '@/i18n' +import { debounce, getEnvBaseUrl } from '@/utils' +import { toast } from '@/utils/toast' defineOptions({ name: 'ChatDetail', @@ -129,7 +129,7 @@ function formatTime(timeStr: string) { } // 播放音频 -async function playAudio(audioId: string) { +const playAudio = debounce(async (audioId: string) => { if (!audioId) { toast.error(t('chatHistory.invalidAudioId')) return @@ -139,8 +139,11 @@ async function playAudio(audioId: string) { // 如果正在播放其他音频,先停止 if (audioContext.value) { audioContext.value.stop() - audioContext.value.destroy() - audioContext.value = null + } + // 如果当前音频ID与请求ID相同暂停播放 + if (playingAudioId.value === audioId) { + playingAudioId.value = null + return } // 获取音频下载ID @@ -151,7 +154,9 @@ async function playAudio(audioId: string) { const audioUrl = `${baseUrl}/agent/play/${downloadId}` // 创建音频上下文 - audioContext.value = uni.createInnerAudioContext() + if (!audioContext.value) { + audioContext.value = uni.createInnerAudioContext() + } audioContext.value.src = audioUrl // 设置播放状态 @@ -185,7 +190,7 @@ async function playAudio(audioId: string) { toast.error(t('chatHistory.playAudioFailed')) playingAudioId.value = null } -} +}, 400) onLoad((options) => { if (options?.sessionId && options?.agentId) { diff --git a/main/manager-mobile/src/pages/voiceprint/index.vue b/main/manager-mobile/src/pages/voiceprint/index.vue index a00711a5..e6ba2ccc 100644 --- a/main/manager-mobile/src/pages/voiceprint/index.vue +++ b/main/manager-mobile/src/pages/voiceprint/index.vue @@ -137,7 +137,6 @@ async function loadChatHistory() { audioId: item.audioId, index, })) - showChatHistoryDialog.value = true } catch (error) { console.error('获取对话记录失败:', error) @@ -368,6 +367,7 @@ onMounted(async () => { // 智能体已简化为默认 loadVoicePrintList() + loadChatHistory() }) // 暴露方法给父组件 @@ -468,7 +468,7 @@ defineExpose({ any + +interface DebouncedFunction extends AnyFunction { + cancel: () => void +} + +/** + * 防抖函数 + * @param fn 要防抖的函数 + * @param delay 延迟时间(毫秒),默认500ms + * @param immediate 是否立即执行,默认false + * @returns 防抖处理后的函数 + */ +export function debounce( + fn: T, + delay = 500, + immediate = false, +): DebouncedFunction { + let timer: ReturnType | null = null + + const debounced = function (this: any, ...args: Parameters) { + if (timer) { + clearTimeout(timer) + } + + if (immediate && !timer) { + fn.apply(this, args) + } + + timer = setTimeout(() => { + if (!immediate) { + fn.apply(this, args) + } + timer = null + }, delay) + } as DebouncedFunction + + debounced.cancel = () => { + if (timer) { + clearTimeout(timer) + timer = null + } + } + + return debounced }