feat: tts语音生成

This commit is contained in:
2025-06-30 09:50:44 +08:00
parent 51e7239c71
commit 06e6b4a8c9
20 changed files with 1135 additions and 30 deletions

View File

@@ -0,0 +1,81 @@
<script setup lang="ts">
import { SpeakerWaveIcon } from "@/assets/Icons";
import { useLayoutStore, useTtsStore } from "@/stores";
const { text, messageId } = defineProps<{
text: string;
messageId: string;
}>();
const ttsStore = useTtsStore();
const layoutStore = useLayoutStore();
const { simpleMode } = storeToRefs(layoutStore);
// 获取当前消息的状态
const isPlaying = computed(() => ttsStore.isPlaying(messageId));
const isLoading = computed(() => ttsStore.isLoading(messageId));
const hasAudio = computed(() => ttsStore.hasAudio(messageId));
// 处理按钮点击
const handleClick = () => {
if (isLoading.value) {
return; // 合成中不响应点击
}
if (hasAudio.value) {
// 如果音频已准备好,切换播放/暂停
if (isPlaying.value) {
ttsStore.pause(messageId);
} else {
ttsStore.play(messageId);
}
} else {
// 如果没有音频开始TTS转换
ttsStore.convertText(text, messageId);
}
};
// 当文本改变时清理之前的音频
watch(
() => text,
() => {
ttsStore.clearAudio(messageId);
}
);
onUnmounted(() => {
ttsStore.clearAudio(messageId);
});
</script>
<template>
<NPopover trigger="hover">
<template #trigger>
<NButton
:loading="isLoading"
@click="handleClick"
quaternary
circle
:disabled="!text.trim()"
>
<SpeakerWaveIcon
v-if="!isLoading"
class="!w-4 !h-4"
:class="{
'': !simpleMode,
'animate-pulse': isPlaying
}"
/>
</NButton>
</template>
<span>
{{
isLoading
? "合成中..."
: isPlaying
? "点击暂停"
: hasAudio
? "点击播放"
: "语音合成"
}}
</span>
</NPopover>
</template>