feat:【AI 大模型】image/index 下的部分页面,使用 unocss
This commit is contained in:
@ -5,139 +5,111 @@
|
||||
@close="handleDrawerClose"
|
||||
custom-class="drawer-class"
|
||||
>
|
||||
<!-- 图片 -->
|
||||
<div class="item">
|
||||
<div class="body">
|
||||
<el-image
|
||||
class="image"
|
||||
:src="detail?.picUrl"
|
||||
:preview-src-list="[detail.picUrl]"
|
||||
preview-teleported
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 时间 -->
|
||||
<div class="item">
|
||||
<div class="tip">时间</div>
|
||||
<div class="body">
|
||||
<div>提交时间:{{ formatTime(detail.createTime, 'yyyy-MM-dd HH:mm:ss') }}</div>
|
||||
<div>生成时间:{{ formatTime(detail.finishTime, 'yyyy-MM-dd HH:mm:ss') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 模型 -->
|
||||
<div class="item">
|
||||
<div class="tip">模型</div>
|
||||
<div class="body"> {{ detail.model }}({{ detail.height }}x{{ detail.width }}) </div>
|
||||
</div>
|
||||
<!-- 提示词 -->
|
||||
<div class="item">
|
||||
<div class="tip">提示词</div>
|
||||
<div class="body">
|
||||
{{ detail.prompt }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 地址 -->
|
||||
<div class="item">
|
||||
<div class="tip">图片地址</div>
|
||||
<div class="body">
|
||||
{{ detail.picUrl }}
|
||||
</div>
|
||||
<!-- 图片预览 -->
|
||||
<div class="mb-5">
|
||||
<el-image
|
||||
:src="detail?.picUrl"
|
||||
:preview-src-list="[detail.picUrl]"
|
||||
preview-teleported
|
||||
class="w-full rounded-2"
|
||||
fit="contain"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 基础信息 -->
|
||||
<el-descriptions title="基础信息" :column="1" :label-width="100" border>
|
||||
<el-descriptions-item label="提交时间">
|
||||
{{ formatTime(detail.createTime, 'yyyy-MM-dd HH:mm:ss') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="生成时间">
|
||||
{{ formatTime(detail.finishTime, 'yyyy-MM-dd HH:mm:ss') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="模型">
|
||||
{{ detail.model }}({{ detail.height }}x{{ detail.width }})
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="提示词">
|
||||
<div class="break-words">{{ detail.prompt }}</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="图片地址">
|
||||
<div class="break-all text-xs">{{ detail.picUrl }}</div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- StableDiffusion 专属区域 -->
|
||||
<div
|
||||
class="item"
|
||||
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.sampler"
|
||||
<el-descriptions
|
||||
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && hasStableDiffusionOptions"
|
||||
title="StableDiffusion 参数"
|
||||
:column="1"
|
||||
:label-width="100"
|
||||
border
|
||||
class="mt-5"
|
||||
>
|
||||
<div class="tip">采样方法</div>
|
||||
<div class="body">
|
||||
<el-descriptions-item v-if="detail?.options?.sampler" label="采样方法">
|
||||
{{
|
||||
StableDiffusionSamplers.find(
|
||||
(item: ImageModelVO) => item.key === detail?.options?.sampler
|
||||
)?.name
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
v-if="
|
||||
detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.clipGuidancePreset
|
||||
"
|
||||
>
|
||||
<div class="tip">CLIP</div>
|
||||
<div class="body">
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="detail?.options?.clipGuidancePreset" label="CLIP">
|
||||
{{
|
||||
StableDiffusionClipGuidancePresets.find(
|
||||
(item: ImageModelVO) => item.key === detail?.options?.clipGuidancePreset
|
||||
)?.name
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.stylePreset"
|
||||
>
|
||||
<div class="tip">风格</div>
|
||||
<div class="body">
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="detail?.options?.stylePreset" label="风格">
|
||||
{{
|
||||
StableDiffusionStylePresets.find(
|
||||
(item: ImageModelVO) => item.key === detail?.options?.stylePreset
|
||||
)?.name
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.steps"
|
||||
>
|
||||
<div class="tip">迭代步数</div>
|
||||
<div class="body">
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="detail?.options?.steps" label="迭代步数">
|
||||
{{ detail?.options?.steps }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.scale"
|
||||
>
|
||||
<div class="tip">引导系数</div>
|
||||
<div class="body">
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="detail?.options?.scale" label="引导系数">
|
||||
{{ detail?.options?.scale }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
v-if="detail.platform === AiPlatformEnum.STABLE_DIFFUSION && detail?.options?.seed"
|
||||
>
|
||||
<div class="tip">随机因子</div>
|
||||
<div class="body">
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="detail?.options?.seed" label="随机因子">
|
||||
{{ detail?.options?.seed }}
|
||||
</div>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- Dall3 专属区域 -->
|
||||
<div class="item" v-if="detail.platform === AiPlatformEnum.OPENAI && detail?.options?.style">
|
||||
<div class="tip">风格选择</div>
|
||||
<div class="body">
|
||||
<el-descriptions
|
||||
v-if="detail.platform === AiPlatformEnum.OPENAI && detail?.options?.style"
|
||||
title="DALL-E 3 参数"
|
||||
:column="1"
|
||||
:label-width="100"
|
||||
border
|
||||
class="mt-5"
|
||||
>
|
||||
<el-descriptions-item label="风格选择">
|
||||
{{ Dall3StyleList.find((item: ImageModelVO) => item.key === detail?.options?.style)?.name }}
|
||||
</div>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- Midjourney 专属区域 -->
|
||||
<div
|
||||
class="item"
|
||||
v-if="detail.platform === AiPlatformEnum.MIDJOURNEY && detail?.options?.version"
|
||||
<el-descriptions
|
||||
v-if="detail.platform === AiPlatformEnum.MIDJOURNEY && hasMidjourneyOptions"
|
||||
title="Midjourney 参数"
|
||||
:column="1"
|
||||
:label-width="100"
|
||||
border
|
||||
class="mt-5"
|
||||
>
|
||||
<div class="tip">模型版本</div>
|
||||
<div class="body">
|
||||
<el-descriptions-item v-if="detail?.options?.version" label="模型版本">
|
||||
{{ detail?.options?.version }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
v-if="detail.platform === AiPlatformEnum.MIDJOURNEY && detail?.options?.referImageUrl"
|
||||
>
|
||||
<div class="tip">参考图</div>
|
||||
<div class="body">
|
||||
<el-image :src="detail.options.referImageUrl" />
|
||||
</div>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="detail?.options?.referImageUrl" label="参考图">
|
||||
<el-image
|
||||
:src="detail.options.referImageUrl"
|
||||
class="max-w-[200px] rounded-2"
|
||||
fit="contain"
|
||||
/>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
@ -156,6 +128,25 @@ import { formatTime } from '@/utils'
|
||||
const showDrawer = ref<boolean>(false) // 是否显示
|
||||
const detail = ref<ImageVO>({} as ImageVO) // 图片详细信息
|
||||
|
||||
// 计算属性:判断是否有 StableDiffusion 选项
|
||||
const hasStableDiffusionOptions = computed(() => {
|
||||
const options = detail.value?.options
|
||||
return (
|
||||
options?.sampler ||
|
||||
options?.clipGuidancePreset ||
|
||||
options?.stylePreset ||
|
||||
options?.steps ||
|
||||
options?.scale ||
|
||||
options?.seed
|
||||
)
|
||||
})
|
||||
|
||||
// 计算属性:判断是否有 Midjourney 选项
|
||||
const hasMidjourneyOptions = computed(() => {
|
||||
const options = detail.value?.options
|
||||
return options?.version || options?.referImageUrl
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
type: Boolean,
|
||||
@ -175,7 +166,7 @@ const handleDrawerClose = async () => {
|
||||
|
||||
/** 监听 drawer 是否打开 */
|
||||
const { show } = toRefs(props)
|
||||
watch(show, async (newValue, oldValue) => {
|
||||
watch(show, async (newValue, _oldValue) => {
|
||||
showDrawer.value = newValue as boolean
|
||||
})
|
||||
|
||||
@ -186,7 +177,7 @@ const getImageDetail = async (id: number) => {
|
||||
|
||||
/** 监听 id 变化,加载最新图片详情 */
|
||||
const { id } = toRefs(props)
|
||||
watch(id, async (newVal, oldVal) => {
|
||||
watch(id, async (newVal, _oldVal) => {
|
||||
if (newVal) {
|
||||
await getImageDetail(newVal)
|
||||
}
|
||||
@ -194,31 +185,3 @@ watch(id, async (newVal, oldVal) => {
|
||||
|
||||
const emits = defineEmits(['handleDrawerClose'])
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.item {
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.body {
|
||||
margin-top: 10px;
|
||||
color: #616161;
|
||||
|
||||
.taskImage {
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,12 +1,19 @@
|
||||
<template>
|
||||
<el-card class="dr-task" body-class="task-card" shadow="never">
|
||||
<el-card
|
||||
class="wh-full"
|
||||
:body-style="{ margin: 0, padding: 0, height: '100%', position: 'relative' }"
|
||||
shadow="never"
|
||||
>
|
||||
<template #header>
|
||||
绘画任务
|
||||
<!-- TODO @fan:看看,怎么优化下这个样子哈。 -->
|
||||
<el-button @click="handleViewPublic">绘画作品</el-button>
|
||||
</template>
|
||||
<!-- 图片列表 -->
|
||||
<div class="task-image-list" ref="imageListRef">
|
||||
<div
|
||||
class="relative flex flex-row flex-wrap content-start h-full overflow-auto p-5 pb-[140px] box-border [&>div]:mr-5 [&>div]:mb-5"
|
||||
ref="imageListRef"
|
||||
>
|
||||
<ImageCard
|
||||
v-for="image in imageList"
|
||||
:key="image.id"
|
||||
@ -15,7 +22,9 @@
|
||||
@on-mj-btn-click="handleImageMidjourneyButtonClick"
|
||||
/>
|
||||
</div>
|
||||
<div class="task-image-pagination">
|
||||
<div
|
||||
class="absolute bottom-[60px] h-[50px] leading-[90px] w-full z-[999] bg-white flex flex-row justify-center items-center"
|
||||
>
|
||||
<Pagination
|
||||
:total="pageTotal"
|
||||
v-model:page="queryParams.pageNo"
|
||||
@ -150,12 +159,12 @@ const handleImageButtonClick = async (type: string, imageDetail: ImageVO) => {
|
||||
}
|
||||
// 下载
|
||||
if (type === 'download') {
|
||||
await download.image({ url: imageDetail.picUrl })
|
||||
download.image({ url: imageDetail.picUrl })
|
||||
return
|
||||
}
|
||||
// 重新生成
|
||||
if (type === 'regeneration') {
|
||||
await emits('onRegeneration', imageDetail)
|
||||
emits('onRegeneration', imageDetail)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -197,49 +206,3 @@ onUnmounted(async () => {
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.dr-task {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.task-card {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.task-image-list {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
padding: 20px 20px 140px;
|
||||
box-sizing: border-box; /* 确保内边距不会增加高度 */
|
||||
|
||||
> div {
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
> div:last-of-type {
|
||||
//margin-bottom: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.task-image-pagination {
|
||||
position: absolute;
|
||||
bottom: 60px;
|
||||
height: 50px;
|
||||
line-height: 90px;
|
||||
width: 100%;
|
||||
z-index: 999;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
<!-- image -->
|
||||
<template>
|
||||
<div class="ai-image">
|
||||
<div class="left">
|
||||
<div class="segmented">
|
||||
<el-segmented v-model="selectPlatform" :options="platformOptions" />
|
||||
<div class="absolute inset-0 flex flex-row wh-full">
|
||||
<div class="flex flex-col p-5 w-[390px]">
|
||||
<div class="mb-[30px]">
|
||||
<el-segmented
|
||||
v-model="selectPlatform"
|
||||
:options="platformOptions"
|
||||
class="w-[350px] !bg-[#ececec] [--el-border-radius-base:16px] [--el-segmented-item-selected-color:#fff]"
|
||||
/>
|
||||
</div>
|
||||
<div class="modal-switch-container">
|
||||
<div class="h-full overflow-y-auto">
|
||||
<Common
|
||||
v-if="selectPlatform === 'common'"
|
||||
ref="commonRef"
|
||||
@ -32,7 +36,7 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="flex-1 bg-white">
|
||||
<ImageList ref="imageListRef" @on-regeneration="handleRegeneration" />
|
||||
</div>
|
||||
</div>
|
||||
@ -79,10 +83,10 @@ const platformOptions = [
|
||||
const models = ref<ModelVO[]>([]) // 模型列表
|
||||
|
||||
/** 绘画 start */
|
||||
const handleDrawStart = async (platform: string) => {}
|
||||
const handleDrawStart = async (_platform: string) => {}
|
||||
|
||||
/** 绘画 complete */
|
||||
const handleDrawComplete = async (platform: string) => {
|
||||
const handleDrawComplete = async (_platform: string) => {
|
||||
await imageListRef.value.getImageList()
|
||||
}
|
||||
|
||||
@ -108,48 +112,3 @@ onMounted(async () => {
|
||||
models.value = await ModelApi.getModelSimpleList(AiModelTypeEnum.IMAGE)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.ai-image {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
width: 390px;
|
||||
|
||||
.segmented .el-segmented {
|
||||
--el-border-radius-base: 16px;
|
||||
--el-segmented-item-selected-color: #fff;
|
||||
background-color: #ececec;
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.modal-switch-container {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
margin-top: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 350px;
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user