This commit is contained in:
parent
a358efeebc
commit
faee446b5a
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'
|
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import {
|
import {
|
||||||
|
@ -21,15 +21,11 @@ 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 indexBG from '@/components/animation/indexBG.vue'
|
||||||
import recording from "@/components/animation/recording.vue"
|
import recording from '@/components/animation/recording.vue'
|
||||||
import inputing from "@/components/animation/inputing.vue"
|
import inputing from '@/components/animation/inputing.vue'
|
||||||
import loding from "@/components/animation/loding.vue"
|
import lodingSpin from '@/components/animation/lodingSpin.vue'
|
||||||
import lodingCir from "@/components/animation/lodingCir.vue"
|
|
||||||
import lodingSpin from "@/components/animation/lodingSpin.vue"
|
|
||||||
|
|
||||||
import IatRecorder from '@/utils/test.js'
|
|
||||||
import { start } from 'repl'
|
|
||||||
// import IatRecorder from '@/utils/larRcorder.js'
|
// import IatRecorder from '@/utils/larRcorder.js'
|
||||||
|
|
||||||
// import socket from "@/websocket/socket";
|
// import socket from "@/websocket/socket";
|
||||||
|
@ -60,26 +56,26 @@ user_channel.on('message', (data: any) => {
|
||||||
if (recordFalg.value == 0) {
|
if (recordFalg.value == 0) {
|
||||||
RecordXunfei()
|
RecordXunfei()
|
||||||
recordFalg.value = 1
|
recordFalg.value = 1
|
||||||
nowStatus.value = 'record'
|
nowStatus.value = 'record'
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RecordXunfei()
|
RecordXunfei()
|
||||||
recordFalg.value = 0
|
recordFalg.value = 0
|
||||||
nowStatus.value = 'loding'
|
nowStatus.value = 'loding'
|
||||||
handleSubmit()
|
handleSubmit()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const changeRecord = ()=>{
|
const changeRecord = () => {
|
||||||
if (recordFalg.value == 0) {
|
if (recordFalg.value == 0) {
|
||||||
RecordXunfei()
|
RecordXunfei()
|
||||||
recordFalg.value = 1
|
recordFalg.value = 1
|
||||||
nowStatus.value = 'record'
|
nowStatus.value = 'record'
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RecordXunfei()
|
RecordXunfei()
|
||||||
recordFalg.value = 0
|
recordFalg.value = 0
|
||||||
nowStatus.value = 'input'
|
nowStatus.value = 'input'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +96,7 @@ const { scrollRef, scrollToBottom, scrollToBottomIfAtBottom } = useScroll()
|
||||||
const { usingContext, toggleUsingContext } = useUsingContext()
|
const { usingContext, toggleUsingContext } = useUsingContext()
|
||||||
|
|
||||||
const { uuid } = route.params as { uuid: string }
|
const { uuid } = route.params as { uuid: string }
|
||||||
|
chatStore.getChatByUuid(+uuid).length = 0
|
||||||
|
|
||||||
const dataSources = computed(() => chatStore.getChatByUuid(+uuid))
|
const dataSources = computed(() => chatStore.getChatByUuid(+uuid))
|
||||||
const conversationList = computed(() =>
|
const conversationList = computed(() =>
|
||||||
|
@ -151,11 +148,11 @@ async function onConversation() {
|
||||||
// 监听WebSocket关闭事件
|
// 监听WebSocket关闭事件
|
||||||
socket.onclose = (event: any) => {
|
socket.onclose = (event: any) => {
|
||||||
console.log('连接已关闭: ', event)
|
console.log('连接已关闭: ', event)
|
||||||
nowStatus.value = 'input'
|
nowStatus.value = 'input'
|
||||||
}
|
}
|
||||||
socket.onerror = (event: any) => {
|
socket.onerror = (event: any) => {
|
||||||
console.log('连接出错: ', event)
|
console.log('连接出错: ', event)
|
||||||
nowStatus.value = 'input'
|
nowStatus.value = 'input'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loading.value)
|
if (loading.value)
|
||||||
|
@ -212,39 +209,40 @@ async function onConversation() {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
nowStatus.value = 'loding'
|
nowStatus.value = 'loding'
|
||||||
|
|
||||||
// 监听WebSocket接收消息事件
|
// 监听WebSocket接收消息事件
|
||||||
socket.onmessage = (event: any) => {
|
socket.onmessage = (event: any) => {
|
||||||
try {
|
try {
|
||||||
const msg = JSON.parse(event.data)
|
const msg = JSON.parse(event.data)
|
||||||
// console.log(`收到消息: `, msg.payload.choices.text[0].content);
|
// console.log(`收到消息: `, msg.payload.choices.text[0].content);
|
||||||
// console.log(`当前消息: `, dataSources.value[dataSources.value.length - 1].text);
|
// console.log(`当前消息: `, dataSources.value[dataSources.value.length - 1].text);
|
||||||
lastText += msg.payload.choices.text[0].content
|
lastText += msg.payload.choices.text[0].content
|
||||||
const loading = true
|
const loading = true
|
||||||
nowStart.value = false
|
nowStart.value = false
|
||||||
updateChat(
|
updateChat(
|
||||||
+uuid,
|
+uuid,
|
||||||
dataSources.value.length - 1,
|
dataSources.value.length - 1,
|
||||||
{
|
{
|
||||||
dateTime: new Date().toLocaleString(),
|
dateTime: new Date().toLocaleString(),
|
||||||
text: lastText,
|
text: lastText,
|
||||||
inversion: false,
|
inversion: false,
|
||||||
error: false,
|
error: false,
|
||||||
loading,
|
loading,
|
||||||
conversationOptions: { conversationId: msg.header.sid, parentMessageId: msg.header.sid },
|
conversationOptions: { conversationId: msg.header.sid, parentMessageId: msg.header.sid },
|
||||||
requestOptions: { prompt: message, options: { ...options } },
|
requestOptions: { prompt: message, options: { ...options } },
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
// 关闭连接
|
// 关闭连接
|
||||||
if(msg.header.code!=0||(event.data&&msg.header.status==2)){
|
if (msg.header.code != 0 || (event.data && msg.header.status == 2)) {
|
||||||
nowStatus.value = 'input'
|
nowStatus.value = 'input'
|
||||||
socket.close()
|
socket.close()
|
||||||
}
|
}
|
||||||
} catch (error) {
|
}
|
||||||
nowStatus.value = 'input'
|
catch (error) {
|
||||||
socket.close()
|
nowStatus.value = 'input'
|
||||||
}
|
socket.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// await fetchChatAPIProcess<Chat.ConversationResponse>({
|
// await fetchChatAPIProcess<Chat.ConversationResponse>({
|
||||||
|
@ -601,7 +599,6 @@ onUnmounted(() => {
|
||||||
controller.abort()
|
controller.abort()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
window.winText = ''
|
window.winText = ''
|
||||||
|
|
||||||
window.addEventListener('test', (e) => {
|
window.addEventListener('test', (e) => {
|
||||||
|
@ -612,42 +609,41 @@ window.addEventListener('test', (e) => {
|
||||||
// setTimeout(()=>{
|
// setTimeout(()=>{
|
||||||
// nowStart.value = false;
|
// nowStart.value = false;
|
||||||
// }, 800)
|
// }, 800)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex w-full h-full my-layout">
|
<div class="flex w-full h-full my-layout">
|
||||||
<indexBG v-if="!isMobile">
|
<indexBG v-if="!isMobile">
|
||||||
<transition mode="out-in" name="fade">
|
<transition mode="out-in" name="fade">
|
||||||
<inputing v-if="nowStatus=='input'" key="input"></inputing>
|
<inputing v-if="nowStatus == 'input'" key="input" />
|
||||||
<recording v-else-if="nowStatus=='record'" key="record"></recording>
|
<recording v-else-if="nowStatus == 'record'" key="record" />
|
||||||
<!-- <loding v-else-if="nowStatus=='loding'" key="loding"></loding> -->
|
<!-- <loding v-else-if="nowStatus=='loding'" key="loding"></loding> -->
|
||||||
<lodingSpin v-else-if="nowStatus=='loding'" key="loding"></lodingSpin>
|
<lodingSpin v-else-if="nowStatus == 'loding'" key="loding" />
|
||||||
<!-- <lodingCir v-else-if="nowStatus=='loding'" key="loding"></lodingCir> -->
|
<!-- <lodingCir v-else-if="nowStatus=='loding'" key="loding"></lodingCir> -->
|
||||||
</transition>
|
</transition>
|
||||||
</indexBG>
|
</indexBG>
|
||||||
<transition name="slide-right-to-left">
|
<transition name="slide-right-to-left">
|
||||||
<div v-if="!nowStart" class="flex flex-col w-full h-full" :style="{'max-width': maxWeight + 'px'}">
|
<div v-if="!nowStart" class="flex flex-col w-full h-full" :style="{ 'max-width': `${maxWeight}px` }">
|
||||||
<HeaderComponent
|
<HeaderComponent
|
||||||
v-if="isMobile"
|
v-if="isMobile"
|
||||||
:using-context="usingContext"
|
:using-context="usingContext"
|
||||||
@export="handleExport"
|
@export="handleExport"
|
||||||
@handle-clear="handleClear"
|
@handle-clear="handleClear"
|
||||||
/>
|
/>
|
||||||
<main class="flex-1 overflow-hidden">
|
<main class="flex-1 overflow-hidden">
|
||||||
<div
|
<div
|
||||||
id="scrollRef"
|
id="scrollRef"
|
||||||
ref="scrollRef"
|
ref="scrollRef"
|
||||||
class="h-full overflow-hidden overflow-y-auto"
|
class="h-full overflow-hidden overflow-y-auto"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
id="image-wrapper"
|
id="image-wrapper"
|
||||||
class="w-full max-w-screen-xl m-auto dark:bg-[#101014]"
|
class="w-full max-w-screen-xl m-auto dark:bg-[#101014]"
|
||||||
:class="[isMobile ? 'p-2' : 'p-4']"
|
:class="[isMobile ? 'p-2' : 'p-4']"
|
||||||
:style="{'max-width': maxWeight + 'px'}"
|
:style="{ 'max-width': `${maxWeight}px` }"
|
||||||
>
|
>
|
||||||
<!-- <div @click="click">录音开始</div> -->
|
<!-- <div @click="click">录音开始</div> -->
|
||||||
<!-- <div>
|
<!-- <div>
|
||||||
浏览器录音听写:<button id="btn_control" @click="click">
|
浏览器录音听写:<button id="btn_control" @click="click">
|
||||||
开始录音
|
开始录音
|
||||||
</button>
|
</button>
|
||||||
|
@ -655,65 +651,67 @@ window.addEventListener('test', (e) => {
|
||||||
<br>
|
<br>
|
||||||
<div id="result" ref="resultRef" /> -->
|
<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"
|
||||||
: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
|
||||||
:style="{'max-width': maxWeight + 'px'}">
|
class="w-full max-w-screen-xl m-auto"
|
||||||
<div class="flex items-center justify-between space-x-2">
|
:style="{ 'max-width': `${maxWeight}px` }"
|
||||||
<HoverButton v-if="recordFalg==0" @click="changeRecord">
|
>
|
||||||
<span class="text-xl text-[#4f555e] dark:text-white">
|
<div class="flex items-center justify-between space-x-2">
|
||||||
录音
|
<HoverButton v-if="recordFalg == 0" @click="changeRecord">
|
||||||
</span>
|
<span class="text-xl text-[#4f555e] dark:text-white">
|
||||||
</HoverButton>
|
录音
|
||||||
<HoverButton v-else-if="recordFalg==1" @click="changeRecord">
|
</span>
|
||||||
<span class="text-xl text-[#4f555e] dark:text-white">
|
</HoverButton>
|
||||||
完成
|
<HoverButton v-else-if="recordFalg == 1" @click="changeRecord">
|
||||||
</span>
|
<span class="text-xl text-[#4f555e] dark:text-white">
|
||||||
</HoverButton>
|
完成
|
||||||
<HoverButton v-if="!isMobile" @click="handleClear">
|
</span>
|
||||||
<span class="text-xl text-[#4f555e] dark:text-white">
|
</HoverButton>
|
||||||
<SvgIcon icon="ri:delete-bin-line" />
|
<HoverButton v-if="!isMobile" @click="handleClear">
|
||||||
</span>
|
<span class="text-xl text-[#4f555e] dark:text-white">
|
||||||
</HoverButton>
|
<SvgIcon icon="ri:delete-bin-line" />
|
||||||
<!-- <HoverButton v-if="!isMobile" @click="handleExport">
|
</span>
|
||||||
|
</HoverButton>
|
||||||
|
<!-- <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="{
|
||||||
|
@ -724,41 +722,41 @@ window.addEventListener('test', (e) => {
|
||||||
<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>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
Loading…
Reference in New Issue