From 5fb58c10b2bb44b3f2d3bdab4d7a6619271e2bbf Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期三, 02 四月 2025 17:51:39 +0800 Subject: [PATCH] smallScreenClick --- src/components/chat/hooks/useAssistantContentOpt.ts | 147 ++++++++++++++++++++++++++++++++++++------------ 1 files changed, 109 insertions(+), 38 deletions(-) diff --git a/src/components/chat/hooks/useAssistantContentOpt.ts b/src/components/chat/hooks/useAssistantContentOpt.ts index d829180..e95a358 100644 --- a/src/components/chat/hooks/useAssistantContentOpt.ts +++ b/src/components/chat/hooks/useAssistantContentOpt.ts @@ -1,34 +1,55 @@ import { ElMessage } from 'element-plus'; -import type { ComputedRef, Ref } from 'vue'; -import { computed, nextTick, ref } from 'vue'; -import useClipboard from 'vue-clipboard3'; -import type { ChatMessage } from '../model/types'; +import { computed, nextTick, onDeactivated, ref } from 'vue'; +// import useClipboard from 'vue-clipboard3'; +import { onClickOutside, useClipboard } from '@vueuse/core'; +import markdownToTxt from 'markdown-to-txt'; import { AnswerState, AnswerType, RoleEnum } from '../model/types'; import { SetHistoryAnswerState } from '/@/api/ai/chat'; -import { useClickOther } from '/@/hooks/useClickOther'; -import { onClickOutside } from '@vueuse/core'; -import { isSharePage } from '/@/stores/chatRoom'; - +import { isSharePage } from '/@/stores/chatRoom'; +import BrowserSpeechSynthesis from '/@/utils/speech/synthesis'; export type AssistantContentOptOption = { sendChatMessage: any; - displayMessageList: ComputedRef<ChatMessage[]>; }; +const activeSpeakItem = ref(null); export const useAssistantContentOpt = (option: AssistantContentOptOption) => { - const { sendChatMessage, displayMessageList } = option; - const { toClipboard } = useClipboard(); - const preQuestion = ref(null); + const isSpeaking = ref(false); + const { sendChatMessage } = option; + const { copy } = useClipboard(); const copyClick = (item) => { - const type = item.content.type; - let text = ''; - if (type === AnswerType.Knowledge) { - text = item.content.values?.map((item) => item.answer).join('\n\n') ?? ''; - } else { - text = item.content.values; - } + const isText = checkIsText(item); + if (!isText) return; + const text = getPlainText(item); ElMessage.success('澶嶅埗鎴愬姛'); - toClipboard(text); + copy(text); + }; + + const checkIsText = (item) => { + const isText = item?.content?.values?.some((item) => item?.content?.type === AnswerType.Knowledge); + return isText; + }; + + const getPlainText = (item) => { + const knowledgeText = item.content.values + .filter((item) => { + const type = item?.content?.type; + return type === AnswerType.Knowledge; + }) + .reduce((acc, cur) => { + const answer = cur?.content?.values + ?.map((item) => { + const mdText = item.answer; + const linkText = item.metadata?.Title; + if (linkText) { + return `${mdText}\n\n${linkText}`; + } + return mdText; + }) + .join('\n\n'); + return acc + answer; + }, ''); + return markdownToTxt(knowledgeText); }; const likeClick = async (item) => { @@ -38,7 +59,6 @@ answer_state: toSetState, }); item.state = toSetState; - }; const unLikeClick = async (item) => { @@ -48,8 +68,6 @@ answer_state: toSetState, }); item.state = toSetState; - - }; const feedbackPosition = ref({ x: 0, @@ -69,10 +87,15 @@ feedbackIsShow.value = true; nextTick(() => { feedbackPosition.value = { - x: -feedbackPanelRef.value[index].$el.clientWidth + offsetX, - y: -feedbackPanelRef.value[index].$el.clientHeight + offsetY, + x: -feedbackPanelRef.value[index]?.$el.clientWidth + offsetX, + y: -feedbackPanelRef.value[index]?.$el.clientHeight + offsetY, }; }); + }; + + const isItemSpeaking = (item) => { + const checkSpeak = activeSpeakItem.value === item && isSpeaking.value; + return checkSpeak; }; onClickOutside( @@ -90,15 +113,9 @@ // feedbackContent.value = ''; // } // ); - const showAskMore = computed(() => { - if (!displayMessageList.value || displayMessageList.value.length === 0) return false; - const last = displayMessageList.value.at(-1); - const isShow = last?.role === RoleEnum.assistant && last?.content?.values && last.content?.askMoreList?.length > 0; - return isShow && !isSharePage ; - }); const showFixQuestion = (item) => { - const isShow = item?.role === RoleEnum.assistant && item?.content?.values && item.content?.origin?.err_json?.fix_question; + const isShow = item?.role === RoleEnum.assistant && item.content?.origin?.sample_question?.length > 0 && !isSharePage.value; return isShow; }; const askMoreClick = (item) => { @@ -107,17 +124,69 @@ }; const fixQuestionClick = (item, originData) => { - if (!item.question) return; - preQuestion.value = originData?.question; + if (!item) return; + // preQuestion.value = originData?.question; try { sendChatMessage({ type: AnswerType.Text, - values: item.question, + values: item, }); } finally { - preQuestion.value = null; + // preQuestion.value = null; } }; + + let isEnterStop = false; + + const resetSpeak = () => { + isSpeaking.value = false; + isEnterStop = false; + const instance = BrowserSpeechSynthesis.getInstance(); + instance.cancel(); + activeSpeakItem.value = null; + }; + + const speechClick = (item) => { + if (!checkIsText(item)) return; + if (activeSpeakItem.value !== item) { + resetSpeak(); + } + isSpeaking.value = !isSpeaking.value; + if (isSpeaking.value) { + startSpeechClick(item); + } else { + stopSpeechClick(); + } + }; + + const startSpeechClick = (item) => { + activeSpeakItem.value = item; + + const instance = BrowserSpeechSynthesis.getInstance(); + instance.onEnd(() => { + resetSpeak(); + }); + if (isEnterStop) { + instance.resume(); + } else { + const text = getPlainText(item); + if (text) { + instance.speak(text); + } + } + isEnterStop = false; + }; + + const stopSpeechClick = () => { + isEnterStop = true; + const instance = BrowserSpeechSynthesis.getInstance(); + instance.pause(); + }; + + onDeactivated(() => { + const instance = BrowserSpeechSynthesis.getInstance(); + instance.cancel(); + }); return { copyClick, @@ -132,8 +201,10 @@ feedbackClick, askMoreClick, fixQuestionClick, - preQuestion, - showAskMore, showFixQuestion, + speechClick, + isSpeaking, + isItemSpeaking, + checkIsText, }; }; -- Gitblit v1.9.3