| | |
| | | <div |
| | | :class="{ 'bg-[#d8d8ff]': item.role === RoleEnum.assistant, 'bg-white': item.role === RoleEnum.user }" |
| | | class="prose text-sm rounded-[6px] p-4 leading-relaxed max-w-[100ch]" |
| | | > |
| | | <component :is="answerTypeMapCom[item.content.type]" :data="item.content.values" /> |
| | | </div> |
| | | |
| | | <!-- <div v-if="item.role === RoleEnum.assistant" class="absolute flex items-center right-0 space-x-2 mr-2 mt-2"> |
| | | v-html="md.render(item.content)" |
| | | ></div> |
| | | <div v-if="item.role === RoleEnum.assistant" class="absolute flex items-center right-0 space-x-2 mr-2 mt-2"> |
| | | <SvgIcon class="cursor-pointer" name="ele-CopyDocument" @click="copyClick(item.content)" /> |
| | | <SvgIcon class="cursor-pointer" name="ywicon icon-dianzan" /> |
| | | <SvgIcon class="cursor-pointer" :size="12" name="ywicon icon-buzan" /> |
| | | </div> --> |
| | | </div> |
| | | </div> |
| | | |
| | | <Loding v-else /> |
| | |
| | | |
| | | <script setup lang="ts"> |
| | | import cryptoJS from 'crypto-js'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import { nextTick, onMounted, ref, watch } from 'vue'; |
| | | import useClipboard from 'vue-clipboard3'; |
| | | import Loding from './components/Loding.vue'; |
| | | import { RecordSet } from './model/Record'; |
| | | import type { ChatContent } from './model/types'; |
| | | import { AnswerType, RoleEnum, answerTypeMapCom, roleImageMap, type ChatMessage } from './model/types'; |
| | | import { QuestionAi } from '/@/api/ai/chat'; |
| | | import { md } from './libs/markdown'; |
| | | import { RoleEnum, roleImageMap, type ChatMessage } from './types'; |
| | | import PlayBar from '/@/components/chat/components/playBar/PlayBar.vue'; |
| | | import router from '/@/router'; |
| | | import { activeChatRoom } from '/@/stores/chatRoom'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import router from '/@/router'; |
| | | |
| | | let apiKey = ''; |
| | | let isConfig = ref(false); |
| | | let isTalking = ref(false); |
| | | let messageContent = ref<ChatContent>({ |
| | | type: AnswerType.Text, |
| | | values: '', |
| | | }); |
| | | let messageContent = ref(''); |
| | | const chatListDom = ref<HTMLDivElement>(); |
| | | const decoder = new TextDecoder('utf-8'); |
| | | const roleAlias = { user: 'ME', assistant: 'ChatGPT', system: 'System' }; |
| | |
| | | }); |
| | | return; |
| | | } |
| | | messageContent.value.values = activeChatRoom.value.title; |
| | | messageContent.value = activeChatRoom.value.title; |
| | | sendOrSave(); |
| | | }); |
| | | |
| | | const questionAi = async (text) => { |
| | | const res = await QuestionAi({ |
| | | question: text, |
| | | }); |
| | | let content: ChatContent = { |
| | | type: AnswerType.Text, |
| | | values: '发生错误!', |
| | | }; |
| | | switch (res.answer_type) { |
| | | case AnswerType.RecordSet: |
| | | content = { |
| | | type: AnswerType.RecordSet, |
| | | values: res.values, |
| | | }; |
| | | break; |
| | | case AnswerType.Text: |
| | | content = { |
| | | type: AnswerType.Text, |
| | | values: res.values, |
| | | }; |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | return content; |
| | | }; |
| | | |
| | | const sendChatMessage = async (content: ChatContent = messageContent.value) => { |
| | | const sendChatMessage = async (content: string = messageContent.value) => { |
| | | try { |
| | | isTalking.value = true; |
| | | // if (messageList.value.length === 0) { |
| | |
| | | // } |
| | | messageList.value.push({ role: RoleEnum.user, content }); |
| | | clearMessageContent(); |
| | | messageList.value.push({ role: RoleEnum.assistant, content }); |
| | | messageList.value.push({ role: RoleEnum.assistant, content: '' }); |
| | | |
| | | // const { body, status } = await chat(messageList.value, getAPIKey()); |
| | | // if (body) { |
| | | // const reader = body.getReader(); |
| | | // await readStream(reader, status); |
| | | // } |
| | | // const a = new Promise<string>((resolve) => { |
| | | // setTimeout(() => { |
| | | // resolve('你好,我是AI语言模型 '); |
| | | // }, 500); |
| | | // }); |
| | | const a = new Promise<string>((resolve) => { |
| | | setTimeout(() => { |
| | | resolve('你好,我是AI语言模型 '); |
| | | }, 500); |
| | | }); |
| | | |
| | | let msg:ChatContent = { |
| | | type:AnswerType.Text, |
| | | values:'' |
| | | }; |
| | | msg = await questionAi(content); |
| | | const msg = await a; |
| | | appendLastMessageContent(msg); |
| | | } catch (error: any) { |
| | | appendLastMessageContent('发生错误!'); |
| | | appendLastMessageContent(error); |
| | | } finally { |
| | | isTalking.value = false; |
| | | } |
| | |
| | | } |
| | | }; |
| | | |
| | | const appendLastMessageContent = (content: ChatContent) => { |
| | | messageList.value.push( |
| | | |
| | | ) |
| | | }; |
| | | const appendLastMessageContent = (content: string) => (messageList.value[messageList.value.length - 1].content += content); |
| | | |
| | | const sendOrSave = () => { |
| | | if (!messageContent.value) return; |
| | | if (!messageContent.value.length) return; |
| | | if (activeChatRoom.value.isInitial) { |
| | | activeChatRoom.value.title = messageContent.value.values; |
| | | activeChatRoom.value.title = messageContent.value; |
| | | activeChatRoom.value.isInitial = false; |
| | | } |
| | | sendChatMessage(); |
| | | if (isConfig.value) { |
| | | if (saveAPIKey(messageContent.value.trim())) { |
| | | switchConfigStatus(); |
| | | } |
| | | clearMessageContent(); |
| | | } else { |
| | | sendChatMessage(); |
| | | } |
| | | }; |
| | | |
| | | const clickConfig = () => { |
| | | if (!isConfig.value) { |
| | | messageContent.value = getAPIKey(); |
| | | } else { |
| | | clearMessageContent(); |
| | | } |
| | | switchConfigStatus(); |
| | | }; |
| | | |
| | | const getSecretKey = () => 'lianginx'; |
| | | |
| | | const saveAPIKey = (apiKey: string) => { |
| | | if (apiKey.slice(0, 3) !== 'sk-' || apiKey.length !== 51) { |
| | | alert('API Key 错误,请检查后重新输入!'); |
| | | return false; |
| | | } |
| | | const aesAPIKey = cryptoJS.AES.encrypt(apiKey, getSecretKey()).toString(); |
| | | localStorage.setItem('apiKey', aesAPIKey); |
| | | return true; |
| | | }; |
| | | |
| | | const getAPIKey = () => { |
| | | if (apiKey) return apiKey; |
| | |
| | | |
| | | const switchConfigStatus = () => (isConfig.value = !isConfig.value); |
| | | |
| | | const clearMessageContent = () => (messageContent.value = null); |
| | | const clearMessageContent = () => (messageContent.value = ''); |
| | | |
| | | const scrollToBottom = () => { |
| | | if (!chatListDom.value) return; |