Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
35b2708c
authored
Jul 16, 2024
by
芋道源码
Committed by
Gitee
Jul 16, 2024
Browse files
Options
Browse Files
Download
Plain Diff
!482 [代码优化]AI: 写作页面样式调整,目录更名writer => write,写作管理更改
Merge pull request !482 from hhhero/dev
parents
69940e27
c4ee9581
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
153 additions
and
80 deletions
+153
-80
src/api/ai/write/index.ts
+57
-37
src/views/ai/utils/constants.ts
+6
-0
src/views/ai/write/index/components/Left.vue
+29
-19
src/views/ai/write/index/components/Right.vue
+28
-13
src/views/ai/write/index/components/Tag.vue
+0
-0
src/views/ai/write/index/index.vue
+3
-4
src/views/ai/write/manager/index.vue
+25
-7
types/global.d.ts
+5
-0
No files found.
src/api/ai/write
r
/index.ts
→
src/api/ai/write/index.ts
View file @
35b2708c
import
{
fetchEventSource
}
from
'@microsoft/fetch-event-source'
import
request
from
'@/config/axios'
import
{
getAccessToken
}
from
'@/utils/auth'
import
{
config
}
from
'@/config/axios/config'
import
{
AiWriteTypeEnum
}
from
'@/views/ai/utils/constants'
import
request
from
'@/config/axios'
export
interface
WriteVO
{
type
:
AiWriteTypeEnum
.
WRITING
|
AiWriteTypeEnum
.
REPLY
// 1:撰写 2:回复
...
...
@@ -21,45 +21,65 @@ export interface WriteVO {
createTime
?:
Date
// 创建时间
}
// TODO @hhero:搞成 WriteApi,类似 ConversationApi 一样。这样更有类的概念,后续引入某个 Api,然后调用它的方法就可以了。
export
const
writeStream
=
({
data
,
onClose
,
onMessage
,
onError
,
ctrl
}:
{
data
:
WriteVO
onMessage
?:
(
res
:
any
)
=>
void
onError
?:
(...
args
:
any
[])
=>
void
onClose
?:
(...
args
:
any
[])
=>
void
ctrl
:
AbortController
})
=>
{
const
token
=
getAccessToken
()
return
fetchEventSource
(
`
${
config
.
base_url
}
/ai/write/generate-stream`
,
{
method
:
'post'
,
headers
:
{
'Content-Type'
:
'application/json'
,
Authorization
:
`Bearer
${
token
}
`
},
openWhenHidden
:
true
,
body
:
JSON
.
stringify
(
data
),
onmessage
:
onMessage
,
onerror
:
onError
,
onclose
:
onClose
,
signal
:
ctrl
.
signal
})
export
interface
AiWritePageReqVO
extends
PageParam
{
userId
?:
number
// 用户编号
type
?:
AiWriteTypeEnum
// 写作类型
platform
?:
string
// 平台
createTime
?:
[
string
,
string
]
// 创建时间
}
export
interface
AiWriteRespVo
{
id
:
number
userId
:
number
type
:
number
platform
:
string
model
:
string
prompt
:
string
generatedContent
:
string
originalContent
:
string
length
:
number
format
:
number
tone
:
number
language
:
number
errorMessage
:
string
createTime
:
string
}
// AI 写作 API
export
const
WriteApi
=
{
// 查询AI 写作分页
getWritePage
:
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
`/ai/write/page`
,
params
})
writeStream
:
({
data
,
onClose
,
onMessage
,
onError
,
ctrl
}:
{
data
:
WriteVO
onMessage
?:
(
res
:
any
)
=>
void
onError
?:
(...
args
:
any
[])
=>
void
onClose
?:
(...
args
:
any
[])
=>
void
ctrl
:
AbortController
})
=>
{
const
token
=
getAccessToken
()
return
fetchEventSource
(
`
${
config
.
base_url
}
/ai/write/generate-stream`
,
{
method
:
'post'
,
headers
:
{
'Content-Type'
:
'application/json'
,
Authorization
:
`Bearer
${
token
}
`
},
openWhenHidden
:
true
,
body
:
JSON
.
stringify
(
data
),
onmessage
:
onMessage
,
onerror
:
onError
,
onclose
:
onClose
,
signal
:
ctrl
.
signal
})
},
// 删除AI 写作
deleteWrite
:
async
(
id
:
number
)
=>
{
return
await
request
.
delete
({
url
:
`/ai/write/delete?id=`
+
id
})
// 获取写作列表
getWritePage
:
(
params
:
AiWritePageReqVO
)
=>
{
return
request
.
get
<
PageResult
<
AiWriteRespVo
[]
>>
({
url
:
`/ai/write/page`
,
params
})
},
// 删除写作
deleteWrite
(
id
:
number
)
{
return
request
.
delete
({
url
:
`/ai/write/delete`
,
params
:
{
id
}
})
}
}
src/views/ai/utils/constants.ts
View file @
35b2708c
...
...
@@ -64,6 +64,12 @@ export enum AiWriteTypeEnum {
REPLY
// 回复
}
// 表格展示对照map
export
const
AiWriteTypeTableRender
=
{
[
AiWriteTypeEnum
.
WRITING
]:
'撰写'
,
[
AiWriteTypeEnum
.
REPLY
]:
'回复'
,
}
// ========== 【图片 UI】相关的枚举 ==========
export
const
ImageHotWords
=
[
'中国旗袍'
,
...
...
src/views/ai/write
r
/index/components/Left.vue
→
src/views/ai/write/index/components/Left.vue
View file @
35b2708c
...
...
@@ -24,26 +24,28 @@
</h3>
</DefineLabel>
<div
class=
"
relative
"
v-bind=
"$attrs"
>
<div
class=
"
flex flex-col
"
v-bind=
"$attrs"
>
<!-- tab -->
<div
class=
"absolute left-1/2 top-2 -translate-x-1/2 w-[303px] rounded-full bg-[#DDDFE3] p-1 z-10"
>
<div
class=
"flex items-center relative after:content-[''] after:block after:bg-white after:h-[30px] after:w-1/2 after:absolute after:top-0 after:left-0 after:transition-transform after:rounded-full"
:class=
"selectedTab === AiWriteTypeEnum.REPLY && 'after:transform after:translate-x-[100%]'"
>
<ReuseTab
v-for=
"tab in tabs"
:key=
"tab.value"
:text=
"tab.text"
:active=
"tab.value === selectedTab"
:itemClick=
"() => switchTab(tab.value)"
/>
<div
class=
"w-full pt-2 bg-[#f5f7f9] flex justify-center"
>
<div
class=
"w-[303px] rounded-full bg-[#DDDFE3] p-1 z-10"
>
<div
class=
"flex items-center relative after:content-[''] after:block after:bg-white after:h-[30px] after:w-1/2 after:absolute after:top-0 after:left-0 after:transition-transform after:rounded-full"
:class=
"
selectedTab === AiWriteTypeEnum.REPLY && 'after:transform after:translate-x-[100%]'
"
>
<ReuseTab
v-for=
"tab in tabs"
:key=
"tab.value"
:text=
"tab.text"
:active=
"tab.value === selectedTab"
:itemClick=
"() => switchTab(tab.value)"
/>
</div>
</div>
</div>
<div
class=
"px-7 pb-2
pt-[46px] overflow-y-auto lg:block w-[380px] box-border bg-[#ECEDEF
] h-full"
class=
"px-7 pb-2
flex-grow overflow-y-auto lg:block w-[380px] box-border bg-[#f5f7f9
] h-full"
>
<div>
<template
v-if=
"selectedTab === 1"
>
...
...
@@ -102,7 +104,7 @@
import
{
createReusableTemplate
}
from
'@vueuse/core'
import
{
ref
}
from
'vue'
import
Tag
from
'./Tag.vue'
import
{
WriteVO
}
from
'
@/api/ai/writer
'
import
{
WriteVO
}
from
'
src/api/ai/write
'
import
{
omit
}
from
'lodash-es'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
AiWriteTypeEnum
,
WriteExample
}
from
'@/views/ai/utils/constants'
...
...
@@ -177,10 +179,18 @@ const initData: WriteVO = {
}
const
formData
=
ref
<
WriteVO
>
({
...
initData
})
/** 用来记录切换之前所填写的数据,切换的时候给赋值回来 **/
const
recordFormData
=
{}
as
Record
<
AiWriteTypeEnum
,
WriteVO
>
/** 切换tab **/
const
switchTab
=
(
value
:
TabType
)
=>
{
selectedTab
.
value
=
value
formData
.
value
=
{
...
initData
}
if
(
value
!==
selectedTab
.
value
)
{
// 保存之前的久数据
recordFormData
[
selectedTab
.
value
]
=
formData
.
value
selectedTab
.
value
=
value
// 将之前的旧数据赋值回来
formData
.
value
=
{
...
initData
,
...
recordFormData
[
value
]
}
}
}
/** 提交写作 */
...
...
src/views/ai/write
r
/index/components/Right.vue
→
src/views/ai/write/index/components/Right.vue
View file @
35b2708c
<
template
>
<div
class=
"h-full box-border flex flex-col px-7"
>
<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"
>
<template
#
icon
>
<Icon
icon=
"ph:copy-bold"
/>
</
template
>
复制
</el-button>
</h3>
<el-card
class=
"my-card h-full"
>
<template
#
header
><h3
class=
"m-0 px-7 shrink-0 flex items-center justify-between"
>
<span>
预览
</span>
<!-- 展示在右上角 -->
<el-button
color=
"#846af7"
v-show=
"showCopy"
@
click=
"copyContent"
size=
"small"
>
<template
#
icon
>
<Icon
icon=
"ph:copy-bold"
/>
</
template
>
复制
</el-button>
</h3></template
>
<div
ref=
"contentRef"
class=
"hide-scroll-bar
flex-grow
box-border overflow-y-auto"
>
<div
ref=
"contentRef"
class=
"hide-scroll-bar
h-full
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
...
...
@@ -36,7 +38,7 @@
/>
</div>
</div>
</
div
>
</
el-card
>
</template>
<
script
setup
lang=
"ts"
>
...
...
@@ -102,4 +104,17 @@ watch(copied, (val) => {
height
:
0
;
}
}
.my-card
{
display
:
flex
;
flex-direction
:
column
;
:deep(.el-card__body)
{
box-sizing
:
border-box
;
flex-grow
:
1
;
overflow-y
:
auto
;
padding
:
0
;
@extend
.hide-scroll-bar;
}
}
</
style
>
src/views/ai/write
r
/index/components/Tag.vue
→
src/views/ai/write/index/components/Tag.vue
View file @
35b2708c
File moved
src/views/ai/write
r
/index/index.vue
→
src/views/ai/write/index/index.vue
View file @
35b2708c
<
template
>
<!-- TODO @hhhero:整体没啥问题了。感觉整体框框的样子可以优化下,可以参考下绘图界面。例如说:1)写作的“预览”和绘图的“绘图任务”的 header;2)左右的边界,有个竖线之类的。 -->
<div
class=
"h-[calc(100vh-var(--top-tool-height)-var(--app-footer-height)-40px)] -m-5 flex"
>
<div
class=
"absolute top-0 left-0 right-0 bottom-0 flex"
>
<Left
:is-writing=
"isWriting"
class=
"h-full"
...
...
@@ -21,7 +20,7 @@
<
script
setup
lang=
"ts"
>
import
Left
from
'./components/Left.vue'
import
Right
from
'./components/Right.vue'
import
*
as
WriteApi
from
'@/api/ai/writer
'
import
{
WriteApi
}
from
'@/api/ai/write
'
import
{
WriteExample
}
from
'@/views/ai/utils/constants'
const
message
=
useMessage
()
...
...
@@ -66,7 +65,7 @@ const submit = (data) => {
}
/** 点击示例触发 */
const
handleExampleClick
=
(
type
:
keyof
typeof
WriteExample
DataJson
)
=>
{
const
handleExampleClick
=
(
type
:
keyof
typeof
WriteExample
)
=>
{
writeResult
.
value
=
WriteExample
[
type
].
data
}
...
...
src/views/ai/write/manager/index.vue
View file @
35b2708c
...
...
@@ -39,7 +39,7 @@
</el-select>
</el-form-item>
<el-form-item
label=
"平台"
prop=
"platform"
>
<el-select
v-model=
"queryParams.
status
"
placeholder=
"请选择平台"
clearable
class=
"!w-240px"
>
<el-select
v-model=
"queryParams.
platform
"
placeholder=
"请选择平台"
clearable
class=
"!w-240px"
>
<el-option
v-for=
"dict in getStrDictOptions(DICT_TYPE.AI_PLATFORM)"
:key=
"dict.value"
...
...
@@ -70,6 +70,7 @@
>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
新增
</el-button>
<!-- TODO @YunaiV 目前没有导出接口,需要导出吗 -->
<el-button
type=
"success"
plain
...
...
@@ -103,7 +104,13 @@
</
template
>
</el-table-column>
<el-table-column
label=
"模型"
align=
"center"
prop=
"model"
width=
"180"
/>
<el-table-column
label=
"生成内容提示"
align=
"center"
prop=
"prompt"
width=
"180"
/>
<el-table-column
label=
"生成内容提示"
align=
"center"
prop=
"prompt"
width=
"180"
show-overflow-tooltip
/>
<el-table-column
label=
"生成的内容"
align=
"center"
prop=
"generatedContent"
width=
"180"
/>
<el-table-column
label=
"原文"
align=
"center"
prop=
"originalContent"
width=
"180"
/>
<el-table-column
label=
"长度"
align=
"center"
prop=
"length"
>
...
...
@@ -136,6 +143,7 @@
<el-table-column
label=
"错误信息"
align=
"center"
prop=
"errorMessage"
/>
<el-table-column
label=
"操作"
align=
"center"
>
<
template
#
default=
"scope"
>
<!-- TODO @YunaiV 目前没有修改接口,写作要可以更改吗-->
<el-button
link
type=
"primary"
...
...
@@ -168,8 +176,8 @@
<
script
setup
lang=
"ts"
>
import
{
DICT_TYPE
,
getIntDictOptions
,
getStrDictOptions
}
from
'@/utils/dict'
import
{
dateFormatter
}
from
'@/utils/formatTime'
// TODO 芋艿:这里应该是 write
import
{
WriteApi
,
WriteVO
}
from
'@/api/ai/writer
'
import
{
useRouter
}
from
'vue-router'
import
{
WriteApi
,
AiWritePageReqVO
,
AiWriteRespVo
}
from
'@/api/ai/write
'
import
*
as
UserApi
from
'@/api/system/user'
/** AI 写作列表 */
...
...
@@ -177,17 +185,18 @@ defineOptions({ name: 'AiWriteManager' })
const
message
=
useMessage
()
// 消息弹窗
const
{
t
}
=
useI18n
()
// 国际化
const
router
=
useRouter
()
// 路由
const
loading
=
ref
(
true
)
// 列表的加载中
const
list
=
ref
<
WriteVO
[]
>
([])
// 列表的数据
const
list
=
ref
<
AiWriteRespVo
[]
>
([])
// 列表的数据
const
total
=
ref
(
0
)
// 列表的总页数
const
queryParams
=
reactive
({
const
queryParams
=
reactive
<
AiWritePageReqVO
>
({
pageNo
:
1
,
pageSize
:
10
,
userId
:
undefined
,
type
:
undefined
,
platform
:
undefined
,
createTime
:
[]
createTime
:
undefined
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
userList
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
...
...
@@ -216,6 +225,15 @@ const resetQuery = () => {
handleQuery
()
}
/** 新增方法,跳转到写作页面 **/
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
switch
(
type
)
{
case
'create'
:
router
.
push
(
'/ai/write'
)
break
}
}
/** 删除按钮操作 */
const
handleDelete
=
async
(
id
:
number
)
=>
{
try
{
...
...
types/global.d.ts
View file @
35b2708c
...
...
@@ -50,4 +50,9 @@ declare global {
name
:
string
children
?:
Tree
[]
|
any
[]
}
// 分页数据公共返回
interface
PageResult
<
T
>
{
list
:
T
// 数据
total
:
number
// 总量
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment