index.vue 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. <!-- TODO @hhhero:挪到 write/index/index.vue 里。因为后续会有 write/manager/index.vue 管理内容 -->
  2. <template>
  3. <div class="h-[calc(100vh-var(--top-tool-height)-var(--app-footer-height)-40px)] -m-5 flex">
  4. <Left :is-writing="isWriting" class="h-full" @submit="submit" @example="handleExampleClick" />
  5. <!-- TODO @hhhero:顶部应该有个预览的 header -->
  6. <!-- TODO @hhhero:整个 Right 组件的框,没铺满的感觉? -->
  7. <Right
  8. :is-writing="isWriting"
  9. @stop-stream="stopStream"
  10. ref="rightRef"
  11. class="flex-grow"
  12. v-model:msg="writeResult"
  13. />
  14. </div>
  15. </template>
  16. <script setup lang="ts">
  17. import Left from './components/Left.vue'
  18. import Right from './components/Right.vue'
  19. // TODO @hhhero:搞成 WriteApi 哈
  20. import { writeStream } from '@/api/ai/writer'
  21. // TODO @hhhero:dataJson 放到 ai/utils/utils.ts
  22. import dataJson from './data.json'
  23. const message = useMessage()
  24. const writeResult = ref('') // 写作结果
  25. const isWriting = ref(false) // 是否正在写作中
  26. const abortController = ref<AbortController>() // // 写作进行中 abort 控制器(控制 stream 写作)
  27. /** 停止 stream 生成 */
  28. const stopStream = () => {
  29. abortController.value?.abort()
  30. isWriting.value = false
  31. }
  32. /** 执行写作 */
  33. const rightRef = ref<InstanceType<typeof Right>>()
  34. const submit = async (data) => {
  35. abortController.value = new AbortController()
  36. writeResult.value = ''
  37. isWriting.value = true
  38. await writeStream({
  39. data,
  40. onMessage: async (res) => {
  41. const { code, data, msg } = JSON.parse(res.data)
  42. if (code !== 0) {
  43. message.alert(`写作异常! ${msg}`)
  44. stopStream()
  45. return
  46. }
  47. writeResult.value = writeResult.value + data
  48. nextTick(() => {
  49. rightRef.value?.scrollToBottom()
  50. })
  51. },
  52. ctrl: abortController.value,
  53. onClose: stopStream,
  54. onError: stopStream // TODO @hhhero: error 的时候,是不是要打印下错误哈
  55. })
  56. }
  57. /** 点击示例触发 */
  58. const handleExampleClick = (type: keyof typeof dataJson) => {
  59. writeResult.value = dataJson[type].data
  60. }
  61. </script>