From 791c94724c5b6e7999b633165e2ce03c628c9b24 Mon Sep 17 00:00:00 2001 From: CaptainB Date: Tue, 24 Sep 2024 14:43:11 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=B5=8F=E8=A7=88=E5=99=A8?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E7=9A=84=E8=AF=AD=E9=9F=B3=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=9A=82=E5=81=9C=E5=92=8C=E7=BB=A7=E7=BB=AD=E6=92=AD=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ai-chat/LogOperationButton.vue | 54 +++++++++++++++++-- ui/src/components/ai-chat/OperationButton.vue | 27 ++++++++-- 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/ui/src/components/ai-chat/LogOperationButton.vue b/ui/src/components/ai-chat/LogOperationButton.vue index 493daf62c..78ab02027 100644 --- a/ui/src/components/ai-chat/LogOperationButton.vue +++ b/ui/src/components/ai-chat/LogOperationButton.vue @@ -90,6 +90,7 @@ const EditMarkDialogRef = ref() const buttonData = ref(props.data) const loading = ref(false) +const utterance = ref(null) function editContent(data: any) { EditContentDialogRef.value.open(data) @@ -101,18 +102,60 @@ function editMark(data: any) { const audioPlayerStatus = ref(false) +function markdownToPlainText(md: string) { + return ( + md + // 移除图片 ![alt](url) + .replace(/!\[.*?\]\(.*?\)/g, '') + // 移除链接 [text](url) + .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') + // 移除 Markdown 标题符号 (#, ##, ###) + .replace(/^#{1,6}\s+/gm, '') + // 移除加粗 **text** 或 __text__ + .replace(/\*\*(.*?)\*\*/g, '$1') + .replace(/__(.*?)__/g, '$1') + // 移除斜体 *text* 或 _text_ + .replace(/\*(.*?)\*/g, '$1') + .replace(/_(.*?)_/g, '$1') + // 移除行内代码 `code` + .replace(/`(.*?)`/g, '$1') + // 移除代码块 ```code``` + .replace(/```[\s\S]*?```/g, '') + // 移除多余的换行符 + .replace(/\n{2,}/g, '\n') + .trim() + ) +} + const playAnswerText = (text: string) => { if (!text) { text = '抱歉,没有查找到相关内容,请重新描述您的问题或提供更多信息。' } + // text 处理成纯文本 + text = markdownToPlainText(text) + audioPlayerStatus.value = true if (props.tts_type === 'BROWSER') { + if (text !== utterance.value?.text) { + window.speechSynthesis.cancel() + } + if (window.speechSynthesis.paused) { + window.speechSynthesis.resume() + return + } // 创建一个新的 SpeechSynthesisUtterance 实例 - const utterance = new SpeechSynthesisUtterance(text) + utterance.value = new SpeechSynthesisUtterance(text) + utterance.value.onend = () => { + audioPlayerStatus.value = false + utterance.value = null + } + utterance.value.onerror = () => { + audioPlayerStatus.value = false + utterance.value = null + } // 调用浏览器的朗读功能 - window.speechSynthesis.speak(utterance) + window.speechSynthesis.speak(utterance.value) } if (props.tts_type === 'TTS') { - audioPlayerStatus.value = true // 恢复上次暂停的播放 if (audioPlayer.value?.src) { audioPlayer.value?.play() @@ -152,10 +195,13 @@ const playAnswerText = (text: string) => { } const pausePlayAnswerText = () => { + audioPlayerStatus.value = false if (props.tts_type === 'TTS') { - audioPlayerStatus.value = false audioPlayer.value?.pause() } + if (props.tts_type === 'BROWSER') { + window.speechSynthesis.pause() + } } function refreshMark() { diff --git a/ui/src/components/ai-chat/OperationButton.vue b/ui/src/components/ai-chat/OperationButton.vue index 874570ef3..ae5273c87 100644 --- a/ui/src/components/ai-chat/OperationButton.vue +++ b/ui/src/components/ai-chat/OperationButton.vue @@ -120,6 +120,7 @@ const audioPlayer = ref(null) const audioPlayerStatus = ref(false) const buttonData = ref(props.data) const loading = ref(false) +const utterance = ref(null) function regeneration() { emit('regeneration') @@ -165,14 +166,29 @@ const playAnswerText = (text: string) => { } // text 处理成纯文本 text = markdownToPlainText(text) + audioPlayerStatus.value = true if (props.tts_type === 'BROWSER') { + if (text !== utterance.value?.text) { + window.speechSynthesis.cancel() + } + if (window.speechSynthesis.paused) { + window.speechSynthesis.resume() + return + } // 创建一个新的 SpeechSynthesisUtterance 实例 - const utterance = new SpeechSynthesisUtterance(text) + utterance.value = new SpeechSynthesisUtterance(text) + utterance.value.onend = () => { + audioPlayerStatus.value = false + utterance.value = null + } + utterance.value.onerror = () => { + audioPlayerStatus.value = false + utterance.value = null + } // 调用浏览器的朗读功能 - window.speechSynthesis.speak(utterance) + window.speechSynthesis.speak(utterance.value) } if (props.tts_type === 'TTS') { - audioPlayerStatus.value = true // 恢复上次暂停的播放 if (audioPlayer.value?.src) { audioPlayer.value?.play() @@ -212,10 +228,13 @@ const playAnswerText = (text: string) => { } const pausePlayAnswerText = () => { + audioPlayerStatus.value = false if (props.tts_type === 'TTS') { - audioPlayerStatus.value = false audioPlayer.value?.pause() } + if (props.tts_type === 'BROWSER') { + window.speechSynthesis.pause() + } }