This commit is contained in:
weipengfei 2023-10-13 13:41:06 +08:00
parent d0b2815367
commit d081e0957c
5 changed files with 194 additions and 144 deletions

View File

@ -0,0 +1,24 @@
<script>
</script>
<template>
<div class="box">
<slot></slot>
</div>
</template>
<style scoped>
.box {
width: 400px;
height: 300px;
border-radius: 20px;
/* background-color: rgba(97, 161, 140, 0.3); */
/* position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); */
display: flex;
justify-content: center;
align-items: center;
}
</style>

View File

@ -14,8 +14,8 @@
<style scoped> <style scoped>
.dots { .dots {
width: 3em; width: 20em;
height: 3em; height: 20em;
display: grid; display: grid;
grid-template-rows: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
@ -24,8 +24,8 @@
} }
.dots > div { .dots > div {
width: 0.5em; width: 4em;
height: 0.5em; height: 4em;
background-color: #3cefff; background-color: #3cefff;
border-radius: 50%; border-radius: 50%;
animation: fade 1.5s alternate ease-in-out infinite; animation: fade 1.5s alternate ease-in-out infinite;

View File

@ -5,9 +5,9 @@
<style scoped> <style scoped>
div { div {
position: relative; position: relative;
width: 2em; width: 20em;
height: 2em; height: 20em;
border: 3px solid #3cefff; border: 2em solid #3cefff;
overflow: hidden; overflow: hidden;
animation: spin 3s ease infinite; animation: spin 3s ease infinite;
} }
@ -17,8 +17,8 @@ div::before {
position: absolute; position: absolute;
top: -3px; top: -3px;
left: -3px; left: -3px;
width: 2em; width: 20em;
height: 2em; height: 20em;
background-color: hsla(185, 100%, 62%, 0.75); background-color: hsla(185, 100%, 62%, 0.75);
transform-origin: center bottom; transform-origin: center bottom;
transform: scaleY(1); transform: scaleY(1);

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div class="div">
<span /> <span />
<span /> <span />
<span /> <span />
@ -8,17 +8,17 @@
</template> </template>
<style scoped> <style scoped>
div { .div {
display: flex; display: flex;
flex-flow: row nowrap; flex-flow: row nowrap;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
width: 2em; width: 20em;
} }
span { span {
width: 0.3em; width: 3em;
height: 1em; height: 6em;
background-color: #3cefff; background-color: #3cefff;
} }

View File

@ -21,6 +21,10 @@ import { useBasicLayout } from '@/hooks/useBasicLayout'
import { useChatStore, usePromptStore } from '@/store' import { useChatStore, usePromptStore } from '@/store'
import { fetchChatAPIProcess } from '@/api' import { fetchChatAPIProcess } from '@/api'
import { t } from '@/locales' import { t } from '@/locales'
import indexBG from "@/components/animation/indexBG.vue"
import recording from "@/components/animation/recording.vue"
import inputing from "@/components/animation/inputing.vue"
import loding from "@/components/animation/loding.vue"
import IatRecorder from '@/utils/test.js' import IatRecorder from '@/utils/test.js'
// import IatRecorder from '@/utils/larRcorder.js' // import IatRecorder from '@/utils/larRcorder.js'
@ -53,10 +57,13 @@ user_channel.on('message', (data: any) => {
if (recordFalg.value == 0) { if (recordFalg.value == 0) {
RecordXunfei() RecordXunfei()
recordFalg.value = 1 recordFalg.value = 1
nowStauts.value = 'record'
} }
else { else {
RecordXunfei() RecordXunfei()
recordFalg.value = 0 recordFalg.value = 0
nowStauts.value = 'loding'
handleSubmit()
} }
}) })
@ -64,10 +71,12 @@ const changeRecord = ()=>{
if (recordFalg.value == 0) { if (recordFalg.value == 0) {
RecordXunfei() RecordXunfei()
recordFalg.value = 1 recordFalg.value = 1
nowStauts.value = 'record'
} }
else { else {
RecordXunfei() RecordXunfei()
recordFalg.value = 0 recordFalg.value = 0
nowStauts.value = 'loding'
} }
} }
@ -99,6 +108,7 @@ const conversationList = computed(() =>
const prompt = ref<string>('') const prompt = ref<string>('')
const loading = ref<boolean>(false) const loading = ref<boolean>(false)
const inputRef = ref<Ref | null>(null) const inputRef = ref<Ref | null>(null)
const nowStauts = ref('input') // , input, loding, record
// PromptStore // PromptStore
const promptStore = usePromptStore() const promptStore = usePromptStore()
@ -194,6 +204,7 @@ async function onConversation() {
}, },
], ],
})) }))
nowStauts = 'loding'
// WebSocket // WebSocket
socket.onmessage = (event: any) => { socket.onmessage = (event: any) => {
@ -203,6 +214,7 @@ async function onConversation() {
lastText += msg.payload.choices.text[0].content lastText += msg.payload.choices.text[0].content
mp3.push(msg.payload.choices.mp3) mp3.push(msg.payload.choices.mp3)
const loading = true const loading = true
nowStauts = 'input'
updateChat( updateChat(
+uuid, +uuid,
dataSources.value.length - 1, dataSources.value.length - 1,
@ -606,135 +618,149 @@ const click = () => {
</script> </script>
<template> <template>
<div class="flex flex-col w-full h-full"> <div class="flex w-full h-full my-layout">
<HeaderComponent <indexBG v-if="!isMobile">
v-if="isMobile" <recording v-if="nowStauts=='record'"></recording>
:using-context="usingContext" <loding v-else-if="nowStauts=='loding'"></loding>
@export="handleExport" <inputing v-else></inputing>
@handle-clear="handleClear" </indexBG>
/> <div class="flex flex-col w-full h-full" :style="{'max-width': maxWeight + 'px'}">
<main class="flex-1 overflow-hidden"> <HeaderComponent
<div v-if="isMobile"
id="scrollRef" :using-context="usingContext"
ref="scrollRef" @export="handleExport"
class="h-full overflow-hidden overflow-y-auto" @handle-clear="handleClear"
> />
<div <main class="flex-1 overflow-hidden">
id="image-wrapper" <div
class="w-full max-w-screen-xl m-auto dark:bg-[#101014]" id="scrollRef"
:class="[isMobile ? 'p-2' : 'p-4']" ref="scrollRef"
:style="{'max-width': maxWeight + 'px'}" class="h-full overflow-hidden overflow-y-auto"
> >
<!-- <div @click="click">录音开始</div> --> <div
<!-- <div> id="image-wrapper"
浏览器录音听写<button id="btn_control" @click="click"> class="w-full max-w-screen-xl m-auto dark:bg-[#101014]"
开始录音 :class="[isMobile ? 'p-2' : 'p-4']"
</button> :style="{'max-width': maxWeight + 'px'}"
</div> >
<br> <!-- <div @click="click">录音开始</div> -->
<div id="result" ref="resultRef" /> --> <!-- <div>
浏览器录音听写<button id="btn_control" @click="click">
开始录音
</button>
</div>
<br>
<div id="result" ref="resultRef" /> -->
<template v-if="!dataSources.length"> <template v-if="!dataSources.length">
<div <div
class="flex items-center justify-center mt-4 text-center text-neutral-300" class="flex items-center justify-center mt-4 text-center text-neutral-300"
> >
<SvgIcon icon="ri:bubble-chart-fill" class="mr-2 text-3xl" /> <SvgIcon icon="ri:bubble-chart-fill" class="mr-2 text-3xl" />
<span>欢迎来到里海AI~</span> <span>欢迎来到里海AI~</span>
</div> </div>
</template> </template>
<template v-else> <template v-else>
<div> <div>
<Message <Message
v-for="(item, index) of dataSources" v-for="(item, index) of dataSources"
:key="index" :key="index"
:date-time="item.dateTime" :date-time="item.dateTime"
:text="item.text" :text="item.text"
:mp3="item.mp3" :mp3="item.mp3"
:inversion="item.inversion" :inversion="item.inversion"
:error="item.error" :error="item.error"
:loading="item.loading" :loading="item.loading"
@regenerate="onRegenerate(index)" @regenerate="onRegenerate(index)"
@delete="handleDelete(index)" @delete="handleDelete(index)"
/> />
<div class="sticky bottom-0 left-0 flex justify-center"> <div class="sticky bottom-0 left-0 flex justify-center">
<NButton v-if="loading" type="warning" @click="handleStop"> <NButton v-if="loading" type="warning" @click="handleStop">
<template #icon> <template #icon>
<SvgIcon icon="ri:stop-circle-line" /> <SvgIcon icon="ri:stop-circle-line" />
</template> </template>
{{ t("common.stopResponding") }} {{ t("common.stopResponding") }}
</NButton> </NButton>
</div> </div>
</div> </div>
</template> </template>
</div> </div>
</div> </div>
</main> </main>
<footer :class="footerClass"> <footer :class="footerClass">
<div class="w-full max-w-screen-xl m-auto" <div class="w-full max-w-screen-xl m-auto"
:style="{'max-width': maxWeight + 'px'}"> :style="{'max-width': maxWeight + 'px'}">
<div class="flex items-center justify-between space-x-2"> <div class="flex items-center justify-between space-x-2">
<HoverButton v-if="recordFalg==0" @click="changeRecord"> <HoverButton v-if="recordFalg==0" @click="changeRecord">
<span class="text-xl text-[#4f555e] dark:text-white"> <span class="text-xl text-[#4f555e] dark:text-white">
录音 录音
</span> </span>
</HoverButton> </HoverButton>
<HoverButton v-else-if="recordFalg==1" @click="changeRecord"> <HoverButton v-else-if="recordFalg==1" @click="changeRecord">
<span class="text-xl text-[#4f555e] dark:text-white"> <span class="text-xl text-[#4f555e] dark:text-white">
完成 完成
</span> </span>
</HoverButton> </HoverButton>
<HoverButton v-if="!isMobile" @click="handleClear"> <HoverButton v-if="!isMobile" @click="handleClear">
<span class="text-xl text-[#4f555e] dark:text-white"> <span class="text-xl text-[#4f555e] dark:text-white">
<SvgIcon icon="ri:delete-bin-line" /> <SvgIcon icon="ri:delete-bin-line" />
</span> </span>
</HoverButton> </HoverButton>
<!-- <HoverButton v-if="!isMobile" @click="handleExport"> <!-- <HoverButton v-if="!isMobile" @click="handleExport">
<span class="text-xl text-[#4f555e] dark:text-white"> <span class="text-xl text-[#4f555e] dark:text-white">
<SvgIcon icon="ri:download-2-line" /> <SvgIcon icon="ri:download-2-line" />
</span> </span>
</HoverButton> --> </HoverButton> -->
<!-- <HoverButton @click="toggleUsingContext"> <!-- <HoverButton @click="toggleUsingContext">
<span <span
class="text-xl" class="text-xl"
:class="{ :class="{
'text-[#4b9e5f]': usingContext, 'text-[#4b9e5f]': usingContext,
'text-[#a8071a]': !usingContext, 'text-[#a8071a]': !usingContext,
}" }"
> >
<SvgIcon icon="ri:chat-history-line" /> <SvgIcon icon="ri:chat-history-line" />
</span> </span>
</HoverButton> --> </HoverButton> -->
<NAutoComplete <NAutoComplete
v-model:value="prompt" v-model:value="prompt"
:options="searchOptions" :options="searchOptions"
:render-label="renderOption" :render-label="renderOption"
> >
<template #default="{ handleInput, handleBlur, handleFocus }"> <template #default="{ handleInput, handleBlur, handleFocus }">
<NInput <NInput
v-model:value="prompt" v-model:value="prompt"
type="textarea" type="textarea"
:placeholder="placeholder" :placeholder="placeholder"
:autosize="{ minRows: 1, maxRows: isMobile ? 4 : 8 }" :autosize="{ minRows: 1, maxRows: isMobile ? 4 : 8 }"
@input="handleInput" @input="handleInput"
@focus="handleFocus" @focus="handleFocus"
@blur="handleBlur" @blur="handleBlur"
@keypress="handleEnter" @keypress="handleEnter"
/> />
</template> </template>
</NAutoComplete> </NAutoComplete>
<NButton <NButton
type="primary" type="primary"
:disabled="buttonDisabled" :disabled="buttonDisabled"
@click="handleSubmit" @click="handleSubmit"
> >
<template #icon> <template #icon>
<span class="dark:text-black"> <span class="dark:text-black">
<SvgIcon icon="ri:send-plane-fill" /> <SvgIcon icon="ri:send-plane-fill" />
</span> </span>
</template> </template>
</NButton> </NButton>
</div> </div>
</div> </div>
</footer> </footer>
</div> </div>
</div>
</template> </template>
<style scoped>
.my-layout{
justify-content: center;
align-items: center;
}
</style>