Skip to content

Commit 61bf6fb

Browse files
committed
【代码优化】AI:绘图 index.vue 代码梳理 60%(StableDiffusion.vue)
1 parent ac46a37 commit 61bf6fb

File tree

7 files changed

+523
-451
lines changed

7 files changed

+523
-451
lines changed

src/api/ai/image/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ export interface ImageVO {
1212
publicStatus: boolean // 公开状态
1313
picUrl: string // 任务地址
1414
errorMessage: string // 错误信息
15-
options: object // 配置 Map<string, string>
15+
options: any // 配置 Map<string, string>
1616
taskId: number // 任务编号
1717
buttons: ImageMidjourneyButtonsVO[] // mj 操作按钮
18-
createTime: string // 创建时间
19-
finishTime: string // 完成时间
18+
createTime: Date // 创建时间
19+
finishTime: Date // 完成时间
2020
}
2121

2222
export interface ImageDrawReqVO {

src/views/ai/image/index/components/ImageDetail.vue

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
<div class="item">
2121
<div class="tip">时间</div>
2222
<div class="body">
23-
<div>提交时间:{{ detail.createTime }}</div>
24-
<div>生成时间:{{ detail.finishTime }}</div>
23+
<div>提交时间:{{ formatTime(detail.createTime, 'yyyy-MM-dd HH:mm:ss') }}</div>
24+
<div>生成时间:{{ formatTime(detail.finishTime, 'yyyy-MM-dd HH:mm:ss') }}</div>
2525
</div>
2626
</div>
2727
<!-- 模型 -->
@@ -43,13 +43,73 @@
4343
{{ detail.picUrl }}
4444
</div>
4545
</div>
46-
<!-- 风格 -->
47-
<div class="item" v-if="detail?.options?.style">
46+
<!-- StableDiffusion 专属区域 -->
47+
<div
48+
class="item"
49+
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.sampler"
50+
>
51+
<div class="tip">采样方法</div>
52+
<div class="body">
53+
{{
54+
StableDiffusionSamplers.find(
55+
(item: ImageModelVO) => item.key === detail?.options?.sampler
56+
)?.name
57+
}}
58+
</div>
59+
</div>
60+
<div
61+
class="item"
62+
v-if="
63+
detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.clipGuidancePreset
64+
"
65+
>
66+
<div class="tip">CLIP</div>
67+
<div class="body">
68+
{{
69+
StableDiffusionClipGuidancePresets.find(
70+
(item: ImageModelVO) => item.key === detail?.options?.clipGuidancePreset
71+
)?.name
72+
}}
73+
</div>
74+
</div>
75+
<div
76+
class="item"
77+
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.stylePreset"
78+
>
4879
<div class="tip">风格</div>
4980
<div class="body">
50-
<!-- TODO @fan:貌似需要把 imageStyleList 搞到 api/image/index.ts 枚举起来? -->
51-
<!-- TODO @fan:这里的展示,可能需要按照平台做区分 -->
52-
{{ detail?.options?.style }}
81+
{{
82+
StableDiffusionStylePresets.find(
83+
(item: ImageModelVO) => item.key === detail?.options?.stylePreset
84+
)?.name
85+
}}
86+
</div>
87+
</div>
88+
<div
89+
class="item"
90+
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.steps"
91+
>
92+
<div class="tip">迭代步数</div>
93+
<div class="body">
94+
{{ detail?.options?.steps }}
95+
</div>
96+
</div>
97+
<div
98+
class="item"
99+
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.scale"
100+
>
101+
<div class="tip">引导系数</div>
102+
<div class="body">
103+
{{ detail?.options?.scale }}
104+
</div>
105+
</div>
106+
<div
107+
class="item"
108+
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.seed"
109+
>
110+
<div class="tip">随机因子</div>
111+
<div class="body">
112+
{{ detail?.options?.seed }}
53113
</div>
54114
</div>
55115
</el-drawer>
@@ -58,6 +118,14 @@
58118
<script setup lang="ts">
59119
import { ImageApi, ImageVO } from '@/api/ai/image'
60120
import ImageCard from './ImageCard.vue'
121+
import {
122+
AiPlatformEnum,
123+
ImageModelVO,
124+
StableDiffusionClipGuidancePresets,
125+
StableDiffusionSamplers,
126+
StableDiffusionStylePresets
127+
} from '@/views/ai/utils/constants'
128+
import { formatTime } from '@/utils'
61129
62130
const showDrawer = ref<boolean>(false) // 是否显示
63131
const detail = ref<ImageVO>({} as ImageVO) // 图片详细信息
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
<!-- dall3 -->
2+
<template>
3+
<div class="prompt">
4+
<el-text tag="b">画面描述</el-text>
5+
<el-text tag="p">建议使用“形容词+动词+风格”的格式,使用“,”隔开</el-text>
6+
<el-input
7+
v-model="prompt"
8+
maxlength="1024"
9+
rows="5"
10+
class="w-100% mt-15px"
11+
input-style="border-radius: 7px;"
12+
placeholder="例如:童话里的小屋应该是什么样子?"
13+
show-word-limit
14+
type="textarea"
15+
/>
16+
</div>
17+
<div class="hot-words">
18+
<div>
19+
<el-text tag="b">随机热词</el-text>
20+
</div>
21+
<el-space wrap class="word-list">
22+
<el-button
23+
round
24+
class="btn"
25+
:type="selectHotWord === hotWord ? 'primary' : 'default'"
26+
v-for="hotWord in ImageHotEnglishWords"
27+
:key="hotWord"
28+
@click="handleHotWordClick(hotWord)"
29+
>
30+
{{ hotWord }}
31+
</el-button>
32+
</el-space>
33+
</div>
34+
<div class="group-item">
35+
<div>
36+
<el-text tag="b">采样方法</el-text>
37+
</div>
38+
<el-space wrap class="group-item-body">
39+
<el-select v-model="sampler" placeholder="Select" size="large" class="!w-350px">
40+
<el-option
41+
v-for="item in StableDiffusionSamplers"
42+
:key="item.key"
43+
:label="item.name"
44+
:value="item.key"
45+
/>
46+
</el-select>
47+
</el-space>
48+
</div>
49+
<div class="group-item">
50+
<div>
51+
<el-text tag="b">CLIP</el-text>
52+
</div>
53+
<el-space wrap class="group-item-body">
54+
<el-select v-model="clipGuidancePreset" placeholder="Select" size="large" class="!w-350px">
55+
<el-option
56+
v-for="item in StableDiffusionClipGuidancePresets"
57+
:key="item.key"
58+
:label="item.name"
59+
:value="item.key"
60+
/>
61+
</el-select>
62+
</el-space>
63+
</div>
64+
<div class="group-item">
65+
<div>
66+
<el-text tag="b">风格</el-text>
67+
</div>
68+
<el-space wrap class="group-item-body">
69+
<el-select v-model="stylePreset" placeholder="Select" size="large" class="!w-350px">
70+
<el-option
71+
v-for="item in StableDiffusionStylePresets"
72+
:key="item.key"
73+
:label="item.name"
74+
:value="item.key"
75+
/>
76+
</el-select>
77+
</el-space>
78+
</div>
79+
<div class="group-item">
80+
<div>
81+
<el-text tag="b">图片尺寸</el-text>
82+
</div>
83+
<el-space wrap class="group-item-body">
84+
<el-input v-model="width" class="w-170px" placeholder="图片宽度" />
85+
<el-input v-model="height" class="w-170px" placeholder="图片高度" />
86+
</el-space>
87+
</div>
88+
<div class="group-item">
89+
<div>
90+
<el-text tag="b">迭代步数</el-text>
91+
</div>
92+
<el-space wrap class="group-item-body">
93+
<el-input
94+
v-model="steps"
95+
type="number"
96+
size="large"
97+
class="!w-350px"
98+
placeholder="Please input"
99+
/>
100+
</el-space>
101+
</div>
102+
<div class="group-item">
103+
<div>
104+
<el-text tag="b">引导系数</el-text>
105+
</div>
106+
<el-space wrap class="group-item-body">
107+
<el-input
108+
v-model="scale"
109+
type="number"
110+
size="large"
111+
class="!w-350px"
112+
placeholder="Please input"
113+
/>
114+
</el-space>
115+
</div>
116+
<div class="group-item">
117+
<div>
118+
<el-text tag="b">随机因子</el-text>
119+
</div>
120+
<el-space wrap class="group-item-body">
121+
<el-input
122+
v-model="seed"
123+
type="number"
124+
size="large"
125+
class="!w-350px"
126+
placeholder="Please input"
127+
/>
128+
</el-space>
129+
</div>
130+
<div class="btns">
131+
<el-button type="primary" size="large" round :loading="drawIn" @click="handleGenerateImage">
132+
{{ drawIn ? '生成中' : '生成内容' }}
133+
</el-button>
134+
</div>
135+
</template>
136+
<script setup lang="ts">
137+
import { ImageApi, ImageDrawReqVO, ImageVO } from '@/api/ai/image'
138+
import { hasChinese } from '@/views/ai/utils/utils'
139+
import {
140+
ImageHotEnglishWords,
141+
StableDiffusionClipGuidancePresets,
142+
StableDiffusionSamplers,
143+
StableDiffusionStylePresets
144+
} from '@/views/ai/utils/constants'
145+
146+
const message = useMessage() // 消息弹窗
147+
148+
// 定义属性
149+
const drawIn = ref<boolean>(false) // 生成中
150+
const selectHotWord = ref<string>('') // 选中的热词
151+
// 表单
152+
const prompt = ref<string>('') // 提示词
153+
const width = ref<number>(512) // 图片宽度
154+
const height = ref<number>(512) // 图片高度
155+
const sampler = ref<string>('DDIM') // 采样方法
156+
const steps = ref<number>(20) // 迭代步数
157+
const seed = ref<number>(42) // 控制生成图像的随机性
158+
const scale = ref<number>(7.5) // 引导系数
159+
const clipGuidancePreset = ref<string>('NONE') // 文本提示相匹配的图像(clip_guidance_preset) 简称 CLIP
160+
const stylePreset = ref<string>('3d-model') // 风格
161+
162+
const emits = defineEmits(['onDrawStart', 'onDrawComplete']) // 定义 emits
163+
164+
/** 选择热词 */
165+
const handleHotWordClick = async (hotWord: string) => {
166+
// 情况一:取消选中
167+
if (selectHotWord.value == hotWord) {
168+
selectHotWord.value = ''
169+
return
170+
}
171+
172+
// 情况二:选中
173+
selectHotWord.value = hotWord // 选中
174+
prompt.value = hotWord // 替换提示词
175+
}
176+
177+
/** 图片生成 */
178+
const handleGenerateImage = async () => {
179+
// 二次确认
180+
if (hasChinese(prompt.value)) {
181+
message.alert('暂不支持中文!')
182+
return
183+
}
184+
await message.confirm(`确认生成内容?`)
185+
186+
try {
187+
// 加载中
188+
drawIn.value = true
189+
// 回调
190+
emits('onDrawStart', 'StableDiffusion')
191+
// 发送请求
192+
const form = {
193+
platform: 'StableDiffusion',
194+
model: 'stable-diffusion-v1-6',
195+
prompt: prompt.value, // 提示词
196+
width: width.value, // 图片宽度
197+
height: height.value, // 图片高度
198+
options: {
199+
seed: seed.value, // 随机种子
200+
steps: steps.value, // 图片生成步数
201+
scale: scale.value, // 引导系数
202+
sampler: sampler.value, // 采样算法
203+
clipGuidancePreset: clipGuidancePreset.value, // 文本提示相匹配的图像 CLIP
204+
stylePreset: stylePreset.value // 风格
205+
}
206+
} as ImageDrawReqVO
207+
await ImageApi.drawImage(form)
208+
} finally {
209+
// 回调
210+
emits('onDrawComplete', 'StableDiffusion')
211+
// 加载结束
212+
drawIn.value = false
213+
}
214+
}
215+
216+
/** 填充值 */
217+
const settingValues = async (detail: ImageVO) => {
218+
prompt.value = detail.prompt
219+
width.value = detail.width
220+
height.value = detail.height
221+
seed.value = detail.options?.seed
222+
steps.value = detail.options?.steps
223+
scale.value = detail.options?.scale
224+
sampler.value = detail.options?.sampler
225+
clipGuidancePreset.value = detail.options?.clipGuidancePreset
226+
stylePreset.value = detail.options?.stylePreset
227+
}
228+
229+
/** 暴露组件方法 */
230+
defineExpose({ settingValues })
231+
</script>
232+
<style scoped lang="scss">
233+
// 提示词
234+
.prompt {
235+
}
236+
237+
// 热词
238+
.hot-words {
239+
display: flex;
240+
flex-direction: column;
241+
margin-top: 30px;
242+
243+
.word-list {
244+
display: flex;
245+
flex-direction: row;
246+
flex-wrap: wrap;
247+
justify-content: start;
248+
margin-top: 15px;
249+
250+
.btn {
251+
margin: 0;
252+
}
253+
}
254+
}
255+
256+
// 模型
257+
.group-item {
258+
margin-top: 30px;
259+
260+
.group-item-body {
261+
margin-top: 15px;
262+
width: 100%;
263+
}
264+
}
265+
266+
.btns {
267+
display: flex;
268+
justify-content: center;
269+
margin-top: 50px;
270+
}
271+
</style>

0 commit comments

Comments
 (0)