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
Commit
3c4327e4
authored
Jun 01, 2024
by
YunaiV
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【代码评审】AI:绘制功能的测试和 review
parent
1eacbe62
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
67 additions
and
45 deletions
+67
-45
src/api/ai/image/index.ts
+10
-6
src/views/ai/image/ImageDetailDrawer.vue
+14
-11
src/views/ai/image/ImageTask.vue
+4
-3
src/views/ai/image/ImageTaskCard.vue
+9
-6
src/views/ai/image/dall3/index.vue
+28
-19
src/views/ai/image/index.vue
+2
-0
No files found.
src/api/ai/image/index.ts
View file @
3c4327e4
import
request
from
'@/config/axios'
// AI API 密钥 VO
// TODO @fan:要不前端不弄太多 VO,就用这个 ImageDetailVO?!
export
interface
ImageDetailVO
{
id
:
number
// 编号
prompt
:
string
// 提示词
status
:
string
// 状态
status
:
number
// 状态
errorMessage
:
string
// 错误信息
type
:
string
// 模型下分不同的类型(清晰、真实...)
taskId
:
number
// dr 任务id
...
...
@@ -31,11 +32,14 @@ export interface ImageDallReqVO {
height
:
string
// 图片高度
}
export
interface
ImageDallReqVO
{
export
interface
ImageDrawReqVO
{
platform
:
string
// 平台
prompt
:
string
// 提示词
model
:
string
// 模型
style
:
string
// 图像生成的风格
size
:
string
// size不能为空
width
:
string
// 图片宽度
height
:
string
// 图片高度
options
:
object
// 绘制参数,Map<String, String>
}
export
interface
ImageMidjourneyImagineReqVO
{
...
...
@@ -57,9 +61,9 @@ export const ImageApi = {
getImageDetail
:
async
(
id
:
number
)
=>
{
return
await
request
.
get
({
url
:
`/ai/image/get-my?id=
${
id
}
`
})
},
//
dall2、dall3 调用
d
all
:
async
(
data
:
ImageDall
ReqVO
)
=>
{
return
await
request
.
post
({
url
:
`/ai/image/d
all
`
,
data
})
//
生成图片
d
rawImage
:
async
(
data
:
ImageDraw
ReqVO
)
=>
{
return
await
request
.
post
({
url
:
`/ai/image/d
raw
`
,
data
})
},
// midjourney - imagine
midjourneyImagine
:
async
(
data
:
ImageMidjourneyImagineReqVO
)
=>
{
...
...
src/views/ai/image/ImageDetailDrawer.vue
View file @
3c4327e4
...
...
@@ -5,7 +5,7 @@
@
close=
"handlerDrawerClose"
custom-class=
"drawer-class"
>
<!--
图片
-->
<!--
图片
-->
<div
class=
"item"
>
<!--
<div
class=
"header"
>
-->
<!--
<div>
图片
</div>
-->
...
...
@@ -13,6 +13,7 @@
<!--
</div>
-->
<!--
</div>
-->
<div
class=
"body"
>
<!-- TODO @fan: 要不,这里只展示图片???不用 ImageTaskCard -->
<ImageTaskCard
:image-detail=
"imageDetail"
/>
</div>
</div>
...
...
@@ -21,6 +22,7 @@
<div
class=
"tip"
>
时间
</div>
<div
class=
"body"
>
<div>
提交时间:
{{
imageDetail
.
createTime
}}
</div>
<!-- TODO @fan:要不加个完成时间的字段 finishTime?updateTime 不算特别合理哈 -->
<div>
生成时间:
{{
imageDetail
.
updateTime
}}
</div>
</div>
</div>
...
...
@@ -38,34 +40,35 @@
{{
imageDetail
.
prompt
}}
</div>
</div>
<!-- 风格 -->
<div
class=
"item"
>
<div
class=
"tip"
>
风格
</div>
<div
class=
"body"
>
{{
imageDetail
.
style
}}
</div>
</div>
<!-- 地址 -->
<div
class=
"item"
>
<div
class=
"tip"
>
地址
</div>
<div
class=
"tip"
>
图片
地址
</div>
<div
class=
"body"
>
{{
imageDetail
.
picUrl
}}
</div>
</div>
<!-- 生成地址 -->
<!-- 生成地址
TODO @fan:这个字段我删除了,要不干掉?
-->
<div
class=
"item"
>
<div
class=
"tip"
>
生成地址
</div>
<div
class=
"body"
>
{{
imageDetail
.
originalPicUrl
}}
</div>
</div>
<!-- 风格 -->
<div
class=
"item"
>
<div
class=
"tip"
>
风格
</div>
<div
class=
"body"
>
<!-- TODO @fan:貌似需要把 imageStyleList 搞到 api/image/index.ts 枚举起来? -->
<!-- TODO @fan:这里的展示,可能需要按照平台做区分 -->
{{
imageDetail
.
options
.
style
}}
</div>
</div>
</el-drawer>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
ImageApi
,
ImageDetailVO
}
from
'@/api/ai/image'
;
import
ImageTaskCard
from
'./ImageTaskCard.vue'
;
import
{
Delete
,
Download
,
More
}
from
"@element-plus/icons-vue"
;
const
showDrawer
=
ref
<
boolean
>
(
false
)
// 是否显示
const
imageDetail
=
ref
<
ImageDetailVO
>
({}
as
ImageDetailVO
)
// 图片详细信息
...
...
src/views/ai/image/ImageTask.vue
View file @
3c4327e4
<
template
>
<el-card
class=
"dr-task"
body-class=
"task-card"
shadow=
"never"
>
<template
#
header
>
绘画任务
</
template
>
...
...
@@ -19,15 +18,16 @@
import
{
ImageApi
,
ImageDetailVO
}
from
'@/api/ai/image'
;
import
ImageDetailDrawer
from
'./ImageDetailDrawer.vue'
import
ImageTaskCard
from
'./ImageTaskCard.vue'
import
{
bool
}
from
"vue-types"
;
const
message
=
useMessage
()
// 消息弹窗
const
imageList
=
ref
<
ImageDetailVO
[]
>
([])
// image 列表
const
imageListInterval
=
ref
<
any
>
()
// image 列表定时器,刷新列表
const
isShowImageDetail
=
ref
<
bool
>
(
false
)
// 是否显示 task 详情
const
isShowImageDetail
=
ref
<
bool
ean
>
(
false
)
// 是否显示 task 详情
const
showImageDetailId
=
ref
<
number
>
(
0
)
// 是否显示 task 详情
// TODO @fan:如果是简单注释,建议用 /** */,主要是现在项目里是这种风格哈,保持一致好点~
/**
* 抽屉 - close
*/
...
...
@@ -72,6 +72,7 @@ const handlerImageBtnClick = async (type, imageDetail: ImageDetailVO) => {
/**
* 下载 - image
*/
// TODO @fan:貌似可以考虑抽到 download 里面,作为一个方法
const
downloadImage
=
async
(
imageUrl
)
=>
{
const
image
=
new
Image
()
image
.
setAttribute
(
'crossOrigin'
,
'anonymous'
)
...
...
src/views/ai/image/ImageTaskCard.vue
View file @
3c4327e4
...
...
@@ -2,10 +2,11 @@
<el-card
body-class=
""
class=
"image-card"
>
<div
class=
"image-operation"
>
<div>
<el-button
type=
"
"
text
bg
v-if=
"imageDetail.status === '10'
"
>
生成中
</el-button>
<el-button
t
ype=
""
text
bg
v-else-if=
"imageDetail.status === '20'
"
>
已完成
</el-button>
<el-button
type=
"danger"
text
bg
v-else-if=
"imageDetail
.status === '30'
"
>
异常
</el-button>
<el-button
type=
"
primary"
text
bg
v-if=
"imageDetail?.status === 10
"
>
生成中
</el-button>
<el-button
t
ext
bg
v-else-if=
"imageDetail?.status === 20
"
>
已完成
</el-button>
<el-button
type=
"danger"
text
bg
v-else-if=
"imageDetail
?.status === 30
"
>
异常
</el-button>
</div>
<!-- TODO @fan:1)按钮要不调整成详情、下载、再次生成、删除?;2)如果是再次生成,就把当前的参数填写到左侧的框框里? -->
<div>
<el-button
class=
"btn"
text
:icon=
"Download"
@
click=
"handlerBtnClick('download', imageDetail)"
/>
...
...
@@ -14,8 +15,9 @@
</div>
</div>
<div
class=
"image-wrapper"
ref=
"cardImageRef"
>
<!-- TODO @fan:要不加个点击,大图预览? -->
<img
class=
"image"
:src=
"imageDetail?.picUrl"
/>
<div
v-if=
"imageDetail
.status === '30'"
>
{{
imageDetail
.
errorMessage
}}
</div>
<div
v-if=
"imageDetail
?.status === 30"
>
{{
imageDetail
?
.
errorMessage
}}
</div>
</div>
</el-card>
</
template
>
...
...
@@ -42,8 +44,9 @@ const handlerBtnClick = async (type, imageDetail: ImageDetailVO) => {
emits
(
'onBtnClick'
,
type
,
imageDetail
)
}
const
handlerLoading
=
async
(
status
:
string
)
=>
{
if
(
status
===
'10'
)
{
const
handlerLoading
=
async
(
status
:
number
)
=>
{
// TODO @fan:这个搞成 Loading 组件,然后通过数据驱动,这样搞可以哇?
if
(
status
===
10
)
{
cardImageLoadingInstance
.
value
=
ElLoading
.
service
({
target
:
cardImageRef
.
value
,
text
:
'生成中...'
...
...
src/views/ai/image/dall3/index.vue
View file @
3c4327e4
...
...
@@ -2,7 +2,8 @@
<
template
>
<div
class=
"prompt"
>
<el-text
tag=
"b"
>
画面描述
</el-text>
<el-text
tag=
"p"
>
建议使用“形容词+动词+风格”的格式,使用“,”隔开.
</el-text>
<el-text
tag=
"p"
>
建议使用“形容词+动词+风格”的格式,使用“,”隔开
</el-text>
<!-- TODO @fan:style 看看能不能哟 unocss 替代 -->
<el-input
v-model=
"prompt"
maxlength=
"1024"
...
...
@@ -32,7 +33,7 @@
</div>
<div
class=
"model"
>
<div>
<el-text
tag=
"b"
>
模型
</el-text>
<el-text
tag=
"b"
>
模型
选择
</el-text>
</div>
<el-space
wrap
class=
"model-list"
>
<div
...
...
@@ -52,14 +53,13 @@
</div>
<div
class=
"image-style"
>
<div>
<el-text
tag=
"b"
>
样式
</el-text>
<el-text
tag=
"b"
>
风格选择
</el-text>
</div>
<el-space
wrap
class=
"image-style-list"
>
<div
:class=
"selectImageStyle === imageStyle ? 'image-style-item selectImageStyle' : 'image-style-item'"
v-for=
"imageStyle in imageStyleList"
:key=
"imageStyle"
:key=
"imageStyle.key"
>
<el-image
:src=
"imageStyle.image"
...
...
@@ -72,7 +72,7 @@
</div>
<div
class=
"image-size"
>
<div>
<el-text
tag=
"b"
>
尺寸
</el-text>
<el-text
tag=
"b"
>
画面比例
</el-text>
</div>
<el-space
wrap
class=
"size-list"
>
<div
class=
"size-item"
...
...
@@ -97,7 +97,7 @@
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
ImageApi
,
ImageD
all
ReqVO
}
from
'@/api/ai/image'
;
import
{
ImageApi
,
ImageD
raw
ReqVO
}
from
'@/api/ai/image'
;
// image 模型
interface
ImageModelVO
{
...
...
@@ -109,6 +109,7 @@ interface ImageModelVO {
// image 大小
interface
ImageSizeVO
{
key
:
string
name
:
string
,
style
:
string
,
width
:
string
,
height
:
string
,
...
...
@@ -120,21 +121,24 @@ const drawIn = ref<boolean>(false) // 生成中
const
selectHotWord
=
ref
<
string
>
(
''
)
// 选中的热词
const
hotWords
=
ref
<
string
[]
>
([
'中国旗袍'
,
'古装美女'
,
'卡通头像'
,
'机甲战士'
,
'童话小屋'
,
'中国长城'
])
// 热词
const
selectModel
=
ref
<
any
>
({})
// 模型
// TODO @fan:image 改成项目里自己的哈
// TODO @fan:这个 image,要不看看网上有没合适的图片,作为占位符,啊哈哈
const
models
=
ref
<
ImageModelVO
[]
>
([
{
key
:
'dall-e-2'
,
name
:
'dall2'
,
image
:
'https://h5.cxyhub.com/images/model_1.png'
,
},
{
key
:
'dall-e-3'
,
name
:
'
dall
3'
,
name
:
'
DALL·E
3'
,
image
:
'https://h5.cxyhub.com/images/model_2.png'
,
},
{
key
:
'dall-e-2'
,
name
:
'DALL·E 2'
,
image
:
'https://h5.cxyhub.com/images/model_1.png'
,
},
])
// 模型
selectModel
.
value
=
models
.
value
[
0
]
const
selectImageStyle
=
ref
<
any
>
({})
// style 样式
// TODO @fan:image 改成项目里自己的哈
const
imageStyleList
=
ref
<
ImageModelVO
[]
>
([
{
key
:
'vivid'
,
...
...
@@ -180,11 +184,13 @@ const props = defineProps({})
// 定义 emits
const
emits
=
defineEmits
([
'onDrawStart'
,
'onDrawComplete'
])
// TODO @fan:如果是简单注释,建议用 /** */,主要是现在项目里是这种风格哈,保持一致好点~
// TODO @fan:handler 应该改成 handle 哈
/**
* 热词 - click
*/
const
handlerHotWordClick
=
async
(
hotWord
:
string
)
=>
{
// 取消
// 取消
选中
if
(
selectHotWord
.
value
==
hotWord
)
{
selectHotWord
.
value
=
''
return
...
...
@@ -238,14 +244,17 @@ const handlerGenerateImage = async () => {
// 回调
emits
(
'onDrawStart'
,
selectModel
.
value
.
key
)
const
form
=
{
platform
:
'OpenAI'
,
prompt
:
prompt
.
value
,
// 提示词
model
:
selectModel
.
value
.
key
,
// 模型
style
:
selectImageStyle
.
value
.
key
,
// 图像生成的风格
width
:
selectImageSize
.
value
.
width
,
// size不能为空
height
:
selectImageSize
.
value
.
height
,
// size不能为空
}
as
ImageDallReqVO
width
:
selectImageSize
.
value
.
width
,
// size 不能为空
height
:
selectImageSize
.
value
.
height
,
// size 不能为空
options
:
{
style
:
selectImageStyle
.
value
.
key
,
// 图像生成的风格
}
}
as
ImageDrawReqVO
// 发送请求
await
ImageApi
.
d
all
(
form
)
await
ImageApi
.
d
rawImage
(
form
)
}
finally
{
// 回调
emits
(
'onDrawComplete'
,
selectModel
.
value
.
key
)
...
...
src/views/ai/image/index.vue
View file @
3c4327e4
...
...
@@ -6,6 +6,7 @@
<el-segmented
v-model=
"selectModel"
:options=
"modelOptions"
/>
</div>
<div
class=
"modal-switch-container"
>
<!-- TODO @fan:1)建议 Dall3 改成 OpenAI 绘图。因为 dall3 其实本质是模型;2)涉及到中英文的地方,中文和英文之间,有个空格哈 -->
<Dall3
v-if=
"selectModel === 'DALL3绘画'"
@
on-draw-start=
"handlerDrawStart"
@
on-draw-complete=
"handlerDrawComplete"
/>
...
...
@@ -19,6 +20,7 @@
</
template
>
<
script
setup
lang=
"ts"
>
// TODO @fan:在整个挪到 /views/ai/image/index 目录。因为我想在 /views/ai/image/manager 做管理的功能,进行下区分!
import
Dall3
from
'./dall3/index.vue'
import
Midjourney
from
'./midjourney/index.vue'
import
ImageTask
from
'./ImageTask.vue'
...
...
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