Files
aida_front/src/component/home/tools/poseTransfer/index.vue
2025-11-14 15:20:46 +08:00

1342 lines
40 KiB
Vue

<template>
<div class="poseTransfer">
<div class="configuratioBox" :class="{ active: button.left }">
<div class="configuratio">
<div class="content">
<div class="video-type-container">
<div class="title">{{ $t('poseTransfer.VideoType') }}</div>
<a-select
class="video-type-selection"
v-model:value="videoType"
size="large"
placeholder="Please select"
>
<a-select-option
v-for="item in options"
:key="item.vlaue"
:value="item.value"
>
{{ item.label }}
</a-select-option>
</a-select>
</div>
<div class="selectImg">
<div class="head">
<div class="text">{{ $t('poseTransfer.SelectDesign') }}</div>
<i
v-show="videoType !== 2"
class="fi fi-rs-interrogation tips-icon"
@click="showTips = true"
/>
</div>
<div class="imgBox" v-mousewheel>
<div
class="item"
:class="{ active: item.id == selectImg.id }"
v-for="(item, index) in fileList"
@click="selectImgItem(item)"
>
<div
class=""
v-if="item.status == 'uploading'"
style="display: flex; align-items: center"
>
<a-spin size="large" />
</div>
<img
v-show="item.designOutfitUrl || item.imgUrl || item.url"
:src="item.designOutfitUrl || item.imgUrl || item.url"
alt=""
/>
<div
v-show="item.designOutfitUrl || item.imgUrl || item.url"
class="btnBox"
>
<div :class="{ active: item.isChecked }">
<i class="fi fi-br-check"></i>
</div>
<div
@click.stop="setUploadDelete(item, index)"
v-if="source != 'design'"
>
<i class="fi fi-rr-trash icon_delete"></i>
</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,
type: 'first'
}"
: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,
type: 'last'
}"
: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 }"
v-for="(item, index) in lastFrameList"
@click="selectImgItem(item, true)"
>
<div
class=""
v-if="item.status == 'uploading'"
style="display: flex; align-items: center"
>
<a-spin size="large" />
</div>
<img
v-show="item.designOutfitUrl || item.imgUrl || item.url"
:src="item.designOutfitUrl || item.imgUrl || item.url"
alt=""
/>
<div
v-show="item.designOutfitUrl || item.imgUrl || item.url"
class="btnBox"
>
<div :class="{ active: item.isChecked }">
<i class="fi fi-br-check"></i>
</div>
<div
@click.stop="setUploadDelete(item, index)"
v-if="source != 'design'"
>
<i class="fi fi-rr-trash icon_delete"></i>
</div>
</div>
</div>
</template>
</div>
</div>
<div class="prompt-input-container" v-show="!showMotion">
<div class="title">{{ $t('ProductImg.Prompt') }}</div>
<promptInput :content="prompt" ref="promptInput" />
</div>
<div class="poses" v-show="showMotion">
<div class="head">
<div class="text">{{ $t('poseTransfer.Selectpose') }}</div>
</div>
<div class="imgBox" v-mousewheel>
<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>
</div>
</div>
<div class="control-container">
<div class="icon-list">
<SvgIcon
v-show="!isVideoPlaying(item.id)"
class="play-icon"
@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>
</div>
</div>
</div>
</div>
<div class="generage_btn_box" style="margin-left: auto">
<!-- <div class="generage_btn started_btn" v-show="!isGenerate" @click="getgenerate">
{{ $t('Generate.Generate') }}
</div> -->
<div class="generage_btn started_btn" v-show="!isGenerate">
<i
class="fi fi-bs-magic-wand"
style="background-color: #000; font-size: 2.3rem; flex: 1; margin: 0"
@click="getgenerate()"
></i>
<div
class="icon iconfont icon-xiala"
:class="{ active: speedState }"
@click.stop="openSpeed"
></div>
<div class="content" v-show="speedState">
<div
v-for="item in speedList"
:key="item.value"
:class="{ active: item.value == speedData.value }"
@click.stop="setSpeed(item)"
:title="item.title"
>
{{ item.label }}
</div>
</div>
</div>
<div v-show="isGenerate" class="generage_btn started_btn">
<i class="fi fi-br-loading"></i>
</div>
<!-- <div v-show="isGenerate && remGenerate" class="generage_btn started_btn">
<i class="fi fi-br-loading"></i>
</div> -->
<!-- <div v-show="remGenerate" @click="setRemoveGenerate" class="generage_btn started_btn">
{{$t('Generate.Close')}}
</div> -->
</div>
</div>
<div class="likeBox">
<!-- {{ locale }}
<img src="@/assets/images/homePage/toolsGuide/productCN.png" alt="">
<img src="@/assets/images/homePage/toolsGuide/productEN.png" alt=""> -->
<div class="element">
<div class="title">
<i class="fi fi-rs-comments"></i>
<span>{{ $t('poseTransfer.LikeVideo') }}</span>
</div>
<div class="content">
<generalDrag
ref="generalDragLeft"
:list="likeList"
:isLike="true"
:isVideo="true"
@setBtn="likeSetBtn"
></generalDrag>
</div>
<!-- <div class="btnLeft" @click="setSize('left')" :class="{'active':button.left}">
<span class="icon iconfont icon-xiala"></span>
</div> -->
<div class="btnRight" @click="setSize('right')" :class="{ active: button.right }">
<span class="icon iconfont icon-xiala"></span>
</div>
</div>
</div>
<div class="noLikeBox" :class="{ active: button.right, designPage: isDesignPage }">
<div class="element">
<div class="title">
<i class="fi fi-rs-comments"></i>
<span>{{ $t('poseTransfer.InputVideo') }}</span>
</div>
<div class="content">
<generalDrag
ref="generalDragRight"
:list="noLikeList"
:isVideo="true"
@setBtn="noLikeSetBtn"
></generalDrag>
</div>
</div>
</div>
<Tips v-model:showModal="showTips" />
</div>
</template>
<script lang="ts">
import {
defineComponent,
computed,
ref,
inject,
nextTick,
watch,
createVNode,
toRefs,
reactive,
onMounted
} from 'vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'
import { Https } from '@/tool/https'
import { useStore } from 'vuex'
import { Upload, message, Modal } from 'ant-design-vue'
import { useI18n } from 'vue-i18n'
import generalDrag from '@/component/modules/generalDrag.vue'
import { getUploadUrl, isMoible, getMinioUrl } from '@/tool/util'
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,
Tips
},
props: {
isDesignPage: {
type: Boolean,
default: false
},
source: {
type: String,
default: ''
}
},
emit: ['unLike'],
setup(props, { emit }) {
const { t, locale } = useI18n()
const store = useStore()
const route = useRoute()
const data: any = reactive({
button: {
left: false,
right: false
},
currentList: [],
fileList: [], // 默认上传图片的fileList
lastSelectImg: {}, // 选中的尾帧
selectImg: {},
token: getCookie('token'),
upload: {
projectId: computed(() => store.state.Workspace.probjects.id),
type: 'first' // first首帧 last尾帧
},
waitList: [],
likeList: computed(() => {
if (!route.query?.id && route.query.tools == 'poseTransfer') {
return []
} else {
return store.state.HomeStoreModule.poseTransfer.likedList
}
}),
noLikeList: computed(() => {
if (!route.query?.id && route.query.tools == 'poseTransfer') {
return []
} else {
return store.state.HomeStoreModule.poseTransfer.list
}
}),
isGenerate: false, //判断是否正在进行generate
remGenerate: false,
removeGenerate: false,
generateTime: null as any,
poseList: [],
selectPose: null as any,
prompt: computed(() => {
if (videoType.value === 2) {
return getFirstFrame(t)
}
if (videoType.value === 3) {
return getFirstAndLastFrame(t)
}
})
})
let speed = reactive({
speedList: [
{
title: '',
label: t('speedList.toproductBasic'),
value: ''
},
{
title: '',
label: t('speedList.toproductFlus'),
value: 'wx'
}
],
speedState: false,
speedData: {
title: 'Generate high-quality content',
label: t('speedList.toproductBasic'),
value: ''
}
})
const showTips = ref(false)
const setIsShowMark: any = inject('setIsShowMark')
const createProbject: any = inject('createProbject', () => {})
const dataDom = reactive({
generalDragLeft: null as any,
generalDragRight: null as any,
scaleVideo: null as any,
promptInput: null as any
})
const selectImgItem = (item: any, isLastFrame = false) => {
// 如果点击已选中的项,则取消选中并清除对应选择
if (item.isChecked) {
item.isChecked = false
if (isLastFrame) {
data.lastSelectImg = {}
} else {
data.selectImg = {}
}
return
}
// 处理尾帧选择
if (isLastFrame) {
;(lastFrameList.value || []).forEach(
(listItem: any) => (listItem.isChecked = false)
)
item.isChecked = true
data.lastSelectImg = item
if (item.url || item.imgUrl) {
data.lastSelectImg.minioUrl = getMinioUrl(item.url || item.imgUrl)
}
return
}
// 处理首帧选择
data.fileList.forEach((listItem: any) => (listItem.isChecked = false))
data.currentList.forEach((listItem: any) => (listItem.isChecked = false))
item.isChecked = true
data.selectImg = item
if (item.url || item.imgUrl) {
data.selectImg.minioUrl = getMinioUrl(item.url || item.imgUrl)
}
}
const openSetData = (designList: any) => {
if (props.isDesignPage) {
//标识design页面打开的tools
data.fileList = designList
} else {
data.currentList = store.state.UploadFilesModule.modularData.toProduct
data.currentList = data.currentList ? data.currentList : []
setIsShowMark(false)
}
// dataDom.generalDrag.openSetData()
if (data.poseList.length == 0) {
getPoseList()
}
}
// 存储视频元素的引用
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 isVideoPlaying = (id: number) => {
return videoPlayingStates.value[id] || false
}
// 播放视频
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
data.selectPose = rv[0]?.id || 1
data.poseList = rv
})
}
const setSize = (str: any) => {
data.button[str] = !data.button[str]
setItemPosition()
}
const setItemPosition = () => {
setTimeout(() => {
dataDom.generalDragLeft.setItemPosition()
dataDom.generalDragRight.setItemPosition()
}, 200)
}
const getgenerate = async () => {
if (!data.selectImg.minioUrl) return message.info(t('ProductImg.jsContent2'))
if (data.isGenerate) return
await new Promise((res, reject) => {
Modal.confirm({
title: t('poseTransfer.jsContent1'),
icon: createVNode(ExclamationCircleOutlined),
okText: 'Yes',
cancelText: 'No',
mask: false,
centered: true,
onOk() {
res()
},
cancel() {
reject()
}
})
})
data.isGenerate = true
// data.remGenerateTime = setTimeout(()=>{
// },10000)
let value = {
poseId: data.selectPose,
projectId: store.state.Workspace.probjects.id,
productImage: data.selectImg.minioUrl,
modelName: speed.speedData.value,
isDefaultLike: false, //表示是否生成就like
parentId: data.selectImg?.parentId, //parentId 添加在指定父级里面
userLikeSortId: null, //是否进行排序
mode: videoType.value
}
if (videoType.value === 2) {
const prompt = dataDom.promptInput.getFullText()
value.prompt = prompt
}
if (videoType.value === 3) {
const prompt = dataDom.promptInput.getFullText()
value.prompt = prompt
const lastFrameProductImage = data.lastSelectImg.minioUrl
value.lastFrameProductImage = lastFrameProductImage
}
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]
data.waitList = list
let state = true
data.generateTime = setInterval(() => {
if (!data.isGenerate || !data.remGenerate) return
if (!state) return
state = false
Https.axiosPost(Https.httpUrls.poseTransformResult, list)
.then(rv => {
state = true
if (data.isGenerate) {
//防止取消后有正在执行的获取状态
// data.waitList = rv.filter((item:any)=>item.status != 'Success' && item.status != 'Fail' && item.status != 'Invalid')
rv.forEach((element: any) => {
if (element.status == 'Success') {
element.url = element.firstFrameUrl
let index = data.noLikeList.findIndex(
(obj: any) => obj.taskId === element.taskId
)
data.noLikeList[index] = element
list = ''
clearInterval(data.generateTime)
clearInterval(data.remGenerateTime)
data.remGenerate = false
data.isGenerate = false
// if(list?.filter)list = list?.filter((item:any) => item !== element.taskId);
store.dispatch('getCredits')
} else if (element.status == 'Fail') {
let index = data.noLikeList.findIndex(
(obj: any) => obj.taskId === element.taskId
)
message.info(t('ProductImg.jsContent3'))
data.noLikeList.splice(index, 1)
clearInterval(data.generateTime)
clearInterval(data.remGenerateTime)
data.remGenerate = false
data.isGenerate = false
store.dispatch('getCredits')
}
})
}
})
.catch(res => {
let index = data.noLikeList.findIndex((obj: any) => obj.taskId === list)
data.noLikeList.splice(index, 1)
clearInterval(data.generateTime)
clearInterval(data.remGenerateTime)
data.isGenerate = false
data.remGenerate = false
})
}, 10000)
}
const setRemoveGenerate = () => {
//取消操作
data.isGenerate = false
data.remGenerate = false
clearInterval(data.generateTime)
if (data.waitList) {
// let str = data.waitList.map((obj:any) => obj.taskId).join(',');
let value = {
uniqueId: data.waitList[0],
userId: store.state.UserHabit.userDetail.userId,
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
type: 'PoseTransferation'
}
Https.axiosGet(Https.httpUrls.generateStopWaiting, { params: value })
.then(rv => {
data.waitList = []
const indexes = data.noLikeList
.map((item, index) => (item?.status !== 'Success' ? index : -1))
.filter(index => index !== -1)
indexes.forEach((itemIndex: number) => {
data.noLikeList.splice(itemIndex, 1)
})
})
.catch(res => {})
}
}
let isSelectObject = false
watch(
() => route?.query,
newVal => {
if (!newVal.id) {
isSelectObject = false
}
},
{ immediate: true }
)
let beforeUpload = async (file: any) => {
const isJpgOrPng =
file.type === 'image/jpeg' ||
file.type === 'image/png' ||
file.type === 'image/jpg' ||
file.type === 'image/bmp'
if (!isJpgOrPng) {
message.info(useI18n().t('MoodboardUpload.jsContent3'))
}
const isLt2M = file.size / 1024 / 1024 < 5
if (!isLt2M) {
message.info(useI18n().t('MoodboardUpload.jsContent4'))
}
if (!data?.upload?.projectId && !isSelectObject) {
isSelectObject = true
await createProbject()
}
return (isJpgOrPng && isLt2M && data.upload.projectId) || Upload.LIST_IGNORE
}
const fileUploadChange = (value: any) => {
let file = value.file
let bor = true
if (file.status === 'done') {
let res = JSON.parse(file.xhr.response)
if (res.errCode == 0) {
file.imgUrl = res.data.url
file.id = res.data.id
data.currentList.forEach((listItem: any) => (listItem.isChecked = false))
// data.fileList.forEach((listItem:any)=>{
// if(listItem.id == file.id){
// listItem.isChecked = true
// }else{
// listItem.isChecked = false
// }
// })
file.type = 'ProductElement'
// if(props.productimgMenu.value == 'Relight'){
// file.type = "ToProductImage"
// }
data.selectImg = res.data
// data.fileList.filter((v: any) => v.status === "done");
let storeData = {
str: 'add',
list: [file]
}
store.commit('setUploadElement', storeData)
} else {
bor = false
}
} else if (file.status === 'error') {
bor = false
}
}
const fileUploadChangeLast = (value: any) => {
const file = value.file
if (file.status === 'done') {
const res = JSON.parse(file.xhr.response)
if (res.errCode == 0) {
file.imgUrl = res.data.url
file.id = res.data.id
file.type = 'ProductElement'
// 取消尾帧列表选中状态
;(value?.fileList || []).forEach(
(listItem: any) => (listItem.isChecked = false)
)
// 设置当前为选中并记录选择
file.isChecked = true
data.lastSelectImg = res.data
}
}
// 同步尾帧文件列表到全局 store
store.commit('setPoseTransferLastFrameList', {
str: 'set',
list: [file]
})
}
const likeSetBtn = (id: any, str: string) => {
data.likeList.forEach((item: any, index: any) => {
if (item.id == id && id) {
if (str == 'zoom') {
showViewVideo({ url: item.videoUrl })
} else if (str == 'like') {
likeFile(item, 'noLike', index)
}
}
})
}
const noLikeSetBtn = (id: any, str: string) => {
if (str == 'delete') {
let value = {
id,
projectId: store.state.Workspace.probjects.id
}
Https.axiosGet(Https.httpUrls.generateDeleteResult, { params: value }).then(
() => {
let index = data.noLikeList.findIndex((v: any) => v.id == id)
data.noLikeList.splice(index, 1)
}
)
} else {
data.noLikeList.forEach((item: any, index: any) => {
if (item.id == id && id) {
if (str == 'zoom') {
showViewVideo({ url: item.videoUrl })
} else if (str == 'like') {
likeFile(item, 'like', index)
}
}
})
}
}
let likeFile = (item: any, str: any, index: any) => {
let url
let value = {}
if (str == 'like') {
value = {
likeOrDislike: 'like',
transformedId: item.id,
projectId: store.state.Workspace.probjects.id,
collectionSortParentId: props.isDesignPage ? item.parentId : ''
}
} else {
value = {
likeOrDislike: 'dislike',
transformedId: item.id,
projectId: store.state.Workspace.probjects.id,
collectionSortParentId: props.isDesignPage ? item.parentId : ''
}
if (props.isDesignPage) {
emit('unLike', item)
}
}
Https.axiosPost(Https.httpUrls.poselikeOrDisike, {}, { params: value })
.then(rv => {
if (str == 'like') {
item.newLike = true
let value = {
likedList: [
{
...item,
sort: rv.sort,
parentId: rv.parentId
}
],
str: 'add',
index: -1
}
store.commit('setPoseTransfer', value)
data.noLikeList.splice(index, 1)
} else {
let value = {
likedList: [
{
...item
}
],
str: 'splice',
index: index
}
data.noLikeList.push(item)
store.commit('setPoseTransfer', value)
}
})
.catch(res => {})
}
const selectPose = (item: any) => {
data.poseList.forEach((listItem: any) => (listItem.isChecked = false))
item.isChecked = true
data.selectPose = item?.id || 1
}
const openSpeed = () => {
speed.speedState = !speed.speedState
if (speed.speedState) {
document.addEventListener('click', openSpeed)
} else {
document.removeEventListener('click', openSpeed)
}
}
const setSpeed = (item: any) => {
speed.speedData = item
speed.speedState = false
document.removeEventListener('click', openSpeed)
}
const setUploadDelete = (item: any, index: any) => {
let value = {
id: item.id
}
Https.axiosPost(
Https.httpUrls.toProductImageElementDelete,
{},
{ params: value }
).then(rv => {
let storeData = {
str: 'delete',
index
}
store.commit('setUploadElement', storeData)
})
}
watch(
() => store.state.HomeStoreModule.uploadElement.length,
(newVal, oldVal) => {
if (props.isDesignPage) return
data.fileList = store.state.HomeStoreModule.uploadElement.filter(
item => item.frameType === 'first'
)
lastFrameList.value = store.state.HomeStoreModule.uploadElement.filter(
item => item.frameType === 'last'
)
data.fileList.forEach((listItem: any) => {
if (listItem.id == data.selectImg.id) {
listItem.isChecked = true
} else {
listItem.isChecked = false
}
})
}
)
// 全局维护尾帧上传列表,保持与主上传一致
const lastFrameList = ref([])
watch(
() => store.state.HomeStoreModule.lastFrameList,
val => {
if (props.isDesignPage) return
lastFrameList.value = val
if (val.length > 0) {
val[0].isChecked = true
}
},
{ immediate: true }
)
watch(
() => data.noLikeList.length,
(newVal, oldVal) => {
nextTick(() => {
let list = store.state.HomeStoreModule.poseTransfer.list
let taskIdList = list.filter((item: any) => !item.videoUrl)[0]
if (taskIdList?.length > 0) {
data.isGenerate = true
data.remGenerate = true
setGenerate(taskIdList[0].taskId)
}
})
},
{ immediate: true }
)
const videoType = ref(2)
const showMotion = computed(() => videoType.value === 1)
const options = ref([
{ vlaue: 2, label: t('poseTransfer.FirstFrame') },
{ value: 3, label: t('poseTransfer.FirstAndLastFrames') },
{ value: 1, label: t('poseTransfer.FirstFrameAndSkeleton') }
])
onBeforeUnmount(() => {
clearInterval(data.generateTime)
clearInterval(data.remGenerateTime)
data.isGenerate = false
data.remGenerate = false
})
return {
...toRefs(speed),
...toRefs(dataDom),
...toRefs(data),
lastFrameList,
openSetData,
selectImgItem,
setSize,
setItemPosition,
getgenerate,
getUploadUrl,
beforeUpload,
fileUploadChange,
fileUploadChangeLast,
setRemoveGenerate,
likeSetBtn,
noLikeSetBtn,
selectPose,
openSpeed,
setSpeed,
setUploadDelete,
locale,
videoType,
options,
showMotion,
setVideoRef,
handlePlayMotion,
isVideoPlaying,
showTips
}
},
directives: {
mousewheel: {
mounted(el) {
el.addEventListener(
'wheel',
(e: WheelEvent) => {
let num = 0
if (e.deltaY > 0) {
num = 25
} else {
num = -25
}
el.scrollBy(num, 0)
},
{ passive: true }
)
}
}
},
provide() {
return {}
}
})
</script>
<style lang="less" scoped>
.poseTransfer {
width: 100%;
height: 100%;
position: relative;
font-size: 2rem;
font-weight: 900;
display: flex;
> .configuratioBox {
display: flex;
flex-direction: column;
align-items: center;
padding-right: 3.8rem;
width: 39rem;
&.active {
width: 0;
overflow: hidden;
}
> .generate {
margin-left: auto;
> .started_btn {
font-weight: 300;
}
.generage_btn {
width: 10rem;
position: relative;
}
.icon-xiala {
margin-left: 1rem;
transition: all 0.3s;
cursor: pointer;
&.active {
transform: rotate(180deg);
}
}
.content {
position: absolute;
top: 100%;
width: 100%;
left: 0rem;
text-align: center;
border-radius: calc(1rem * 1.2);
overflow: hidden;
z-index: 3;
margin-top: 0.2rem;
> div {
background: #cccccc;
line-height: 2;
font-size: 1.8rem;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&.active {
background-color: #616161;
}
}
> div:hover {
background: #999999;
}
}
}
}
> .configuratioBox > .configuratio {
width: 100%;
padding-bottom: 1rem;
> .content {
> .selectImg,
> .poses {
display: flex;
flex-direction: column;
> .imgBox {
flex: 1;
max-height: 45rem;
margin-top: 2rem;
display: flex;
flex-wrap: nowrap;
width: 100%;
overflow: hidden;
overflow-x: auto;
column-gap: 2.4rem;
position: relative;
> .item {
width: 12.7rem;
height: 17.8rem;
cursor: pointer;
overflow: hidden;
display: flex;
justify-content: center;
flex-shrink: 0;
position: relative;
:deep(.ant-checkbox-wrapper) {
position: absolute;
top: 2rem;
right: 2rem;
}
> .btnBox {
position: absolute;
right: 1rem;
top: 1rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
> div {
width: 2rem;
height: 2rem;
display: flex;
border: 1px solid;
align-items: center;
border-radius: 0.5rem;
justify-content: center;
cursor: pointer;
margin-bottom: 1rem;
> i {
display: flex;
}
> .fi-br-check {
color: #fff;
display: none;
}
&.active {
background: #000;
> i {
display: flex;
color: #fff;
}
}
}
}
> .btnBox {
position: absolute;
right: 1rem;
top: 1rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
> div {
width: 2rem;
height: 2rem;
display: flex;
border: 1px solid;
align-items: center;
border-radius: 0.5rem;
justify-content: center;
cursor: pointer;
margin-bottom: 1rem;
> i {
display: flex;
}
> .fi-br-check {
color: #fff;
display: none;
}
&.active {
background: #000;
> i {
display: flex;
color: #fff;
}
}
}
}
> img {
width: 100%;
object-fit: contain;
border: 1px solid #d0d0d0;
}
}
> .upload_item {
border: none;
}
.control-container {
width: 100%;
height: 3.3rem;
position: absolute;
bottom: 0;
left: 0;
background: linear-gradient(
180deg,
rgba(8, 9, 13, 0) 0%,
rgba(8, 9, 13, 0.27) 80.37%
);
display: flex;
align-items: flex-end;
justify-content: center;
.icon-list {
height: 50%;
width: calc(100% - 1.6rem);
// border-top: 1px solid #fff;
display: flex;
box-sizing: border-box;
justify-content: flex-start;
align-items: center;
.play-icon {
width: initial;
height: initial;
}
}
}
}
> .head {
color: #000;
font-weight: 600;
display: flex;
align-items: center;
column-gap: 1rem;
.tips-icon {
cursor: pointer;
display: flex;
}
> .text {
// display: inline-block;
font-size: 1.6rem;
}
}
}
.prompt-input-container {
margin-top: 4rem;
}
.title {
font-size: 1.8rem;
color: #000;
margin-bottom: 1.4rem;
}
> .poses {
margin-top: 3rem;
}
}
}
> .likeBox,
> .noLikeBox {
flex: 1;
position: relative;
> .element {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
> .btnLeft,
> .btnRight {
position: absolute;
width: 3rem;
height: 7rem;
background: #fff;
border: 2px solid;
border-right: none;
border-radius: 2rem 0 0 2rem;
top: 50%;
transform: translate(-100%, -50%);
left: 0;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
cursor: pointer;
transition: all 0.3s;
> span {
transition: all 0.3s;
transform: rotate(90deg);
}
&.active {
> span {
transform: rotate(270deg);
}
}
}
> .btnRight {
left: calc(100% + 3rem);
transform: translate(-100%, -50%) rotate(180deg);
&:hover {
width: 4rem;
left: calc(100% + 4rem);
}
}
> .content {
flex: 1;
overflow: hidden;
padding: 1.7rem 2rem;
border-radius: 3rem;
background: #f7f8fa;
}
> .title {
margin-bottom: 2rem;
font-size: 1.6rem;
font-weight: 900;
> span {
margin-left: 1rem;
}
}
}
}
> .designPage {
margin-right: 4rem;
}
> .noLikeBox {
padding-left: 2.3rem;
&.active {
flex: 0;
overflow: hidden;
}
}
.upload_file_item {
width: 100%;
height: 100%;
:deep(.ant-upload-picture-card-wrapper) {
width: 100% !important;
height: 100%;
.ant-upload-list-picture-card {
width: 100%;
height: 100%;
.ant-upload-select-picture-card {
width: 100%;
height: 100%;
border: 1px solid #000;
background: #fff;
}
}
}
}
.video-type-container {
margin-bottom: 4rem;
.title {
font-size: 1.8rem;
color: #000;
margin-bottom: 1.4rem;
}
:deep(.ant-select) {
width: 100%;
.ant-select-selector {
border: 2px solid #d0d0d0;
border-radius: 1rem;
}
}
}
}
</style>