|
@@ -1,6 +1,7 @@
|
|
|
import { ref, toRaw } from 'vue'
|
|
import { ref, toRaw } from 'vue'
|
|
|
import type { ChatMessage, ToolCallInfo, SessionListItem, UploadedFile, MessageSegment } from './interface'
|
|
import type { ChatMessage, ToolCallInfo, SessionListItem, UploadedFile, MessageSegment } from './interface'
|
|
|
import { useUserStore } from '@/stores/user'
|
|
import { useUserStore } from '@/stores/user'
|
|
|
|
|
+import { useDiscreteApi } from '@/composable/useDiscreteApi'
|
|
|
import { chatDB } from './chatDB'
|
|
import { chatDB } from './chatDB'
|
|
|
import {
|
|
import {
|
|
|
getAiSessionList,
|
|
getAiSessionList,
|
|
@@ -24,6 +25,9 @@ export interface SessionLoadDoneInfo {
|
|
|
// 文件下载标记:$$FILE_DOWNLOAD:{...}$$(模块作用域,避免每次调用重新编译)
|
|
// 文件下载标记:$$FILE_DOWNLOAD:{...}$$(模块作用域,避免每次调用重新编译)
|
|
|
const FILE_MARKER_RE = /\$\$FILE_DOWNLOAD:([\s\S]*?)\$\$/g
|
|
const FILE_MARKER_RE = /\$\$FILE_DOWNLOAD:([\s\S]*?)\$\$/g
|
|
|
|
|
|
|
|
|
|
+// 全局消息提示(模块作用域,避免每次调用重建 discrete api 实例)
|
|
|
|
|
+const { message } = useDiscreteApi()
|
|
|
|
|
+
|
|
|
// 解析出的行内文件片段(用于内联下载按钮)
|
|
// 解析出的行内文件片段(用于内联下载按钮)
|
|
|
interface ParsedFileChunk {
|
|
interface ParsedFileChunk {
|
|
|
kind: 'file'
|
|
kind: 'file'
|
|
@@ -162,25 +166,42 @@ export function useAiChat() {
|
|
|
isLoadingSession.value = true
|
|
isLoadingSession.value = true
|
|
|
try {
|
|
try {
|
|
|
const data = await createAiSession()
|
|
const data = await createAiSession()
|
|
|
- if (data?.sessionId) {
|
|
|
|
|
- // 保存当前会话消息到 IndexedDB
|
|
|
|
|
- if (currentSessionId.value && messages.value.length > 0) {
|
|
|
|
|
- await saveLocalMessages()
|
|
|
|
|
- }
|
|
|
|
|
- // 切换到新会话
|
|
|
|
|
- currentSessionId.value = data.sessionId
|
|
|
|
|
- messages.value = []
|
|
|
|
|
- welcomeMessage.value = data.welcomeMessage || '欢迎使用AI助手'
|
|
|
|
|
- currentAgent.value = data.agentId || ''
|
|
|
|
|
- currentModel.value = data.modelId || ''
|
|
|
|
|
- contextUsage.value = 0
|
|
|
|
|
- turnDuration.value = 0
|
|
|
|
|
- // 刷新列表
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 后端未返回有效 sessionId:视为创建失败,明确提示,不静默停留在旧会话
|
|
|
|
|
+ if (!data?.sessionId) {
|
|
|
|
|
+ message.error('创建新会话失败,请稍后重试')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 保存当前会话消息到 IndexedDB
|
|
|
|
|
+ if (currentSessionId.value && messages.value.length > 0) {
|
|
|
|
|
+ await saveLocalMessages()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 切换到新会话(先落地本地状态,保证 UI 一定切过去)
|
|
|
|
|
+ currentSessionId.value = data.sessionId
|
|
|
|
|
+ messages.value = []
|
|
|
|
|
+ welcomeMessage.value = data.welcomeMessage || '欢迎使用AI助手'
|
|
|
|
|
+ currentAgent.value = data.agentId || ''
|
|
|
|
|
+ currentModel.value = data.modelId || ''
|
|
|
|
|
+ contextUsage.value = 0
|
|
|
|
|
+ turnDuration.value = 0
|
|
|
|
|
+
|
|
|
|
|
+ // 刷新列表:新会话作为活跃会话由后端返回(IsActive=true),需要重新拉取才能在侧边栏正确展示/高亮。
|
|
|
|
|
+ // 列表刷新失败不影响已完成的切换,仅退化为侧边栏暂不显示,下次进入会自动纠正。
|
|
|
|
|
+ try {
|
|
|
await fetchSessionList()
|
|
await fetchSessionList()
|
|
|
|
|
+ // 校验新会话确实出现在列表中,未出现给出提示(便于定位后端归档/列表问题)
|
|
|
|
|
+ if (!sessionList.value.some(s => s.sessionId === data.sessionId)) {
|
|
|
|
|
+ message.warning('新会话已创建,但暂未出现在历史列表中')
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ catch {
|
|
|
|
|
+ message.warning('新会话已创建,历史列表刷新失败')
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- catch {
|
|
|
|
|
- // 忽略
|
|
|
|
|
|
|
+ catch (err: any) {
|
|
|
|
|
+ message.error(`创建新会话失败:${err?.message || '未知错误'}`)
|
|
|
}
|
|
}
|
|
|
finally {
|
|
finally {
|
|
|
isLoadingSession.value = false
|
|
isLoadingSession.value = false
|