This commit is contained in:
2025-11-04 18:49:37 +08:00
parent b95fff224b
commit 8850a06fea
103 changed files with 15337 additions and 771 deletions

View File

@@ -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;
}
};

View 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;
}
};

View 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;
}
};

View File

@@ -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;
}
};

View 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;
}
};

View File

@@ -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;
}
};

View File

@@ -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';

View File

@@ -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;
}
};

View File

@@ -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);
// }
// }
// }
// }
// }
};