feat: 新增中断但是未测试

This commit is contained in:
何嘉悦 2025-06-03 20:26:55 +08:00
parent 53644936d2
commit b2574805fd
10 changed files with 39 additions and 12 deletions

BIN
dist.rar

Binary file not shown.

View File

@ -2,7 +2,7 @@ import type { ChatMessageVo, GetChatListParams, SendDTO } from './types';
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) {

View File

@ -1,2 +1,4 @@
export * from './auth';
export * from './chat';
export * from './model';
export * from './session';

View File

@ -3,7 +3,7 @@
import type { ConversationItem } from 'vue-element-plus-x/types/Conversations';
import type { ChatSessionVo } from '@/api/session/types';
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 SvgIcon from '@/components/SvgIcon/index.vue';
import Collapse from '@/layouts/components/Header/components/Collapse.vue';

View File

@ -1,5 +1,6 @@
<!-- 每个回话对应的聊天内容 -->
<script setup lang="ts">
import type { HookFetchRequest } from 'node_modules/hook-fetch/types/utils';
import type { AnyObject } from 'typescript-api-pro';
import type { Sender } from 'vue-element-plus-x';
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 { ThinkingStatus } from 'vue-element-plus-x/types/Thinking';
import { useRoute } from 'vue-router';
import { send } from '@/api/chat/index';
import { send } from '@/api';
import FilesSelect from '@/components/FilesSelect/index.vue';
import ModelSelect from '@/components/ModelSelect/index.vue';
import { useChatStore } from '@/stores/modules/chat';
@ -29,11 +30,19 @@ const modelStore = useModelStore();
const filesStore = useFilesStore();
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 senderRef = ref<InstanceType<typeof Sender> | null>(null);
const bubbleItems = ref<MessageItem[]>([]);
const bubbleListRef = ref<BubbleListInstance | null>(null);
const isLoading = ref(false);
//
let sendRequest: HookFetchRequest<any, any> | null = null;
watch(
() => route.params?.id,
@ -125,7 +134,7 @@ async function startSSE(chatContent: string) {
// BubbleList
bubbleListRef.value?.scrollToBottom();
const res = send({
sendRequest = send({
messages: bubbleItems.value
.filter((item: any) => item.role === 'user')
.map((item: any) => ({
@ -137,7 +146,7 @@ async function startSSE(chatContent: string) {
model: modelStore.currentModelInfo.modelName ?? '',
});
for await (const chunk of res) {
for await (const chunk of sendRequest.stream()) {
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) {
const i = bubbleItems.value.length;
const obj: MessageItem = {
key: i,
avatar: isUser
? 'https://avatars.githubusercontent.com/u/76239030?v=4'
? avatar.value
: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
avatarSize: '32px',
role: isUser ? 'user' : 'system',
@ -228,6 +247,7 @@ watch(
allow-speech
:loading="isLoading"
@submit="startSSE"
@cancel="cancelSSE"
>
<template #header>
<div class="sender-header p-12px pt-6px pb-0px">

View File

@ -1,11 +1,17 @@
import type { ChatMessageVo } from '@/api/chat/types';
import { defineStore } from 'pinia';
import { getChatList } from '@/api/chat';
import { getChatList } from '@/api';
import { useUserStore } from './user';
export const useChatStore = defineStore('chat', () => {
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);
@ -27,7 +33,7 @@ export const useChatStore = defineStore('chat', () => {
// variant: 'shadow',
// shape: 'corner',
avatar: isUser
? 'https://avatars.githubusercontent.com/u/76239030?v=4'
? avatar
: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
avatarSize: '32px',
typing: false,

View File

@ -1,6 +1,6 @@
import type { GetSessionListVO } from '@/api/model/types';
import { defineStore } from 'pinia';
import { getModelList } from '@/api/model/index';
import { getModelList } from '@/api';
// 模型管理
export const useModelStore = defineStore('model', () => {

View File

@ -9,7 +9,7 @@ import {
get_session,
get_session_list,
update_session,
} from '@/api/session';
} from '@/api';
import { useUserStore } from './user';
export const useSessionStore = defineStore('session', () => {

View File

@ -3,7 +3,7 @@
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {};
export {}
/* prettier-ignore */
declare module 'vue' {

View File

@ -5,7 +5,6 @@ interface ImportMetaEnv {
readonly VITE_WEB_TITLE_EN: string;
readonly VITE_WEB_ENV: string;
readonly VITE_WEB_BASE_API: string;
readonly VITE_BUILD_COMPRESS: string;
readonly VITE_API_URL: string;
}