index.vue 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. <template>
  2. <div class="absolute top-0 left-0 right-0 bottom-0 flex">
  3. <Left
  4. :is-writing="isWriting"
  5. class="h-full"
  6. @submit="submit"
  7. @reset="reset"
  8. @example="handleExampleClick"
  9. />
  10. <Right
  11. :is-writing="isWriting"
  12. @stop-stream="stopStream"
  13. ref="rightRef"
  14. class="flex-grow"
  15. v-model:content="writeResult"
  16. />
  17. </div>
  18. </template>
  19. <script setup lang="ts">
  20. import Left from './components/Left.vue'
  21. import Right from './components/Right.vue'
  22. import * as WriteApi from '@/api/ai/writer'
  23. import { WriteExample } from '@/views/ai/utils/constants'
  24. const message = useMessage()
  25. const writeResult = ref('') // 写作结果
  26. const isWriting = ref(false) // 是否正在写作中
  27. const abortController = ref<AbortController>() // // 写作进行中 abort 控制器(控制 stream 写作)
  28. /** 停止 stream 生成 */
  29. const stopStream = () => {
  30. abortController.value?.abort()
  31. isWriting.value = false
  32. }
  33. /** 执行写作 */
  34. const rightRef = ref<InstanceType<typeof Right>>()
  35. const submit = (data) => {
  36. abortController.value = new AbortController()
  37. writeResult.value = ''
  38. isWriting.value = true
  39. WriteApi.writeStream({
  40. data,
  41. onMessage: async (res) => {
  42. const { code, data, msg } = JSON.parse(res.data)
  43. if (code !== 0) {
  44. message.alert(`写作异常! ${msg}`)
  45. stopStream()
  46. return
  47. }
  48. writeResult.value = writeResult.value + data
  49. // 滚动到底部
  50. await nextTick()
  51. rightRef.value?.scrollToBottom()
  52. },
  53. ctrl: abortController.value,
  54. onClose: stopStream,
  55. onError: (...err) => {
  56. console.error('写作异常', ...err)
  57. stopStream()
  58. }
  59. })
  60. }
  61. /** 点击示例触发 */
  62. const handleExampleClick = (type: keyof typeof WriteExampleDataJson) => {
  63. writeResult.value = WriteExample[type].data
  64. }
  65. /** 点击重置的时候清空写作的结果**/
  66. const reset = () => {
  67. writeResult.value = ''
  68. }
  69. </script>