|
@@ -1,53 +1,79 @@
|
|
|
<script setup lang="ts">
|
|
|
import { watch } from 'vue'
|
|
|
import AChat from '@/views/OaSystem/aiQA/components/AChat.vue'
|
|
|
+import AResult from '@/views/OaSystem/aiQA/components/AResult.vue'
|
|
|
import ExampleChat from '@/views/OaSystem/aiQA/components/ExampleChat.vue'
|
|
|
import sendImg from '@/assets/imgs/ai/send.png'
|
|
|
import QChat from '@/views/OaSystem/aiQA/components/QChat.vue'
|
|
|
-import useSSE from '@/hooks/web/useSSE'
|
|
|
+import { useSSE, type AResultRecord } from '@/hooks/web/useSSE'
|
|
|
import { kbChat } from '@/service/aiService'
|
|
|
|
|
|
interface ChatContentProps {
|
|
|
- currentQuestion: string
|
|
|
- changeQuestion: (q: string) => void
|
|
|
+ currentQuestion: string[]
|
|
|
+ changeQuestion: (q: string, init?: boolean) => void
|
|
|
}
|
|
|
|
|
|
const props = defineProps<ChatContentProps>()
|
|
|
const { currentQuestion } = toRefs(props)
|
|
|
const { changeQuestion } = props
|
|
|
const textarea = ref('')
|
|
|
+const contents = reactive<{ string: AResultRecord }>({}) //对话记录,以问题为key保存
|
|
|
|
|
|
-const { data, mutation: startChat } = useSSE({ mutationFn: kbChat })
|
|
|
+const { data, mutation: startChat } = useSSE({
|
|
|
+ mutationFn: kbChat,
|
|
|
+ onSuccess: (res) => {
|
|
|
+ const question = currentQuestion.value[currentQuestion.value.length - 1]
|
|
|
+ contents[question] = res
|
|
|
+ }
|
|
|
+})
|
|
|
|
|
|
-const handleClear = () => {
|
|
|
- changeQuestion('')
|
|
|
+const handleClear = (): void => {
|
|
|
+ changeQuestion('', true)
|
|
|
}
|
|
|
|
|
|
-const handleSend = () => {
|
|
|
+const handleSend = (): void => {
|
|
|
changeQuestion(textarea.value)
|
|
|
textarea.value = ''
|
|
|
}
|
|
|
|
|
|
/*监控问题变化,开启问答*/
|
|
|
-watch(currentQuestion, (newVal) => {
|
|
|
- if (newVal) {
|
|
|
- startChat({ query: newVal })
|
|
|
- }
|
|
|
-})
|
|
|
+watch(
|
|
|
+ currentQuestion,
|
|
|
+ (newVal) => {
|
|
|
+ const length = newVal?.length ?? 0
|
|
|
+ const qText = newVal[length - 1]
|
|
|
+ if (qText) {
|
|
|
+ startChat({ query: qText })
|
|
|
+ }
|
|
|
+ if (length <= 1) {
|
|
|
+ //首条对话, 重置对话记录
|
|
|
+ Object.keys(contents).forEach((key) => {
|
|
|
+ delete contents[key]
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+)
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
<div class="chat-content">
|
|
|
<div class="message-body">
|
|
|
- <template v-if="currentQuestion">
|
|
|
- <QChat>{{ currentQuestion }}</QChat>
|
|
|
- <AChat v-if="data?.result?.['3'] == null"> {{ data.content }}</AChat>
|
|
|
- <AChat v-else> {{ data?.result?.['3']?.choices?.[0]?.delta?.content }}</AChat>
|
|
|
+ <template v-if="(currentQuestion?.length ?? 0) > 0">
|
|
|
+ <template v-for="question in currentQuestion" :key="question">
|
|
|
+ <QChat>{{ question }}</QChat>
|
|
|
+ <!-- 思维链 -->
|
|
|
+ <AChat v-if="contents?.[question] == null"> {{ data.content }}...</AChat>
|
|
|
+ <AChat v-else>
|
|
|
+ <!-- 回答结果 -->
|
|
|
+ <AResult :data="contents[question]" />
|
|
|
+ </AChat>
|
|
|
+ </template>
|
|
|
</template>
|
|
|
<template v-else>
|
|
|
<!-- 引导对话 -->
|
|
|
<AChat>
|
|
|
- <ExampleChat />
|
|
|
+ <ExampleChat :changeQuestion="changeQuestion" />
|
|
|
</AChat>
|
|
|
</template>
|
|
|
</div>
|