feat: 新增中断但是未测试
This commit is contained in:
parent
53644936d2
commit
b2574805fd
@ -2,7 +2,7 @@ import type { ChatMessageVo, GetChatListParams, SendDTO } from './types';
|
|||||||
import { get, post } from '@/utils/request';
|
import { get, post } from '@/utils/request';
|
||||||
|
|
||||||
// 发送消息
|
// 发送消息
|
||||||
export const send = (data: SendDTO) => post<null>('/chat/send', data).stream();
|
export const send = (data: SendDTO) => post<null>('/chat/send', data);
|
||||||
|
|
||||||
// 新增对应会话聊天记录
|
// 新增对应会话聊天记录
|
||||||
export function addChat(data: ChatMessageVo) {
|
export function addChat(data: ChatMessageVo) {
|
||||||
|
|||||||
@ -1,2 +1,4 @@
|
|||||||
export * from './auth';
|
export * from './auth';
|
||||||
|
export * from './chat';
|
||||||
|
export * from './model';
|
||||||
export * from './session';
|
export * from './session';
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import type { ConversationItem } from 'vue-element-plus-x/types/Conversations';
|
import type { ConversationItem } from 'vue-element-plus-x/types/Conversations';
|
||||||
import type { ChatSessionVo } from '@/api/session/types';
|
import type { ChatSessionVo } from '@/api/session/types';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { get_session } from '@/api/session';
|
import { get_session } from '@/api';
|
||||||
import logo from '@/assets/images/logo.png';
|
import logo from '@/assets/images/logo.png';
|
||||||
import SvgIcon from '@/components/SvgIcon/index.vue';
|
import SvgIcon from '@/components/SvgIcon/index.vue';
|
||||||
import Collapse from '@/layouts/components/Header/components/Collapse.vue';
|
import Collapse from '@/layouts/components/Header/components/Collapse.vue';
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<!-- 每个回话对应的聊天内容 -->
|
<!-- 每个回话对应的聊天内容 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { HookFetchRequest } from 'node_modules/hook-fetch/types/utils';
|
||||||
import type { AnyObject } from 'typescript-api-pro';
|
import type { AnyObject } from 'typescript-api-pro';
|
||||||
import type { Sender } from 'vue-element-plus-x';
|
import type { Sender } from 'vue-element-plus-x';
|
||||||
import type { BubbleProps } from 'vue-element-plus-x/types/Bubble';
|
import type { BubbleProps } from 'vue-element-plus-x/types/Bubble';
|
||||||
@ -7,7 +8,7 @@ import type { BubbleListInstance } from 'vue-element-plus-x/types/BubbleList';
|
|||||||
import type { FilesCardProps } from 'vue-element-plus-x/types/FilesCard';
|
import type { FilesCardProps } from 'vue-element-plus-x/types/FilesCard';
|
||||||
import type { ThinkingStatus } from 'vue-element-plus-x/types/Thinking';
|
import type { ThinkingStatus } from 'vue-element-plus-x/types/Thinking';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { send } from '@/api/chat/index';
|
import { send } from '@/api';
|
||||||
import FilesSelect from '@/components/FilesSelect/index.vue';
|
import FilesSelect from '@/components/FilesSelect/index.vue';
|
||||||
import ModelSelect from '@/components/ModelSelect/index.vue';
|
import ModelSelect from '@/components/ModelSelect/index.vue';
|
||||||
import { useChatStore } from '@/stores/modules/chat';
|
import { useChatStore } from '@/stores/modules/chat';
|
||||||
@ -29,11 +30,19 @@ const modelStore = useModelStore();
|
|||||||
const filesStore = useFilesStore();
|
const filesStore = useFilesStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
// 用户头像
|
||||||
|
const avatar = computed(() => {
|
||||||
|
const userInfo = userStore.userInfo;
|
||||||
|
return userInfo?.avatar || 'https://avatars.githubusercontent.com/u/76239030?v=4';
|
||||||
|
});
|
||||||
|
|
||||||
const inputValue = ref('');
|
const inputValue = ref('');
|
||||||
const senderRef = ref<InstanceType<typeof Sender> | null>(null);
|
const senderRef = ref<InstanceType<typeof Sender> | null>(null);
|
||||||
const bubbleItems = ref<MessageItem[]>([]);
|
const bubbleItems = ref<MessageItem[]>([]);
|
||||||
const bubbleListRef = ref<BubbleListInstance | null>(null);
|
const bubbleListRef = ref<BubbleListInstance | null>(null);
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
// 记录发送的返回
|
||||||
|
let sendRequest: HookFetchRequest<any, any> | null = null;
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.params?.id,
|
() => route.params?.id,
|
||||||
@ -125,7 +134,7 @@ async function startSSE(chatContent: string) {
|
|||||||
// 这里有必要调用一下 BubbleList 组件的滚动到底部 手动触发 自动滚动
|
// 这里有必要调用一下 BubbleList 组件的滚动到底部 手动触发 自动滚动
|
||||||
bubbleListRef.value?.scrollToBottom();
|
bubbleListRef.value?.scrollToBottom();
|
||||||
|
|
||||||
const res = send({
|
sendRequest = send({
|
||||||
messages: bubbleItems.value
|
messages: bubbleItems.value
|
||||||
.filter((item: any) => item.role === 'user')
|
.filter((item: any) => item.role === 'user')
|
||||||
.map((item: any) => ({
|
.map((item: any) => ({
|
||||||
@ -137,7 +146,7 @@ async function startSSE(chatContent: string) {
|
|||||||
model: modelStore.currentModelInfo.modelName ?? '',
|
model: modelStore.currentModelInfo.modelName ?? '',
|
||||||
});
|
});
|
||||||
|
|
||||||
for await (const chunk of res) {
|
for await (const chunk of sendRequest.stream()) {
|
||||||
handleDataChunk(chunk.result as AnyObject);
|
handleDataChunk(chunk.result as AnyObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,13 +163,23 @@ async function startSSE(chatContent: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 中断请求
|
||||||
|
async function cancelSSE() {
|
||||||
|
sendRequest?.abort();
|
||||||
|
isLoading.value = false;
|
||||||
|
// 结束最后一条消息打字状态
|
||||||
|
if (bubbleItems.value.length) {
|
||||||
|
bubbleItems.value[bubbleItems.value.length - 1].typing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 添加消息 - 维护聊天记录
|
// 添加消息 - 维护聊天记录
|
||||||
function addMessage(message: string, isUser: boolean) {
|
function addMessage(message: string, isUser: boolean) {
|
||||||
const i = bubbleItems.value.length;
|
const i = bubbleItems.value.length;
|
||||||
const obj: MessageItem = {
|
const obj: MessageItem = {
|
||||||
key: i,
|
key: i,
|
||||||
avatar: isUser
|
avatar: isUser
|
||||||
? 'https://avatars.githubusercontent.com/u/76239030?v=4'
|
? avatar.value
|
||||||
: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
||||||
avatarSize: '32px',
|
avatarSize: '32px',
|
||||||
role: isUser ? 'user' : 'system',
|
role: isUser ? 'user' : 'system',
|
||||||
@ -228,6 +247,7 @@ watch(
|
|||||||
allow-speech
|
allow-speech
|
||||||
:loading="isLoading"
|
:loading="isLoading"
|
||||||
@submit="startSSE"
|
@submit="startSSE"
|
||||||
|
@cancel="cancelSSE"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="sender-header p-12px pt-6px pb-0px">
|
<div class="sender-header p-12px pt-6px pb-0px">
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
import type { ChatMessageVo } from '@/api/chat/types';
|
import type { ChatMessageVo } from '@/api/chat/types';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { getChatList } from '@/api/chat';
|
import { getChatList } from '@/api';
|
||||||
import { useUserStore } from './user';
|
import { useUserStore } from './user';
|
||||||
|
|
||||||
export const useChatStore = defineStore('chat', () => {
|
export const useChatStore = defineStore('chat', () => {
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
// 用户头像
|
||||||
|
const avatar = computed(() => {
|
||||||
|
const userInfo = userStore.userInfo;
|
||||||
|
return userInfo?.avatar || 'https://avatars.githubusercontent.com/u/76239030?v=4';
|
||||||
|
});
|
||||||
|
|
||||||
// 是否开启深度思考
|
// 是否开启深度思考
|
||||||
const isDeepThinking = ref<boolean>(false);
|
const isDeepThinking = ref<boolean>(false);
|
||||||
|
|
||||||
@ -27,7 +33,7 @@ export const useChatStore = defineStore('chat', () => {
|
|||||||
// variant: 'shadow',
|
// variant: 'shadow',
|
||||||
// shape: 'corner',
|
// shape: 'corner',
|
||||||
avatar: isUser
|
avatar: isUser
|
||||||
? 'https://avatars.githubusercontent.com/u/76239030?v=4'
|
? avatar
|
||||||
: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
||||||
avatarSize: '32px',
|
avatarSize: '32px',
|
||||||
typing: false,
|
typing: false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import type { GetSessionListVO } from '@/api/model/types';
|
import type { GetSessionListVO } from '@/api/model/types';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { getModelList } from '@/api/model/index';
|
import { getModelList } from '@/api';
|
||||||
|
|
||||||
// 模型管理
|
// 模型管理
|
||||||
export const useModelStore = defineStore('model', () => {
|
export const useModelStore = defineStore('model', () => {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
get_session,
|
get_session,
|
||||||
get_session_list,
|
get_session_list,
|
||||||
update_session,
|
update_session,
|
||||||
} from '@/api/session';
|
} from '@/api';
|
||||||
import { useUserStore } from './user';
|
import { useUserStore } from './user';
|
||||||
|
|
||||||
export const useSessionStore = defineStore('session', () => {
|
export const useSessionStore = defineStore('session', () => {
|
||||||
|
|||||||
2
types/components.d.ts
vendored
2
types/components.d.ts
vendored
@ -3,7 +3,7 @@
|
|||||||
// Generated by unplugin-vue-components
|
// Generated by unplugin-vue-components
|
||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
// biome-ignore lint: disable
|
// biome-ignore lint: disable
|
||||||
export {};
|
export {}
|
||||||
|
|
||||||
/* prettier-ignore */
|
/* prettier-ignore */
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
|
|||||||
1
types/import_meta.d.ts
vendored
1
types/import_meta.d.ts
vendored
@ -5,7 +5,6 @@ interface ImportMetaEnv {
|
|||||||
readonly VITE_WEB_TITLE_EN: string;
|
readonly VITE_WEB_TITLE_EN: string;
|
||||||
readonly VITE_WEB_ENV: string;
|
readonly VITE_WEB_ENV: string;
|
||||||
readonly VITE_WEB_BASE_API: string;
|
readonly VITE_WEB_BASE_API: string;
|
||||||
readonly VITE_BUILD_COMPRESS: string;
|
|
||||||
readonly VITE_API_URL: string;
|
readonly VITE_API_URL: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user