2025-11-11 14:20:04 +08:00
|
|
|
|
<template>
|
2025-11-17 16:45:40 +08:00
|
|
|
|
<!-- <div ref="modalContainer"></div> -->
|
2025-11-11 14:20:04 +08:00
|
|
|
|
<a-modal
|
|
|
|
|
|
class="prompt-modal generalModel"
|
2025-11-20 13:39:23 +08:00
|
|
|
|
:class="{ design: isDesignPage }"
|
2025-11-11 14:20:04 +08:00
|
|
|
|
v-model:visible="showModal"
|
|
|
|
|
|
:footer="null"
|
|
|
|
|
|
width="78%"
|
|
|
|
|
|
:maskClosable="false"
|
|
|
|
|
|
:centered="true"
|
|
|
|
|
|
:closable="false"
|
|
|
|
|
|
wrapClassName="#app"
|
|
|
|
|
|
:keyboard="false"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="generalModel_btn">
|
|
|
|
|
|
<div class="generalModel_closeIcon" @click.stop="handleClose()">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="100%"
|
|
|
|
|
|
height="100%"
|
|
|
|
|
|
viewBox="0 0 46 46"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
|
|
>
|
|
|
|
|
|
<circle cx="23" cy="23" r="23" fill="#000" fill-opacity="0.3" />
|
|
|
|
|
|
<rect
|
|
|
|
|
|
x="32.5063"
|
|
|
|
|
|
y="12"
|
|
|
|
|
|
width="3"
|
|
|
|
|
|
height="29"
|
|
|
|
|
|
rx="1.5"
|
|
|
|
|
|
transform="rotate(45 32.5063 12)"
|
|
|
|
|
|
fill="white"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<rect
|
|
|
|
|
|
x="34.6274"
|
|
|
|
|
|
y="32.5059"
|
|
|
|
|
|
width="3"
|
|
|
|
|
|
height="29"
|
|
|
|
|
|
rx="1.5"
|
|
|
|
|
|
transform="rotate(135 34.6274 32.5059)"
|
|
|
|
|
|
fill="white"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="title-container">
|
|
|
|
|
|
<div class="title">{{ $t('ProductImg.PromptAssit') }}</div>
|
|
|
|
|
|
<div class="sub-title">{{ $t('ProductImg.AssitSubTitle') }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="example-content">
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="example-wrapper"
|
|
|
|
|
|
v-for="item in Object.keys(exampleList)"
|
|
|
|
|
|
:key="item"
|
|
|
|
|
|
:class="item"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="example-item" v-for="value in exampleList[item]" :key="value.title">
|
|
|
|
|
|
<img :src="value.src" />
|
|
|
|
|
|
<SvgIcon
|
|
|
|
|
|
v-if="value.isOriginal"
|
|
|
|
|
|
class="download-icon"
|
|
|
|
|
|
name="CDownload"
|
|
|
|
|
|
size="20"
|
|
|
|
|
|
color="#8E8E8E"
|
|
|
|
|
|
@click.stop="handleDownload(value)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="prompt-list">
|
|
|
|
|
|
<div v-for="item in promptList" :key="item" class="prompt-item">
|
|
|
|
|
|
<SvgIcon
|
|
|
|
|
|
name="CCopy"
|
|
|
|
|
|
size="25"
|
|
|
|
|
|
color="#BCBCBC"
|
|
|
|
|
|
class="copy-icon"
|
|
|
|
|
|
@click.stop="handleCopy(item)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
{{ item }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</a-modal>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2025-11-20 13:39:23 +08:00
|
|
|
|
import { ref, useTemplateRef, onMounted, computed } from 'vue'
|
2025-11-11 14:20:04 +08:00
|
|
|
|
import { message } from 'ant-design-vue'
|
|
|
|
|
|
import originalDress from '@/assets/images/product/original_dress.png'
|
|
|
|
|
|
import generatedDress from '@/assets/images/product/geneated_dress.png'
|
|
|
|
|
|
import originalModel from '@/assets/images/product/original_model.png'
|
|
|
|
|
|
import generatedModel from '@/assets/images/product/generated_model.png'
|
|
|
|
|
|
import generatedSketch from '@/assets/images/product/generated_sketch.png'
|
2025-11-20 13:39:23 +08:00
|
|
|
|
import maleSingleGarmentSketch from '@/assets/images/product/male_single_garment_sketch.png'
|
|
|
|
|
|
import maleSingleGarmentResult from '@/assets/images/product/male_single_garment_result.png'
|
|
|
|
|
|
import maleSingleModelSketch from '@/assets/images/product/male_single_garment_model_sketch.png'
|
|
|
|
|
|
import maleSingleModelResult from '@/assets/images/product/male_single_garment_model_sketch.png'
|
|
|
|
|
|
import femaleChildModelResult from '@/assets/images/product/single_female_child_model_result.png'
|
|
|
|
|
|
import maleSingleChildSketch from '@/assets/images/product/single_male_child_model_sketch.png'
|
|
|
|
|
|
import maleSingleChildResult from '@/assets/images/product/single_male_child_model_result.png'
|
|
|
|
|
|
|
2025-11-11 14:20:04 +08:00
|
|
|
|
import { downloadIamge } from '@/tool/util'
|
|
|
|
|
|
import { useI18n } from 'vue-i18n'
|
2025-11-20 13:39:23 +08:00
|
|
|
|
import { useStore } from 'vuex'
|
|
|
|
|
|
|
2025-11-11 14:20:04 +08:00
|
|
|
|
const { t, locale } = useI18n()
|
2025-11-20 13:39:23 +08:00
|
|
|
|
const store = useStore()
|
2025-11-11 14:20:04 +08:00
|
|
|
|
|
2025-11-12 13:24:30 +08:00
|
|
|
|
const props = defineProps<{
|
2025-11-20 13:39:23 +08:00
|
|
|
|
isDesignPage: boolean
|
2025-11-11 14:20:04 +08:00
|
|
|
|
}>()
|
|
|
|
|
|
|
2025-11-20 13:39:23 +08:00
|
|
|
|
const promptList = computed(() => {
|
|
|
|
|
|
const isFromDesignPage = props.source === 'design' || props.isDesignPage
|
|
|
|
|
|
const { ageGroup, httpType, sex } = store.state.Workspace.probjects
|
|
|
|
|
|
const isSingleDesign = httpType === 'SINGLE_DESIGN'
|
|
|
|
|
|
const isAdult = ageGroup === 'Adult'
|
|
|
|
|
|
const isFemale = sex === 'Female'
|
|
|
|
|
|
|
|
|
|
|
|
if (!isFromDesignPage) {
|
|
|
|
|
|
// 如果不是从design来的,返回两个提示词
|
|
|
|
|
|
return [t('ProductImg.UploadWithoutModel'), t('ProductImg.UploadWithModel')]
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 如果是从design来的
|
|
|
|
|
|
if (isSingleDesign) {
|
|
|
|
|
|
// SINGLE_DESIGN: 两个提示词
|
|
|
|
|
|
// 根据年龄和性别选择对应的提示词
|
|
|
|
|
|
let firstPrompt: string // 不带模特的提示词
|
|
|
|
|
|
let secondPrompt: string // 带模特的提示词
|
|
|
|
|
|
|
|
|
|
|
|
if (isAdult) {
|
|
|
|
|
|
// 成人
|
|
|
|
|
|
if (isFemale) {
|
|
|
|
|
|
// 成人女
|
|
|
|
|
|
firstPrompt = t('ProductImg.SingleAdultFemaleWithoutModel')
|
|
|
|
|
|
secondPrompt = t('ProductImg.SingleAdultFemaleWithModel')
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 成人男
|
|
|
|
|
|
firstPrompt = t('ProductImg.SingleAdultMaleWithoutModel')
|
|
|
|
|
|
secondPrompt = t('ProductImg.SingleAdultMaleWithModel')
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 儿童
|
|
|
|
|
|
if (isFemale) {
|
|
|
|
|
|
// 儿童女
|
|
|
|
|
|
firstPrompt = t('ProductImg.SingleChildFemaleWithoutModel')
|
|
|
|
|
|
secondPrompt = t('ProductImg.SingleChildFemaleWithModel')
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 儿童男
|
|
|
|
|
|
firstPrompt = t('ProductImg.SingleChildMaleWithoutModel')
|
|
|
|
|
|
secondPrompt = t('ProductImg.SingleChildMaleWithModel')
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return [firstPrompt, secondPrompt]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-11-11 14:20:04 +08:00
|
|
|
|
const modalContainer = useTemplateRef('modalContainer')
|
|
|
|
|
|
const showModal = defineModel<boolean>('showModal', { required: true })
|
|
|
|
|
|
|
|
|
|
|
|
const garmentExample = [
|
|
|
|
|
|
{
|
2025-11-20 13:39:23 +08:00
|
|
|
|
title: 'Original Dress',
|
2025-11-11 14:20:04 +08:00
|
|
|
|
src: originalDress,
|
|
|
|
|
|
isOriginal: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2025-11-20 13:39:23 +08:00
|
|
|
|
title: 'Generated Result',
|
2025-11-11 14:20:04 +08:00
|
|
|
|
src: generatedDress
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
const sketchExample = [
|
|
|
|
|
|
{
|
2025-11-20 13:39:23 +08:00
|
|
|
|
title: 'Origianl Sketch',
|
2025-11-11 14:20:04 +08:00
|
|
|
|
src: originalDress,
|
|
|
|
|
|
isOriginal: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2025-11-20 13:39:23 +08:00
|
|
|
|
title: 'Generated Sketch',
|
2025-11-11 14:20:04 +08:00
|
|
|
|
src: generatedSketch
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
const modelExample = [
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'originalModel',
|
|
|
|
|
|
src: originalModel,
|
|
|
|
|
|
isOriginal: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'generatedModel',
|
|
|
|
|
|
src: generatedModel
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
|
2025-11-20 13:39:23 +08:00
|
|
|
|
const femaleAdultGarment = [...garmentExample]
|
|
|
|
|
|
const femaleAdultWithModel = [...modelExample]
|
|
|
|
|
|
const maleAdultGarment = [
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'originalDress',
|
|
|
|
|
|
src: maleSingleGarmentSketch,
|
|
|
|
|
|
isOriginal: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'generated male sketch',
|
|
|
|
|
|
src: maleSingleGarmentResult
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
const maleAdultWithModel = [
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'original male model',
|
|
|
|
|
|
src: maleSingleModelSketch,
|
|
|
|
|
|
isOriginal: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'generated male model',
|
|
|
|
|
|
src: maleSingleModelResult
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
const childFemaleGarment = [...garmentExample]
|
|
|
|
|
|
const childFemaleWithModel = [
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'Origianl Sketch',
|
|
|
|
|
|
src: originalDress,
|
|
|
|
|
|
isOriginal: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'Generated female girl Sketch',
|
|
|
|
|
|
src: femaleChildModelResult
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
const childMaleGarment = [...maleAdultGarment]
|
|
|
|
|
|
const childMaleWithModel = [
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'original sketch',
|
|
|
|
|
|
src: maleSingleChildSketch,
|
|
|
|
|
|
isOriginal: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: 'generate child male model',
|
|
|
|
|
|
src: maleSingleChildResult
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
const exampleList = computed(() => {
|
|
|
|
|
|
let obj = {}
|
|
|
|
|
|
if (!props.isDesignPage) {
|
|
|
|
|
|
obj = {
|
|
|
|
|
|
garmentExample,
|
|
|
|
|
|
sketchExample,
|
|
|
|
|
|
modelExample
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const { ageGroup, httpType, sex } = store.state.Workspace.probjects
|
|
|
|
|
|
const isSingleDesign = httpType === 'SINGLE_DESIGN'
|
|
|
|
|
|
if (!isSingleDesign) return {}
|
|
|
|
|
|
const isAdult = ageGroup === 'Adult'
|
|
|
|
|
|
const isFemale = sex === 'Female'
|
|
|
|
|
|
if (isAdult) {
|
|
|
|
|
|
if (isFemale) {
|
|
|
|
|
|
obj = {
|
|
|
|
|
|
femaleAdultGarment,
|
|
|
|
|
|
femaleAdultWithModel
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
obj = {
|
|
|
|
|
|
maleAdultGarment,
|
|
|
|
|
|
maleAdultWithModel
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (isFemale) {
|
|
|
|
|
|
obj = {
|
|
|
|
|
|
childFemaleGarment,
|
|
|
|
|
|
childFemaleWithModel
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
obj = {
|
|
|
|
|
|
childMaleGarment,
|
|
|
|
|
|
childMaleWithModel
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return obj
|
|
|
|
|
|
})
|
2025-11-11 14:20:04 +08:00
|
|
|
|
|
|
|
|
|
|
const handleClose = () => {
|
|
|
|
|
|
showModal.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const handleDownload = value => {
|
|
|
|
|
|
const { title, src } = value
|
|
|
|
|
|
downloadIamge(src, title)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const handleCopy = async (value: string) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
|
|
|
|
await navigator.clipboard.writeText(value)
|
|
|
|
|
|
message.success(t('ProductImg.CopySuccess'))
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 降级方案:使用传统的 document.execCommand 方法
|
|
|
|
|
|
const textArea = document.createElement('textarea')
|
|
|
|
|
|
textArea.value = value
|
|
|
|
|
|
textArea.style.position = 'fixed'
|
|
|
|
|
|
textArea.style.left = '-999999px'
|
|
|
|
|
|
textArea.style.top = '-999999px'
|
|
|
|
|
|
document.body.appendChild(textArea)
|
|
|
|
|
|
textArea.focus()
|
|
|
|
|
|
textArea.select()
|
|
|
|
|
|
try {
|
|
|
|
|
|
document.execCommand('copy')
|
2025-11-12 13:24:30 +08:00
|
|
|
|
message.success(t('ProductImg.CopySuccess'))
|
2025-11-11 14:20:04 +08:00
|
|
|
|
} catch (err) {
|
|
|
|
|
|
message.error(t('ProductImg.CopyFailed'))
|
|
|
|
|
|
}
|
|
|
|
|
|
document.body.removeChild(textArea)
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
message.error(t('ProductImg.CopyFailed'))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
|
|
|
.prompt-modal {
|
|
|
|
|
|
.title-container {
|
|
|
|
|
|
.title {
|
|
|
|
|
|
font-size: 3.5rem;
|
|
|
|
|
|
color: #181818;
|
|
|
|
|
|
}
|
|
|
|
|
|
.sub-title {
|
|
|
|
|
|
font-size: 2rem;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
color: #000;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.example-content {
|
|
|
|
|
|
margin-top: 4.3rem;
|
|
|
|
|
|
padding-left: 7.4rem;
|
|
|
|
|
|
display: flex;
|
2025-11-17 16:45:40 +08:00
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
overflow-y: hidden;
|
2025-11-20 13:39:23 +08:00
|
|
|
|
|
2025-11-11 14:20:04 +08:00
|
|
|
|
.example-wrapper {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 0;
|
|
|
|
|
|
&.garmentExample {
|
|
|
|
|
|
margin-right: 9.6rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
&.sketchExample {
|
|
|
|
|
|
margin-right: 1.6rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
.example-item {
|
|
|
|
|
|
width: 20.3rem;
|
|
|
|
|
|
height: 38.4rem;
|
|
|
|
|
|
margin-left: -2px;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
img {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
.download-icon {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0.77rem;
|
|
|
|
|
|
right: 0.84rem;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-20 13:39:23 +08:00
|
|
|
|
|
2025-11-11 14:20:04 +08:00
|
|
|
|
.prompt-list {
|
|
|
|
|
|
margin-top: 3.5rem;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
column-gap: 6.3rem;
|
|
|
|
|
|
.prompt-item {
|
|
|
|
|
|
height: 12.8rem;
|
|
|
|
|
|
line-height: 2.3rem;
|
|
|
|
|
|
padding: 1.8rem 3.5rem 1.8rem 2rem;
|
|
|
|
|
|
color: #969696;
|
|
|
|
|
|
font-size: 1.9rem;
|
|
|
|
|
|
border: 1px solid #000;
|
|
|
|
|
|
border-radius: 0.8rem;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
// &:first-child{
|
|
|
|
|
|
// width: 53.6rem;
|
|
|
|
|
|
// }
|
|
|
|
|
|
.copy-icon {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 1.1rem;
|
|
|
|
|
|
right: 1rem;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-20 13:39:23 +08:00
|
|
|
|
&.design {
|
|
|
|
|
|
.example-content {
|
|
|
|
|
|
padding-left: 0;
|
|
|
|
|
|
justify-content: space-around;
|
|
|
|
|
|
}
|
|
|
|
|
|
.prompt-list {
|
|
|
|
|
|
justify-content: space-around;
|
|
|
|
|
|
.prompt-item {
|
|
|
|
|
|
width: 40%;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-11 14:20:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
:deep(.generalModel .ant-modal-body) {
|
|
|
|
|
|
padding: 5rem 4.4rem 8rem 4.6rem;
|
|
|
|
|
|
}
|
|
|
|
|
|
.c-svg {
|
|
|
|
|
|
width: initial;
|
|
|
|
|
|
height: initial;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|