调整部分bug

This commit is contained in:
X1627315083
2025-05-28 10:28:07 +08:00
parent 608a4dec89
commit 9fc2bcaedf
78 changed files with 2034 additions and 10193 deletions

View File

@@ -0,0 +1,437 @@
<template>
<div class="createCloud" ref="createCloud"></div>
<a-modal
class="createCloud_modal generalModel"
v-model:visible="operationsModal"
:footer="null"
:get-container="() => $refs.createCloud"
width="50%"
:height="'77rem'"
:maskClosable="false"
:centered="true"
:closable="false"
:mask="true"
wrapClassName="#app"
:keyboard="false"
>
<div class="generalModel_btn">
<div class="generalModel_closeIcon" @click.stop="cancelDsign()">
<svg width="46" height="46" viewBox="0 0 46 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="23" cy="23" r="23" fill="white" fill-opacity="0.3"/>
<rect x="32.5063" y="12" width="3" height="29" rx="1.5" transform="rotate(45 32.5063 12)" fill="#000"/>
<rect x="34.6274" y="32.5059" width="3" height="29" rx="1.5" transform="rotate(135 34.6274 32.5059)" fill="#000"/>
</svg>
</div>
</div>
<div class="modal_title_text">
<div>Create Cloud Generation Tasks</div>
</div>
<div class="allUserPoeration_center admin_page">
<div class="admin_state_item">
<span>Task type <span>*</span></span>
<a-select
v-model:value="buildType"
allowClear
style="width: 200px"
placeholder="Please select"
:options="cloudList"
@change="changeBuildType"
></a-select>
</div>
<div class="admin_state_item" v-show="buildType">
<span>Quantity <span>*</span></span>
<input
v-model="numberOfImages"
placeholder="Please enter number"
type="text"
style="width: 200px"
@input="changeNumberOfImages"
/>
</div>
<!-- toProductimg -->
<div v-show="buildType == 'toProductImage'" class="admin_state_item ">
<span>{{$t('ProductImg.Similarity')}}</span>
<div class="sliderAndImput" style="width: 200px">
<a-slider class="system_silder"
v-model:value="similarity"
:tooltipVisible="false"
:step="5"
>
</a-slider>
<input type="number" readonly v-model="similarity">
</div>
</div>
<div v-show="buildType == 'relight'" class="admin_state_item ">
<span>{{$t('ProductImg.RelightDirection')}}</span>
<a-select style="width: 200px" v-model:value="relightDirection" :options="relightDirectionList"></a-select>
</div>
<div v-show="buildType == 'relight'" class="admin_state_item ">
<span>{{$t('ProductImg.Highlight')}}</span>
<div class="sliderAndImput" style="width: 200px">
<a-slider class="system_silder"
v-model:value="brightenValue"
:tooltipVisible="false"
:max="3"
:min="1"
:step="0.1"
>
</a-slider>
<input type="number" readonly v-model="brightenValue">
</div>
</div>
<div v-show="buildType == 'toProductImage' || buildType == 'relight'" class="admin_state_item">
<span>Keyword</span>
<input
v-model="generateText"
:placeholder="$t('Generate.inputContent1')"
type="text"
style="width: 200px"
/>
</div>
<div class="selectImgList generalScroll" v-mousewheel v-show="exhibitionImgList.length>0">
<div v-for="item in exhibitionImgList" class="item">
<img :src="item.designOutfitUrl||item.url" alt="">
</div>
</div>
<!-- <div class="admin_state_item" style="width: 100%;">
<span style="margin: 0;">Generation time19min</span>
</div> -->
<div v-show="buildType" class="admin_state_item" style="width: 100%;">
<span style="margin: 0;">Cost credit{{credits * numberOfImages}}</span>
</div>
</div>
<div class="allUserPoeration_btn admin_page">
<!-- <div class="admin_search_item" @click="cancelDsign">
Close
</div> -->
<div class="admin_search_item" @click="setOk">
OK
</div>
</div>
</a-modal>
<div class="mark_loading" v-show="loadingShow">
<a-spin size="large" />
</div>
</template>
<script>
import { defineComponent, computed, reactive, watch, onMounted, nextTick, toRefs } from "vue";
import { Https } from "@/tool/https";
import { Modal, message } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import { formatTime,isEmail } from "@/tool/util";
import dayjs, { Dayjs } from 'dayjs';
import { useStore } from "vuex";
import { useI18n } from "vue-i18n";
import {getMinioUrl} from '@/tool/util'
const md5 = require("md5");
export default defineComponent({
components: {
},
props:{
cloudList:{
type:Array,
default:[]
}
},
emits: ['getContentList'],
setup(props,{emit}) {
const store = useStore();
let operations = reactive({
operationsModal:false,
loadingShow:false,
})
let operationsData = reactive({
buildType:'',
numberOfImages:'',
credits:0,
exhibitionImgList:[],//选择的图片
selectObject:computed(()=>store.state.Workspace.probjects),//选择的项目
//toProduct
generateText:'',//输入的内容
similarity:30,
brightenValue:1,//亮度
relightDirection:'Right Light',//打光方向
relightDirectionList:[
{
value:'Right Light',
label:useI18n().t('ProductImg.RightLight')
},{
value:'Left Light',
label:useI18n().t('ProductImg.LeftLight')
},{
value:'Top Light',
label:useI18n().t('ProductImg.TopLight')
},{
value:'Bottom Light',
label:useI18n().t('ProductImg.BottomLight')
}
]
})
let init = ()=>{
operations.operationsModal = true
}
const changeBuildType = ()=>{
if(operationsData.buildType == 'design'){
operationsData.exhibitionImgList = []
}else if(operationsData.buildType == 'toProductImage'){
operationsData.exhibitionImgList = store.state.UploadFilesModule.modularData.design.likeData
}else if(operationsData.buildType == 'relight'){
operationsData.exhibitionImgList = store.state.UploadFilesModule.modularData.toProduct
}else if(operationsData.buildType == 'poseTransfer'){
operationsData.exhibitionImgList = store.state.UploadFilesModule.modularData.toProduct
}
props.cloudList.forEach((item)=>{
if(item.value == operationsData.buildType){
operationsData.credits = item.consumption
}
})
}
let getPorductImg = ()=>{
let modularData = store.state.UploadFilesModule.modularData
let list = []
if(operationsData.buildType == 'toProductImage' || operationsData.buildType == 'relight'){
let productOrRelight = []
if(operationsData.buildType == 'toProductImage')productOrRelight = modularData.design.likeData
if(operationsData.buildType == 'relight')productOrRelight = modularData.toProduct
productOrRelight.forEach((item)=>{
if(!item.id)return
let obj = {
"createTime": "",
"elementId": 0,
"elementType": "",
"id": 0,
"isLike": 0,
"taskId": "",
"toProductImageRecordId": 0,
"url": "",
}
obj.elementId = item.designOutfitId
obj.elementType = 'DesignOutfit'
if(operationsData.buildType == 'relight'){
obj.elementId = item.id
obj.elementType = 'ToProductImage'
}
list.push(obj)
})
}
return list
}
const getImageStrength = () => {
let imageStrength = operationsData.similarity == 100? 95 :operationsData.similarity
return imageStrength;
};
const getPoseTransformData = ()=>{
let list = []
let toProduct = store.state.UploadFilesModule.modularData.toProduct
toProduct.forEach((item)=>{
let obj = {
poseId:1,
productImage:getMinioUrl(item.url)
}
list.push(obj)
})
return list
}
let setAddData = ()=>{
return {
"buildType": operationsData.buildType,
nums: operationsData.numberOfImages,
projectId: operationsData.selectObject.id,
//productimg
toProductImage:{
prompt:operationsData.generateText,//输入的内容
toProductImageVOList:getPorductImg(),//选择的图片
projectId: operationsData.selectObject.id,
direction:operationsData.relightDirection,//打光方向
brightenValue:operationsData.brightenValue,
imageStrength:(100 - getImageStrength())/100,
},
//poseTransform
poseTransform:getPoseTransformData(),
private: operationsData.selectObject.id,
ToProductImageDTO: operationsData.selectObject.id,
}
}
let cancelDsign = ()=>{
operationsData.buildType=''
operationsData.numberOfImages=''
operations.operationsModal = false
}
let setOk = ()=>{
let data
data = setAddData()
if(operationsData.buildType == 'toProductImage'){
if(data.toProductImage.toProductImageVOList.length == 0)return message.warning("You need to go to the Design module and generate a design result first before you can use the 'To Product Image' cloud generation feature.")
}else if(operationsData.buildType == 'relight'){
if(data.toProductImage.toProductImageVOList.length == 0)return message.warning("You need to go to the 'To Product Image' module and generate a result first before you can use the 'Relight' cloud generation feature.")
}else if(operationsData.buildType == 'poseTransfer'){
if(data.poseTransform.length == 0)return message.warning("You must first generate results in the 'To Product Image' module before you can use the 'Transfer Pose' cloud generation feature.")
}
if(!data.buildType || !data.nums)return message.warning('Please check the input box marked with *')
operations.loadingShow = true
Https.axiosPost(Https.httpUrls.designCloud, data).then(
(rv) => {
if (rv) {
operations.loadingShow = false
cancelDsign()
emit('getContentList')
}
}).catch((error) => {
operations.loadingShow = false
})
}
const changeNumberOfImages = ()=>{
if(operationsData.buildType =='relight' || operationsData.buildType == 'poseTransfer'){
if(operationsData.exhibitionImgList.length < Number(operationsData.numberOfImages)){
operationsData.numberOfImages = operationsData.exhibitionImgList.length
}
}
}
return {
...toRefs(operations),
...toRefs(operationsData),
cancelDsign,
init,
focus,
blur,
setOk,
changeBuildType,
changeNumberOfImages,
};
},
data() {
return {
};
},
mounted() {},
methods: {
},
directives:{
mousewheel:{
mounted (el) {
el.addEventListener('mouseenter', (e)=> {
if(el.scrollWidth > el.clientWidth){
el.parentElement.style.overflowY = 'hidden';
}
});
// 鼠标移出事件
el.addEventListener('mouseleave', ()=> {
el.parentElement.style.overflowY = 'auto';
});
el.addEventListener('wheel',(e)=>{
let num = 0
if(e.deltaY > 0){
num = 25
}else{
num = -25
}
el.scrollBy(num, 0);
},{ passive: true })
}
},
},
});
</script>
<style lang="less" scoped>
:deep(.ant-modal-mask){
background: rgba(0, 0, 0, 0.2);
}
:deep(.createCloud_modal){
.ant-modal-body{
display: flex;
flex-direction: column;
}
}
</style>
<style lang="less" scoped>
.createCloud_modal {
.closeIcon {
z-index: 2;
}
.allUserPoeration_btn{
display: flex;
flex-direction: row;
height: auto;
justify-content: flex-end;
padding: 1rem 0;
.admin_search_item{
margin-bottom: 0;
}
}
.allUserPoeration_center{
flex: 1;
overflow-y: auto;
flex-direction: row;
flex-wrap: wrap;
align-content: flex-start;
padding: 0 2rem;
> .selectImgList{
width: 100%;
display: flex;
overflow-x: auto;
align-items: center;
flex-wrap: nowrap;
height: 20rem;
margin: 2rem 0;
> .item{
height: 100%;
margin-right: 1rem;
&:last-child{
margin-right: 0;
}
> img{
height: 100%;
}
}
//
}
> .admin_state_item{
width: auto;
// width: 100%;
display: flex;
flex-direction: column;
align-items: flex-start;
> span{
text-align: left;
margin: 0;
margin-bottom: 1.5rem;
font-weight: 600;
}
:deep(> .ant-select > .ant-select-selector){
border-radius: 1.6rem;
}
> input{
border-radius: 1.6rem;
}
>.sliderAndImput{
display: flex;
align-items: center;
flex: 1;
:deep(> .ant-slider){
// border-radius: 1.6rem;
flex: 1;
}
> input{
border-radius: 1.6rem;
width: 4rem;
margin-left: 1rem;
height: 100%;
border-radius: 1rem;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,343 @@
<template>
<div class="uploading">
<div class="title">
<div class="list">
<div
class="titleItem active"
>
<span class="detailText">All</span>
</div>
</div>
<div class="createCloud">
<div class="gallery_btn" @click="createClound">Create</div>
</div>
</div>
<div class="contentList">
<div class="title">
<div class="titleItem" v-for="item in cloudTiltleList" :key="item.value">
{{ item.name }}
</div>
</div>
<div class="content">
<tr v-for="(row, index) in contentList" :key="index">
<td v-for="header in cloudTiltleList" :key="header.value">
<span v-show="header.value != 'operation'">
{{header?.fun?header.fun(row[header.value]) : row[header.value]}}
</span>
<span style="color: #007EE5; cursor: pointer;" v-show="header.value == 'operation'" @click="detailIamge(row)">
Review
</span>
</td>
</tr>
</div>
<a-pagination style="text-align: center;" v-model:current="currentPage" :total="total" show-less-items />
</div>
<createCloud ref="createCloud" :cloudList="generateList[workflowType]" @getContentList="submitGetContentList"></createCloud>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,onMounted,nextTick,createVNode,toRefs, reactive, onBeforeUnmount} from 'vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
import createCloud from "./createCloud.vue";
import { da } from 'element-plus/es/locale';
export default defineComponent({
components:{
createCloud,
},
props:{
workflowType:{
type:String,
default:'' as any,
required:true
}
},
emits:['retrieve'],
setup(props,{emit}) {
const store = useStore();
const data = reactive({
pageType:'list',
pageSize:10,
currentPage:1,
total:0,
selectObject:computed(()=>store.state.Workspace.probjects),//选择的项目
generateList:{
seriesDesign:[
{
label:'Design',
value:'design',
consumption:0,
},{
label:'To Product Image',
value:'toProductImage',
consumption:5,
},{
label:'Relight',
value:'relight',
consumption:5,
},{
label:'Transfer Pose',
value:'poseTransfer',
consumption:10,
},
],
singleProductDesign:[
{
label:'Design',
value:'design',
consumption:0,
},{
label:'To Product Image',
value:'toProductImage',
consumption:5,
},
],
// printDesign:[
// {
// label:'1',
// value:100,
// }
// ],
productDrawingDesign:[
{
label:'To Product Image',
value:'toProductImage',
consumption:5,
},{
label:'Relight',
value:'relight',
consumption:5,
},{
label:'Transfer Pose',
value:'poseTransfer',
consumption:10,
},
],
// printingDesign3D:[
// {
// label:'1',
// value:100,
// }
// ],
// sketchDesign:[]
},
cloudTiltleList:[
{
name:'Task type',
value:'buildType',
fun:(value:any)=>{
let str = ''
if(value == 'design')str = 'Design'
if(value == 'toProductImage')str = 'To Product Image'
if(value == 'relight')str = 'Relight'
if(value == 'poseTransfer')str = 'Transfer Pose'
return str
}
},{
name:'Quantity generated',
value:'nums',
},{
name:'Creation time',
value:'updateTime',
fun:(value:any)=>{
if(!value)return
return value.split('T')[0] + ' ' + value.split('T')[1].split('.')[0]
}
},{
name:'Start time',
value:'updateTime',
fun:(value:any)=>{
//没开始内容为 -
if(!value)return
return value.split('T')[0] + ' ' + value.split('T')[1].split('.')[0]
}
},{
name:'End time',
value:'updateTime',
fun:(value:any)=>{
if(!value)return
return value.split('T')[0] + ' ' + value.split('T')[1].split('.')[0]
}
},{
name:'Status',
value:'process',
fun:(value:any)=>{
if(value == '100.00%'){
return 'Completed'
}else{
return value
}
}
},{
name:'Operation',
value:'operation',
},
] as any,
contentList:[
] as any,
isGetContentList:false as any,
})
const dataDom = reactive({
createCloud,
})
const createClound = ()=>{
data.isGetContentList = false
dataDom.createCloud.init()
}
const detailIamge = (item:any)=>{
//去除里面的T2025-04-17T13:45:43
if(item.process == '100.00%' || item.status == 1){
let value = {
taskId:item.taskId,
page:1,
size:10,
buildType:item.buildType,
}
Https.axiosPost(Https.httpUrls.getDesignCloudResult,value).then((rv)=>{
console.log(rv)
if(rv.design && rv.design.length > 0){
store.commit('addDesignCollectionList',rv.design)
emit('retrieve','design')
}else if(rv.toProductImage && rv.toProductImage.length > 0){
store.commit('setCloudList',{str:'toProduct',list:rv.toProductImage})
emit('retrieve','toProduct')
}else if(rv.relight && rv.relight.length > 0){
store.commit('setCloudList',{str:'relight',list:rv.relight})
emit('retrieve','relight')
}else if(rv.poseTransfer && rv.poseTransfer.length > 0){
store.commit('setCloudList',{str:'poseTransfer',list:rv.poseTransfer})
emit('retrieve','poseTransfer')
}
data.isGetContentList = false
})
}
}
const getContentList = ()=>{
if(data.isGetContentList){
let value = {
page:data.currentPage,
size:data.pageSize,
projectId: data.selectObject.id,
}
Https.axiosPost(Https.httpUrls.cloudPage,value).then((rv)=>{
data.contentList = rv.content
data.total = rv.total
let arr = rv.content
let result = arr.some((item:any) => (item.process !== '100.00%' && item.status !== 1));
if(!result)data.isGetContentList = false
setTimeout(()=>{
getContentList()
},1500)
})
}
}
const submitGetContentList = ()=>{
data.isGetContentList = true
getContentList()
}
onBeforeUnmount(()=>{
data.isGetContentList = false
})
onMounted(()=>{
data.isGetContentList = true
getContentList()
})
return{
...toRefs(dataDom),
...toRefs(data),
createClound,
detailIamge,
getContentList,
submitGetContentList,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.uploading{
width: 100%;
height: 100%;
position: relative;
padding-top: 3rem;
display: flex;
flex-direction: column;
> .title{
width: 100%;
display: flex;
> .list{
display: flex;
margin-bottom: 2.5rem;
> .titleItem:last-child{
margin-right: 0;
}
> .titleItem{
position: relative;
cursor: pointer;
margin-right: 6.5rem;
}
> .titleItem::before {
position: absolute;
content: "";
display: block;
background: #000;
height: calc(.4rem*1.2);
left: 50%;
transform: translateX(-50%);
bottom: -.5rem;
width: 0px;
transition: 0.3s all;
}
> .active {
color: #000;
font-weight: 600;
}
> .active::before {
width: 100%;
}
}
> .createCloud{
margin-left: auto;
}
}
> .contentList{
flex: 1;
overflow: hidden;
padding-top: 2.5rem;
display: flex;
flex-direction: column;
> .content tr , > .title{
display: flex;
justify-content: space-between;
padding: 0 1.2rem;
}
> .title{
background: #F7F7F7;
> .titleItem{
line-height: 4.6rem;
font-size: 2rem;
color: #666666;
width: calc(100% / 4);
text-align: center;
}
}
.content{
flex: 1;
overflow: hidden;
> tr{
> td{
text-align: center;
width: calc(100% / 4);
line-height: 4.6rem;
font-size: 2.2rem;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,191 @@
<template>
<div class="canvasArgument">
<div class="label_item">
<div >{{ $t('exportModel.Layer') }}:</div>
<i class="icon iconfont icon-shangyiceng" @click="canvasGeneral.setLayerIndex('Front')"></i>
<i class="icon iconfont icon-shangyiceng2" @click="canvasGeneral.setLayerIndex('Forward')"></i>
<i class="icon iconfont icon-xiayiceng" @click="canvasGeneral.setLayerIndex('Backwards')"></i>
<i class="icon iconfont icon-shangyiceng1" @click="canvasGeneral.setLayerIndex('Back')"></i>
</div>
<div class="label_item" v-show="
canvasGeneral.operation != 'movePosition' &&
canvasGeneral.operation != 'move' &&
canvasGeneral.brushwork.value != 'RibbonBrush' &&
canvasGeneral.brushwork.value != 'LongfurBrush'&&
canvasGeneral.operation != 'zoomIn' &&
canvasGeneral.operation != 'zoomOut' &&
canvasGeneral.operation != 'dashedPencil' &&
canvasGeneral.operation != 'dashed'">
<div >{{ $t('exportModel.Size') }}:</div>
<input @change="canvasGeneral.setFontFamily" type="range" @input="canvasGeneral.setPencilWidth" min="3" max="50" v-model="canvasGeneral.brushwork.width[canvasGeneral.operation]">
</div>
<div class="label_item" v-show="canvasGeneral.operation == 'pencil'">
<div >{{ $t('exportModel.Brushwork') }}:</div>
<a-select ref="select" class="label_select" size="small" v-model:value="canvasGeneral.brushwork.value"
style="width: 12rem "
@change="canvasGeneral.brushworkChange"
>
<a-select-option class="label_select_item" v-for="item in canvasGeneral.pencilList.brushList" :value="item.value">
<img style="width: 100%;" :src="item.url" alt="">
</a-select-option>
</a-select>
</div>
<div class="label_item texture" v-show="canvasGeneral.operation == 'texture'">
<div >{{ $t('exportModel.Texture') }}:</div>
<a-select ref="select" class="label_select" size="small" v-model:value="canvasGeneral.texture.value"
style="width: 12rem "
@change="canvasGeneral.textureValueChange"
>
<a-select-option class="label_select_item" v-for="item in canvasGeneral.texture.list" :value="item.value">
<img :src="item.url" alt="">
</a-select-option>
</a-select>
</div>
<div class="label_item" v-show="
canvasGeneral.operation != 'pencil' &&
canvasGeneral.operation != 'eraser'&&
canvasGeneral.operation != 'movePosition' &&
canvasGeneral.operation != 'move'&&
canvasGeneral.operation != 'text'&&
canvasGeneral.operation != 'texture'&&
canvasGeneral.operation != ''&&
canvasGeneral.operation != 'zoomIn' &&
canvasGeneral.operation != 'zoomOut' &&
canvasGeneral.operation != 'dashedPencil' &&
canvasGeneral.operation != 'dashed'">
<div >{{ $t('exportModel.FillBack') }}:</div>
<div class="leftAlign">
<i class="icon iconfont icon-tuceng1" @click="canvasGeneral.setOperationMode('fill')" :class="{active:canvasGeneral.operationMode == 'fill'}"></i>
<i class="icon iconfont icon-tuceng" @click="canvasGeneral.setOperationMode('border')" :class="{active:canvasGeneral.operationMode == 'border'}"></i>
</div>
</div>
<!-- <div class="label_item" v-show="canvasGeneral.operation == 'movePosition'">
<div >{{ $t('exportModel.Layer') }}:</div>
<div class="leftAlign">
<i class="icon iconfont icon-shangyiceng" @click="canvasGeneral.setLayerIndex('Front')"></i>
<i class="icon iconfont icon-shangyiceng2" @click="canvasGeneral.setLayerIndex('Forward')"></i>
<i class="icon iconfont icon-xiayiceng" @click="canvasGeneral.setLayerIndex('Backwards')"></i>
<i class="icon iconfont icon-shangyiceng1" @click="canvasGeneral.setLayerIndex('Back')"></i>
</div>
</div> -->
<div class="label_item" v-show="(canvasGeneral.operation == '' || canvasGeneral.operation == 'text' || canvasGeneral.createPatterning.textDataShow) && canvasGeneral.operation != 'movePosition' && canvasGeneral.operation != 'move'">
<div>Font Family</div>
<a-select ref="select" class="label_select" size="small" v-model:value="canvasGeneral.fontFamily"
style="flex: 1;width: 15rem;"
@change="canvasGeneral.setFontFamily"
:style="{'font-family':canvasGeneral.fontFamily}"
>
<a-select-option class="label_select_item" v-for="item in canvasGeneral.pencilList.textFontFamilyList" :style="{'font-family':item.value}" :value="item.value">
{{item.name}}
</a-select-option>
</a-select>
</div>
<div class="label_item" style="margin-left: auto;">
<span style="margin-right: 2rem;">Show Models</span>
<a-switch v-model:checked="isShowBg" @change="showBg" />
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,ref,reactive,nextTick,toRefs,inject} from 'vue'
export default defineComponent({
components:{},
setup(){
let testModal = ref(true)
let canvasGeneral:any = inject('canvasObj')
const data = reactive({
colorHistoryList:[],
operation:'',
isShowBg:true,
})
const setOperation = (str:any)=>{
data.operation = str
}
const setOper = ()=>{
setOperation('')
}
document.addEventListener('click',setOper)
const closeModal = ()=>{
document.removeEventListener('click',setOper)
}
const showBg = ()=>{
canvasGeneral.showBg(data.isShowBg)
}
return {
canvasGeneral,
...toRefs(data),
testModal,
setOperation,
closeModal,
showBg,
}
}
});
</script>
<style lang='less' scoped>
.canvasArgument{
display: flex;
flex-wrap: wrap;
height: 100%;
.label_item{
margin-right: 2rem;
position: relative;
display: flex;
align-items: center;
.leftAlign{
display: flex;
}
.labelHover_show{
position: absolute;
width: 100%;
height: 10rem;
top: 100%;
z-index: 2;
display: block;
border-radius: 4px;
border: 1px solid;
padding: .5rem 1rem;
background: #fff;
div{
width: 2rem;
height: 2rem;
margin-right: .5rem;
margin-bottom: .5rem;
display: inline-block;
cursor: pointer;
}
}
input{
height: 100%;
width: 12rem;
}
&.wH input{
width: 5rem;
}
.title{
margin-right: 1rem;
}
.icon-xiala{
cursor: pointer;
transform: rotate(0deg);
height: 4rem;
width: 4rem;
transition: all .3s;
line-height: 4rem;
text-align: center;
&.active{
transform: rotate(180deg);
}
}
}
.label_item:hover{
// .labelHover_show{
// display: flex;
// }
}
}
</style>

View File

@@ -0,0 +1,122 @@
<template>
<div class="canvasContent_box">
<div class="canvasContent" ref="canvasScaleDom">
<div class="generalCanvas_center canvas" ref="canvasDom">
<div class="editFrontBack_pencilbtn" v-show="!isShowMark" :style="canvasGeneral.pencilbtnStyle"></div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,reactive,nextTick,toRefs,inject,createVNode, onMounted, watch} from 'vue'
import { Modal,message } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { useI18n } from 'vue-i18n'
import { useStore } from "vuex";
export default defineComponent({
component:{},
setup(props,{emit}){
const store = useStore();
let {t} = useI18n()
let canvasType = inject('canvasType')
let canvasGeneral:any = inject('canvasObj')
const data:any = reactive({
canvasDom:null,
isShowMark:false,
pencilbtnStyle:{},
isCanva:false,
selectObject:computed(()=>store.state.Workspace.probjects),//选择的项目
})
const dataDom = reactive({
canvasScaleDom:null as any,
})
watch(()=>data.selectObject.model.id,(newVal:any)=>{
if(newVal){
canvasGeneral.upDataRectBGImg(data.selectObject.model.url)
}
})
const createCanvas = ()=>{
if(data.isCanva)return
nextTick(async ()=>{
let width = dataDom.canvasScaleDom.offsetWidth
let canvasSize = {width,height:width}
data.isCanva = true
let img = data.selectObject.model.url
await canvasGeneral.canvasInit(data.canvasDom,canvasSize,img,'',{noErasable:true})
let oldCanvas = store.state.HomeStoreModule.canvasData.deReconstruction
if(oldCanvas)canvasGeneral.setLoadFromJSON(oldCanvas, () => {});
// if(oldCanvas)canvasGeneral.canvas.loadFromJSON(oldCanvas, () => {});
})
}
const openMode = (data:any)=>{
let {yes,no} = data
console.log(yes,no);
Modal.confirm({
title: '是否栅格化',
icon: createVNode(ExclamationCircleOutlined),
okText: 'Yes',
cancelText: 'No',
mask:false,
centered:true,
onOk() {
yes()
},
onCancel(){
no()
}
});
yes()
}
const openSetData = ()=>{
createCanvas()
}
onMounted(()=>{
})
return {
canvasGeneral,
...toRefs(data),
...toRefs(dataDom),
openSetData,
}
}
});
</script>
<style lang='less' scoped>
.canvasContent_box{
height: 100%;
width: 100%;
// padding: 2rem;
background: #e6e6e6;
.canvasContent{
height: 100%;
width: 100%;
position: relative;
}
}
.generalCanvas_center{
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
&.canvas{
}
.editFrontBack_pencilbtn{
position: absolute;
z-index: 1;
border-radius: 50%;
border: 1px solid #000;
pointer-events: none;
transform: translate(-50%,-50%);
}
:deep(.canvas-container){
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
// background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC);
}
}
</style>

View File

@@ -0,0 +1,305 @@
<template>
<div class="detail" ref="detailDom"
@mousemove="mousemove($event)"
@touchmove="touchmove($event)"
>
<div class="layer">
<div class="layer-item button" @click="canvasGeneral.createLayer">
新建图层
</div>
<div class="layer-item-box-scroll">
<div class="layer-item-box" :style="{'height':layerList.length * 6 + 'rem'}">
<div class="layer-item"
v-for="item,index in layerList"
:key="item"
:style="item?.style"
@click="canvasGeneral.selectLayer(item.id)"
@mousedown="mousedown($event,item,index)"
@touchstart="touchstart($event,item,index)"
@contextmenu="openMenu($event,item,index)"
:class="{'active':item.id == canvasGeneral.layer.selectLayer.id}">
<!-- <div @click.stop="canvasGeneral.layerShowHide(item.id,item)">{{ item.isShow }}</div> -->
<i class="fi" :class="[(item.isShow)?'fi-rr-eye':'fi-rr-eye-crossed']" @click.stop="canvasGeneral.layerShowHide(item.id,item)"></i>
<img :src="item.img" alt="">
<div>
{{ item.name }}
</div>
<div @click.stop="canvasGeneral.layerDelete(index,item.id)" :class="{noDelete:canvasGeneral.layer.list.length == 1}">删除</div>
</div>
</div>
</div>
</div>
<div class="layer-menu" :style="styleMenu">
<div class="layer-menu-item" @click="canvasGeneral.copyLayer(itemMenu.id)">复制</div>
<div class="layer-menu-item" @click="canvasGeneral.layerDelete(itemMenu.index,itemMenu.id)">删除</div>
<div class="layer-menu-item" v-if="itemMenu.groupType == 'Object'" @click="canvasGeneral.setGridOrObject(itemMenu.id,'Grid')">设置栅格化</div>
<div class="layer-menu-item" v-if="itemMenu.groupType == 'Grid'" @click="canvasGeneral.setGridOrObject(itemMenu.id,'Object')">取消栅格化</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,ref,reactive,nextTick,toRefs,inject,watch,computed} from 'vue'
import { getMousePosition } from "@/tool/mdEvent";
export default defineComponent({
component:{},
setup(){
let canvasGeneral:any = inject('canvasObj')
const data = reactive({
detailDom:null as any,
layerList:computed(()=>canvasGeneral.layer.list) as any,
styleMenu:{
left:0+'px',
top:0+'px',
display:'none',
},
itemMenu:{} as any,
})
watch(()=>canvasGeneral.layer.list.length, (newValue, oldValue) => {
let sortedArr = data.layerList.map((item:any) => ({ ...item })).sort((a:any, b:any) => b.index - a.index)
sortedArr.forEach((item:any,index:any)=>{
item.index = sortedArr.length - index
})
data.layerList.forEach((item:any) => {
//图层高度50px 下边距10px
sortedArr.forEach((sortedArrItem:any)=>{
if(item.id == sortedArrItem.id){
item.index = sortedArrItem.index
}
let style = {
top:(data.layerList.length - item.index) * 60 + 'px',
transition:'all .3s',
}
item.style = style
})
});
},{immediate:true});
const incident:any = reactive({
isDown:false,
selectStyleTop:null,
selectStyle:null,
downPoint:null,
select:null,
radius:25,
})
const openMenu = (event:any,item:any,index:number)=>{
if(event.preventDefault)event.preventDefault();
data.itemMenu = item;
data.itemMenu.index = index
let position = data.detailDom.getBoundingClientRect();
data.styleMenu = {
left:event.clientX - position.left+'px',
top:event.clientY - position.top+'px',
display:'block',
}
}
document.onclick = ()=>{
data.styleMenu.display = 'none'
data.itemMenu = {};
}
let mousedown = (event:any,item:any,index:number)=>{
if(event.button != 0)return
let e:any = getMousePosition(event,false)
mouseDownOperation(e,item,index)
}
let ipadDownTime:any = null
let touchstart = (event:any,item:any,index:number)=>{
let e:any = getMousePosition(event,true)
mouseDownOperation(e,item,index)
clearTimeout(ipadDownTime)
ipadDownTime = setTimeout(()=>{
openMenu(e,item,index)
},1000)
}
let mouseDownOperation = (e:any,item:any,index:number)=>{
incident.isDown = true
incident.selectStyleTop = item.style.top
incident.selectStyle = item.style
incident.selectStyle.transition = 'none'
incident.select = item
incident.downPoint = e.clientY
}
let mousemove = (event:any)=>{
let e:any = getMousePosition(event,false)
mouseMoveOperation(e)
}
let touchmove = (event:any)=>{
let e:any = getMousePosition(event,true)
clearTimeout(ipadDownTime)
if(data.styleMenu.display != 'none')data.styleMenu.display = 'none'
mouseMoveOperation(e)
}
let mouseMoveOperation = (e:any)=>{
if(incident.isDown){
let domTop = Number(incident.selectStyleTop.split('px')[0])
let gTop = domTop + (e.clientY - incident.downPoint)
if(gTop < 0){
gTop = 0
}
incident.select.style.top = gTop + 'px'
data.layerList.forEach((item:any,index:number) => {
let itemTop = Number(item.style.top.split('px')[0])
if(Math.abs(gTop - itemTop) < 30 && item.id != incident.select.id){
let itemIndex = item.index
// if(gTop - itemTop > 0){
// console.log('从下往上');
// }
// if(gTop - itemTop < 0){
// console.log('从上往下');
// }
item.index = incident.select.index
incident.select.index = itemIndex
}
})
sort(data.layerList,'move')
}
}
const mouseUp = ()=>{
if(data.styleMenu.display == 'none')clearTimeout(ipadDownTime)
if(incident.isDown){
if(incident.selectStyle)incident.selectStyle.transition = 'all .3s'
incident.selectStyleTop = null
incident.isDown = false
incident.selectStyle = null
incident.select = null
sort(data.layerList,'up')
}
}
document.onmouseup = mouseUp
document.ontouchend = mouseUp
//排序
let time:any = null
let sort = (list:any,str:string)=>{
clearTimeout(time)
// list = list.sort((a:any, b:any) =>{
// return b.index - a.index;
// });
list.forEach((item:any) => {
if(str == 'move'){
if(item.id != incident.select.id)item.style.top = (list.length - item.index) * 60 + 'px'
}else{
item.style.top = (list.length - item.index) * 60 + 'px'
}
});
if(str == 'up')time = setTimeout(()=>canvasGeneral.upLayerIndex(list),500)
}
return {
canvasGeneral,
...toRefs(data),
openMenu,
mousedown,
touchstart,
mousemove,
touchmove,
}
}
});
</script>
<style lang='less' scoped>
.detail{
width: 100%;
height: 100%;
padding: 1rem;
border: 1px solid #dcdfe6;
position: relative;
* {
-webkit-user-drag: none;
-moz-user-drag: none;
-ms-user-drag: none;
user-drag: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}
.layer{
display: flex;
flex-direction: column;
height: 100%;
.layer-button{
}
.layer-item{
display: flex;
justify-content: space-between;
align-items: center;
padding: .5rem 2rem;
border: 1px solid #e6e6e6;
margin-bottom: 10px;
height: 50px;
border-radius: 4px;
i{
font-size: 18px;
}
&.active{
background: #e6e6e6;
}
.noDelete{
background: #e6e6e6;
opacity: .4;
pointer-events: none;
}
&.button{
justify-content: center;
cursor: pointer;
}
img{
height: 100%;
width: 35px;
object-fit: contain;
}
div{
cursor: pointer;
}
&:last-child{
margin-bottom: 0;
}
}
.layer-item-box-scroll{
flex: 1;
overflow-y: auto;
.layer-item-box{
position: relative;
.layer-item{
position: absolute;
width: 100%;
}
}
}
}
.layer-menu{
position: absolute;
width: 60%;
line-height: 4rem;
background: #fff;
border-radius: 4px;
border: 1px solid;
overflow: hidden;
>div{
border-bottom: 1px solid;
padding: 0 2rem;
cursor: pointer;
}
>div:hover{
background: #e6e6e6;
}
>div:last-child{
border-bottom: none;
}
}
}
</style>

View File

@@ -0,0 +1,221 @@
<template>
<div class="generalCanvas">
<div class="argument-box">
<argument ref="argument" v-if="canvasObj.canvas"></argument>
</div>
<div class="canvasBox">
<tool ref="tool" v-if="canvasObj.canvas" @toolLiquefaction="toolLiquefaction"></tool>
<div class="canvas">
<canvasContent ref="canvasContent"></canvasContent>
</div>
<!-- <div class="detail-box">
<detail ref="detail" v-if="canvasObj.canvas"></detail>
</div> -->
</div>
<div class="mark_loading" v-show="isShowMark">
<a-spin size="large" />
</div>
</div>
<liquefaction ref="liquefaction" @submitLiquefaction="submitLiquefaction"></liquefaction>
</template>
<script>
import {defineComponent, toRefs, provide, h, ref, nextTick, onBeforeUnmount, reactive, onMounted,
} from "vue";
import {message} from 'ant-design-vue'
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from "vue-i18n";
import canvasGeneral from "@/tool/canvasGeneralCopy";
import tool from "./tool.vue"
import argument from "./argument.vue"
import detail from "./detail.vue"
import canvasContent from "./canvasContent.vue"
import liquefaction from "@/component/modules/liquefaction.vue";
export default defineComponent({
components: {
tool,
argument,
detail,
canvasContent,
liquefaction,
},
emits:['setGenerateImg'],
setup(props,{emit}) {
const { t } = useI18n();
const store = useStore();
const isShowMark = ref(false)
const component = reactive({
argument:ref(null),tool:ref(null),detail:ref(null),canvasContent:ref(null)
})
const dataDom = reactive({
canvasContent:null,
})
let liquefaction = ref(null)
let liquefactionData = ref()
let groupDashed = ref(null)//用来判断是否需要对group添加img
let canvasType = 'export'
let canvasObj = reactive(new canvasGeneral('zz'))
provide('canvasType',canvasType)
provide('canvasObj',canvasObj)
provide('isShowMark',isShowMark)
const close = ()=>{
component.forEach((item)=>{
if(item.value.closeModal)item.value.closeModal()
})
}
let expoet = ()=>{
console.log( canvasObj.selectExport());
console.log( canvasObj.allExport());
}
const setLiquefaction = async ()=>{//进入液化页面
canvasObj.getLiquefactionImgObj().then((data)=>{
if(data?.img){
liquefactionData.value = data
liquefaction.value.init(data.img)
}else {
message.info(t('exportModel.jsContent6'))
return null;
}
})
}
const toolLiquefaction = ()=>{//工具点击按钮
setLiquefaction()
}
const submitLiquefaction = (rv)=>{//液化回参
canvasObj.setLiquefactionImgObj(liquefactionData.value,rv)
// liquefactionData.value.setSrc(rv, (value)=>{
// // liquefactionData.value.scaleToWidth(originalWidth);
// // liquefactionData.value.scaleToHeight(originalHeight);
// delete liquefactionData.value.minioUrl
// if(groupDashed.value && groupDashed.value._objects.length == 1){
// value.set({
// left:-groupDashed.value.width/2,
// top:-groupDashed.value.height/2,
// })
// groupDashed.value.insertAt(value)
// // canvasObj.addDashedImg(value)
// }
// canvasObj.canvas.renderAll();
// canvasObj.updateCanvasState()
// });
}
const openSetData = ()=>{
dataDom.canvasContent.openSetData()
}
const addImage = (data)=>{
canvasObj.addImage(data)
}
const getData = async ()=>{
await canvasObj.detailSubmit().then((img)=>{
emit('setGenerateImg',img)
})
}
const getCanvasData = ()=>{
var json = canvasObj.canvas.toJSON(['src','minioUrl','custom','perPixelTargetFind','hasBorders','selectable','hasControls','erasable']);
// console.log(JSON.stringify(json));
json.objects.forEach(item=>{
if(item.type == 'image'){
delete item.src
}
})
let canvasExport = {
canvas:json,
groupList: canvasObj.layer.list
}
return canvasExport
}
onMounted(() => {
});
onBeforeUnmount(()=>{
// canvasGeneral.canvasClear()
})
return {
...toRefs(dataDom),
isShowMark,
liquefaction,
canvasObj,
close,
expoet,
toolLiquefaction,
submitLiquefaction,
openSetData,
addImage,
getData,
getCanvasData,
};
},
data(prop) {
return {
};
},
computed: {
},
watch: {
},
mounted() {},
methods: {
},
});
</script>
<style lang="less" scoped>
.generalCanvas{
width: 100%;
height: 100%;
position: relative;
display: flex;
flex-direction: column;
overflow: hidden;
.argument-box,
.canvasBox,
.detail-box{
:deep(i){
font-size: 2.5rem;
cursor: pointer;
width: 3rem;
height: 3rem;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: all .3s;
margin-bottom: .5rem;
&.active{
border: 1px solid;
border-radius: .4rem;
}
&.icon-xiala{
transform: rotate(-90deg);
}
&.icon-xialaActive{
transform: rotate(90deg);
}
}
}
.argument-box{
margin-left: 4rem;
height: 4rem;
margin-bottom: 1rem;
}
.canvasBox{
flex: 1;
overflow: hidden;
display: flex;
.canvas{
flex: 1;
overflow: hidden;
}
}
.detail-box{
width: 20%;
margin-left: 1rem;
}
}
</style>

View File

@@ -0,0 +1,167 @@
<template>
<div class="canvasTool">
<i class="icon iconfont icon-chehui" @click="historyState('')"></i>
<i class="icon iconfont icon-fanchehui" @click="historyState('reverse')"></i>
<i class="icon iconfont icon-bianji" @click="setOperation('pencil')" :class="{active:canvasGeneral.operation == 'pencil'}"></i>
<i class="fi fi-rr-hand-paper" @click="setOperation('move')" :class="{active:canvasGeneral.operation == 'move'}"></i>
<i class="icon iconfont icon-move" @click="setOperation('movePosition')" :class="{active:canvasGeneral.operation == 'movePosition'}"></i>
<i class="icon iconfont icon-xiangpi_huaban1" @click="setOperation('eraser')" :class="{active:canvasGeneral.operation == 'eraser'}"></i>
<!-- <i class="icon iconfont icon-xiala" :class="closeNav.tool?'icon-rotate':''" @click.stop="setCloseNav('tool')"></i> -->
<i class="fi fi-rr-square-dashed" @click="setOperation('dashed')" :class="{active:canvasGeneral.operation == 'dashed'}"></i>
<i class="fi fi-rr-scalpel-path" @click="setOperation('dashedPencil')" :class="{active:canvasGeneral.operation == 'dashedPencil'}"></i>
<i class="fi fi-rr-zoom-in" @click="setOperation('zoomIn')" :class="{active:canvasGeneral.operation == 'zoomIn'}"></i>
<i class="fi fi-rr-zoom-out" @click="setOperation('zoomOut')" :class="{active:canvasGeneral.operation == 'zoomOut'}"></i>
<i class="icon iconfont icon-IC-yehua" @click="setLiquefaction()"></i>
<div class="label_item uploadImage">
<i class="icon fi fi-br-upload" ></i>
<input type="file" @change="uploadImage">
</div>
<i class="icon iconfont" @click="setOperation('text')" :class="{active:canvasGeneral.operation == 'text'}">T</i>
<i class="icon iconfont icon-xiala" :class="{'icon-xialaActive':isMove}" @click.stop="openMore"></i>
<div class="btnModal" v-show="isMove" :style="moveStyle">
<!-- <i class="icon iconfont icon-xian" @click="setOperation('fold')" :class="{active:canvasGeneral.operation == 'fold'}"></i> -->
<i class="icon iconfont icon-checkbox-full" @click="setOperation('rect')" :class="{active:canvasGeneral.operation == 'rect'}"></i>
<!-- <i class="icon iconfont icon-zhixian" @click="setOperation('line')" :class="{active:canvasGeneral.operation == 'line'}"></i> -->
<!-- <i class="icon iconfont icon-circle" @click="setOperation('circle')" :class="{active:canvasGeneral.operation == 'circle'}"></i> -->
<i class="icon iconfont icon-sanjiaoxing" @click="setOperation('triangle')" :class="{active:canvasGeneral.operation == 'triangle'}"></i>
<i class="icon iconfont icon-tx-fill-tuoyuanxing" @click="setOperation('ellipse')" :class="{active:canvasGeneral.operation == 'ellipse'}"></i>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,ref,reactive,nextTick,toRefs,inject} from 'vue'
import {base64ToFile} from '@/tool/util'
import { Https } from "@/tool/https";
export default defineComponent({
component:{},
emits:['toolLiquefaction'],
setup(props,{emit}){
let canvasGeneral:any = inject('canvasObj')
let isShowMark:any = inject('isShowMark')
const data:any = reactive({
isMove:false,
moveStyle:{},
})
const uploadImage = (event:any)=>{
isShowMark.value = true
const file = event.target.files[0];
let input = event.target
setOperation('movePosition')
if (file) {
const reader = new FileReader();
reader.onload = (e:any) => {
let file = base64ToFile(e.target.result,'upload')
let formData = new FormData();
formData.append("file", file);
let config = {headers:{'Content-Type':'multipart/form-data','Accept':'*/*' }}
Https.axiosPost(Https.httpUrls.canvasElementUpload, formData,config).then((rv)=>{
rv.imgUrl = rv.minioUrl
isShowMark.value = false
canvasGeneral.addImage(rv)
})
input.value = ''
};
reader.readAsDataURL(file);
}
}
const historyState = (str:any)=>{
canvasGeneral.historyState(str)
}
const setOperation = (str:any)=>{
canvasGeneral.setOperation(str)
}
const openMore = (e:any)=>{
data.isMove=!data.isMove
if(data.isMove){
let domPoint = e.target.getBoundingClientRect()
let domParentPoint = e.target.parentElement.getBoundingClientRect()
const left = domPoint.left - domParentPoint.left;
const top = domPoint.top - domParentPoint.top;
data.moveStyle.top = top + 'px'
data.moveStyle.left = left + domPoint.width + 2 + 'px'
}
}
const setMore = ()=>{
data.isMove = false
}
let setLiquefaction = ()=>{
emit('toolLiquefaction')
}
document.addEventListener('click',setMore)
const closeModal = ()=>{
document.removeEventListener('click',setMore)
}
return {
canvasGeneral,
...toRefs(data),
uploadImage,
historyState,
setOperation,
openMore,
closeModal,
setLiquefaction,
}
}
});
</script>
<style lang='less' scoped>
.canvasTool::-webkit-scrollbar{
display: none;
}
.canvasTool{
display: flex;
flex-direction: column;
position: relative;
align-items: center;
&.leftAlign{
justify-content: flex-start;
}
&.leftAlign{
justify-content: flex-start;
}
.uploadImage{
width: 3rem;
height: 3rem;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
i{
zoom:.8;
}
input{
height: 0;
width: 0;
border: none;
}
}
.uploadImage{
position: relative;
input{
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
opacity: 0;
z-index: 2;
cursor: pointer;
}
}
.btnModal{
position: absolute;
z-index: 2;
background: #fff;
top: 0;
border: 1px solid;
display: flex;
padding: .5rem 1rem;
border-radius: 4px;
}
}
</style>

View File

@@ -0,0 +1,262 @@
<template>
<div class="deReconstruction">
<div class="selectSektch itemBox">
<div class="type">
<a-select
v-model:value="segmentationType"
show-search
:allowClear="false"
style="width: 100%"
placeholder="Please select"
:options="[{value:'product',label:'product'},{value:'sketch',label:'sketch'}]"
></a-select>
<!-- <label>
<div class="text">product</div>
<input type="radio" value="product" v-model="segmentationType">
</label>
<label>
<div class="text">sketch</div>
<input type="radio" value="sketch" v-model="segmentationType">
</label> -->
</div>
<selectList @selectImgItem="selectImgItem" :segmentationType="segmentationType" :isSegmentation="true" upLoadHttpsUrl="/api/element/imageSegmentation" level1Type="Sketchboard" :randomId="false" type="sketch" :catecoryList="sketchCatecoryList"></selectList>
</div>
<div class="canvas itemBox">
<canvasBox @setGenerateImg="setGenerateImg" ref="canvasBox"></canvasBox>
</div>
<div class="finished itemBox">
<div class="btnTop">
<div class="gallery_btn" @click="getCanvasImg">Generate line</div>
<div v-show="!generateImg?.[0]?.isLike" class="icon iconfont icon-jushoucang icon_like" @click="generateLike('like')"></div>
<div v-show="generateImg?.[0]?.isLike" class="icon iconfont icon-jushoucanggift" @click="generateLike('noLike')"></div>
</div>
<div class="content">
<img v-if="generateImg?.[0]?.url" :src="generateImg?.[0]?.url" alt="">
<sketchCategory v-if="generateImg?.[0]?.url" v-model:disignTypeList="sketchCatecoryList" :item="generateImg[0]" :isSpread="false"></sketchCategory>
</div>
<div class="btnBottom" @click="getCanvasData">
<div class="gallery_btn">Download</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive, inject} from 'vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
import selectList from '@/component/DetailCopy/detailLeft/module/selectList.vue'
import sketchCategory from "@/component/HomePage/sketchCategory.vue";
import canvasBox from "./canvas/index.vue";
export default defineComponent({
components:{
selectList,sketchCategory,canvasBox
},
props:{
},
emits:[],
setup(props,{emit}) {
const store = useStore();
const data = reactive({
sketchCatecoryList:computed(()=>{
return store.state.Workspace.probjects.positionList
}),
segmentationType:'product',
generateImg:computed(()=>store.state.HomeStoreModule.deReconstruction) as any,
})
const setIsShowMark:any = inject('setIsShowMark')
const dataDom = reactive({
canvasBox:null as any,
})
const selectImgItem = (data:any)=>{
if(!data.designType){
canvasAddImg(data)
}else{
// data.minioUrl = data.url
// dataDom.canvasBox.addImage(data)
getSegmentation(data)
}
}
const canvasAddImg = (list:any)=>{
list.segmentedImages.forEach((url:any) => {
list.imgUrl = url
dataDom.canvasBox.addImage(list)
});
}
const getSegmentation = (value:any)=>{
let param = new FormData();
param.append('id',value.id)
param.append('file','')
param.append('type',data.segmentationType)
let config:any = {headers:{'Content-Type':'multipart/form-data','Accept':'*/*' }}
Https.axiosPost(Https.httpUrls.imageSegmentation,param,config)
.then((rv:any) => {
// console.log(rv);
canvasAddImg(rv[0])
}
).catch(rv=>{
})
}
const openSetData = ()=>{
dataDom.canvasBox.openSetData()
}
const getCanvasImg = ()=>{
dataDom.canvasBox.getData()
}
const setGenerateImg = (base64:any)=>{
let value = {
"collagePicture": base64,
"gender": store.state.Workspace.probjects.sex,
"projectId": store.state.Workspace.probjects.id
}
setIsShowMark(true)
Https.axiosPost(Https.httpUrls.genSketchRecon,value).then((rv)=>{
if(rv){
data.sketchCatecoryList.forEach((item:any)=>{
if(item.value == rv.category){
rv.categoryValue = item.value
rv.category = item.name
}
})
rv.isLike = false
let value = {
list: [rv],
str:'add',
index:-1,
}
store.commit('setDeReconstruction',value)
setIsShowMark(false)
}
})
}
const generateLike = (str:string)=>{
if(data.generateImg[0].id == -1)return
if(str == 'like'){
let value={
"gender": store.state.Workspace.probjects.sex,
"generateDetailId": data.generateImg[0].id,
"level1Type": "Sketchboard",
"level2Type": data.generateImg[0].categoryValue,
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
}
Https.axiosPost(Https.httpUrls.generateLike,value).then((rv)=>{
if(rv){
data.generateImg[0].isLike = true
}
})
}else{
let value = {
"generateDetailId": data.generateImg[0].id,
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
}
Https.axiosGet(Https.httpUrls.generateDislike, {params:value}).then(
(rv) => {
data.generateImg[0].isLike = false
}
).catch(res=>{
});
}
}
const setCanvas = (str:string)=>{
dataDom.canvasBox.setCanvas(str)
}
const getCanvasData = ()=>{
let data = dataDom.canvasBox.getCanvasData()
return data
}
return{
...toRefs(dataDom),
...toRefs(data),
selectImgItem,
openSetData,
getCanvasImg,
setGenerateImg,
generateLike,
getCanvasData,
setCanvas,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.deReconstruction{
width: 100%;
height: 100%;
position: relative;
display: flex;
> .itemBox{
margin-right: 2rem;
padding: 2rem;
background: #f7f8fa;
border-radius: 3rem;
// flex: 1;
&.selectSektch{
width: 37rem;
flex-shrink: 0;
> .type{
display: flex;
justify-content: space-between;
> :deep(.ant-select){
margin: 1rem 0;
.ant-select-selector{
border-radius: 2rem;
}
}
>label{
display: flex;
align-items: center;
>div{
font-size: 2rem;
margin-left: 1rem;
}
}
}
}
&.canvas{
flex: 1;
}
&.finished{
width: 58rem;
display: flex;
flex-direction: column;
> .btnTop{
display: flex;
justify-content: space-between;
> .icon{
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
width: 6rem;
height: 6rem;
border: 1px solid;
border-radius: 50%;
}
}
> .content{
flex: 1;
// overflow: hidden;
margin: 10rem 0;
position: relative;
> img{
width: 100%;
height: 100%;
object-fit: contain;
}
}
> .btnBottom{
text-align: right;
}
}
}
> .itemBox:last-child{
margin-right: 0;
}
}
</style>

View File

@@ -0,0 +1,213 @@
<template>
<div class="threeDownPage" ref="threeDownPage">
<!-- height="65rem" -->
<a-modal class="generalModel"
v-model:visible="threeDown"
:footer="null"
width="77rem"
height="35rem"
:maskClosable="false"
:mask="true"
:centered="true"
:closable="false"
:get-container="() => $refs.threeDownPage"
wrapClassName="#app"
:keyboard="false"
>
<div class="generalModel_btn">
<div class="generalModel_closeIcon" @click.stop="cancelDsign()">
<svg width="46" height="46" viewBox="0 0 46 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="23" cy="23" r="23" fill="white" fill-opacity="0.3"/>
<rect x="32.5063" y="12" width="3" height="29" rx="1.5" transform="rotate(45 32.5063 12)" fill="black"/>
<rect x="34.6274" y="32.5059" width="3" height="29" rx="1.5" transform="rotate(135 34.6274 32.5059)" fill="black"/>
</svg>
</div>
</div>
<div style="display: flex; flex-direction: column; height: 100%;">
<div class="modal_title_text" style="text-align: center;">
<div>Please select the size of the clothing</div>
</div>
<div class="content">
<div class="downItem" v-for="item,key in loadList">
<div class="title">{{ key }}</div>
<div class="keyList">
<div class="item" :class="{active:(DSizeItem == select?.size && key == select?.sizeType)}" v-for="DSizeItem in item" @click="downloadIamge(DSizeItem,key)">
{{ DSizeItem }}
</div>
</div>
</div>
</div>
<div style="width: 100%; display: flex; margin-top: auto;">
<div class="gallery_btn" :class="{btnActive:!select.sizeType}" @click="setDown" style="width: 13rem; margin-left: auto;">Download</div>
</div>
</div>
<div class="mark_loading" v-show="isShowMark">
<a-spin size="large" />
</div>
</a-modal>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive, onMounted} from 'vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
import { getCookie } from "@/tool/cookie";
import { Modal,message } from 'ant-design-vue';
import {getUploadUrl,rgbToHsv,isMoible} from '@/tool/util'
export default defineComponent({
components:{
},
props:{
},
emits:['submitBrandAdd'],
setup(props,{emit}) {
const {t} = useI18n()
const store = useStore();
const data = reactive({
threeDown:false,
isShowMark:Object(''),
loadList:{
aa:[{a:1}],
bb:[{a:1}],
cc:[{a:1}]
},
select:{
sizeType:'',
size:'',
threeDSimpleId:-1,
},
})
const dataDom = reactive({
})
const cancelDsign = ()=>{
data.threeDown = false;
data.select.sizeType = ''
data.select.size = ''
}
const getDowList = (id:any)=>{
data.isShowMark = true
let value = {
threeDSimpleId:id,
// threeDSimpleId:id,
}
Https.axiosPost(Https.httpUrls.getThreeDSize,{},{params:value}).then((res:any)=>{
data.loadList = res.sizeTypeMap
data.isShowMark = false
data.select.threeDSimpleId = id
}).catch((err:any)=>{
data.isShowMark = false
})
}
const setDown = ()=>{
data.isShowMark = true
let value = {
...data.select,
}
let config = {
params:value
}
Https.axiosGet(Https.httpUrls.downloadZip,config).then((res:any)=>{
let a = document.createElement('a');
a.href = res;
a.download = 'model.zip'; // 设置下载的文件名
a.click(); // 触发下载
URL.revokeObjectURL(a.href); // 释放 URL 对象
data.isShowMark = false
}).catch((err:any)=>{
data.isShowMark = false
})
}
const openDown = (id:any)=>{
data.threeDown = true;
getDowList(id)
}
const downloadIamge = (DSizeItem:any,key:any)=>{
data.select.sizeType = key
data.select.size = DSizeItem
}
return{
...toRefs(dataDom),
...toRefs(data),
cancelDsign,
setDown,
openDown,
downloadIamge,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
:deep(.ant-modal-mask){
background: rgba(0,0,0,0.3);
}
.threeDownPage{
width: 100%;
height: 100%;
position: relative;
:deep(.generalModel){
.gallery_btn{
&.btnActive{
pointer-events: none;
background: rgba(0, 0, 0, .4);
border: none;
}
}
.content{
display: flex;
flex-direction: column;
flex: 1;
padding-left: 6rem;
// width: 55rem;
// margin: 0 auto;
> .downItem{
display: flex;
font-size: 2rem;
font-weight: 600;
margin-bottom: 1rem;
text-align: center;
align-items:center;
> .title{
margin-right: 1.5rem;
width: 3.5rem;
text-align: right;
white-space: nowrap;
}
> .keyList{
display: flex;
flex-wrap: wrap;
> .item{
font-weight: 300;
width: 5.5rem;
height: 5.5rem;
border: 1px solid #000;
display: flex;
align-items: center;
justify-content: center;
transition: all .3s;
&.active{
background: #000;
color: #fff;
}
&:hover{
background: #000;
color: #fff;
}
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,372 @@
<template>
<div class="patternMaking3D">
<div class="selectModel">
<div class="heard selectList">
<div :class="{active:libraryOrModel == 'model'}" @click="setLibraryOrModel('model')">Clothing</div>
<div :class="{active:libraryOrModel == 'print'}" @click="setLibraryOrModel('print')">Print</div>
</div>
<div class="list" v-show="libraryOrModel == 'model'" v-if="maskShow">
<div v-for="item in modelList" class="modelItem" :class="{active:item.id == selectModel.id}" @click="setSelectModel(item)">
<img :src="item.url" alt="">
</div>
<div v-show="!isNoData" class="material_content_list_loding">
<span class="page_loading" v-show="!isShowLoading" v-observe></span>
<span v-show="isShowLoading">
<a-spin size="large" />
</span>
</div>
</div>
<div class="list printList" v-show="libraryOrModel == 'print'">
<div v-for="item in printList" class="modelItem" :class="{active:item.id == selectModel.id}" @click="setMaterial(item)">
<img :src="item.url || item.imgUrl" alt="">
</div>
</div>
</div>
<div class="model" v-show="selectModel.id != -1">
<div class="heard">
<div class="text">Technical sketch</div>
<div class="switch">
front
<a-switch v-model:checked="isFront" />
back
</div>
</div>
<div class="modelBox">
<div v-show="!imgOrThree" class="img">
<img v-show="!isFront" :src="selectModel.threeDLayoutList?.[0]?.url" alt="">
<img v-show="isFront" :src="selectModel.threeDLayoutList?.[1]?.url" alt="">
</div>
<threeBox v-if="imgOrThree" ref="threeBox"></threeBox>
</div>
<div class="gallery_btn" v-show="!imgOrThree" @click="setImgOrThree(true)">3D view</div>
<div class="gallery_btn" v-show="imgOrThree" @click="setImgOrThree(false)">Img view</div>
</div>
<div class="flatPatterm" v-show="selectModel.id != -1">
<div class="heard">Flat pattern</div>
<div class="modelBox">
<div class="img">
<img :src="selectModel.threeDPatternLayoutUrl" alt="">
<div class="btn">
<i class="fi fi-bs-expand-arrows-alt" @click.stop="openScaleImage()"></i>
</div>
</div>
</div>
<div class="gallery_btn" @click="openDown()">Download</div>
</div>
<div class="download">
<download ref="download"></download>
</div>
<scaleImage ref="scaleImage"></scaleImage>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive, watch} from 'vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
import threeBox from "./three.vue"
import download from "./download.vue"
import scaleImage from "@/component/HomePage/scaleImage.vue";
export default defineComponent({
components:{
threeBox,download,scaleImage
},
props:{
},
emits:[],
setup(props,{emit}) {
const store = useStore();
const data = reactive({
selectModel:{
id:-1,
} as any,
// printCatecoryList:computed(()=>{
// return store.state.UserHabit.printType
// }),
selectObject:computed(()=>store.state.Workspace.probjects),//选择的项目
modelList:[] as any,
printList:computed(()=>store.state.UploadFilesModule.allBoardData.printboardFiles),
isShowMark:false,
isNoData:false,
isShowLoading:false,
currentPage:1,
pageSize:10,
imgOrThree:false,
isFront:false,
maskShow:false,
libraryOrModel:'model'
})
watch(()=>data.selectObject.sex,(newVal)=>{
data.modelList = []
data.currentPage = 0,
data.isNoData = false
data.isShowMark = false
})
const setSelectModel = (item:any)=>{
data.isShowMark = true
const value = {
threeDSimpleId:item.threeDSimpleId,
}
Https.axiosPost(Https.httpUrls.getLayoutDetail,{},{params:value}).then((res:any)=>{
data.selectModel = res
data.selectModel.id = item.id
data.isShowMark = false
data.imgOrThree = false
// if(data.imgOrThree){
// dataDom.threeBox.openSetData()
// }
let stateData = {
threeDsimpleId:item.id
}
store.commit('setPatternMaking3D',stateData)
}).catch((err:any)=>{
data.isShowMark = false
})
}
const dataDom = reactive({
threeBox:null as any,
download:null as any,
scaleImage:null as any,
})
const openSetData = ()=>{
nextTick(()=>{
let id = store.state.HomeStoreModule.patternMaking3D.threeDsimpleId
if(id && data.selectModel.id == -1)setSelectModel({threeDSimpleId:id})
})
setTimeout(()=>{
data.maskShow = true
},500)
}
const getModelList = ()=>{
if(data.isShowMark && !data.isNoData)return
let value = {
page: data.currentPage,
size:data.pageSize,
sex:data.selectObject.sex,
}
data.isShowLoading = true
Https.axiosPost(Https.httpUrls.threeDPage,value).then(
(rv: any) => {
if(rv.content.length == 0)data.isNoData = true
data.modelList.push(...rv.content)
data.isShowLoading = false
}
).catch((res)=>{
data.isNoData = true
});
}
const setImgOrThree = (boolean:boolean)=>{
data.imgOrThree = boolean
if(boolean){
nextTick(()=>{
dataDom.threeBox.openSetData(data.selectModel)
// dataDom.threeBox.openSetData(data.selectModel.threeDPatternLayoutUrl)
})
}
}
const downList = ()=>{
let value = {
}
Https.axiosGet(Https.httpUrls.threeDPage,value).then(
)
}
const openDown = ()=>{
dataDom.download.openDown(data.selectModel.id)
}
const setLibraryOrModel = (str:any)=>{
if(str == 'print' && data.selectModel.id == -1)return
data.libraryOrModel = str
}
const setMaterial = (item:any)=>{
dataDom.threeBox.addMaterial(item)
}
const openScaleImage = ()=>{
let scaleImage:any = dataDom.scaleImage
scaleImage.isLike = false
scaleImage.init([{imgUrl:data.selectModel.threeDPatternLayoutUrl}],0)
}
return{
...toRefs(dataDom),
...toRefs(data),
setSelectModel,
openSetData,
getModelList,
setImgOrThree,
openDown,
setLibraryOrModel,
setMaterial,
openScaleImage
}
},
directives:{
observe:{
mounted (el,binding) {
// console.log(binding.instance);
let this_:any = binding.instance
this_.isShowMark = false
this_.isNoData = false
let parentDom = el.parentNode
this_.getModelList()
new IntersectionObserver(
(entries, observer) => {
// 如果不是相交,则直接返回
// console.log(entries[0]);
if (!entries[0].intersectionRatio) return;
this_.currentPage += 1
this_.getModelList()
},
).observe(el);
},
},
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.patternMaking3D{
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
display: flex;
font-size: 1.4rem;
> .selectModel,> .model,>.flatPatterm{
padding: 3rem 2rem;
display: flex;
flex-direction: column;
> .heard{
font-size: 2rem;
font-weight: 600;
display: flex;
justify-content: space-between;
width: 100%;
&.selectList{
justify-content: flex-start;
> div{
position: relative;
margin-right: 2rem;
margin-bottom: 2rem;
}
> div::before{
position: absolute;
content: "";
display: block;
background: #000;
height: calc(.4rem*1.2);
left: 50%;
transform: translateX(-50%);
bottom: -.5rem;
width: 0px;
transition: 0.3s all;
}
> .active {
color: #000;
font-weight: 600;
}
> .active::before {
width: 100%;
}
}
> .switch{
font-weight: 400;
}
}
}
> .selectModel{
width: 40%;
// width: 70rem;
flex-shrink: 0;
height: 100%;
background: #f7f8fa;
border-radius: 3rem;
> .list{
flex: 1;
display: flex;
flex-wrap: wrap;
overflow-y: auto;
align-content: flex-start;
&.printList{
> .modelItem{
aspect-ratio: 1 / 1;
>img{
padding: 0;
}
}
}
> .modelItem{
width: calc(100% / 4 - 1rem);
margin: .5rem;
aspect-ratio: 1 / 1.2;
// height: 10rem;
border-radius: 2rem;
border: 2px solid #D4D4D4;
cursor: pointer;
> img{
width: 100%;
height: 100%;
object-fit: contain;
padding: 1rem;
}
&.active{
border: 2px solid #000;
}
}
}
}
> .model ,> .flatPatterm{
flex: 1;
overflow: hidden;
align-items: center;
> .modelBox{
width: 100%;
// height: 20rem;
// height: 75rem;
flex: 1;
padding: 1rem 0;
overflow: hidden;
margin: auto;
>.img{
width: 100%;
height: 100%;
position: relative;
> .btn{
position: absolute;
right: 2rem;
top: 2rem;
> i{
cursor: pointer;
}
}
img{
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
}
.material_content_list_loding{
text-align: center;
height: 50px;
width: 100%;
.page_loading{
display: block;
width: 50px;
height: 50px;
margin: 0 auto;
}
}
.download{
width: 0;
height: 0;
}
}
</style>

View File

@@ -0,0 +1,552 @@
<template>
<div class="three">
<div class="parameter">
<label>
<span>scaleX:</span>
<a-slider class="system_silder"
v-model:value="repeat.x"
:tooltipVisible="false"
@change="changeRepeat"
:max="6"
:step="0.001"
:min="0.002"
>
</a-slider>
</label>
<label>
<span>scaleY:</span>
<a-slider class="system_silder"
v-model:value="repeat.y"
:tooltipVisible="false"
@change="changeRepeat"
:max="6"
:min="0.002"
:step="0.001"
>
</a-slider>
</label>
<i class="fi fi-br-link" :class="{'fi-br-link':isLock,'fi-bs-link-slash':!isLock}" @click="setLock"></i>
</div>
<div class="model" ref="threeDom">
</div>
<div class="load" v-show="load.state">
<i class="fi fi-rr-cubes"></i>
<div class="text">Load...</div>
<div class="loadBox">
<div class="schedule" :style="{width:load.progress+'%'}"></div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,shallowRef,provide,nextTick,onMounted,toRefs, reactive, onBeforeUnmount} from 'vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
// @ts-ignore
import * as THREE from 'three';
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";
import gsap from 'gsap';
import { env } from 'echarts';
export default defineComponent({
components:{
},
props:{
},
emits:[],
setup(props,{emit}) {
const store = useStore();
const data = reactive({
scene:shallowRef() as any,//场景
group:shallowRef() as any,//组
camera:shallowRef() as any,//相机
renderer:shallowRef() as any,//渲染器
pointLight:shallowRef() as any,//光
controls:shallowRef() as any,//监听鼠标、键盘事件
textureLoader:shallowRef() as any,//材质
load:{
state:false,
progress:0 as any,
},
repeat:{
x:1,
y:1,
},
animationId:null as any,
isLock:false,
})
const dataDom = reactive({
threeDom:null as any,
})
const dataTime = reactive({
updataRepeat:null as any
})
const init = ()=>{
data.scene = new THREE.Scene();
data.group = new THREE.Group()
data.scene.add(data.group)
//创建相机对象
// this.camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
data.camera = new THREE.PerspectiveCamera(45, dataDom.threeDom.offsetWidth / dataDom.threeDom.offsetHeight, 0.1, 10000);
data.camera.position.set(0, 90, 6); //设置相机位置
data.camera.lookAt(data.scene.position); //设置相机方向(指向的场景对象)
/**
* 创建渲染器对象
*/
let width = dataDom.threeDom.offsetWidth; //窗口宽度
let height = dataDom.threeDom.offsetHeight; //窗口高度
data.renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true,//深度缓存 防止模型闪烁重影
});
// data.renderer.outpuEncoding = THREE?.RGBEEncoding//设置输出颜色编码格式
data.renderer.toneMapping = THREE.ACESFilmicToneMapping;//设置色调
data.renderer.toneMappingExposure = 1.3;
data.renderer.shadowMap.enabled = true;
data.renderer.setPixelRatio(window.devicePixelRatio);
data.renderer.setSize(width, height); //设置渲染区域尺寸
data.renderer.setClearColor(0xffffff, 1); //设置背景颜色
dataDom.threeDom.innerHTML = '';
dataDom.threeDom.appendChild(data.renderer.domElement);
// 设置渲染器大小
//环境光
let ambient = new THREE.AmbientLight(0xffffff,.8);
data.scene.add(ambient);
data.controls = new OrbitControls(data.camera,data.renderer.domElement)//监听鼠标、键盘事件;
// data.controls.minDistance = 500; // 设置相机与焦点的最小距离
// data.controls.maxDistance = 4000; // 设置相机与焦点的最大距离
data.controls.mouseButtons = {
// LEFT:THREE.MOUSE.PAN, // 左键 拖动(默认旋转ROTATE)
LEFT:THREE.MOUSE.ROTATE, // 左键 拖动(默认旋转ROTATE)
MIDDLE:THREE.MOUSE.DOLLY, // 滑轮 缩放
RIGHT:THREE.MOUSE.PAN // 右键 旋转默认拖动PAN
// RIGHT:THREE.MOUSE.ROTAafTE // 右键 旋转默认拖动PAN
}
/**
* 光源设置
*/
//点光源
/**
* AmbientLight 环境光
PointLight 点光源
DirectionalLight 平行光,比如太阳光
SpotLight 聚光源
*/
data.pointLight = new THREE.DirectionalLight(0xffffff,.5);
data.pointLight.intensity = 1.2
data.pointLight.castShadow = true//开启阴影
data.pointLight.shadow.mapSize = new THREE.Vector2(width, height)
data.scene.add(data.pointLight); //点光源添加到场景中
// data.pointLight.position.set(400, 200, 300); //点光源位置
data.pointLight.position.y = 400;
data.pointLight.position.z = 200;
data.pointLight.position.x = 200;
let floorGeometry = new THREE.PlaneGeometry(5000, 3000)//地板大小
let floorMaterial = new THREE.MeshPhongMaterial({ color: "#7e7ab0", })
let floorMesh = new THREE.Mesh(floorGeometry, floorMaterial);
floorMesh.rotation.x = -0.5 * Math.PI;
floorMesh.receiveShadow = true;
floorMesh.position.y = -0.001;
// data.scene.add(floorMesh);
const textureLoader = new THREE.TextureLoader();
// const texture = textureLoader.load('/3dModel/sketch-thick.jpg');
data.scene.background = new THREE.Color("#fff");
// data.scene.background = texture;
let openModel = (event:any)=>{
let mouse=new THREE.Vector2();
let raycaster=new THREE.Raycaster();
mouse.x=(event.clientX/window.innerWidth)*2-1;
mouse.y=-(event.clientY/window.innerHeight)*2+1;
raycaster.setFromCamera(mouse, data.camera);
let intersects = raycaster.intersectObjects(data.scene.children);
return intersects
}
dataDom.threeDom.ondblclick = (event:any)=>{
let intersects = openModel(event);
if(!intersects || intersects.length<=0) return
const bbox = new THREE.Box3().setFromObject(intersects[0].object);
const size = new THREE.Vector3();
let target2 = bbox.getCenter(size);//获取选中包围起来后的中心坐标
animateCamera(data.camera.position,intersects[0].point,data.controls.target,target2)
}
let isTweening = false;
function animateCamera(current1:any, target1:any, current2:any, target2:any){
if (isTweening) return
isTweening = true
let options = {
x1: current1.x, // 相机当前位置x
y1: current1.y, // 相机当前位置y
z1: current1.z, // 相机当前位置z
x2: current2.x, // 控制当前的中心点x
y2: current2.y, // 控制当前的中心点y
// z2: current2.z // 控制当前的中心点z
}
gsap.to(options,{
x1: 0, // 新的相机位置x
y1: target2.y, // 新的相机位置y
z1: 2500, // 新的相机位置z
x2: 0, // 新的控制中心点位置x
y2: target2.y, // 新的控制中心点位置x
duration:1,
ease:'linear',
onUpdate:()=>{
data.camera.position.x = options.x1;
data.camera.position.y = options.y1;
data.camera.position.z = options.z1;
data.controls.target.x = options.x2;
data.controls.target.y = options.y2;
// data.controls.target.z = object.z2;
data.controls.update();
},
onComplete:()=>{
isTweening = false
}
// z2: target2.z // 新的控制中心点位置x
})
}
// let setHighlight = (obj:any)=>{
// outlinePass.selectedObjects = obj;
// }
data.controls.enableDamping = true;
let animate = ()=>{
data.animationId = requestAnimationFrame(animate);
// data.renderer.render(data.scene, data.camera);
// model.rotation.x += 0.01; //旋转物体
var vector = data.camera.position.clone()
data.controls.update();
data.renderer.render(data.scene, data.camera);
// point.position.set(vector.x,vector.y,vector.z);
// group.rotation.y += 0.01;
// composer.render();
};
animate();
}
const setModel = async (url:any)=>{
clearModel()
await addModel(url)
// addMaterial()
}
const addMaterial =async (item:any)=>{
//添加图片材质
let url = item.url || item.url || item.imgUrl
data.load.state = true
let textureLoader = new THREE.TextureLoader()
await textureLoader.load(url, // 图片放在public/textures目录下
(texture:any) => {
data.textureLoader = texture
// 3. 配置纹理参数
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
// texture.wrapS = THREE.ClampToEdgeWrapping; // 水平方向不重复
// texture.wrapT = THREE.ClampToEdgeWrapping; // 垂直方向不重复
// texture.repeat.set(1, 1); // 纹理重复次数
texture.anisotropy = 32; // 提高纹理清晰度
data.group?.traverse((child:any) => {
if (child.isMesh) {
console.log(child.name)
// 5. 创建新材质(根据需求选择材质类型)
const textureWidth = texture.image.width;
const textureHeight = texture.image.height;
const box = new THREE.Box3().setFromObject(child);
const modelWidth = box.getSize(new THREE.Vector3()).x;
const modelHeight = box.getSize(new THREE.Vector3()).y;
data.repeat.x = 2 - modelWidth / textureWidth;
data.repeat.y = 2 - modelHeight / textureHeight;
let patternMaking3D = store.state.HomeStoreModule.patternMaking3D
if(patternMaking3D.x)data.repeat.x = patternMaking3D.x
if(patternMaking3D.y)data.repeat.y = patternMaking3D.y
// texture.repeat.set(1, 1); // 纹理重复次数
texture.repeat.set(2 - data.repeat.x, 2 - data.repeat.y); // 纹理重复次数
const newMaterial = new THREE.MeshStandardMaterial({
map: texture, // 基础颜色贴图
roughness: 0.7, // 表面粗糙度 (0-1)
metalness: .2, // 金属质感 (0-1)
side: THREE.DoubleSide // 双面渲染
});
// 7. 如果需要单独控制某些子模型的UV
if (child.geometry.attributes.uv) {
const uvs = child.geometry.attributes.uv.array;
// 计算UV边界
let minU = Infinity, maxU = -Infinity;
let minV = Infinity, maxV = -Infinity;
for (let i = 0; i < uvs.length; i += 2) {
minU = Math.min(minU, uvs[i]);
maxU = Math.max(maxU, uvs[i]);
minV = Math.min(minV, uvs[i+1]);
maxV = Math.max(maxV, uvs[i+1]);
}
const uvWidth = maxU - minU;
const uvHeight = maxV - minV;
// 仅对非小UV区域设置材质
if (!(uvWidth < 1.2 || uvHeight < 1.2)) {
const newMaterial = new THREE.MeshStandardMaterial({
map: texture,
roughness: 0.7,
metalness: 0.2,
side: THREE.DoubleSide
});
child.material = newMaterial;
}else{
// child.material = new THREE.MeshStandardMaterial({
// transparent: true,
// opacity: 0, // 完全透明
// side: THREE.DoubleSide
// });
}
child.geometry.attributes.uv.needsUpdate = true;
}
}
data.load.state = false
},(xhr:any) => { // 加载进度回调
const percent = xhr.total == 0?100:(xhr.loaded / xhr.total * 100).toFixed(2);
data.load.progress = percent
// updateProgressBar(Number(percent));
},(error:any) => {
console.error('纹理加载失败:', error);
data.load.state = false
});
let value = {
collectionElementId:item.id,
x:data.repeat.x,
y:data.repeat.y,
}
store.commit('setPatternMaking3D',value)
})
}
const addModel = async (url:any)=>{
await new Promise((resolve, reject) => {
var fbxLoader = new GLTFLoader();
let drac = new DRACOLoader()
drac.setDecoderPath('/draco/')
fbxLoader.setDRACOLoader(drac)
// fbxLoader.load('/3dModel/222/1111.glb',
fbxLoader.load(url,
(obj:any) => {
let scene = obj.scene;
var box = new THREE.Box3().setFromObject(scene);
var center = box.getCenter(new THREE.Vector3());
data.controls.target.copy(center);
// data.controls.autoRotate = true
data.camera.position.y = center.y;
data.camera.position.z = 1000;
data.pointLight.position.y = 250;
data.pointLight.position.z = 1250;
data.group.add(scene);
resolve('')
},(xhr:any) => { // 加载进度回调
const percent = xhr.total == 0?100:(xhr.loaded / xhr.total * 100).toFixed(2);
data.load.progress = percent
// updateProgressBar(Number(percent));
},(error:any) => { // 加载失败回调
console.error('模型加载失败:', error);
reject('')
})
})
}
const clearModel = ()=>{
const oldGroup:any = data.group;
data.group = new THREE.Group();
data.scene.add(data.group);
data.scene.remove(oldGroup);
}
// const loadThree = ()=>{
// init()
// }
const getModelUrl = (value:any)=>{
return new Promise((resolve, reject) => {
// Https.axiosGet(Https.httpUrls.getThreeDGlb,{params:{threeDSimpleId:value.id},env:{binary:true}}).then((rv)=>{
// //二进制流转本地路径
// console.log(rv)
// resolve(rv)
// }).catch(()=>{
// reject('')
// })
// //fetch get请求携带token
// fetch("https://develop.api.aida.com.hk/api/project/getThreeDGlb?threeDSimpleId=1", {
// headers:{
// authorization:'Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI4OCIsInN1YiI6IntcImNvdW50cnlcIjpcIkNoaW5hXCIsXCJpZFwiOjg4LFwibGFuZ3VhZ2VcIjpcIkVOR0xJU0hcIixcInVzZXJuYW1lXCI6XCJzaGJcIn0iLCJpYXQiOjE3NDMzNDkwNjQsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE3NTE5ODkwNjR9.gmL0JufYy9wd23qCY-ibwhgpXZ2X68WAiHSeC99I4x7cipWyxLaQmuIBk2SJSdWBm0tTN2Mx-etXO9a7MtQmpw',
// }
// }).then(res => {
// return res.blob();
// }).then((res) => {
// var url = URL.createObjectURL(res);
// console.log(url, res)
// resolve(url)
// }).catch(err => {
// console.log(err);
// })
resolve(value.threeDSimpleUrl)
})
}
const openSetData = async (value:any)=>{
if(!data.scene){
init()
}
data.load.state = true
const modeUrl = await getModelUrl(value)
await setModel(modeUrl)
let patternMaking3D = store.state.HomeStoreModule.patternMaking3D
if(patternMaking3D.printMinioUrl)await addMaterial({url:patternMaking3D.printMinioUrl})
data.load.state = false
}
const changeRepeat = (e:any)=>{
if(data.isLock)data.repeat.x = e
if(data.isLock)data.repeat.y = e
clearTimeout(dataTime.updataRepeat)
dataTime.updataRepeat = setTimeout(()=>{
data.repeat.x = data.repeat.x == 6 ? 5.999 : data.repeat.x
data.repeat.y = data.repeat.y == 6 ? 5.999 : data.repeat.y
data.textureLoader.repeat.set(6 - data.repeat.x,6 - data.repeat.y); // 纹理重复次数
let value = {
x:data.repeat.x,
y:data.repeat.y,
}
store.commit('setPatternMaking3D',value)
},1000)
}
const setLock = ()=>{
data.isLock = !data.isLock
}
onMounted(()=>{
})
onBeforeUnmount(()=>{
if(data.animationId){
cancelAnimationFrame(data.animationId);
data.animationId = null;
}
data.scene.traverse((child:any) => {
if (child.material) {
child.material.dispose();
}
if (child.geometry) {
child.geometry.dispose();
}
child = null;
});
data.renderer.forceContextLoss();
data.renderer.dispose();
data.scene.clear();
data.scene = null;
data.camera = null;
data.controls = null;
data.renderer.domElement = null;
data.renderer = null;
})
return{
...toRefs(dataDom),
...toRefs(data),
openSetData,
addMaterial,
changeRepeat,
setLock,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.three{
width: 100%;
height: 100%;
position: relative;
flex: 1;
overflow: hidden;
> .parameter{
display: flex;
align-items: center;
> label{
display: flex;
align-items: center;
flex: 1;
padding-right: 2rem;
// &:not(:last-child){
// margin-right: 3rem;
// }
> span{
font-size: 2rem;
margin-right: 1rem;
}
}
> i{
width: 3rem;
height: 3rem;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
&.active{
opacity: .7;
}
}
}
> .model{
width: 100%;
height: 100%;
}
> .load{
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(0, 0, 0, .2);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
color: #fff;
> i{
font-size: 3rem;
}
> .loadBox{
width: 15rem;
height: 1rem;
border-radius: 1rem;
background: #fff;
overflow: hidden;
> .schedule{
height: 100%;
background: greenyellow;
}
}
}
}
</style>

View File

@@ -0,0 +1,615 @@
<template>
<div class="poseTransfer">
<div class="configuratioBox" :class="{active:button.left}">
<div class="configuratio">
<!-- <div class="title">Give pose for them to select</div> -->
<div class="content">
<!-- <selectList @selectImgItem="selectImgItem" level1Type="Printboard" type="print"></selectList> -->
<div class="selectImg">
<div class="head">
<div class="text">Choose design to transfer</div>
</div>
<div class="imgBox" v-mousewheel>
<div class="item" :class="{active:item.id == selectImg.id}" v-for="item in currentList" @click="selectImgItem(item)">
<img :src="item.imgUrl || item.url" alt="">
<a-checkbox v-model:checked="item.isChecked"></a-checkbox>
</div>
<div class="item" :class="{active:item.id == selectImg.id}" v-for="item in fileList" @click="selectImgItem(item)">
<img :src="item.imgUrl || item.url" alt="">
<a-checkbox v-model:checked="item.isChecked"></a-checkbox>
</div>
<div class="upload_item item">
<div class="upload_file_item">
<a-upload
:action="getUploadUrl() + '/api/history/toProductImageElementUpload'"
list-type="picture-card"
:capture="null"
:data="{
...upload,
}"
:headers="{ Authorization: token }"
:before-upload="beforeUpload"
v-model:file-list="fileList"
:multiple="true"
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>
</div>
</div>
<div class="poses">
<div class="head">
<div class="text">Choose pose</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)"
>
<a-checkbox v-model:checked="item.isChecked"></a-checkbox>
</div>
</div>
</div>
</div>
</div>
<div class="generate input_border">
<div class="generage_btn started_btn" v-show="!isGenerate" @click="getgenerate">
{{ $t('Generate.Generate') }}
</div>
<div v-show="isGenerate && !remGenerate" class="generage_btn started_btn">
<i class="fi fi-br-loading"></i>
</div>
<div v-show="remGenerate" @click="removeGenerate" class="generage_btn started_btn">
{{$t('Generate.Close')}}
</div>
</div>
</div>
<div class="likeBox">
<div class="element">
<div class="title"><i class="fi fi-rs-comments"></i><span>Selected Video</span></div>
<div class="content">
<generalDrag ref="generalDragLeft" v-if="isState" :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}">
<div class="element">
<div class="title"><i class="fi fi-rs-comments"></i><span>Generated Video</span></div>
<div class="content">
<generalDrag ref="generalDragRight" v-if="isState" :list="noLikeList" :isVideo="true" @setBtn="noLikeSetBtn"></generalDrag>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,inject,nextTick,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 selectList from '@/component/DetailCopy/module/selectList.vue';
export default defineComponent({
components:{
generalDrag,
// selectList,
},
props:{
isState:{
type:Boolean,
default:false,
}
},
emits:[],
setup(props,{emit}) {
const {t} = useI18n()
const store = useStore();
const data:any = reactive({
button:{
left:false,
right:false,
},
currentList:[],
fileList:[],
selectImg:{},
token:getCookie('token'),
upload:{
projectId:store.state.Workspace.probjects.id
},
waitList:[],
likeList:computed(()=>store.state.HomeStoreModule.poseTransfer),
noLikeList:[],
isGenerate:false,//判断是否正在进行generate
remGenerate:false,
removeGenerate:false,
generateTime:null as any,
poseList:[],
selectPose:null as any,
})
const setIsShowMark:any = inject('setIsShowMark')
const dataDom = reactive({
generalDragLeft:null as any,
generalDragRight:null as any,
scaleVideo:null as any,
})
const selectImgItem = (item:any,)=>{
data.selectImg = item
data.fileList.forEach((listItem:any)=>listItem.isChecked = false)
console.log(data.currentList)
data.currentList.forEach((listItem:any)=>listItem.isChecked = false)
item.isChecked = true
if(item.url || item.imgUrl)data.selectImg.minioUrl = getMinioUrl(item.url || item.imgUrl)
}
const openSetData = ()=>{
// dataDom.generalDrag.openSetData()
data.currentList = store.state.UploadFilesModule.modularData.toProduct
setIsShowMark(false)
if(data.poseList.length == 0){
getPoseList()
}
setCloudImg()
}
const setCloudImg = ()=>{
let arr = store.state.UploadFilesModule.cloudList
let list = JSON.parse(JSON.stringify(arr.poseTransfer)) || []
console.log(list)
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 gifPause = (e:any,item:any)=>{
e.target.src = item.firstFrame//静态图片
}
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 = ()=>{
if(!data.selectImg.minioUrl)return
if(data.isGenerate)return
data.isGenerate = true
data.remGenerateTime = setTimeout(()=>{
data.remGenerate = true
},10000)
let value = {
poseId:data.selectPose,
projectId:store.state.Workspace.probjects.id,
productImage:data.selectImg.minioUrl,
}
Https.axiosGet(Https.httpUrls.poseTransform,{params:value}).then((rv)=>{
data.noLikeList.unshift({taskId:rv})
setGenerate(rv)
}).catch((res:any)=>{
data.isGenerate = false
clearInterval(data.remGenerateTime)
data.remGenerate = false
})
}
const setGenerate = (dataList:any)=>{
let list:any = dataList
let dataNum = dataList.length
let state = true
data.generateTime = setInterval(()=>{
if(!data.isGenerate || !data.remGenerate)return
if(!state)return
state = false
Https.axiosGet(Https.httpUrls.poseTransformResult,{params:{taskId:list}}).then(
(rv) => {
rv=[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
console.log(list)
list = ''
// if(list?.filter)list = list?.filter((item:any) => item !== element.taskId);
}else if(element.status == 'Fail'){
}
});
data.waitList = list
if((!list)|| (rv.filter((item:any)=>item.status == 'Invalid').length ==list.length)){
if(rv.filter((item:any)=>item.status == 'Invalid').length ==dataNum){
message.info(t('Generate.effectPoor'));
}else{
}
// this.store.dispatch('getCredits')
clearInterval(data.generateTime)
clearInterval(data.remGenerateTime)
data.remGenerate = false
data.isGenerate = false
}
}
}
).catch(res=>{
data.noLikeList = data.noLikeList.filter((item:any)=>item.taskId != list)
clearInterval(data.generateTime)
clearInterval(data.remGenerateTime)
data.isGenerate = false
data.remGenerate = false
});
},1000)
}
const removeGenerate = ()=>{
//取消操作
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,
userId:store.state.UserHabit.userDetail.userId,
timeZone:Intl.DateTimeFormat().resolvedOptions().timeZone,
type: 'PoseTransferation'
}
Https.axiosGet(Https.httpUrls.generateStopWaiting, {params:value}).then(
(rv) => {
data.waitList = []
data.noLikeList = data.noLikeList.filter((item:any)=>item.status == 'Success')
}
).catch(res=>{
});
}
}
let beforeUpload = (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'));
}
return (isJpgOrPng && isLt2M) || 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.fileList.forEach((listItem:any)=>listItem.isChecked = false)
data.currentList.forEach((listItem:any)=>listItem.isChecked = false)
file.isChecked = true
file.type = 'ProductElement'
// if(props.productimgMenu.value == 'Relight'){
// file.type = "ToProductImage"
// }
data.selectImg = res.data
data.fileList.filter((v: any) => v.status === "done");
}else{
bor = false
}
// this.showFileList = productImgData.fileList
} else if (file.status === "error") {
bor = false
}
}
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'){
data.noLikeList = data.noLikeList.filter((v:any) => v.id != id);
}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,
}
}else{
value = {
likeOrDislike:'dislike',
transformedId:item.id,
}
}
Https.axiosPost(Https.httpUrls.poselikeOrDisike, {},{params:value}).then(
(rv) => {
if(str == 'like'){
let value = {
list:[item],
str:'add',
index:-1,
}
store.commit("setPoseTransfer", value);
data.noLikeList.splice(index,1)
}else{
let value = {
list:[item],
str:'splice',
index:index,
}
data.noLikeList.push(item)
store.commit("setPoseTransfer", value);
}
}
).catch(res=>{
});
}
const selectPose = (item:any)=>{
item.isChecked = true
data.selectPose = item?.id || 1
data.poseList.forEach((listItem:any)=>listItem.isChecked = false)
}
onMounted(()=>{
// showViewVideo({url:'https://www.minio.aida.com.hk:12025/api/v1/download-shared-object/aHR0cHM6Ly93d3cubWluaW8uYWlkYS5jb20uaGs6MTIwMjQvYWlkYS11c2Vycy84OS9wb3NlX3RyYW5zZm9ybV92aWRlby8xMjMtODkubXA0P1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9N0tOVDdNWlNLWkRXM1RVOEJZVlklMkYyMDI1MDQwOCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA0MDhUMDUxOTM1WiZYLUFtei1FeHBpcmVzPTQzMTk5JlgtQW16LVNlY3VyaXR5LVRva2VuPWV5SmhiR2NpT2lKSVV6VXhNaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpoWTJObGMzTkxaWGtpT2lJM1MwNVVOMDFhVTB0YVJGY3pWRlU0UWxsV1dTSXNJbVY0Y0NJNk1UYzBOREV4T0RneE9Td2ljR0Z5Wlc1MElqb2lZV1J0YVc0aWZRLmY0Z3RoTU1BeC1GUnM3eGhWNFdjTUFCUW5lU19BVkIxUDlYbnJQbEFNWUFsVnJwY3RpYXgtU2cyY2FkZHZ0a0VCOU1NbWxGeUlIbU90aGhUWDlqN2lnJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZ2ZXJzaW9uSWQ9bnVsbCZYLUFtei1TaWduYXR1cmU9Yjg5YmQ4ZDg5M2I4ZjBjYmYxZDI3NDFjZmY0NGRiZGNmYWM2NmU0ZGM2OGIwYzQzZDA2OGI4YjYzZjE5YjhhOA'})
})
return{
...toRefs(dataDom),
...toRefs(data),
openSetData,
selectImgItem,
setSize,
setItemPosition,
gifPlay,
gifPause,
getgenerate,
getUploadUrl,
beforeUpload,
fileUploadChange,
removeGenerate,
likeSetBtn,
noLikeSetBtn,
selectPose,
}
},
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;
&.active{
width: 0;
overflow: hidden;
}
> .generate{
margin-left: auto;
> .started_btn{
font-weight: 300;
}
}
}
> .configuratioBox > .configuratio{
width: 31.8rem;
padding-bottom: 1rem;
> .title{
// font-size: 2.6rem;
}
> .content{
// margin-top: 4rem;
margin-top: 1.8rem;
> .selectImg,> .poses{
display: flex;
flex-direction: column;
> .imgBox{
flex: 1;
max-height: 45rem;
margin-top: 2rem;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
width: 100%;
overflow: hidden;
overflow-x: auto;
> .item{
margin-right: 1rem;
width: calc(100% / 2 - .5rem);
cursor: pointer;
overflow: hidden;
display: flex;
justify-content: center;
flex-shrink: 0;
height: 25rem;
position: relative;
// &.active{
// border: 2px solid;
// }
:deep(.ant-checkbox-wrapper){
position: absolute;
top: 2rem;
right: 2rem;
}
> img{
width: 100%;
object-fit: contain;
}
}
> .upload_item{
border: none;
}
}
> .head{
color: #000;
font-weight: 600;
> .text{
display: inline-block;
font-size: 1.6rem;
}
}
}
> .poses{
margin-top: 3rem;
}
}
}
> .likeBox ,> .noLikeBox{
margin-top: 1.8rem;
flex: 1;
position: relative;
> .element{
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
> .btnLeft,> .btnRight{
position: absolute;
width: 4rem;
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;
>span{
transition: all .3s;
transform: rotate(90deg);
}
&.active{
>span{
transform: rotate(270deg);
}
}
}
> .btnRight{
left: calc(100% + 4rem) ;
transform: translate(-100%,-50%) rotate(180deg);
}
> .content{
flex: 1;
padding: 1.7rem 2rem;
border-radius: 3rem;
background: #f7f8fa;
}
> .title{
margin-bottom: 2rem;
font-size: 1.6rem;
font-weight: 900;
> span{
margin-left: 1rem;
}
}
}
}
> .noLikeBox{
padding-left: 2.3rem;
&.active{
flex: 0;
overflow: hidden;
}
}
}
</style>

File diff suppressed because it is too large Load Diff