1
0

api.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import { defHttp } from '/@/utils/http/axios';
  2. enum Api {
  3. unified = '/ventAI/api/chat',
  4. getHistoryList = '/ventAI/api/sessions',
  5. getDetail = '/ventAI/api/chat/history/',
  6. deleteSession = '/ventAI/api/sessions/',
  7. }
  8. /**
  9. * 历史会话接口
  10. */
  11. export const getHistoryList = (params) => defHttp.get({ url: Api.getHistoryList, params }, { joinParamsToUrl: true, isTransformResponse: false });
  12. /**
  13. * 获取历史会话详情
  14. * @param session_id - 会话ID
  15. */
  16. export const getDetail = (session_id: string) => defHttp.get({ url: Api.getDetail + session_id }, { isTransformResponse: false });
  17. /**
  18. * 删除会话
  19. * @param session_id - 会话ID
  20. */
  21. export const deleteSession = (session_id: string) => defHttp.delete({ url: Api.deleteSession + session_id }, { isTransformResponse: false });
  22. /**
  23. * 统一对话接口(SSE流式响应)
  24. * @param params.message - 用户输入的文本,必填
  25. * @param params.session_id - 会话唯一标识ID,不传参时服务端自动生成全新会话ID
  26. * @param params.file - 上传的PDF文件,可选
  27. * @param onChunk - 流式数据回调函数
  28. * @returns Promise<{ session_id: string }>
  29. */
  30. export const unifiedStream = async (
  31. params: { message: string; session_id?: string; file?: File },
  32. onChunk: (chunk: string) => void
  33. ): Promise<{ session_id: string }> => {
  34. try {
  35. const formData = new FormData();
  36. formData.append('message', params.message);
  37. if (params.session_id) {
  38. formData.append('session_id', params.session_id);
  39. }
  40. if (params.file) {
  41. formData.append('file', params.file);
  42. }
  43. const response = await fetch(Api.unified, {
  44. method: 'POST',
  45. body: formData,
  46. });
  47. if (!response.ok) {
  48. throw new Error(`HTTP错误: ${response.status}`);
  49. }
  50. const reader = response.body!.getReader();
  51. const decoder = new TextDecoder();
  52. let buffer = '';
  53. let sessionId = '';
  54. let isDone = false;
  55. // eslint-disable-next-line no-constant-condition
  56. while (true) {
  57. const { done, value } = await reader.read();
  58. if (done || isDone) break;
  59. buffer += decoder.decode(value, { stream: true });
  60. const lines = buffer.split('\n');
  61. buffer = lines.pop() || '';
  62. for (const line of lines) {
  63. if (line.trim() === '') continue;
  64. if (line.startsWith('data: ')) {
  65. const dataStr = line.replace(/^data: /, '');
  66. try {
  67. const data = JSON.parse(dataStr);
  68. onChunk(line);
  69. if (data.type === 'done' || data.type === 'error') {
  70. if (data.session_id) {
  71. sessionId = data.session_id;
  72. }
  73. isDone = true;
  74. break;
  75. }
  76. } catch (e) {
  77. console.warn('SSE数据解析失败:', dataStr);
  78. }
  79. }
  80. }
  81. if (isDone) break;
  82. }
  83. return { session_id: sessionId };
  84. } catch (error) {
  85. console.error('统一对话流式请求失败:', error);
  86. throw error;
  87. }
  88. };