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

pull/478/MERGE
YunaiV 2024-07-10 12:49:54 +08:00
parent e53786e8bd
commit ece1533436
7 changed files with 47 additions and 45 deletions

View File

@ -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,

View File

@ -353,3 +353,18 @@ export const NijiVersionList = [
label: 'v5'
}
]
// ========== 【写作 UI】相关的枚举 ==========
/** 写作点击示例时的数据 **/
export const WriteExample = {
write: {
prompt: 'vue',
data: 'Vue.js 是一种用于构建用户界面的渐进式 JavaScript 框架。它的核心库只关注视图层,易于上手,同时也便于与其他库或已有项目整合。\n\nVue.js 的特点包括:\n- 响应式的数据绑定Vue.js 会自动将数据与 DOM 同步,使得状态管理变得更加简单。\n- 组件化Vue.js 允许开发者通过小型、独立和通常可复用的组件构建大型应用。\n- 虚拟 DOMVue.js 使用虚拟 DOM 实现快速渲染,提高了性能。\n\n在 Vue.js 中,一个典型的应用结构可能包括:\n1. 根实例:每个 Vue 应用都需要一个根实例作为入口点。\n2. 组件系统:可以创建自定义的可复用组件。\n3. 指令:特殊的带有前缀 v- 的属性,为 DOM 元素提供特殊的行为。\n4. 插值:用于文本内容,将数据动态地插入到 HTML。\n5. 计算属性和侦听器:用于处理数据的复杂逻辑和响应数据变化。\n6. 条件渲染:根据条件决定元素的渲染。\n7. 列表渲染:用于显示列表数据。\n8. 事件处理:响应用户交互。\n9. 表单输入绑定:处理表单输入和验证。\n10. 组件生命周期钩子:在组件的不同阶段执行特定的函数。\n\nVue.js 还提供了官方的路由器 Vue Router 和状态管理库 Vuex以支持构建复杂的单页应用SPA。\n\n在开发过程中开发者通常会使用 Vue CLI这是一个强大的命令行工具用于快速生成 Vue 项目脚手架,集成了诸如 Babel、Webpack 等现代前端工具,以及热重载、代码检测等开发体验优化功能。\n\nVue.js 的生态系统还包括大量的第三方库和插件,如 VuetifyUI 组件库、Vue Test Utils测试工具这些都极大地丰富了 Vue.js 的开发生态。\n\n总的来说Vue.js 是一个灵活、高效的前端框架,适合从小型项目到大型企业级应用的开发。它的易用性、灵活性和强大的社区支持使其成为许多开发者的首选框架之一。'
},
reply: {
originalContent: '领导,我想请假',
prompt: '不批',
data: '您的请假申请已收悉,经核实和考虑,暂时无法批准您的请假申请。\n\n如有特殊情况或紧急事务请及时与我联系。\n\n祝工作顺利。\n\n谢谢。'
}
}

View File

@ -11,16 +11,3 @@
export const hasChinese = (str: string) => {
return /[\u4e00-\u9fa5]/.test(str)
}
/** 写作点击示例时的数据 **/
export const WriteExampleDataJson = {
write: {
prompt: 'vue',
data: 'Vue.js 是一种用于构建用户界面的渐进式 JavaScript 框架。它的核心库只关注视图层,易于上手,同时也便于与其他库或已有项目整合。\n\nVue.js 的特点包括:\n- 响应式的数据绑定Vue.js 会自动将数据与 DOM 同步,使得状态管理变得更加简单。\n- 组件化Vue.js 允许开发者通过小型、独立和通常可复用的组件构建大型应用。\n- 虚拟 DOMVue.js 使用虚拟 DOM 实现快速渲染,提高了性能。\n\n在 Vue.js 中,一个典型的应用结构可能包括:\n1. 根实例:每个 Vue 应用都需要一个根实例作为入口点。\n2. 组件系统:可以创建自定义的可复用组件。\n3. 指令:特殊的带有前缀 v- 的属性,为 DOM 元素提供特殊的行为。\n4. 插值:用于文本内容,将数据动态地插入到 HTML。\n5. 计算属性和侦听器:用于处理数据的复杂逻辑和响应数据变化。\n6. 条件渲染:根据条件决定元素的渲染。\n7. 列表渲染:用于显示列表数据。\n8. 事件处理:响应用户交互。\n9. 表单输入绑定:处理表单输入和验证。\n10. 组件生命周期钩子:在组件的不同阶段执行特定的函数。\n\nVue.js 还提供了官方的路由器 Vue Router 和状态管理库 Vuex以支持构建复杂的单页应用SPA。\n\n在开发过程中开发者通常会使用 Vue CLI这是一个强大的命令行工具用于快速生成 Vue 项目脚手架,集成了诸如 Babel、Webpack 等现代前端工具,以及热重载、代码检测等开发体验优化功能。\n\nVue.js 的生态系统还包括大量的第三方库和插件,如 VuetifyUI 组件库、Vue Test Utils测试工具这些都极大地丰富了 Vue.js 的开发生态。\n\n总的来说Vue.js 是一个灵活、高效的前端框架,适合从小型项目到大型企业级应用的开发。它的易用性、灵活性和强大的社区支持使其成为许多开发者的首选框架之一。'
},
reply: {
originalContent: '领导,我想请假',
prompt: '不批',
data: '您的请假申请已收悉,经核实和考虑,暂时无法批准您的请假申请。\n\n如有特殊情况或紧急事务请及时与我联系。\n\n祝工作顺利。\n\n谢谢。'
}
}

View File

@ -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里边定义可复用的组件DefineLabelReuseLabel是采用的解构赋值都是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 里边定义可复用的组件DefineLabelReuseLabel 是采用的解构赋值都是 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
})
}

View File

@ -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.valuetrue
/** 复制成功的时候 copied.value 为 true */
watch(copied, (val) => {
if (val) {
message.success('复制成功')

View File

@ -1,4 +1,5 @@
<template>
<!-- TODO @hhhero整体没啥问题了感觉整体框框的样子可以优化下可以参考下绘图界面例如说1写作的预览和绘图的绘图任务 header2左右的边界有个竖线之类的 -->
<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
}
/** 点击重置的时候清空写作的结果**/