feat: 弹窗&prompt i18n

This commit is contained in:
zhangyh
2025-11-14 15:10:32 +08:00
parent 80472a9cec
commit c32afb99ce
11 changed files with 444 additions and 162 deletions

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path fill="currentColor" d="M14 10h-2v12h2zm6 0h-2v12h2z" />
<path fill="currentColor" d="M16 4A12 12 0 1 1 4 16A12 12 0 0 1 16 4m0-2a14 14 0 1 0 14 14A14 14 0 0 0 16 2" />
</svg>

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@@ -1,7 +1,7 @@
<template>
<div ref="modalContainer"></div>
<a-modal
class="prompt-modal generalModel"
class="tips-modal generalModel"
v-model:visible="showModal"
:footer="null"
:get-container="() => $refs.modalContainer"
@@ -44,17 +44,36 @@
</div>
</div>
<div class="title-container">
<div class="title">{{ $t('ProductImg.PromptAssit') }}</div>
<div class="sub-title">{{ $t('ProductImg.AssitSubTitle') }}</div>
<div class="title">{{ $t('poseTransfer.Tips') }}</div>
<div class="sub-title">
{{ $t('poseTransfer.TipsStart') }}
<i class="fi fi-ss-box-open" />
{{ $t('poseTransfer.TipsEnd') }}
</div>
</div>
<div class="diliver" />
<div class="content">
<div class="frame-item">
<img class="tips-frame" :src="firstFrame" />
<div class="frame-name">{{ $t('poseTransfer.FirstFrame') }}</div>
</div>
<img :src="add" class="add" />
<div class="frame-item">
<img class="tips-frame" :src="lastFrame" />
<div class="frame-name">{{ $t('poseTransfer.LastFrame') }}</div>
</div>
</div>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, useTemplateRef } from 'vue'
import { downloadIamge } from '@/tool/util'
import { useI18n } from 'vue-i18n'
import firstFrame from '@/assets/images/product/first_frame.png'
import add from '@/assets/images/product/add.png'
import lastFrame from '@/assets/images/product/last_frame.png'
const { t, locale } = useI18n()
const modalContainer = useTemplateRef('modalContainer')
@@ -66,7 +85,7 @@ const handleClose = () => {
</script>
<style lang="less" scoped>
.prompt-modal {
.tips-modal {
.title-container {
.title {
font-size: 3.5rem;
@@ -78,5 +97,35 @@ const handleClose = () => {
color: #000;
}
}
.diliver {
height: 1px;
background: #dfdfdf;
margin: 4rem 0;
}
.content {
display: flex;
justify-content: center;
align-items: center;
column-gap: 4.8rem;
.add {
width: 3.5rem;
height: 3.5rem;
}
.frame-item {
text-align: center;
.tips-frame {
width: 21.3rem;
height: 36.1rem;
}
.frame-name{
margin-top: 1.2rem;
font-size: 2.6rem;
font-weight: 400;
}
}
}
}
:deep(.generalModel .ant-modal-body) {
padding: 4rem 11rem 4rem 14rem;
}
</style>

View File

@@ -23,7 +23,11 @@
<div class="selectImg">
<div class="head">
<div class="text">{{ $t('poseTransfer.SelectDesign') }}</div>
<i class="fi fi-rs-interrogation tips-icon" />
<i
v-show="videoType !== 2"
class="fi fi-rs-interrogation tips-icon"
@click="showTips = true"
/>
</div>
<div class="imgBox" v-mousewheel>
<div
@@ -59,7 +63,60 @@
</div>
</div>
</div>
<div
class="upload_item item"
v-show="!isDesignPage && !(videoType === 3 && fileList.length > 0)"
>
<div class="upload_file_item">
<a-upload
key="common"
:action="getUploadUrl() + '/api/history/toProductImageElementUpload'"
list-type="picture-card"
:capture="null"
:data="{
...upload
}"
:headers="{ Authorization: token }"
:before-upload="beforeUpload"
:multiple="!!upload.projectId"
accept=".jpg,.png,.jpeg,.bmp"
@change="file => fileUploadChange(file)"
>
<div class="upload_tip_block">
<i class="fi fi-br-upload"></i>
<!-- <img class="upload_img_icon" src="@/assets/images/homePage/add_file.png"> -->
</div>
</a-upload>
</div>
</div>
<template v-if="videoType === 3">
<div
class="upload_item item last_frames"
v-show="!isDesignPage && lastFrameList?.length < 1"
>
<div class="upload_file_item">
<a-upload
key="lastframes"
:action="
getUploadUrl() + '/api/history/toProductImageElementUpload'
"
list-type="picture-card"
:capture="null"
:data="{
...upload
}"
:headers="{ Authorization: token }"
:before-upload="beforeUpload"
accept=".jpg,.png,.jpeg,.bmp"
@change="file => fileUploadChangeLast(file)"
>
<div class="upload_tip_block">
<i class="fi fi-br-upload"></i>
<!-- <img class="upload_img_icon" src="@/assets/images/homePage/add_file.png"> -->
</div>
</a-upload>
</div>
</div>
<div
class="item lastframe-list"
:class="{ active: item.id == selectImg.id }"
@@ -94,60 +151,6 @@
</div>
</div>
</template>
<template v-if="fileList.length < 1">
<div class="upload_item item" v-show="!isDesignPage">
<div class="upload_file_item">
<a-upload
key="common"
:action="
getUploadUrl() + '/api/history/toProductImageElementUpload'
"
list-type="picture-card"
:capture="null"
:data="{
...upload
}"
:headers="{ Authorization: token }"
:before-upload="beforeUpload"
:multiple="!!upload.projectId"
accept=".jpg,.png,.jpeg,.bmp"
@change="file => fileUploadChange(file)"
>
<div class="upload_tip_block">
<i class="fi fi-br-upload"></i>
<!-- <img class="upload_img_icon" src="@/assets/images/homePage/add_file.png"> -->
</div>
</a-upload>
</div>
</div>
</template>
<template v-if="videoType === 3 && lastFrameList?.length < 1">
<div class="upload_item item last_frames" v-show="!isDesignPage">
<div class="upload_file_item">
<a-upload
key="lastframes"
:action="
getUploadUrl() + '/api/history/toProductImageElementUpload'
"
list-type="picture-card"
:file-list="lastFrameList"
:capture="null"
:data="{
...upload
}"
:headers="{ Authorization: token }"
:before-upload="beforeUpload"
accept=".jpg,.png,.jpeg,.bmp"
@change="file => fileUploadChangeLast(file)"
>
<div class="upload_tip_block">
<i class="fi fi-br-upload"></i>
<!-- <img class="upload_img_icon" src="@/assets/images/homePage/add_file.png"> -->
</div>
</a-upload>
</div>
</div>
</template>
</div>
</div>
<div class="prompt-input-container" v-show="!showMotion">
@@ -159,13 +162,13 @@
<div class="text">{{ $t('poseTransfer.Selectpose') }}</div>
</div>
<div class="imgBox" v-mousewheel>
<div class="item" v-for="item in poseList" @click="selectPose(item)">
<img
:src="item.firstFrame"
alt=""
@mouseenter.stop="gifPlay($event, item)"
@mouseleave.stop="gifPause($event, item)"
/>
<div
class="item"
v-for="item in poseList"
:key="item.id"
@click="selectPose(item)"
>
<video :ref="el => setVideoRef(item.id, el)" :src="item.video" />
<div class="btnBox">
<div :class="{ active: item.isChecked }">
<i class="fi fi-br-check"></i>
@@ -174,12 +177,21 @@
<div class="control-container">
<div class="icon-list">
<SvgIcon
v-show="!isVideoPlaying(item.id)"
class="play-icon"
@click="handlePlayMotion(item)"
@click.stop="handlePlayMotion(item)"
name="CPlay"
size="10"
color="#fff"
/>
<SvgIcon
v-show="isVideoPlaying(item.id)"
class="play-icon pause"
@click.stop="handlePlayMotion(item)"
name="CPause"
size="10"
color="#fff"
/>
</div>
</div>
</div>
@@ -267,6 +279,7 @@
</div>
</div>
</div>
<Tips v-model:showModal="showTips" />
</div>
</template>
<script lang="ts">
@@ -293,11 +306,14 @@ import { getCookie, setCookie } from '@/tool/cookie'
import showViewVideo from '@/tool/mount'
import router from '@/router'
import promptInput from './promptInput.vue'
import Tips from './Tips.vue'
import { getFirstFrame, getFirstAndLastFrame } from './prompt'
export default defineComponent({
components: {
generalDrag,
promptInput
promptInput,
Tips
},
props: {
isDesignPage: {
@@ -349,12 +365,14 @@ export default defineComponent({
generateTime: null as any,
poseList: [],
selectPose: null as any,
prompt: [
{ id: '1', type: 'text', value: '11111' },
{ id: '2', type: 'input', value: '222', placeholder: '[请输入内容]' },
{ id: '3', type: 'text', value: '333333' },
{ id: '4', type: 'input', value: '', placeholder: '[请输入内容]' }
]
prompt: computed(() => {
if (videoType.value === 2) {
return getFirstFrame(t)
}
if (videoType.value === 3) {
return getFirstAndLastFrame(t)
}
})
})
let speed = reactive({
speedList: [
@@ -376,6 +394,7 @@ export default defineComponent({
value: ''
}
})
const showTips = ref(false)
const setIsShowMark: any = inject('setIsShowMark')
const createProbject: any = inject('createProbject', () => {})
const dataDom = reactive({
@@ -431,24 +450,52 @@ export default defineComponent({
if (data.poseList.length == 0) {
getPoseList()
}
// setCloudImg()
}
// const setCloudImg = ()=>{
// let arr = store.state.UploadFilesModule.cloudList
// let list = JSON.parse(JSON.stringify(arr.poseTransfer)) || []
// list.forEach((item:any)=>{
// item.url = item.firstFrameUrl
// data.noLikeList.unshift(item)
// })
// store.commit('clearCloudList','poseTransfer')
// }
const gifPlay = (e: any, item: any) => {
e.target.src = item.gif //使用gif图片
// 存储视频元素的引用
const videoRefs = ref<Record<number, HTMLVideoElement | null>>({})
// 存储视频播放状态
const videoPlayingStates = ref<Record<number, boolean>>({})
// 设置视频 ref
const setVideoRef = (id: number, el: HTMLVideoElement | null) => {
if (el) {
videoRefs.value[id] = el
// 初始化播放状态
videoPlayingStates.value[id] = !el.paused
// 监听播放事件
el.addEventListener('play', () => {
videoPlayingStates.value[id] = true
})
// 监听暂停事件
el.addEventListener('pause', () => {
videoPlayingStates.value[id] = false
})
// 监听结束事件
el.addEventListener('ended', () => {
videoPlayingStates.value[id] = false
})
}
}
const gifPause = (e: any, item: any) => {
e.target.src = item.firstFrame //静态图片
// 检查视频是否正在播放
const isVideoPlaying = (id: number) => {
return videoPlayingStates.value[id] || false
}
const handlePlayMotion = item => {}
// 播放视频
const handlePlayMotion = (item: any) => {
const video = videoRefs.value[item.id]
if (video) {
if (video.paused) {
video.play().catch(err => {
console.error('播放视频失败:', err)
})
} else {
video.pause()
}
}
}
const getPoseList = () => {
Https.axiosGet(Https.httpUrls.getAllPose).then(rv => {
rv[0].isChecked = true
@@ -485,10 +532,7 @@ export default defineComponent({
}
})
})
.then(() => {})
.catch(() => {
return
})
data.isGenerate = true
// data.remGenerateTime = setTimeout(()=>{
// },10000)
@@ -513,36 +557,35 @@ export default defineComponent({
const lastFrameProductImage = data.lastSelectImg.minioUrl
value.lastFrameProductImage = lastFrameProductImage
}
console.table('videoType:', videoType.value, '请求参数', value)
// Https.axiosPost(Https.httpUrls.poseTransform, value)
// .then(rv => {
// data.remGenerate = true
// data.noLikeList.unshift({
// taskId: rv.taskId,
// parentId: data.selectImg.parentId
// })
// setGenerate(rv.taskId)
// })
// .catch((res: any) => {
// data.isGenerate = false
// clearInterval(data.remGenerateTime)
// data.remGenerate = false
// if (res.errCode === 2) {
// Modal.confirm({
// title: res.errMsg,
// icon: createVNode(ExclamationCircleOutlined),
// okText: 'Yes',
// cancelText: 'No',
// mask: false,
// zIndex: 99999,
// centered: true,
// onOk() {
// store.commit('setUpgradePlan', true)
// },
// onCancel() {}
// })
// }
// })
Https.axiosPost(Https.httpUrls.poseTransform, value)
.then(rv => {
data.remGenerate = true
data.noLikeList.unshift({
taskId: rv.taskId,
parentId: data.selectImg.parentId
})
setGenerate(rv.taskId)
})
.catch((res: any) => {
data.isGenerate = false
clearInterval(data.remGenerateTime)
data.remGenerate = false
if (res.errCode === 2) {
Modal.confirm({
title: res.errMsg,
icon: createVNode(ExclamationCircleOutlined),
okText: 'Yes',
cancelText: 'No',
mask: false,
zIndex: 99999,
centered: true,
onOk() {
store.commit('setUpgradePlan', true)
},
onCancel() {}
})
}
})
}
const setGenerate = (dataList: any) => {
let list: any = [dataList]
@@ -646,7 +689,6 @@ export default defineComponent({
if (!isLt2M) {
message.info(useI18n().t('MoodboardUpload.jsContent4'))
}
console.log(data?.upload, isSelectObject)
if (!data?.upload?.projectId && !isSelectObject) {
isSelectObject = true
await createProbject()
@@ -654,7 +696,6 @@ export default defineComponent({
return (isJpgOrPng && isLt2M && data.upload.projectId) || Upload.LIST_IGNORE
}
const fileUploadChange = (value: any) => {
console.log('普通上传或上传首帧---', value)
let file = value.file
let bor = true
if (file.status === 'done') {
@@ -689,7 +730,6 @@ export default defineComponent({
}
}
const fileUploadChangeLast = (value: any) => {
console.log('上传尾帧 ---', value)
const file = value.file
if (file.status === 'done') {
const res = JSON.parse(file.xhr.response)
@@ -767,7 +807,6 @@ export default defineComponent({
if (props.isDesignPage) {
emit('unLike', item)
}
console.log(props.isDesignPage)
}
Https.axiosPost(Https.httpUrls.poselikeOrDisike, {}, { params: value })
.then(rv => {
@@ -883,9 +922,9 @@ export default defineComponent({
const videoType = ref(2)
const showMotion = computed(() => videoType.value === 1)
const options = ref([
{ vlaue: 2, label: 'First frame' },
{ value: 3, label: 'First and last frames' },
{ value: 1, label: 'First frame and skeleton' }
{ vlaue: 2, label: t('poseTransfer.FirstFrame') },
{ value: 3, label: t('poseTransfer.FirstAndLastFrames') },
{ value: 1, label: t('poseTransfer.FirstFrameAndSkeleton') }
])
onBeforeUnmount(() => {
@@ -904,8 +943,6 @@ export default defineComponent({
selectImgItem,
setSize,
setItemPosition,
gifPlay,
gifPause,
getgenerate,
getUploadUrl,
beforeUpload,
@@ -921,7 +958,11 @@ export default defineComponent({
locale,
videoType,
options,
showMotion
showMotion,
setVideoRef,
handlePlayMotion,
isVideoPlaying,
showTips
}
},
directives: {
@@ -1139,7 +1180,7 @@ export default defineComponent({
.icon-list {
height: 50%;
width: calc(100% - 1.6rem);
border-top: 1px solid #fff;
// border-top: 1px solid #fff;
display: flex;
box-sizing: border-box;
justify-content: flex-start;

View File

@@ -0,0 +1,30 @@
export const getFirstAndLastFrame = (t: (key: string) => string) => [
{ id: '1', type: 'text', value: t('poseTransfer.firstAndLastFrameText1') },
{
id: '2',
type: 'input',
value: '',
placeholder: t('poseTransfer.firstAndLastFramePlaceholder1')
},
{ id: '3', type: 'text', value: t('poseTransfer.firstAndLastFrameText2') },
{ id: '4', type: 'input', value: '', placeholder: t('poseTransfer.firstAndLastFramePlaceholder2') },
{
id: '5',
type: 'text',
value: t('poseTransfer.firstAndLastFrameText3')
}
]
export const getFirstFrame = (t: (key: string) => string) => [
{ id: '1', type: 'text', value: t('poseTransfer.firstFrameText1') },
{ id: '2', type: 'input', value: '', placeholder: t('poseTransfer.firstFramePlaceholder1') },
{ id: '3', type: 'text', value: t('poseTransfer.firstFrameText2') },
{ id: '4', type: 'input', value: '', placeholder: t('poseTransfer.firstFramePlaceholder2') },
{ id: '5', type: 'text', value: t('poseTransfer.firstFrameText3') },
{ id: '6', type: 'input', value: '', placeholder: t('poseTransfer.firstFramePlaceholder3') },
{ id: '7', type: 'text', value: t('poseTransfer.firstFrameText4') },
{ id: '8', type: 'input', value: '', placeholder: t('poseTransfer.firstFramePlaceholder4') },
{ id: '9', type: 'text', value: t('poseTransfer.firstFrameText5') },
{ id: '10', type: 'input', value: '', placeholder: t('poseTransfer.firstFramePlaceholder5') },
{ id: '11', type: 'text', value: t('poseTransfer.firstFrameText6') }
]

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, onMounted, reactive, toRefs, nextTick } from "vue";
import { ref, onMounted, reactive, toRefs, nextTick, useTemplateRef, watch } from "vue";
interface ContentItem {
id: string;
@@ -336,18 +336,62 @@ const initPlaceholders = () => {
}
const getFullText = () => {
return content.value.map(item => {
if (item.type === 'text') {
return item.value
} else {
// 只获取用户实际输入的值,即使为空也显示空括号
return `${item.value}`
}
}).join('')
if(assistModel.value){
return content.value.map(item => {
if (item.type === 'text') {
return item.value
} else {
// 如果 input 没有输入 value则用 placeholder 填充,并去掉首尾的 []
if (item.value) {
return ` ${item.value} `
} else if (item.placeholder) {
let placeholderText = item.placeholder
// 去掉首尾的 []
if (placeholderText.startsWith('[') && placeholderText.endsWith(']')) {
placeholderText = placeholderText.slice(1, -1)
}
return ` ${placeholderText} `
}
return ''
}
}).join('')
}
return textareaValue.value
}
const textareaValue = ref('')
const assistModel= ref(false)
const handleClickAssistBtn = () => {
assistModel.value = !assistModel.value
}
// 监听 assistModel 变化,切换到 textarea 模式时调整高度
watch(assistModel, (newVal) => {
if (!newVal) {
// 切换到 textarea 模式
nextTick(() => {
handleInputResize()
})
}
})
const textareaRef = useTemplateRef<HTMLTextAreaElement>('textareaRef')
const handleInputResize = () => {
const textarea = textareaRef.value
if (textarea) {
textarea.style.height = 'auto'
textarea.style.height = textarea.scrollHeight + 'px'
}
}
onMounted(() => {
initPlaceholders()
// 如果初始状态是 textarea 模式,设置初始高度
if (!assistModel.value) {
nextTick(() => {
handleInputResize()
})
}
})
defineExpose({
@@ -357,16 +401,42 @@ defineExpose({
</script>
<template>
<div ref="editableArea" class="promptInput" @keydown="handleKeydown" @click="handleContainerClick">
<div v-show="!assistModel" class="textarea-container">
<textarea
class="area"
v-model="textareaValue"
ref="textareaRef"
@input="handleInputResize"
:placeholder="$t('poseTransfer.PormptPlaceholder')"
/>
<div class="asistant-btn" @click="handleClickAssistBtn">
<i class="fi fi-bs-magic-wand asistant-icon"></i>
<span>{{ $t('ProductImg.PromptAssit') }}</span>
</div>
</div>
<div v-show="assistModel" ref="editableArea" class="promptInput" @keydown="handleKeydown" @click="handleContainerClick">
<template v-for="(item, index) in content" :key="item.id">
<span v-if="item.type === 'text'" class="text-field" :data-index="index" contenteditable="plaintext-only">{{
item.value }}</span>
<span
v-if="item.type === 'text'"
class="text-field"
:data-index="index"
contenteditable="plaintext-only">
{{item.value }}
</span>
<span v-else class="input-field" :data-index="index">
<span class="input-content" contenteditable="plaintext-only" @input="(e) => handleInputChange(index, e)"
@keydown="(e) => handleInputKeydown(e, index)" @blur="() => handleInputBlur(index)"></span>
<span
class="input-content"
contenteditable="plaintext-only"
@input="(e) => handleInputChange(index, e)"
@keydown="(e) => handleInputKeydown(e, index)"
@blur="() => handleInputBlur(index)"></span>
</span>
</template>
<div class="asistant-btn" @click="handleClickAssistBtn">
<i class="fi fi-bs-magic-wand asistant-icon"></i>
<span>{{ $t('ProductImg.PromptAssit') }}</span>
</div>
</div>
</template>
@@ -387,6 +457,9 @@ defineExpose({
white-space: pre-wrap;
user-select: text;
cursor: text;
position: relative;
padding-bottom: 4rem;
.text-field {
display: inline;
@@ -399,8 +472,8 @@ defineExpose({
.input-field {
display: inline-block;
background: #e3f2fd;
border: 1px solid #bbdefb;
// background: #e3f2fd;
// border: 1px solid #bbdefb;
margin: 0 .2rem;
padding: .2rem 1rem;
font-size: 1.8rem;
@@ -408,15 +481,62 @@ defineExpose({
.input-content {
outline: none;
color: #1976d2;
display: inline-block;
min-width: 2rem;
&.has-placeholder {
color: #95a5a6;
font-style: italic;
color: #b9b9b9;
// font-style: italic;
}
}
}
}
.textarea-container{
position: relative;
border-radius: 10px;
border: 2px solid #dcdfe6;
padding: 1.5rem 1.5rem 3rem;
height: auto;
.area{
width: 100%;
min-height: 12rem;
height: auto;
background: white;
line-height: 1.6;
outline: none;
white-space: pre-wrap;
user-select: text;
cursor: text;
position: relative;
// padding-bottom: 4rem;
resize: none;
border: none;
}
}
.asistant-btn {
height: 2.3rem;
padding: 0 0.6rem;
font-size: 1rem;
font-weight: 400;
color: #313131;
position: absolute;
bottom: 1.3rem;
left: 1.3rem;
display: flex;
column-gap: 0.3rem;
justify-content: center;
align-items: center;
background-color: #f2f2f2;
border: 1px solid #dfdfdf;
border-radius: 0.5rem;
cursor: pointer;
.asistant-icon {
font-size: 1rem;
margin-right: 0;
width: initial;
// margin-top: -0.2rem;
}
}
</style>

View File

@@ -311,8 +311,29 @@ export default {
'专业产品摄影:服装以自然形态展示,无模特。采用影棚灯光。保留精确细节——图案、色彩、质感、装饰元素。', // 上传线稿,不带模特
VideoType: '视频类型',
FirstFrame: '首帧',
LastFrame:'尾帧',
FirstAndLastFrames: '首帧和尾帧',
FirstFrameAndSkeleton: '首帧和骨架'
FirstFrameAndSkeleton: '首帧和骨架',
Tips: '提示',
TipsStart: '你可以使用"',
TipsEnd: '编辑产品图"来生成首帧或尾帧图片',
PormptPlaceholder:'输入你想描述的场景...',
firstAndLastFrameText1: '随着视频的进行,使用',
firstAndLastFramePlaceholder1: '[相机运动]',
firstAndLastFrameText2: '来跟随动作,在',
firstAndLastFramePlaceholder2: '[光线]',
firstAndLastFrameText3: '下,保持模型身份、风格和服装在所有帧中的完全一致性。',
firstFrameText1: '场景设置为',
firstFramePlaceholder1: '[场景]',
firstFrameText2: ',模特做',
firstFramePlaceholder2: '[拍摄动作]',
firstFrameText3: ',使用',
firstFramePlaceholder3: '[相机运动]',
firstFrameText4: '结合',
firstFramePlaceholder4: '[相机运动]',
firstFrameText5: ',在',
firstFramePlaceholder5: '[光线]',
firstFrameText6: '下,完善整体视觉效果。'
},
LibraryPage: {
library: '收藏',

View File

@@ -321,8 +321,29 @@ export default {
'Professional product photo: garment displayed with natural shape, no model. Studio lighting. Preserve exact details - patterns, colors, textures, embellishments.', // 上传线稿,不带模特
VideoType: 'Video Type',
FirstFrame: 'First frame',
LastFrame: 'Last frame',
FirstAndLastFrames: 'First and last frames',
FirstFrameAndSkeleton: 'First frame and skeleton',
Tips: 'Tips',
TipsStart: 'User can use ',
TipsEnd: 'Edit Product Image to generate first or last frames.',
PormptPlaceholder: 'Enter the scene you want to describe...',
firstAndLastFrameText1: 'As the video progresses, use',
firstAndLastFramePlaceholder1: '[Camera Movement]',
firstAndLastFrameText2: 'to follow the motion, under',
firstAndLastFramePlaceholder2: '[Light]',
firstAndLastFrameText3: ', maintaining full consistency of model identity, styling, and outfit across all frames.',
firstFrameText1: 'Set the',
firstFramePlaceholder1: '[Scene]',
firstFrameText2: ', where the model',
firstFramePlaceholder2: '[Motion]',
firstFrameText3: 'use a',
firstFramePlaceholder3: '[Camera Movement]',
firstFrameText4: 'combined with a',
firstFramePlaceholder4: '[Camera Movement]',
firstFrameText5: ', under',
firstFramePlaceholder5: '[Light]',
firstFrameText6: ', complementing the look.'
},
LibraryPage: {
library: 'Library',

View File

@@ -73,18 +73,14 @@ const HomeStoreModule : Module<DesignDetail,RootState> = {
state.showSketchList = data
},
setPoseTransferLastFrameList(state,data){
console.log('设置尾帧store-------------')
// 支持两种方式set 替换整个列表add/删除与 uploadElement 一致
if(data.str === 'set'){
state.poseTransfer.lastFrameList = data.list || []
state.lastFrameList = data.list || []
return
}
if(data.str === 'add'){
state.poseTransfer.lastFrameList.unshift(...(data.list || []))
}else{
state.poseTransfer.lastFrameList.splice(data.index,1)
state.lastFrameList = []
}
},
},
setDesignCollectionList(state,data){
state.designCollectionList = data
},