useSSE.ts 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import { ref, reactive, onBeforeUnmount } from 'vue'
  2. import { SSEApi } from '@/interface/ai'
  3. interface UseSSEQueryBody {
  4. mutationFn: (body: SSEApi) => void
  5. onMessage?: (data: any) => void
  6. onError?: (err: any) => void
  7. }
  8. interface AResult {
  9. content: string // 思考过程
  10. result: object // 最终结果(含有多个对象,通过状态为key区分)
  11. }
  12. const useSSE = (body: UseSSEQueryBody) => {
  13. const { mutationFn, onMessage, onError } = body
  14. const data = reactive<AResult>({ content: '', result: {} })
  15. const loading = ref<boolean>(false)
  16. const ctrlAbout = new AbortController()
  17. // 思考过程更新
  18. const contentChange = (text: string): void => {
  19. data.content += text
  20. }
  21. // 结果更新
  22. const resultChange = (key: string, result: object): void => {
  23. data.result[key] = result
  24. }
  25. // 对话结束回调
  26. const answerDone = () => {
  27. loading.value = false
  28. }
  29. const mutation = (paramBody: any) => {
  30. loading.value = true
  31. mutationFn?.({
  32. paramBody,
  33. signal: ctrlAbout.signal,
  34. onMessage: (result: any) => {
  35. onMessage?.(result)
  36. },
  37. onError: (err) => {
  38. console.log('error: ', err)
  39. ctrlAbout.abort()
  40. onError?.(err)
  41. },
  42. contentChange,
  43. resultChange,
  44. answerDone
  45. })
  46. }
  47. onBeforeUnmount(() => {
  48. ctrlAbout.abort()
  49. })
  50. return { data, ctrlAbout, loading, mutation }
  51. }
  52. export default useSSE