Right.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <template>
  2. <div class="h-full box-border flex flex-col px-7">
  3. <h3 class="m-0 h-14 -mx-7 px-7 shrink-0 flex items-center justify-between bg-[#ecedef]">
  4. <span>预览</span>
  5. <!-- 展示在右上角 -->
  6. <el-button color="#846af7" v-show="showCopy" @click="copyContent" size="small">
  7. <template #icon>
  8. <Icon icon="ph:copy-bold" />
  9. </template>
  10. 复制
  11. </el-button>
  12. </h3>
  13. <div ref="contentRef" class="hide-scroll-bar flex-grow box-border overflow-y-auto">
  14. <div class="w-full min-h-full relative flex-grow bg-white box-border p-3 sm:p-7">
  15. <!-- 终止生成内容的按钮 -->
  16. <el-button
  17. v-show="isWriting"
  18. class="absolute bottom-2 sm:bottom-5 left-1/2 -translate-x-1/2 z-36"
  19. @click="emits('stopStream')"
  20. size="small"
  21. >
  22. <template #icon>
  23. <Icon icon="material-symbols:stop" />
  24. </template>
  25. 终止生成
  26. </el-button>
  27. <el-input
  28. id="inputId"
  29. type="textarea"
  30. v-model="compContent"
  31. autosize
  32. :input-style="{ boxShadow: 'none' }"
  33. resize="none"
  34. placeholder="生成的内容……"
  35. />
  36. </div>
  37. </div>
  38. </div>
  39. </template>
  40. <script setup lang="ts">
  41. import { useClipboard } from '@vueuse/core'
  42. const message = useMessage() // 消息弹窗
  43. const { copied, copy } = useClipboard() // 粘贴板
  44. const props = defineProps({
  45. content: {
  46. // 生成的结果
  47. type: String,
  48. default: ''
  49. },
  50. isWriting: {
  51. // 是否正在生成文章
  52. type: Boolean,
  53. default: false
  54. }
  55. })
  56. const emits = defineEmits(['update:content', 'stopStream'])
  57. /** 通过计算属性,双向绑定,更改生成的内容,考虑到用户想要更改生成文章的情况 */
  58. const compContent = computed({
  59. get() {
  60. return props.content
  61. },
  62. set(val) {
  63. emits('update:content', val)
  64. }
  65. })
  66. /** 滚动 */
  67. const contentRef = ref<HTMLDivElement>()
  68. defineExpose({
  69. scrollToBottom() {
  70. contentRef.value?.scrollTo(0, contentRef.value?.scrollHeight)
  71. }
  72. })
  73. /** 点击复制的时候复制内容 */
  74. const showCopy = computed(() => props.content && !props.isWriting) // 是否展示复制按钮,在生成内容完成的时候展示
  75. const copyContent = () => {
  76. copy(props.content)
  77. }
  78. /** 复制成功的时候 copied.value 为 true */
  79. watch(copied, (val) => {
  80. if (val) {
  81. message.success('复制成功')
  82. }
  83. })
  84. </script>
  85. <style lang="scss" scoped>
  86. .hide-scroll-bar {
  87. -ms-overflow-style: none;
  88. scrollbar-width: none;
  89. &::-webkit-scrollbar {
  90. width: 0;
  91. height: 0;
  92. }
  93. }
  94. </style>