Browse Source

【代码评审】写作:生成部分

YunaiV 11 months ago
parent
commit
ece1533436

+ 3 - 1
src/api/ai/writer/index.ts

@@ -2,9 +2,10 @@ import { fetchEventSource } from '@microsoft/fetch-event-source'
 
 import { getAccessToken } from '@/utils/auth'
 import { config } from '@/config/axios/config'
+import { AiWriteTypeEnum } from '@/views/ai/utils/constants'
 
 export interface WriteVO {
-  type: 1 | 2 // 1:撰写 2:回复
+  type: AiWriteTypeEnum.WRITING | AiWriteTypeEnum.REPLY // 1:撰写 2:回复
   prompt: string // 写作内容提示 1。撰写 2回复
   originalContent: string // 原文
   length: number // 长度
@@ -13,6 +14,7 @@ export interface WriteVO {
   language: number // 语言
 }
 
+// TODO @hhero:搞成 WriteApi,类似 ConversationApi 一样。这样更有类的概念,后续引入某个 Api,然后调用它的方法就可以了。
 export const writeStream = ({
   data,
   onClose,

File diff suppressed because it is too large
+ 7 - 0
src/views/ai/utils/constants.ts


File diff suppressed because it is too large
+ 0 - 5
src/views/ai/utils/utils.ts


+ 15 - 11
src/views/ai/writer/components/Left.vue → src/views/ai/writer/index/components/Left.vue

@@ -24,7 +24,6 @@
     </h3>
   </DefineLabel>
 
-  <!-- TODO @hhhero 小屏幕的时候是定位在左边的,大屏是分开的 -->
   <div class="relative" v-bind="$attrs">
     <!-- tab -->
     <div
@@ -106,12 +105,11 @@ import Tag from './Tag.vue'
 import { WriteVO } from '@/api/ai/writer'
 import { omit } from 'lodash-es'
 import { getIntDictOptions } from '@/utils/dict'
-import { WriteExampleDataJson } from '@/views/ai/utils/utils'
-import { AiWriteTypeEnum } from "@/views/ai/utils/constants";
+import { AiWriteTypeEnum, WriteExample } from '@/views/ai/utils/constants'
 
 type TabType = WriteVO['type']
 
-const message = useMessage()
+const message = useMessage() // 消息弹窗
 
 defineProps<{
   isWriting: boolean
@@ -127,15 +125,17 @@ const emits = defineEmits<{
 const example = (type: 'write' | 'reply') => {
   formData.value = {
     ...initData,
-    ...omit(WriteExampleDataJson[type], ['data'])
+    ...omit(WriteExample[type], ['data'])
   }
   emits('example', type)
 }
+
 /** 重置,将表单值作为初选值 **/
 const reset = () => {
-  formData.value = {...initData}
+  formData.value = { ...initData }
   emits('reset')
 }
+
 const selectedTab = ref<TabType>(AiWriteTypeEnum.WRITING)
 const tabs: {
   text: string
@@ -151,10 +151,12 @@ const [DefineTab, ReuseTab] = createReusableTemplate<{
 }>()
 
 /**
- * 可以在template里边定义可复用的组件,DefineLabel,ReuseLabel是采用的解构赋值,都是Vue组件
- * 直接通过组件的形式使用,<DefineLabel v-slot="{ label, hint, hintClick }">中间是需要复用的组件代码</DefineLabel>,通过<ReuseLabel />来使用定义的组件
- * DefineLabel里边的v-slot="{ label, hint, hintClick }“相当于是解构了组件的prop,需要注意的是boolean类型,需要显式的赋值比如 <ReuseLabel :flag="true" />
- * 事件也得以prop形式传入,不能是@event的形式,比如下面的hintClick需要<ReuseLabel :hintClick="() => { doSomething }"/>
+ * 可以在 template 里边定义可复用的组件,DefineLabel,ReuseLabel 是采用的解构赋值,都是 Vue 组件
+ *
+ * 直接通过组件的形式使用,<DefineLabel v-slot="{ label, hint, hintClick }"> 中间是需要复用的组件代码 <DefineLabel />,通过 <ReuseLabel /> 来使用定义的组件
+ * DefineLabel 里边的 v-slot="{ label, hint, hintClick }"相当于是解构了组件的 prop,需要注意的是 boolean 类型,需要显式的赋值比如 <ReuseLabel :flag="true" />
+ * 事件也得以 prop 形式传入,不能是 @event的形式,比如下面的 hintClick 需要<ReuseLabel :hintClick="() => { doSomething }"/>
+ *
  * @see https://vueuse.org/createReusableTemplate
  */
 const [DefineLabel, ReuseLabel] = createReusableTemplate<{
@@ -174,12 +176,14 @@ const initData: WriteVO = {
   format: 1
 }
 const formData = ref<WriteVO>({ ...initData })
+
 /** 切换tab **/
 const switchTab = (value: TabType) => {
   selectedTab.value = value
   formData.value = { ...initData }
 }
 
+/** 提交写作 */
 const submit = () => {
   if (selectedTab.value === 2 && !formData.value.originalContent) {
     message.warning('请输入原文')
@@ -192,7 +196,7 @@ const submit = () => {
   emits('submit', {
     /** 撰写的时候没有 originalContent 字段**/
     ...(selectedTab.value === 1 ? omit(formData.value, ['originalContent']) : formData.value),
-    /** 使用选中tab值覆盖当前的type类型 **/
+    /** 使用选中 tab 值覆盖当前的 type 类型 **/
     type: selectedTab.value
   })
 }

+ 6 - 13
src/views/ai/writer/components/Right.vue → src/views/ai/writer/index/components/Right.vue

@@ -3,22 +3,15 @@
     <h3 class="m-0 h-14 -mx-7 px-7 shrink-0 flex items-center justify-between bg-[#ecedef]">
       <span>预览</span>
       <!-- 展示在右上角 -->
-      <el-button
-        color="#846af7"
-        v-show="showCopy"
-        @click="copyContent"
-        size="small"
-      >
+      <el-button color="#846af7" v-show="showCopy" @click="copyContent" size="small">
         <template #icon>
           <Icon icon="ph:copy-bold" />
         </template>
         复制
       </el-button>
-
-
     </h3>
 
-    <div ref="contentRef" class="hide-scroll-bar flex-grow box-border overflow-y-auto ">
+    <div ref="contentRef" class="hide-scroll-bar flex-grow box-border overflow-y-auto">
       <div class="w-full min-h-full relative flex-grow bg-white box-border p-3 sm:p-7">
         <!-- 终止生成内容的按钮 -->
         <el-button
@@ -49,8 +42,8 @@
 <script setup lang="ts">
 import { useClipboard } from '@vueuse/core'
 
-const message = useMessage()
-const { copied, copy } = useClipboard()
+const message = useMessage() // 消息弹窗
+const { copied, copy } = useClipboard() // 粘贴板
 
 const props = defineProps({
   content: {
@@ -67,7 +60,7 @@ const props = defineProps({
 
 const emits = defineEmits(['update:content', 'stopStream'])
 
-// 通过计算属性,双向绑定,更改生成的内容,考虑到用户想要更改生成文章的情况
+/** 通过计算属性,双向绑定,更改生成的内容,考虑到用户想要更改生成文章的情况 */
 const compContent = computed({
   get() {
     return props.content
@@ -91,7 +84,7 @@ const copyContent = () => {
   copy(props.content)
 }
 
-// 复制成功的时候copied.value为true
+/** 复制成功的时候 copied.value 为 true */
 watch(copied, (val) => {
   if (val) {
     message.success('复制成功')

+ 0 - 0
src/views/ai/writer/components/Tag.vue → src/views/ai/writer/index/components/Tag.vue


+ 8 - 7
src/views/ai/writer/index/index.vue

@@ -1,4 +1,5 @@
 <template>
+  <!-- TODO @hhhero:整体没啥问题了。感觉整体框框的样子可以优化下,可以参考下绘图界面。例如说:1)写作的“预览”和绘图的“绘图任务”的 header;2)左右的边界,有个竖线之类的。 -->
   <div class="h-[calc(100vh-var(--top-tool-height)-var(--app-footer-height)-40px)] -m-5 flex">
     <Left
       :is-writing="isWriting"
@@ -18,10 +19,10 @@
 </template>
 
 <script setup lang="ts">
-import Left from '../components/Left.vue'
-import Right from '../components/Right.vue'
+import Left from './components/Left.vue'
+import Right from './components/Right.vue'
 import * as WriteApi from '@/api/ai/writer'
-import { WriteExampleDataJson } from '@/views/ai/utils/utils'
+import { WriteExample } from '@/views/ai/utils/constants'
 
 const message = useMessage()
 
@@ -51,9 +52,9 @@ const submit = (data) => {
         return
       }
       writeResult.value = writeResult.value + data
-      nextTick(() => {
-        rightRef.value?.scrollToBottom()
-      })
+      // 滚动到底部
+      await nextTick()
+      rightRef.value?.scrollToBottom()
     },
     ctrl: abortController.value,
     onClose: stopStream,
@@ -66,7 +67,7 @@ const submit = (data) => {
 
 /** 点击示例触发 */
 const handleExampleClick = (type: keyof typeof WriteExampleDataJson) => {
-  writeResult.value = WriteExampleDataJson[type].data
+  writeResult.value = WriteExample[type].data
 }
 
 /** 点击重置的时候清空写作的结果**/

Some files were not shown because too many files changed in this diff