feat: 高级工具转产品图 prompt assist弹窗内容修改

This commit is contained in:
zhangyh
2025-11-20 13:39:23 +08:00
parent ae142b8edf
commit f28eaef252
12 changed files with 301 additions and 140 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 709 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 KiB

View File

@@ -168,7 +168,10 @@
</div> </div>
</div> </div>
<div class="prompt-input-container" v-show="!showMotion"> <div class="prompt-input-container" v-show="!showMotion">
<div class="title">{{ $t('ProductImg.Prompt') }}</div> <div class="title">
<span>{{ $t('ProductImg.Prompt') }}</span>
<i class="fi fi-rs-interrogation tips-icon" />
</div>
<promptInput :content="inputPrompt" ref="promptInput" /> <promptInput :content="inputPrompt" ref="promptInput" />
</div> </div>
<div class="poses" v-show="showMotion"> <div class="poses" v-show="showMotion">
@@ -1527,6 +1530,15 @@ export default defineComponent({
} }
.prompt-input-container { .prompt-input-container {
margin-top: 4rem; margin-top: 4rem;
.title{
display: flex;
align-items: center;
column-gap: 1rem;
i{
display: flex;
cursor: pointer;
}
}
} }
.title { .title {
font-size: 1.8rem; font-size: 1.8rem;

View File

@@ -2,6 +2,7 @@
<!-- <div ref="modalContainer"></div> --> <!-- <div ref="modalContainer"></div> -->
<a-modal <a-modal
class="prompt-modal generalModel" class="prompt-modal generalModel"
:class="{ design: isDesignPage }"
v-model:visible="showModal" v-model:visible="showModal"
:footer="null" :footer="null"
width="78%" width="78%"
@@ -82,44 +83,102 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, useTemplateRef, onMounted } from 'vue' import { ref, useTemplateRef, onMounted, computed } from 'vue'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import originalDress from '@/assets/images/product/original_dress.png' import originalDress from '@/assets/images/product/original_dress.png'
import generatedDress from '@/assets/images/product/geneated_dress.png' import generatedDress from '@/assets/images/product/geneated_dress.png'
import originalModel from '@/assets/images/product/original_model.png' import originalModel from '@/assets/images/product/original_model.png'
import generatedModel from '@/assets/images/product/generated_model.png' import generatedModel from '@/assets/images/product/generated_model.png'
import generatedSketch from '@/assets/images/product/generated_sketch.png' import generatedSketch from '@/assets/images/product/generated_sketch.png'
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'
import { downloadIamge } from '@/tool/util' import { downloadIamge } from '@/tool/util'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useStore } from 'vuex'
const { t, locale } = useI18n() const { t, locale } = useI18n()
const store = useStore()
const props = defineProps<{ const props = defineProps<{
promptList: string[] isDesignPage: boolean
}>() }>()
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]
}
}
})
const modalContainer = useTemplateRef('modalContainer') const modalContainer = useTemplateRef('modalContainer')
const showModal = defineModel<boolean>('showModal', { required: true }) const showModal = defineModel<boolean>('showModal', { required: true })
const garmentExample = [ const garmentExample = [
{ {
title: 'originalDress', title: 'Original Dress',
src: originalDress, src: originalDress,
isOriginal: true isOriginal: true
}, },
{ {
title: 'generatedDress', title: 'Generated Result',
src: generatedDress src: generatedDress
} }
] ]
const sketchExample = [ const sketchExample = [
{ {
title: 'origianlDress', title: 'Origianl Sketch',
src: originalDress, src: originalDress,
isOriginal: true isOriginal: true
}, },
{ {
title: 'generatedSketch', title: 'Generated Sketch',
src: generatedSketch src: generatedSketch
} }
] ]
@@ -136,11 +195,98 @@ const modelExample = [
} }
] ]
const exampleList = { 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, garmentExample,
sketchExample, sketchExample,
modelExample 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
})
const handleClose = () => { const handleClose = () => {
showModal.value = false showModal.value = false
@@ -200,6 +346,7 @@ const handleCopy = async (value: string) => {
justify-content: space-between; justify-content: space-between;
overflow-x: auto; overflow-x: auto;
overflow-y: hidden; overflow-y: hidden;
.example-wrapper { .example-wrapper {
display: flex; display: flex;
gap: 0; gap: 0;
@@ -227,6 +374,7 @@ const handleCopy = async (value: string) => {
} }
} }
} }
.prompt-list { .prompt-list {
margin-top: 3.5rem; margin-top: 3.5rem;
display: flex; display: flex;
@@ -252,6 +400,18 @@ const handleCopy = async (value: string) => {
} }
} }
} }
&.design {
.example-content {
padding-left: 0;
justify-content: space-around;
}
.prompt-list {
justify-content: space-around;
.prompt-item {
width: 40%;
}
}
}
} }
:deep(.generalModel .ant-modal-body) { :deep(.generalModel .ant-modal-body) {
padding: 5rem 4.4rem 8rem 4.6rem; padding: 5rem 4.4rem 8rem 4.6rem;

View File

@@ -320,8 +320,15 @@
}" }"
:isProductimg="true" :isProductimg="true"
></scaleImage> ></scaleImage>
<Prompt v-if="productimgMenu.value == 'ToProductImage'" v-model:showModal="showPromptAssist" :promptList="promptTextList" /> <Prompt
<PromptEditProduct v-if="productimgMenu.value == 'Relight'" v-model:showModal="showPromptAssist"></PromptEditProduct> v-if="productimgMenu.value == 'ToProductImage'"
v-model:showModal="showPromptAssist"
:isDesignPage="isDesignPage"
/>
<PromptEditProduct
v-if="productimgMenu.value == 'Relight'"
v-model:showModal="showPromptAssist"
></PromptEditProduct>
</div> </div>
</template> </template>
@@ -727,8 +734,8 @@ export default defineComponent({
let remPrductimgTime: any = null let remPrductimgTime: any = null
let prductimgTime: any = null let prductimgTime: any = null
let getPrductimg = () => { let getPrductimg = () => {
// 未输入prompt时不可生成 // 非高级工具 未输入prompt时不可生成
if (!productImgData.searchName[props.productimgMenu.value]) { if (!productImgData.searchName[props.productimgMenu.value] && !props.isDesignPage) {
message.info(t('ProductImg.noPrompt')) message.info(t('ProductImg.noPrompt'))
return return
} }
@@ -784,22 +791,6 @@ export default defineComponent({
} }
productImgData.isProductimg = true productImgData.isProductimg = true
// 设置默认prompt
if (!productImgData.searchName[props.productimgMenu.value]) {
const isFromDesignPage = props.source == 'design' || props.isDesignPage
const { ageGroup, httpType } = store.state.Workspace.probjects
const isSingleDesign = httpType === 'SINGLE_DESIGN'
if (!isFromDesignPage) {
data.prompt = t('poseTransfer.UploadWithModel')
} else if (ageGroup === 'Adult') {
data.prompt = isSingleDesign
? t('poseTransfer.SingleAdultTryOn')
: t('poseTransfer.SeriesAdultTryOn')
} else if (isSingleDesign) {
data.prompt = t('poseTransfer.SingleGarment')
}
}
let url = Https.httpUrls.toProduct let url = Https.httpUrls.toProduct
if (props.productimgMenu.value == 'Relight') { if (props.productimgMenu.value == 'Relight') {
url = Https.httpUrls.relight url = Https.httpUrls.relight
@@ -1107,36 +1098,16 @@ export default defineComponent({
}) })
// 计算属性:根据条件生成提示词列表 // 计算属性:根据条件生成提示词列表
const promptTextList = computed(() => {
const isFromDesignPage = props.source === 'design' || props.isDesignPage
const { ageGroup, httpType } = store.state.Workspace.probjects
const isSingleDesign = httpType === 'SINGLE_DESIGN'
const isAdult = ageGroup === 'Adult'
if (!isFromDesignPage) {
// 如果不是从design来的返回两个提示词
return [t('poseTransfer.UploadWithoutModel'), t('poseTransfer.UploadWithModel')]
} else {
// 如果是从design来的
if (isSingleDesign) {
// SINGLE_DESIGN: 两个提示词
const secondPrompt = isAdult
? t('poseTransfer.SingleAdultTryOn')
: t('poseTransfer.SingleChildTryOn')
return [t('poseTransfer.SingleGarment'), secondPrompt]
} else {
// SERIES_DESIGN: 一个提示词
return [
isAdult
? t('poseTransfer.SeriesAdultTryOn')
: t('poseTransfer.SeriesChildTryOn')
]
}
}
})
const showPromptAssist = ref(false) const showPromptAssist = ref(false)
const handleClickAssistBtn = () => { const handleClickAssistBtn = () => {
const { httpType } = store.state.Workspace.probjects
const isSingleDesign = httpType === 'SINGLE_DESIGN'
if (props.isDesignPage && !isSingleDesign) {
const promptText = t('ProductImg.Series')
productImgData.searchName[props.productimgMenu.value] = promptText
return
}
showPromptAssist.value = true showPromptAssist.value = true
} }
@@ -1150,7 +1121,6 @@ export default defineComponent({
productimgMenuList, productimgMenuList,
RelightDirectionList, RelightDirectionList,
RelightDirection, RelightDirection,
promptTextList,
showPromptAssist, showPromptAssist,
setproduct, setproduct,

View File

@@ -314,6 +314,30 @@ export default {
ChangeBarInfo: '移除服装', ChangeBarInfo: '移除服装',
ChangeGarden: '在花园,清晨时分。', ChangeGarden: '在花园,清晨时分。',
ChangeGardenInfo: '添加配饰', ChangeGardenInfo: '添加配饰',
SingleGarment:
'专业产品摄影:服装展示于隐形模特上,模特不可见。完整保留设计细节——所有图案、颜色、质地及细节特征。', // 单品样衣
SingleChildMaleWithoutModel:
'将此图像转换为真实服装,展示于白色工作室中:服装悬挂于隐形人体模型上。',
SingleChildMaleWithModel:
'将这张图片转换为真实儿童模特,模特身着该服装,在白色摄影棚内以站立姿势面向镜头。',
SingleChildFemaleWithoutModel:
'将此图像转换为真实服装,展示于白色工作室中:服装悬挂于隐形人体模型上。',
SingleChildFemaleWithModel:
'将此图像转化为真实儿童模特,穿着该服装,置于白色摄影棚内,面向镜头,保持站立姿势。',
SingleAdultMaleWithoutModel:
'将此图像转换为真实服装,展示于白色工作室中:服装悬挂于隐形人体模型上。',
SingleAdultMaleWithModel:
'将此图像转化为真实模特,让模特身着该服装,在白色摄影棚内面向镜头保持站立姿势。',
SingleAdultFemaleWithoutModel:
'将此图像转换为真实服装,展示于白色工作室中:服装悬挂于隐形人体模型上。',
SingleAdultFemaleWithModel:
'将此图像转化为真实模特,让模特身着该服装,在白色摄影棚内面向镜头保持站立姿势。',
Series: '在白色摄影棚内,面向镜头,站立姿势。',
UploadWithModel:
'创建真实感十足的摄影棚照片,模特需身着该服装站立于白色摄影棚中。若原有模特存在则保留,否则生成合适模特。保持站立姿势,面向镜头。', // 上传线稿,带模特
UploadWithoutModel:
'将此图像转换为真实服装,展示于白色工作室中:服装悬挂于隐形人体模型上。' // 上传线稿,不带模特
}, },
poseTransfer: { poseTransfer: {
SelectDesign: '产品图', SelectDesign: '产品图',
@@ -325,20 +349,6 @@ export default {
jsContent1: '生成视频预计需要三分钟,请问是否继续', jsContent1: '生成视频预计需要三分钟,请问是否继续',
NeedFirstFrame: '请选择首帧图片', NeedFirstFrame: '请选择首帧图片',
NeedLastFrame: '请选择尾帧图片', NeedLastFrame: '请选择尾帧图片',
SingleGarment:
'专业产品摄影:服装展示于隐形模特上,模特不可见。完整保留设计细节——所有图案、颜色、质地及细节特征。', // 单品样衣
SingleChildTryOn:
'生成一名儿童模特穿着该服装的逼真工作室照片。采用站姿,面向镜头。保留服装的精确细节——所有图案、颜色、纹理及装饰元素。', // 单品儿童试穿
SingleAdultTryOn:
'生成模特穿着该服装的逼真摄影棚照片。采用站姿面向镜头。保留服装的精确细节——所有图案、颜色、纹理及装饰元素。', // 单品成人试穿
SeriesAdultTryOn:
'制作真实感十足的摄影棚照片:模特保持站立姿势,面向镜头,服装细节完全保留原貌。', // 系列成人试穿
SeriesChildTryOn:
'将此图像转化为逼真的真实儿童模特,保持站立姿势并直面镜头,保留服装的原有图案、风格和色彩,呈现工作室级别的照片质量。', // 系列儿童试穿
UploadWithModel:
'生成真实模特穿着该服装的逼真摄影棚照片采用站立姿势面向镜头。保留服装所有细节——包括图案、颜色、纹理、装饰元素呈现摄影棚级别的8K分辨率照片支持HDR效果、景深控制、柔光效果及高细节呈现。请勿返还原始图像。', // 上传线稿,带模特
UploadWithoutModel:
'专业产品摄影:服装以自然形态展示,无模特。采用影棚灯光。保留精确细节——图案、色彩、质感、装饰元素。', // 上传线稿,不带模特
VideoType: '视频类型', VideoType: '视频类型',
FirstFrame: '首帧', FirstFrame: '首帧',
LastFrame: '尾帧', LastFrame: '尾帧',

View File

@@ -324,6 +324,29 @@ export default {
ChangeBarInfo: 'Remove Garment', ChangeBarInfo: 'Remove Garment',
ChangeGarden: 'In the garden, in the morning.', ChangeGarden: 'In the garden, in the morning.',
ChangeGardenInfo: 'Add Accessories', ChangeGardenInfo: 'Add Accessories',
SingleGarment:
'Professional product photo: garment on invisible mannequin, no model visible. Preserve exact design - all patterns, colors, textures, details.', // 单品样衣
SingleChildMaleWithoutModel:
'Transform this image into a real garment showing in the white studio: garment on invisible mannequin.',
SingleChildMaleWithModel:
'Transform this image into a real child model stand and wear this garment, in the white studio, facing camera, standing posture.',
SingleChildFemaleWithoutModel:
'Transform this image into a real garment showing in the white studio: garment on invisible mannequin.',
SingleChildFemaleWithModel:
'Transform this image into a real child model stand and wear this garment, in the white studio, facing camera, standing posture.',
SingleAdultMaleWithoutModel:
'Transform this image into a real garment showing in the white studio: garment on invisible mannequin.',
SingleAdultMaleWithModel:
'Transform this image into a real model stand and wear this garment, in the white studio, facing camera, standing posture.',
SingleAdultFemaleWithoutModel:
'Transform this image into a real garment showing in the white studio: garment on invisible mannequin.',
SingleAdultFemaleWithModel:
'Transform this image into a real model stand and wear this garment, in the white studio, facing camera, standing posture.',
Series: 'In the white studio, facing camera, standing posture.',
UploadWithModel:
'Create realistic studio photo with real people model standing and wearing this garment, in white studio, Keep original model if present, or generate appropriate model, Standing pose, facing camera.', // 上传线稿,带模特
UploadWithoutModel:
'Transform this image into a real garment showing in the white studio: garment on invisible mannequin' // 上传线稿,不带模特
}, },
poseTransfer: { poseTransfer: {
SelectDesign: 'Product image', SelectDesign: 'Product image',
@@ -335,20 +358,6 @@ export default {
jsContent1: 'Video generation will take approximately 3 minutes. Continue?', jsContent1: 'Video generation will take approximately 3 minutes. Continue?',
NeedFirstFrame: 'Please select the first frame image', NeedFirstFrame: 'Please select the first frame image',
NeedLastFrame: 'Please select the last frame image', NeedLastFrame: 'Please select the last frame image',
SingleGarment:
'Professional product photo: garment on invisible mannequin, no model visible. Preserve exact design - all patterns, colors, textures, details.', // 单品样衣
SingleChildTryOn:
'Generate realistic studio photo of a child model wearing this garment. Standing pose, facing camera. Preserve exact garment details - all patterns, colors, textures, embellishments.', // 单品儿童试穿
SingleAdultTryOn:
'Generate realistic studio photo of a model wearing this garment. Standing pose, facing camera. Preserve exact garment details - all patterns, colors, textures, embellishments.', // 单品成人试穿
SeriesAdultTryOn:
'Create a realistic studio photo: same model standing, facing camera, exact same garment details preserved.', // 系列成人
SeriesChildTryOn:
'Transform this image into a realistic, the same real child model , Maintain a standing posture and face the camera directly, keep the same pattern, style and colour of these garment, studio-quality photograph.', // 系列儿童
UploadWithModel:
'Generate realistic studio photo of a real model wearing this garment, standing pose, facing camera. Preserve exact garment details - all patterns, colors, textures, embellishments, studio-quality photograph, 8K, HDR, DOF, soft lighting, high detail. Do not return the original image.', // 上传线稿,带模特
UploadWithoutModel:
'Professional product photo: garment displayed with natural shape, no model. Studio lighting. Preserve exact details - patterns, colors, textures, embellishments.', // 上传线稿,不带模特
VideoType: 'Video Type', VideoType: 'Video Type',
FirstFrame: 'First frame', FirstFrame: 'First frame',
LastFrame: 'Last frame', LastFrame: 'Last frame',