dify
This commit is contained in:
@@ -1,32 +1,125 @@
|
||||
/**
|
||||
* @description 智能体配置相关API
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
* @author AI Assistant
|
||||
* @since 2025-11-04
|
||||
*/
|
||||
|
||||
import { api } from '@/apis/index';
|
||||
import type { AiAgentConfig, ResultDomain } from '@/types';
|
||||
import type { AiAgentConfig, ResultDomain, PageDomain, PageParam } from '@/types';
|
||||
|
||||
/**
|
||||
* 智能体配置API服务
|
||||
*/
|
||||
export const aiAgentConfigApi = {
|
||||
/**
|
||||
* 获取智能体配置
|
||||
* 创建智能体
|
||||
* @param agentConfig 智能体配置
|
||||
* @returns Promise<ResultDomain<AiAgentConfig>>
|
||||
*/
|
||||
async getAgentConfig(): Promise<ResultDomain<AiAgentConfig>> {
|
||||
const response = await api.get<AiAgentConfig>('/ai/agent-config');
|
||||
async createAgent(agentConfig: AiAgentConfig): Promise<ResultDomain<AiAgentConfig>> {
|
||||
const response = await api.post<AiAgentConfig>('/ai/agent', agentConfig);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新智能体配置
|
||||
* @param config 配置数据
|
||||
* 更新智能体
|
||||
* @param agentConfig 智能体配置
|
||||
* @returns Promise<ResultDomain<AiAgentConfig>>
|
||||
*/
|
||||
async updateAgentConfig(config: AiAgentConfig): Promise<ResultDomain<AiAgentConfig>> {
|
||||
const response = await api.put<AiAgentConfig>('/ai/agent-config', config);
|
||||
async updateAgent(agentConfig: AiAgentConfig): Promise<ResultDomain<AiAgentConfig>> {
|
||||
const response = await api.put<AiAgentConfig>('/ai/agent', agentConfig);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除智能体
|
||||
* @param agentId 智能体ID
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async deleteAgent(agentId: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.delete<boolean>(`/ai/agent/${agentId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取智能体详情
|
||||
* @param agentId 智能体ID
|
||||
* @returns Promise<ResultDomain<AiAgentConfig>>
|
||||
*/
|
||||
async getAgentById(agentId: string): Promise<ResultDomain<AiAgentConfig>> {
|
||||
const response = await api.get<AiAgentConfig>(`/ai/agent/${agentId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取启用的智能体列表
|
||||
* @returns Promise<ResultDomain<AiAgentConfig[]>>
|
||||
*/
|
||||
async listEnabledAgents(): Promise<ResultDomain<AiAgentConfig[]>> {
|
||||
const response = await api.get<AiAgentConfig[]>('/ai/agent/enabled');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取智能体列表(支持过滤)
|
||||
* @param filter 过滤条件
|
||||
* @returns Promise<ResultDomain<AiAgentConfig[]>>
|
||||
*/
|
||||
async listAgents(filter?: Partial<AiAgentConfig>): Promise<ResultDomain<AiAgentConfig[]>> {
|
||||
const response = await api.post<AiAgentConfig[]>('/ai/agent/list', filter || {});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 分页查询智能体
|
||||
* @param filter 过滤条件
|
||||
* @param pageParam 分页参数
|
||||
* @returns Promise<PageDomain<AiAgentConfig>>
|
||||
*/
|
||||
async pageAgents(filter: Partial<AiAgentConfig>, pageParam: PageParam): Promise<PageDomain<AiAgentConfig>> {
|
||||
const response = await api.post<PageDomain<AiAgentConfig>>('/ai/agent/page', {
|
||||
filter,
|
||||
pageParam
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新智能体状态
|
||||
* @param agentId 智能体ID
|
||||
* @param status 状态(0禁用 1启用)
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async updateAgentStatus(agentId: string, status: number): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.put<boolean>(`/ai/agent/${agentId}/status`, { status });
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新Dify配置
|
||||
* @param agentId 智能体ID
|
||||
* @param difyAppId Dify应用ID
|
||||
* @param difyApiKey Dify API Key
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async updateDifyConfig(agentId: string, difyAppId: string, difyApiKey: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.put<boolean>(`/ai/agent/${agentId}/dify`, {
|
||||
difyAppId,
|
||||
difyApiKey
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查智能体名称是否存在
|
||||
* @param name 名称
|
||||
* @param excludeId 排除的ID(用于更新时)
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async checkNameExists(name: string, excludeId?: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.get<boolean>('/ai/agent/check-name', {
|
||||
params: { name, excludeId }
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
|
||||
198
schoolNewsWeb/src/apis/ai/chat-history.ts
Normal file
198
schoolNewsWeb/src/apis/ai/chat-history.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* @description AI对话历史相关API
|
||||
* @author AI Assistant
|
||||
* @since 2025-11-04
|
||||
*/
|
||||
|
||||
import { api } from '@/apis/index';
|
||||
import type {
|
||||
AiConversation,
|
||||
AiMessage,
|
||||
ConversationSearchParams,
|
||||
MessageSearchParams,
|
||||
UserChatStatistics,
|
||||
ConversationStatistics,
|
||||
BatchExportParams,
|
||||
ResultDomain,
|
||||
PageDomain
|
||||
} from '@/types';
|
||||
|
||||
/**
|
||||
* 对话历史API服务
|
||||
*/
|
||||
export const chatHistoryApi = {
|
||||
/**
|
||||
* 分页查询用户的会话列表
|
||||
* @param params 搜索参数
|
||||
* @returns Promise<PageDomain<AiConversation>>
|
||||
*/
|
||||
async pageUserConversations(params: ConversationSearchParams): Promise<PageDomain<AiConversation>> {
|
||||
const response = await api.post<PageDomain<AiConversation>>('/ai/history/conversations/page', params);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 搜索会话(全文搜索标题和摘要)
|
||||
* @param params 搜索参数
|
||||
* @returns Promise<PageDomain<AiConversation>>
|
||||
*/
|
||||
async searchConversations(params: MessageSearchParams): Promise<PageDomain<AiConversation>> {
|
||||
const response = await api.post<PageDomain<AiConversation>>('/ai/history/conversations/search', params);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 搜索消息内容(全文搜索)
|
||||
* @param params 搜索参数
|
||||
* @returns Promise<PageDomain<AiMessage>>
|
||||
*/
|
||||
async searchMessages(params: MessageSearchParams): Promise<PageDomain<AiMessage>> {
|
||||
const response = await api.post<PageDomain<AiMessage>>('/ai/history/messages/search', params);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 收藏/取消收藏会话
|
||||
* @param conversationId 会话ID
|
||||
* @param isFavorite 是否收藏
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async toggleFavorite(conversationId: string, isFavorite: boolean): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.put<boolean>(`/ai/history/conversation/${conversationId}/favorite`, {
|
||||
isFavorite
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 置顶/取消置顶会话
|
||||
* @param conversationId 会话ID
|
||||
* @param isPinned 是否置顶
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async togglePin(conversationId: string, isPinned: boolean): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.put<boolean>(`/ai/history/conversation/${conversationId}/pin`, {
|
||||
isPinned
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量删除会话
|
||||
* @param conversationIds 会话ID列表
|
||||
* @returns Promise<ResultDomain<number>>
|
||||
*/
|
||||
async batchDeleteConversations(conversationIds: string[]): Promise<ResultDomain<number>> {
|
||||
const response = await api.post<number>('/ai/history/conversations/batch-delete', {
|
||||
conversationIds
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取用户的对话统计信息
|
||||
* @param userId 用户ID(可选,默认当前用户)
|
||||
* @returns Promise<ResultDomain<UserChatStatistics>>
|
||||
*/
|
||||
async getUserChatStatistics(userId?: string): Promise<ResultDomain<UserChatStatistics>> {
|
||||
const response = await api.get<UserChatStatistics>('/ai/history/statistics/user', {
|
||||
params: { userId }
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取会话的详细统计
|
||||
* @param conversationId 会话ID
|
||||
* @returns Promise<ResultDomain<ConversationStatistics>>
|
||||
*/
|
||||
async getConversationStatistics(conversationId: string): Promise<ResultDomain<ConversationStatistics>> {
|
||||
const response = await api.get<ConversationStatistics>(`/ai/history/statistics/conversation/${conversationId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 导出会话记录(Markdown格式)
|
||||
* @param conversationId 会话ID
|
||||
* @returns Promise<ResultDomain<string>>
|
||||
*/
|
||||
async exportConversationAsMarkdown(conversationId: string): Promise<ResultDomain<string>> {
|
||||
const response = await api.get<string>(`/ai/history/export/markdown/${conversationId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 导出会话记录(JSON格式)
|
||||
* @param conversationId 会话ID
|
||||
* @returns Promise<ResultDomain<string>>
|
||||
*/
|
||||
async exportConversationAsJson(conversationId: string): Promise<ResultDomain<string>> {
|
||||
const response = await api.get<string>(`/ai/history/export/json/${conversationId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量导出会话
|
||||
* @param params 导出参数
|
||||
* @returns Promise<ResultDomain<string>>
|
||||
*/
|
||||
async batchExportConversations(params: BatchExportParams): Promise<ResultDomain<string>> {
|
||||
const response = await api.post<string>('/ai/history/export/batch', params);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 下载导出文件
|
||||
* @param conversationId 会话ID
|
||||
* @param format 格式(markdown/json)
|
||||
*/
|
||||
downloadExport(conversationId: string, format: 'markdown' | 'json'): void {
|
||||
const url = `${api.defaults.baseURL}/ai/history/export/download/${conversationId}?format=${format}`;
|
||||
window.open(url, '_blank');
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量下载导出文件
|
||||
* @param conversationIds 会话ID列表
|
||||
* @param format 格式(markdown/json)
|
||||
*/
|
||||
batchDownloadExport(conversationIds: string[], format: 'markdown' | 'json'): void {
|
||||
const url = `${api.defaults.baseURL}/ai/history/export/batch-download?format=${format}&ids=${conversationIds.join(',')}`;
|
||||
window.open(url, '_blank');
|
||||
},
|
||||
|
||||
/**
|
||||
* 清理过期会话(软删除超过N天的会话)
|
||||
* @param days 天数
|
||||
* @returns Promise<ResultDomain<number>>
|
||||
*/
|
||||
async cleanExpiredConversations(days: number): Promise<ResultDomain<number>> {
|
||||
const response = await api.post<number>('/ai/history/clean', { days });
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取用户最近的对话
|
||||
* @param limit 数量限制(默认10)
|
||||
* @returns Promise<ResultDomain<AiConversation>>
|
||||
*/
|
||||
async getRecentConversations(limit?: number): Promise<ResultDomain<AiConversation>> {
|
||||
const response = await api.get<AiConversation>('/ai/history/recent', {
|
||||
params: { limit }
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取热门会话(基于消息数或Token数)
|
||||
* @param limit 数量限制(默认10)
|
||||
* @returns Promise<ResultDomain<AiConversation>>
|
||||
*/
|
||||
async getPopularConversations(limit?: number): Promise<ResultDomain<AiConversation>> {
|
||||
const response = await api.get<AiConversation>('/ai/history/popular', {
|
||||
params: { limit }
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
|
||||
238
schoolNewsWeb/src/apis/ai/chat.ts
Normal file
238
schoolNewsWeb/src/apis/ai/chat.ts
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* @description AI对话相关API
|
||||
* @author AI Assistant
|
||||
* @since 2025-11-04
|
||||
*/
|
||||
|
||||
import { api } from '@/apis/index';
|
||||
import type {
|
||||
AiConversation,
|
||||
AiMessage,
|
||||
ChatRequest,
|
||||
ChatResponse,
|
||||
ResultDomain,
|
||||
StreamCallback
|
||||
} from '@/types';
|
||||
|
||||
/**
|
||||
* AI对话API服务
|
||||
*/
|
||||
export const chatApi = {
|
||||
/**
|
||||
* 流式对话(SSE)
|
||||
* @param request 对话请求
|
||||
* @param callback 流式回调
|
||||
* @returns Promise<ResultDomain<AiMessage>>
|
||||
*/
|
||||
async streamChat(request: ChatRequest, callback?: StreamCallback): Promise<ResultDomain<AiMessage>> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const eventSource = new EventSource(
|
||||
`${api.defaults.baseURL}/ai/chat/stream?` +
|
||||
new URLSearchParams({
|
||||
agentId: request.agentId,
|
||||
conversationId: request.conversationId || '',
|
||||
query: request.query,
|
||||
knowledgeIds: request.knowledgeIds?.join(',') || ''
|
||||
})
|
||||
);
|
||||
|
||||
let fullMessage = '';
|
||||
|
||||
eventSource.addEventListener('message', (event) => {
|
||||
const data = event.data;
|
||||
fullMessage += data;
|
||||
callback?.onMessage?.(data);
|
||||
});
|
||||
|
||||
eventSource.addEventListener('end', (event) => {
|
||||
const metadata = JSON.parse(event.data);
|
||||
callback?.onMessageEnd?.(metadata);
|
||||
eventSource.close();
|
||||
|
||||
resolve({
|
||||
success: true,
|
||||
data: metadata as AiMessage,
|
||||
message: '对话成功'
|
||||
});
|
||||
});
|
||||
|
||||
eventSource.addEventListener('error', (event: any) => {
|
||||
const error = new Error(event.data || '对话失败');
|
||||
callback?.onError?.(error);
|
||||
eventSource.close();
|
||||
reject(error);
|
||||
});
|
||||
|
||||
eventSource.onerror = (error) => {
|
||||
callback?.onError?.(error as Error);
|
||||
eventSource.close();
|
||||
reject(error);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 阻塞式对话(非流式)
|
||||
* @param request 对话请求
|
||||
* @returns Promise<ResultDomain<AiMessage>>
|
||||
*/
|
||||
async blockingChat(request: ChatRequest): Promise<ResultDomain<AiMessage>> {
|
||||
const response = await api.post<AiMessage>('/ai/chat/blocking', request);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 停止对话生成
|
||||
* @param messageId 消息ID
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async stopChat(messageId: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.post<boolean>(`/ai/chat/stop/${messageId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建新会话
|
||||
* @param agentId 智能体ID
|
||||
* @param title 会话标题(可选)
|
||||
* @returns Promise<ResultDomain<AiConversation>>
|
||||
*/
|
||||
async createConversation(agentId: string, title?: string): Promise<ResultDomain<AiConversation>> {
|
||||
const response = await api.post<AiConversation>('/ai/chat/conversation', {
|
||||
agentId,
|
||||
title
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取会话信息
|
||||
* @param conversationId 会话ID
|
||||
* @returns Promise<ResultDomain<AiConversation>>
|
||||
*/
|
||||
async getConversation(conversationId: string): Promise<ResultDomain<AiConversation>> {
|
||||
const response = await api.get<AiConversation>(`/ai/chat/conversation/${conversationId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新会话
|
||||
* @param conversation 会话信息
|
||||
* @returns Promise<ResultDomain<AiConversation>>
|
||||
*/
|
||||
async updateConversation(conversation: AiConversation): Promise<ResultDomain<AiConversation>> {
|
||||
const response = await api.put<AiConversation>('/ai/chat/conversation', conversation);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除会话
|
||||
* @param conversationId 会话ID
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async deleteConversation(conversationId: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.delete<boolean>(`/ai/chat/conversation/${conversationId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取用户的会话列表
|
||||
* @param agentId 智能体ID(可选)
|
||||
* @returns Promise<ResultDomain<AiConversation[]>>
|
||||
*/
|
||||
async listUserConversations(agentId?: string): Promise<ResultDomain<AiConversation[]>> {
|
||||
const response = await api.get<AiConversation[]>('/ai/chat/conversations', {
|
||||
params: { agentId }
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取会话的消息列表
|
||||
* @param conversationId 会话ID
|
||||
* @returns Promise<ResultDomain<AiMessage[]>>
|
||||
*/
|
||||
async listMessages(conversationId: string): Promise<ResultDomain<AiMessage[]>> {
|
||||
const response = await api.get<AiMessage[]>(`/ai/chat/conversation/${conversationId}/messages`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取单条消息
|
||||
* @param messageId 消息ID
|
||||
* @returns Promise<ResultDomain<AiMessage>>
|
||||
*/
|
||||
async getMessage(messageId: string): Promise<ResultDomain<AiMessage>> {
|
||||
const response = await api.get<AiMessage>(`/ai/chat/message/${messageId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 重新生成回答
|
||||
* @param messageId 原消息ID
|
||||
* @param callback 流式回调(可选)
|
||||
* @returns Promise<ResultDomain<AiMessage>>
|
||||
*/
|
||||
async regenerateAnswer(messageId: string, callback?: StreamCallback): Promise<ResultDomain<AiMessage>> {
|
||||
if (callback) {
|
||||
// 使用流式方式重新生成
|
||||
return new Promise((resolve, reject) => {
|
||||
const eventSource = new EventSource(
|
||||
`${api.defaults.baseURL}/ai/chat/regenerate/${messageId}?stream=true`
|
||||
);
|
||||
|
||||
eventSource.addEventListener('message', (event) => {
|
||||
callback.onMessage?.(event.data);
|
||||
});
|
||||
|
||||
eventSource.addEventListener('end', (event) => {
|
||||
const metadata = JSON.parse(event.data);
|
||||
callback.onMessageEnd?.(metadata);
|
||||
eventSource.close();
|
||||
resolve({
|
||||
success: true,
|
||||
data: metadata as AiMessage,
|
||||
message: '重新生成成功'
|
||||
});
|
||||
});
|
||||
|
||||
eventSource.addEventListener('error', (event: any) => {
|
||||
const error = new Error(event.data || '重新生成失败');
|
||||
callback.onError?.(error);
|
||||
eventSource.close();
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// 使用阻塞方式重新生成
|
||||
const response = await api.post<AiMessage>(`/ai/chat/regenerate/${messageId}`);
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 异步生成会话摘要
|
||||
* @param conversationId 会话ID
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async generateSummary(conversationId: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.post<boolean>(`/ai/chat/conversation/${conversationId}/summary`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 评价消息
|
||||
* @param messageId 消息ID
|
||||
* @param rating 评分(1=好评,-1=差评,0=取消评价)
|
||||
* @param feedback 反馈内容(可选)
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async rateMessage(messageId: string, rating: number, feedback?: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.post<boolean>(`/ai/chat/message/${messageId}/rate`, {
|
||||
rating,
|
||||
feedback
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* @description 对话相关API
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
|
||||
import { api } from '@/apis/index';
|
||||
import type { AiConversation, ResultDomain } from '@/types';
|
||||
|
||||
/**
|
||||
* 对话API服务
|
||||
*/
|
||||
export const conversationApi = {
|
||||
/**
|
||||
* 获取用户对话列表
|
||||
* @param userID 用户ID
|
||||
* @returns Promise<ResultDomain<AiConversation>>
|
||||
*/
|
||||
async getConversationList(userID: string): Promise<ResultDomain<AiConversation>> {
|
||||
const response = await api.get<AiConversation>('/ai/conversation/list', { userID });
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建对话
|
||||
* @param conversation 对话数据
|
||||
* @returns Promise<ResultDomain<AiConversation>>
|
||||
*/
|
||||
async createConversation(conversation: AiConversation): Promise<ResultDomain<AiConversation>> {
|
||||
const response = await api.post<AiConversation>('/ai/conversation/create', conversation);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除对话
|
||||
* @param conversationID 对话ID
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async deleteConversation(conversationID: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.delete<boolean>(`/ai/conversation/${conversationID}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 清空对话记录
|
||||
* @param conversationID 对话ID
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async clearConversation(conversationID: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.post<boolean>(`/ai/conversation/${conversationID}/clear`);
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
168
schoolNewsWeb/src/apis/ai/document-segment.ts
Normal file
168
schoolNewsWeb/src/apis/ai/document-segment.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* @description Dify 文档分段管理 API
|
||||
* @author AI Assistant
|
||||
* @since 2025-11-04
|
||||
*/
|
||||
|
||||
import { api } from '@/apis/index';
|
||||
import type { ResultDomain } from '@/types';
|
||||
import type {
|
||||
DifySegmentListResponse,
|
||||
DifyChildChunkListResponse,
|
||||
DifyChildChunkResponse,
|
||||
SegmentUpdateRequest,
|
||||
SegmentCreateRequest
|
||||
} from '@/types/ai';
|
||||
|
||||
/**
|
||||
* 文档分段管理 API
|
||||
*/
|
||||
export const documentSegmentApi = {
|
||||
/**
|
||||
* 获取文档的所有分段(父级)
|
||||
* @param datasetId Dify数据集ID
|
||||
* @param documentId Dify文档ID
|
||||
* @returns Promise<ResultDomain<DifySegmentListResponse>>
|
||||
*/
|
||||
async getDocumentSegments(
|
||||
datasetId: string,
|
||||
documentId: string
|
||||
): Promise<ResultDomain<DifySegmentListResponse>> {
|
||||
const response = await api.get<DifySegmentListResponse>(
|
||||
`/ai/dify/datasets/${datasetId}/documents/${documentId}/segments`
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取分段的子块列表
|
||||
* @param datasetId Dify数据集ID
|
||||
* @param documentId Dify文档ID
|
||||
* @param segmentId 分段ID
|
||||
* @returns Promise<ResultDomain<DifyChildChunkListResponse>>
|
||||
*/
|
||||
async getChildChunks(
|
||||
datasetId: string,
|
||||
documentId: string,
|
||||
segmentId: string
|
||||
): Promise<ResultDomain<DifyChildChunkListResponse>> {
|
||||
const response = await api.get<DifyChildChunkListResponse>(
|
||||
`/ai/dify/datasets/${datasetId}/documents/${documentId}/segments/${segmentId}/child_chunks`
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新子块内容
|
||||
* @param datasetId Dify数据集ID
|
||||
* @param documentId Dify文档ID
|
||||
* @param segmentId 分段ID
|
||||
* @param childChunkId 子块ID
|
||||
* @param content 新内容
|
||||
* @returns Promise<ResultDomain<DifyChildChunkResponse>>
|
||||
*/
|
||||
async updateChildChunk(
|
||||
datasetId: string,
|
||||
documentId: string,
|
||||
segmentId: string,
|
||||
childChunkId: string,
|
||||
content: string
|
||||
): Promise<ResultDomain<DifyChildChunkResponse>> {
|
||||
const requestBody: SegmentUpdateRequest = { content };
|
||||
const response = await api.patch<DifyChildChunkResponse>(
|
||||
`/ai/dify/datasets/${datasetId}/documents/${documentId}/segments/${segmentId}/child_chunks/${childChunkId}`,
|
||||
requestBody
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建新的子块
|
||||
* @param datasetId Dify数据集ID
|
||||
* @param documentId Dify文档ID
|
||||
* @param segmentId 分段ID
|
||||
* @param content 分段内容
|
||||
* @returns Promise<ResultDomain<DifyChildChunkResponse>>
|
||||
*/
|
||||
async createChildChunk(
|
||||
datasetId: string,
|
||||
documentId: string,
|
||||
segmentId: string,
|
||||
content: string
|
||||
): Promise<ResultDomain<DifyChildChunkResponse>> {
|
||||
const requestBody: SegmentCreateRequest = { content };
|
||||
const response = await api.post<DifyChildChunkResponse>(
|
||||
`/ai/dify/datasets/${datasetId}/documents/${documentId}/segments/${segmentId}/child_chunks`,
|
||||
requestBody
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除子块
|
||||
* @param datasetId Dify数据集ID
|
||||
* @param documentId Dify文档ID
|
||||
* @param segmentId 分段ID
|
||||
* @param childChunkId 子块ID
|
||||
* @returns Promise<ResultDomain<void>>
|
||||
*/
|
||||
async deleteChildChunk(
|
||||
datasetId: string,
|
||||
documentId: string,
|
||||
segmentId: string,
|
||||
childChunkId: string
|
||||
): Promise<ResultDomain<void>> {
|
||||
const response = await api.delete<void>(
|
||||
`/ai/dify/datasets/${datasetId}/documents/${documentId}/segments/${segmentId}/child_chunks/${childChunkId}`
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量获取所有分段和子块
|
||||
* @param datasetId Dify数据集ID
|
||||
* @param documentId Dify文档ID
|
||||
* @returns Promise<DifyChildChunk[]> 所有子块的扁平列表
|
||||
*/
|
||||
async getAllSegmentsWithChunks(
|
||||
datasetId: string,
|
||||
documentId: string
|
||||
): Promise<any[]> {
|
||||
// 1. 获取所有父级分段
|
||||
const segmentsResult = await this.getDocumentSegments(datasetId, documentId);
|
||||
|
||||
if (!segmentsResult.success || !segmentsResult.data?.data) {
|
||||
throw new Error('获取分段列表失败');
|
||||
}
|
||||
|
||||
// 2. 对每个父级分段,获取其子块
|
||||
const allChunks: any[] = [];
|
||||
|
||||
for (const segment of segmentsResult.data.data) {
|
||||
try {
|
||||
const chunksResult = await this.getChildChunks(
|
||||
datasetId,
|
||||
documentId,
|
||||
segment.id
|
||||
);
|
||||
|
||||
if (chunksResult.success && chunksResult.data?.data) {
|
||||
// 为每个子块添加父级分段信息(用于显示)
|
||||
const chunksWithSegmentInfo = chunksResult.data.data.map(chunk => ({
|
||||
...chunk,
|
||||
parentSegmentId: segment.id,
|
||||
parentPosition: segment.position,
|
||||
parentKeywords: segment.keywords
|
||||
}));
|
||||
allChunks.push(...chunksWithSegmentInfo);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`获取分段 ${segment.id} 的子块失败:`, error);
|
||||
// 继续处理其他分段
|
||||
}
|
||||
}
|
||||
|
||||
return allChunks;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,48 +1,117 @@
|
||||
/**
|
||||
* @description 文件上传相关API
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
* @description AI文件上传相关API
|
||||
* @author AI Assistant
|
||||
* @since 2025-11-04
|
||||
*/
|
||||
|
||||
import { api } from '@/apis/index';
|
||||
import type { AiUploadFile, FileUploadResponse, ResultDomain } from '@/types';
|
||||
import type { AiUploadFile, ResultDomain, FileUploadResponse, PageDomain, PageParam } from '@/types';
|
||||
|
||||
/**
|
||||
* 文件上传API服务
|
||||
*/
|
||||
export const fileUploadApi = {
|
||||
/**
|
||||
* 上传文件
|
||||
* @param file 文件
|
||||
* @param userID 用户ID
|
||||
* 上传单个文件到知识库
|
||||
* @param knowledgeId 知识库ID
|
||||
* @param file 文件对象
|
||||
* @returns Promise<ResultDomain<FileUploadResponse>>
|
||||
*/
|
||||
async uploadFile(file: File, userID: string): Promise<ResultDomain<FileUploadResponse>> {
|
||||
async uploadFile(knowledgeId: string, file: File): Promise<ResultDomain<FileUploadResponse>> {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('userID', userID);
|
||||
|
||||
const response = await api.upload<FileUploadResponse>('/ai/file/upload', formData);
|
||||
formData.append('knowledgeId', knowledgeId);
|
||||
|
||||
const response = await api.post<FileUploadResponse>('/ai/file/upload', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取上传文件列表
|
||||
* @param userID 用户ID
|
||||
* @returns Promise<ResultDomain<AiUploadFile>>
|
||||
* 批量上传文件
|
||||
* @param knowledgeId 知识库ID
|
||||
* @param files 文件列表
|
||||
* @returns Promise<ResultDomain<FileUploadResponse[]>>
|
||||
*/
|
||||
async getUploadFileList(userID: string): Promise<ResultDomain<AiUploadFile>> {
|
||||
const response = await api.get<AiUploadFile>('/ai/file/list', { userID });
|
||||
async batchUploadFiles(knowledgeId: string, files: File[]): Promise<ResultDomain<FileUploadResponse[]>> {
|
||||
const formData = new FormData();
|
||||
files.forEach(file => {
|
||||
formData.append('files', file);
|
||||
});
|
||||
formData.append('knowledgeId', knowledgeId);
|
||||
|
||||
const response = await api.post<FileUploadResponse[]>('/ai/file/batch-upload', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除上传文件
|
||||
* @param fileID 文件ID
|
||||
* 删除文件
|
||||
* @param fileId 文件ID
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async deleteUploadFile(fileID: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.delete<boolean>(`/ai/file/${fileID}`);
|
||||
async deleteFile(fileId: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.delete<boolean>(`/ai/file/${fileId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取文件详情
|
||||
* @param fileId 文件ID
|
||||
* @returns Promise<ResultDomain<AiUploadFile>>
|
||||
*/
|
||||
async getFileById(fileId: string): Promise<ResultDomain<AiUploadFile>> {
|
||||
const response = await api.get<AiUploadFile>(`/ai/file/${fileId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取知识库的文件列表
|
||||
* @param knowledgeId 知识库ID
|
||||
* @returns Promise<ResultDomain<AiUploadFile[]>>
|
||||
*/
|
||||
async listFilesByKnowledge(knowledgeId: string): Promise<ResultDomain<AiUploadFile[]>> {
|
||||
const response = await api.get<AiUploadFile[]>(`/ai/file/knowledge/${knowledgeId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 分页查询文件
|
||||
* @param filter 过滤条件
|
||||
* @param pageParam 分页参数
|
||||
* @returns Promise<PageDomain<AiUploadFile>>
|
||||
*/
|
||||
async pageFiles(filter: Partial<AiUploadFile>, pageParam: PageParam): Promise<PageDomain<AiUploadFile>> {
|
||||
const response = await api.post<PageDomain<AiUploadFile>>('/ai/file/page', {
|
||||
filter,
|
||||
pageParam
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 同步文件状态(从Dify)
|
||||
* @param fileId 文件ID
|
||||
* @returns Promise<ResultDomain<AiUploadFile>>
|
||||
*/
|
||||
async syncFileStatus(fileId: string): Promise<ResultDomain<AiUploadFile>> {
|
||||
const response = await api.post<AiUploadFile>(`/ai/file/${fileId}/sync`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量同步文件状态
|
||||
* @param fileIds 文件ID列表
|
||||
* @returns Promise<ResultDomain<number>>
|
||||
*/
|
||||
async batchSyncFileStatus(fileIds: string[]): Promise<ResultDomain<number>> {
|
||||
const response = await api.post<number>('/ai/file/batch-sync', { fileIds });
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
/**
|
||||
* @description 智能体相关API
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
* @description AI模块API导出
|
||||
* @author AI Assistant
|
||||
* @since 2025-11-04
|
||||
*/
|
||||
|
||||
// 重新导出各个子模块
|
||||
export { aiAgentConfigApi } from './agent-config';
|
||||
export { conversationApi } from './conversation';
|
||||
export { messageApi } from './message';
|
||||
export { knowledgeApi } from './knowledge';
|
||||
export { fileUploadApi } from './file-upload';
|
||||
export { chatApi } from './chat';
|
||||
export { chatHistoryApi } from './chat-history';
|
||||
export { documentSegmentApi } from './document-segment';
|
||||
|
||||
// 为了向后兼容,保留旧的导出名称
|
||||
export { chatApi as conversationApi } from './chat';
|
||||
export { chatApi as messageApi } from './chat';
|
||||
|
||||
@@ -1,52 +1,146 @@
|
||||
/**
|
||||
* @description 知识库相关API
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
* @description AI知识库相关API
|
||||
* @author AI Assistant
|
||||
* @since 2025-11-04
|
||||
*/
|
||||
|
||||
import { api } from '@/apis/index';
|
||||
import type { AiKnowledge, ResultDomain } from '@/types';
|
||||
import type { AiKnowledge, ResultDomain, PageDomain, PageParam, KnowledgePermissionParams } from '@/types';
|
||||
|
||||
/**
|
||||
* 知识库API服务
|
||||
*/
|
||||
export const knowledgeApi = {
|
||||
/**
|
||||
* 获取知识库列表
|
||||
* @returns Promise<ResultDomain<AiKnowledge>>
|
||||
*/
|
||||
async getKnowledgeList(): Promise<ResultDomain<AiKnowledge>> {
|
||||
const response = await api.get<AiKnowledge>('/ai/knowledge/list');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 创建知识库条目
|
||||
* 创建知识库
|
||||
* @param knowledge 知识库数据
|
||||
* @returns Promise<ResultDomain<AiKnowledge>>
|
||||
*/
|
||||
async createKnowledge(knowledge: AiKnowledge): Promise<ResultDomain<AiKnowledge>> {
|
||||
const response = await api.post<AiKnowledge>('/ai/knowledge/create', knowledge);
|
||||
const response = await api.post<AiKnowledge>('/ai/knowledge', knowledge);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新知识库条目
|
||||
* 更新知识库
|
||||
* @param knowledge 知识库数据
|
||||
* @returns Promise<ResultDomain<AiKnowledge>>
|
||||
*/
|
||||
async updateKnowledge(knowledge: AiKnowledge): Promise<ResultDomain<AiKnowledge>> {
|
||||
const response = await api.put<AiKnowledge>('/ai/knowledge/update', knowledge);
|
||||
const response = await api.put<AiKnowledge>('/ai/knowledge', knowledge);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除知识库条目
|
||||
* @param knowledgeID 知识库ID
|
||||
* 删除知识库
|
||||
* @param knowledgeId 知识库ID
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async deleteKnowledge(knowledgeID: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.delete<boolean>(`/ai/knowledge/${knowledgeID}`);
|
||||
async deleteKnowledge(knowledgeId: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.delete<boolean>(`/ai/knowledge/${knowledgeId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取知识库详情
|
||||
* @param knowledgeId 知识库ID
|
||||
* @returns Promise<ResultDomain<AiKnowledge>>
|
||||
*/
|
||||
async getKnowledgeById(knowledgeId: string): Promise<ResultDomain<AiKnowledge>> {
|
||||
const response = await api.get<AiKnowledge>(`/ai/knowledge/${knowledgeId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取用户可见的知识库列表
|
||||
* @returns Promise<ResultDomain<AiKnowledge[]>>
|
||||
*/
|
||||
async listUserKnowledges(): Promise<ResultDomain<AiKnowledge[]>> {
|
||||
const response = await api.get<AiKnowledge[]>('/ai/knowledge/user');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取知识库列表(支持过滤)
|
||||
* @param filter 过滤条件
|
||||
* @returns Promise<ResultDomain<AiKnowledge[]>>
|
||||
*/
|
||||
async listKnowledges(filter?: Partial<AiKnowledge>): Promise<ResultDomain<AiKnowledge[]>> {
|
||||
const response = await api.post<AiKnowledge[]>('/ai/knowledge/list', filter || {});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 分页查询知识库
|
||||
* @param filter 过滤条件
|
||||
* @param pageParam 分页参数
|
||||
* @returns Promise<PageDomain<AiKnowledge>>
|
||||
*/
|
||||
async pageKnowledges(filter: Partial<AiKnowledge>, pageParam: PageParam): Promise<PageDomain<AiKnowledge>> {
|
||||
const response = await api.post<PageDomain<AiKnowledge>>('/ai/knowledge/page', {
|
||||
filter,
|
||||
pageParam
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 同步知识库到Dify
|
||||
* @param knowledgeId 知识库ID
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async syncToDify(knowledgeId: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.post<boolean>(`/ai/knowledge/${knowledgeId}/sync`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 从Dify同步知识库状态
|
||||
* @param knowledgeId 知识库ID
|
||||
* @returns Promise<ResultDomain<AiKnowledge>>
|
||||
*/
|
||||
async syncFromDify(knowledgeId: string): Promise<ResultDomain<AiKnowledge>> {
|
||||
const response = await api.get<AiKnowledge>(`/ai/knowledge/${knowledgeId}/sync`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 设置知识库权限
|
||||
* @param params 权限参数
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async setPermissions(params: KnowledgePermissionParams): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.post<boolean>('/ai/knowledge/permissions', params);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取知识库权限
|
||||
* @param knowledgeId 知识库ID
|
||||
* @returns Promise<ResultDomain<any>>
|
||||
*/
|
||||
async getPermissions(knowledgeId: string): Promise<ResultDomain<any>> {
|
||||
const response = await api.get<any>(`/ai/knowledge/${knowledgeId}/permissions`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查用户是否有权限访问知识库
|
||||
* @param knowledgeId 知识库ID
|
||||
* @returns Promise<ResultDomain<boolean>>
|
||||
*/
|
||||
async checkPermission(knowledgeId: string): Promise<ResultDomain<boolean>> {
|
||||
const response = await api.get<boolean>(`/ai/knowledge/${knowledgeId}/check-permission`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取知识库统计信息
|
||||
* @param knowledgeId 知识库ID
|
||||
* @returns Promise<ResultDomain<any>>
|
||||
*/
|
||||
async getStats(knowledgeId: string): Promise<ResultDomain<any>> {
|
||||
const response = await api.get<any>(`/ai/knowledge/${knowledgeId}/stats`);
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/**
|
||||
* @description 消息相关API
|
||||
* @author yslg
|
||||
* @since 2025-10-15
|
||||
*/
|
||||
|
||||
import { api } from '@/apis/index';
|
||||
import type { AiMessage, ChatRequest, ChatResponse, ResultDomain } from '@/types';
|
||||
|
||||
/**
|
||||
* 消息API服务
|
||||
*/
|
||||
export const messageApi = {
|
||||
/**
|
||||
* 获取对话消息列表
|
||||
* @param conversationID 对话ID
|
||||
* @returns Promise<ResultDomain<AiMessage>>
|
||||
*/
|
||||
async getMessageList(conversationID: string): Promise<ResultDomain<AiMessage>> {
|
||||
const response = await api.get<AiMessage>(`/ai/message/list`, { conversationID });
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
* @param request 消息请求
|
||||
* @returns Promise<ResultDomain<ChatResponse>>
|
||||
*/
|
||||
async sendMessage(request: ChatRequest): Promise<ResultDomain<ChatResponse>> {
|
||||
const response = await api.post<ChatResponse>('/ai/message/send', request);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 流式发送消息
|
||||
* @param request 消息请求
|
||||
* @param onMessage 消息回调
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
// async sendMessageStream(request: ChatRequest, onMessage: (message: string) => void): Promise<void> {
|
||||
// const response = await api.post('/ai/message/stream', { ...request, stream: true }, {
|
||||
// responseType: 'stream'
|
||||
// });
|
||||
|
||||
// // 处理流式响应
|
||||
// const reader = response.data.getReader();
|
||||
// const decoder = new TextDecoder();
|
||||
// let done = false;
|
||||
|
||||
// while (!done) {
|
||||
// const readResult = await reader.read();
|
||||
// done = readResult.done;
|
||||
// if (done) break;
|
||||
|
||||
// const chunk = decoder.decode(readResult.value);
|
||||
// const lines = chunk.split('\n');
|
||||
|
||||
// for (const line of lines) {
|
||||
// if (line.startsWith('data: ')) {
|
||||
// const data = line.slice(6);
|
||||
// if (data === '[DONE]') return;
|
||||
|
||||
// try {
|
||||
// const parsed = JSON.parse(data);
|
||||
// onMessage(parsed.content || '');
|
||||
// } catch (e) {
|
||||
// console.error('解析流式数据失败:', e);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
};
|
||||
Reference in New Issue
Block a user