From 1edcef49f83d7c7e8c1fb3325e4e6ac5052e236c Mon Sep 17 00:00:00 2001 From: zhangyh Date: Wed, 19 Nov 2025 10:31:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BC=B9=E7=AA=97=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../home/design/editDesignType/index.vue | 507 ++++++++++++++++-- .../home/tools/poseTransfer/Product.vue | 2 +- .../home/tools/poseTransfer/promptInput.vue | 1 + 3 files changed, 455 insertions(+), 55 deletions(-) diff --git a/src/component/home/design/editDesignType/index.vue b/src/component/home/design/editDesignType/index.vue index 5cd05aca..d2aea53f 100644 --- a/src/component/home/design/editDesignType/index.vue +++ b/src/component/home/design/editDesignType/index.vue @@ -1,6 +1,9 @@ +
@@ -245,13 +324,31 @@ :src="generateCourse?.url || selectGenerate?.url" alt="" /> - +
+
@@ -260,6 +357,13 @@
+ @@ -281,9 +385,15 @@ import { downloadIamge, getMinioUrl, downloadVideoWithFetch } from '@/tool/util' import { useI18n } from 'vue-i18n' import { useStore } from 'vuex' import Prompt from '@/component/home/tools/toProduct/Prompt.vue' +import promptInput from '@/component/home/tools/poseTransfer/promptInput.vue' +import Product from '@/component/home/tools/poseTransfer/Product.vue' +import { + getFirstFrame, + getFirstAndLastFrame +} from '@/component/home/tools/poseTransfer/prompt' export default defineComponent({ - components: { Prompt }, + components: { Prompt, promptInput, Product }, props: { productData: { type: Object, @@ -314,6 +424,27 @@ export default defineComponent({ }) let { t } = useI18n() const textareaRef = useTemplateRef('textareaRef') + const videoType = ref(2) + const showMotion = computed(() => videoType.value === 1) + const options = ref([ + { value: 2, label: t('poseTransfer.FirstFrame') }, + { value: 3, label: t('poseTransfer.FirstAndLastFrames') }, + { value: 1, label: t('poseTransfer.FirstFrameAndSkeleton') } + ]) + + const firstFrameImage = ref(null) + const lastFrameImage = ref(null) + + const promptInputRef = useTemplateRef('promptInputRef') + const prompt = computed(() => { + if (videoType.value === 2) { + return getFirstFrame(t) + } + if (videoType.value === 3) { + return getFirstAndLastFrame(t) + } + }) + let productimg = reactive({ isGenerate: false, //判断是否进行generate textarea: null as any, @@ -391,7 +522,7 @@ export default defineComponent({ } let scaleImage: any = ref(false) let loadingShow = ref(false) - let isComparison = ref(false) + let isComparison = ref(false) // home/design组件中修改的,当前组件没有修改 const visible = ref(false) const setVisible = (value: any): void => { visible.value = value @@ -477,14 +608,14 @@ export default defineComponent({ return obj } const getPoseTransformData = () => { - return { + const params: any = { poseId: productimg.selectPose, projectId: productimg.selectObject.id, productImage: getMinioUrl( productimg.scaleImageList[productimg.scaleImageIndex].sourceUrl ), modelName: speed.speedData.value, - mode: 1, + mode: videoType.value, parentId: productimg.selectGenerate.parentId || productimg.selectGenerate.userLikeSortId, userLikeSortId: @@ -493,6 +624,38 @@ export default defineComponent({ : null, isDefaultLike: true //表示是否生成就like } + + // 使用首帧/尾帧选择覆盖默认的源图 + if (videoType.value === 2 || videoType.value === 3) { + if (firstFrameImage.value) { + const src = + firstFrameImage.value.miniourl || + firstFrameImage.value.minioUrl || + firstFrameImage.value.productImage || + firstFrameImage.value.url || + firstFrameImage.value.imgUrl + if (src) { + params.productImage = getMinioUrl(src) + } + } + } + + if (videoType.value === 3 && lastFrameImage.value) { + const lastSrc = + lastFrameImage.value.miniourl || + lastFrameImage.value.minioUrl || + lastFrameImage.value.productImage || + lastFrameImage.value.url || + lastFrameImage.value.imgUrl + if (lastSrc) { + params.lastFrameProductImage = getMinioUrl(lastSrc) + } + } + if (videoType.value !== 1) { + const prompt = promptInputRef.value.getFullText() + params.prompt = prompt + } + return params } let getPrductimg = async () => { let obj = getData() @@ -901,6 +1064,44 @@ export default defineComponent({ } } } + // 生成结果视频的引用和播放状态 + const generateResultVideoRef = ref(null) + const isGenerateResultVideoPlaying = ref(false) + + // 设置生成结果视频 ref + const setGenerateResultVideoRef = (el: HTMLVideoElement | null) => { + if (el) { + generateResultVideoRef.value = el + // 初始化播放状态 + isGenerateResultVideoPlaying.value = !el.paused + // 监听播放事件 + el.addEventListener('play', () => { + isGenerateResultVideoPlaying.value = true + }) + // 监听暂停事件 + el.addEventListener('pause', () => { + isGenerateResultVideoPlaying.value = false + }) + // 监听结束事件 + el.addEventListener('ended', () => { + isGenerateResultVideoPlaying.value = false + }) + } + } + + // 播放/暂停生成结果视频 + const handlePlayGenerateResult = () => { + const video = generateResultVideoRef.value + if (video) { + if (video.paused) { + video.play().catch(err => { + console.error('播放视频失败:', err) + }) + } else { + video.pause() + } + } + } const setSelectPose = (item: any, index: number) => { productimg.poseList.forEach((poseItem: any) => { poseItem.isChecked = false @@ -960,6 +1161,51 @@ export default defineComponent({ const newHeight = textarea.scrollHeight textarea.style.height = newHeight + 'px' } + + const showProductList = ref(false) + const productType = ref('first') + const fullProductImages = computed(() => { + return productimg.likeDesignCollectionList.flatMap(item => item.childList || []) + }) + const handleOpenProduct = (type: 'first' | 'last') => { + productType.value = type + showProductList.value = true + } + + const handleConfirmProduct = ({ data: productData }: { data: any }) => { + if (!productData) return + if (productType.value === 'first') { + firstFrameImage.value = productData + } else if (productType.value === 'last') { + lastFrameImage.value = productData + } + showProductList.value = false + } + + const handleDeleteFrame = (type: 'first' | 'last') => { + if (type === 'first') { + firstFrameImage.value = null + } else if (type === 'last') { + lastFrameImage.value = null + } + } + + const isPoseTransfer = computed(() => { + return ( + productimg.scaleImageList[productimg.scaleImageIndex]?.resultType === + 'PoseTransfer' + ) + }) + + const showCompare = computed(() => { + // isComparison.value + if (!isPoseTransfer.value) { + return isComparison.value + } else { + return videoType.value === 3 ? false : true + } + }) + onBeforeUnmount(() => { clearInterval(prductimgTime) clearInterval(remPrductimgTime) @@ -992,13 +1238,31 @@ export default defineComponent({ setVideoRef, handlePlayMotion, isVideoPlaying, + setGenerateResultVideoRef, + handlePlayGenerateResult, + isGenerateResultVideoPlaying, generateProceedList, init, cancelDsign, prductimgTime, remPrductimgTime, ifMaximumLength, - textareaRef + textareaRef, + videoType, + options, + showMotion, + prompt, + promptInputRef, + firstFrameImage, + lastFrameImage, + handleOpenProduct, + handleConfirmProduct, + handleDeleteFrame, + productType, + showProductList, + fullProductImages, + isPoseTransfer, + showCompare } }, data() { @@ -1091,8 +1355,13 @@ export default defineComponent({ .editDesignType_modal { overflow: visible !important; } +.generalModel.posetransfer { + .ant-modal-body { + padding: 4.5rem 7rem; + } +} - diff --git a/src/component/home/tools/poseTransfer/Product.vue b/src/component/home/tools/poseTransfer/Product.vue index 8960cf94..5dcaa159 100644 --- a/src/component/home/tools/poseTransfer/Product.vue +++ b/src/component/home/tools/poseTransfer/Product.vue @@ -200,7 +200,7 @@ const handleConfirm = () => { img { width: 100%; height: 100%; - object-fit: cover; + object-fit: contain; display: block; } diff --git a/src/component/home/tools/poseTransfer/promptInput.vue b/src/component/home/tools/poseTransfer/promptInput.vue index e8e188c9..c38b7c8c 100644 --- a/src/component/home/tools/poseTransfer/promptInput.vue +++ b/src/component/home/tools/poseTransfer/promptInput.vue @@ -509,6 +509,7 @@ defineExpose({ border: 2px solid #dcdfe6; padding: 1.5rem 1.5rem 3rem; height: auto; + font-size: 1.8rem; .area { width: 100%; min-height: 12rem;