布局修改 部分bug修复

This commit is contained in:
X1627315083
2025-08-22 10:27:48 +08:00
parent 141821a843
commit 594bf5ce0a
275 changed files with 5675 additions and 13049 deletions

View File

@@ -0,0 +1,416 @@
<template>
<div class="color">
<div class="detailText">{{$t('DesignPrintOperation.CurrentColor')}}</div>
<div class="pallet">
<pallet :selectColor="selectColor" @selectUplpadColor="selectUplpadColor"></pallet>
</div>
<div class="detailText">{{$t('DesignPrintOperation.Colorpelette')}}</div>
<div class="colorBox">
<div v-for="item,index in colorList.list[selectDetail.id]" @click="setSelectColor(item,index)" class="colorBoxItem" :class="{active:colorList.index == index}">
<div v-if="item" class="box">
<div v-show="!item.gradient" class="background" :style="{'background-color':item.hex}"></div>
<div v-show="!item.gradient" class="text">{{ item.hex }}</div>
<div v-show="!item.gradient" class="text">{{ item.name }}</div>
<div v-show="item.gradient" class="backgroundImg" :style="{'background-image':`linear-gradient(${item.gradient?.angle}deg,${setGradient(item.gradient)})`}"></div>
</div>
</div>
</div>
<div class="detailText">{{$t('DesignPrintOperation.Colorfromimage')}}</div>
<div class="uploadImage">
<upload @selectUplpadColor="selectUplpadColor"></upload>
</div>
<div class="detailText">{{$t('DesignPrintOperation.ColorCode')}}</div>
<div class="colorCode">
<div class="generalModel_state">
<div class="generalModel_state_item">
<input class="search_input" placeholder="Tcx valuee.g:19-4052)" v-model="tcxToColor" style="width: 100%;" @keydown.enter="getTcxColor()">
<i class="fi fi-br-search" @click="getTcxColor"></i>
</div>
</div>
<!-- <div class="getTcxColorBtn" @click="getTcxColor">{{$t('DesignPrintOperation.ExtractColor')}}</div> -->
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,watch,nextTick,toRefs, reactive, onMounted} from 'vue'
// import setDesignItem from '@/component/Detail/setDesignItem2.vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { useStore } from "vuex";
import { Https } from "@/tool/https";
import { useI18n } from 'vue-i18n'
import { rgbaToHex,rgbToHsv } from "@/tool/util"
import { message,Upload} from 'ant-design-vue';
import upload from './upload.vue'
import pallet from './pallet.vue'
export default defineComponent({
components:{
upload,pallet
},
setup(props,{emit}) {
const store = useStore();
const {t} = useI18n();
const colorData = reactive({
selectTitle:'current',
selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
allBoardData:computed(()=>store.state.UploadFilesModule.allBoardData),
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType),
colorList:{
list:{},
index:-1,
} as any,
selectColor:{} as any,
setGradient:computed(()=>{
return (gradient:any)=>{
let gradientStr = ''
if(!gradient?.gradientList)return
gradient.gradientList.sort((a:any, b:any) => {
let aArr = a.left.split('%')[0]
let bArr = b.left.split('%')[0]
return aArr - bArr;
});
gradient.gradientList.forEach((item:any,index:any)=>{
let str = ','
if(gradient.gradientList.length == index+1)str = ''
gradientStr += `rgba(${item.rgba.r},${item.rgba.g},${item.rgba.b},${item.rgba.a}) ${item.left}${str}`
})
return `${gradientStr}`
}
}),
tcxToColor:'',
})
watch(()=>colorData.selectColor,async (newVal,oldVal)=>{
if(newVal.rgba && newVal.rgba?.r){
let data:any = await getColorName(newVal.rgba)
newVal.name = data.name
newVal.tcx = data.tcx
colorData.colorList.list[colorData.selectDetail.id][colorData.colorList.index] = newVal
let value = {
data:newVal,
str:'color'
}
store.commit('DesignDetail/setNewDetail',value)
}else{
let value = {
data:{},
str:'color'
}
store.commit('DesignDetail/setNewDetail',value)
}
})
watch(()=>colorData.selectDetail.id,(newVal,oldVal)=>{
if(!newVal)return
if(!colorData.colorList?.list?.[newVal]){
colorData.colorList.list[newVal] = []
}else{
return
}
let isNoSelect = false
let pushIndex = 0
for (let index = 0; index < 9; index++) {
colorData.allBoardData.colorBoards
let item:any = {}
item = colorData.allBoardData.colorBoards[index]
let color = colorData.allBoardData.colorBoards?.[index]
if(!color?.rgba && color?.rgbValue)color.rgba = color.rgbValue
if(
colorData.allBoardData.colorBoards?.[index] &&
colorData.selectDetail.color.rgba?.r == color?.rgba?.r &&
colorData.selectDetail.color.rgba?.g == color?.rgba?.g &&
colorData.selectDetail.color.rgba?.b == color?.rgba?.b &&
JSON.stringify(colorData.selectDetail.color.gradient) == JSON.stringify(color?.gradient)
&& colorData.selectDetail.color.rgba?.r
){
isNoSelect = true
colorData.selectColor = item
colorData.colorList.index = index
}else if(color?.rgba?.r){
pushIndex = index
item = {
hex:rgbaToHex([color?.rgba.r,color?.rgba.g,color?.rgba.b]),
id:color?.id,
rgba:{
r:color?.rgba.r,
g:color?.rgba.g,
b:color?.rgba.b,
},
tcx:color?.tcx,
name:color?.name,
}
if(color?.gradient){
item.gradient = color?.gradient
}
colorData.colorList.index = index
colorData.selectColor = item
}
colorData.colorList.list[newVal].push(item)
}
if(!isNoSelect){
if(!colorData.selectDetail.color?.rgba?.r)return
let item = {
hex:rgbaToHex([colorData.selectDetail.color.rgba.r,colorData.selectDetail.color.rgba.g,colorData.selectDetail.color.rgba.b]),
id:colorData.selectDetail.color.id,
rgba:{
r:colorData.selectDetail.color.rgba.r,
g:colorData.selectDetail.color.rgba.g,
b:colorData.selectDetail.color.rgba.b,
},
tcx:colorData.selectDetail.color.tcx,
name:colorData.selectDetail.color.name,
} as any
if(colorData.selectDetail.color.gradient){
item.gradient = colorData.selectDetail.color.gradient
}
colorData.selectColor = item
colorData.colorList.index = pushIndex + 1
colorData.colorList.list[newVal][pushIndex + 1] = item
}
// for (let index = 0; index < 9; index++) {
// colorData.allBoardData.colorBoards
// let item:any = {}
// item = colorData.allBoardData.colorBoards[index]
// if(
// colorData.allBoardData.colorBoards?.[index] &&
// colorData.selectDetail.color.rgba?.r == colorData.allBoardData.colorBoards?.[index]?.rgba?.r &&
// colorData.selectDetail.color.rgba?.g == colorData.allBoardData.colorBoards?.[index]?.rgba?.g &&
// colorData.selectDetail.color.rgba?.b == colorData.allBoardData.colorBoards?.[index]?.rgba?.b &&
// JSON.stringify(colorData.selectDetail.color.gradient) == JSON.stringify(colorData.allBoardData.colorBoards?.[index]?.gradient)
// && colorData.selectDetail.color.rgba?.r
// ){
// console.log(13212)
// if(!isOneChecked){
// isOneChecked = true
// if(colorData.allBoardData.colorBoards?.[index].gradient){
// item.gradient = colorData.allBoardData.colorBoards?.[index].gradient
// }
// colorData.selectColor = item
// colorData.colorList.index = index
// }
// }else if(colorData.selectDetail.color.rgba?.r){
// if(!isNoSelect){
// item = {
// hex:rgbaToHex([colorData.selectDetail.color.rgba.r,colorData.selectDetail.color.rgba.g,colorData.selectDetail.color.rgba.b]),
// id:colorData.selectDetail.color.id,
// rgba:{
// r:colorData.selectDetail.color.rgba.r,
// g:colorData.selectDetail.color.rgba.g,
// b:colorData.selectDetail.color.rgba.b,
// },
// tcx:colorData.selectDetail.color.tcx,
// name:colorData.selectDetail.color.name,
// }
// if(colorData.selectDetail.color.gradient){
// item.gradient = colorData.selectDetail.color.gradient
// }
// colorData.colorList.index = index
// colorData.selectColor = item
// isNoSelect = true
// }else{
// item = {}
// }
// }
// colorData.colorList.list[newVal].push(item)
// }
},{immediate: true})
const selectImgItem = ()=>{
}
const getColorName = (color:any)=>{
let rgb:any = [color.r, color.g, color.b];
let hsv = rgbToHsv(rgb);
let data = [{
h: hsv[0],
s: hsv[1],
v: hsv[2],
}]
return new Promise((resolve, reject) => {
Https.axiosPost(Https.httpUrls.getRgbByHsvBatch, data)
.then((rv) => {
if (rv) {
resolve(rv[0])
}
})
.catch((res) => {
resolve({name:'--',tcx:'--'})
});
})
}
const selectUplpadColor = (item:any)=>{
colorData.selectColor = JSON.parse(JSON.stringify(item))
}
const setSelectColor = (item:any,index:number)=>{
colorData.colorList.index = index
if(item?.rgba){
colorData.selectColor = item
}else{
// colorData.colorList.list[colorData.selectDetail.id][index] = {}
colorData.selectColor = {}
}
}
const getTcxColor = ()=>{
if(!colorData.tcxToColor){
return
}
let pattern = /^\d{2}-\d{4}$/;
if(pattern.test(colorData.tcxToColor)){
Https.axiosGet(Https.httpUrls.getRgbByTcx + '?tcx=' + colorData.tcxToColor).then((rv) =>{
if(rv && rv.name){
let hex = rgbaToHex([rv.r,rv.g,rv.b,rv.a? rv.a :1])
let value = {
hex:hex,
rgba:{
r:rv.r,
g:rv.g,
b:rv.b,
},
name:rv.name,
tcx:rv.tcx,
id:rv.id,
}
colorData.selectColor = value
}else{
message.info(t('DesignDetailAlter.jsContent6'))
}
})
}else{
message.info(t('ColorboardUpload.jsContent5'))
}
}
onMounted(()=>{
if(colorData.allBoardData.colorBoards){
colorData.allBoardData.colorBoards.forEach((item:any)=>{
item.rgba = item.rgbValue
let rgba = [item.rgbValue.r,item.rgbValue.g,item.rgbValue.b]
item.hex = rgbaToHex(rgba)
})
}
})
return{
...toRefs(colorData),
selectImgItem,
selectUplpadColor,
setSelectColor,
getTcxColor,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.color{
// width: 34rem;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
overflow-y: auto;
> .detailText{
margin-bottom: .5rem;
}
> .pallet{
margin-bottom: 2rem;
}
> .colorBox{
margin-bottom: 1rem;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
> .colorBoxItem{
// margin: 1rem 0;
margin-bottom: 1rem;
width: 32%;
height: 11rem;
border-radius: .5rem;
border: 1px solid #999;
cursor: pointer;
display: flex;
flex-direction: column;
&.active{
border: 2px solid #000;
}
>.box{
width: 100%;
height: 100%;
> .background{
flex: 1;
height: 7rem;
width: 100%;
}
> .text{
font-weight: 600;
line-height: 2rem;
text-align: center;
white-space: nowrap; /* 禁止换行 */
overflow: hidden; /* 隐藏溢出内容 */
text-overflow: ellipsis;
}
> .backgroundImg{
width: 100%;
height: 100%;
}
}
}
}
> .uploadImage{
flex-shrink: 0;
margin-bottom: 3rem;
border: 1px dashed transparent;
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
height: 10rem;
width: 100%;
border-radius: .5rem;
}
> .colorCode{
margin-bottom: 3rem;
> .generalModel_state{
> .generalModel_state_item{
width: 100%;
margin: 0;
border-radius: 1rem;
border: 1px solid;
overflow: hidden;
display: flex;
input{
border: none;
background: #f4f4f4;
}
i{
width: 5rem;
border-left: 1px solid;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
height: 100%;
background: #f4f4f4;
}
}
}
> .getTcxColorBtn{
background: #BDBDBD;
border-radius: 5rem;
line-height: 6rem;
text-align: center;
margin-top: 2rem;
cursor: pointer;
width: 100%;
transition: all .3s;
&:hover{
background: #d4d4d4;
}
}
}
}
</style>

View File

@@ -0,0 +1,641 @@
<template>
<div class="pallet">
<div class="palletColo" @click="openPallet">
<div v-show="!selectColor.gradient" class="palletBackColor" :title="selectColor.name" :style="{'background-color':selectColor.hex}">
{{ selectColor.hex }}
</div>
<div v-show="selectColor.gradient" class="palletBackColor" :style="{'background-image':`linear-gradient(${selectColor.gradient?.angle}deg,${setGradient(selectColor.gradient)})`}">
</div>
</div>
<div class="palletBox">
<div v-show="palletShow" class="color_setting_block">
<Chrome class="chrome_color" v-model="color_"></Chrome>
<div class="color_setting_operateSingle">
<div class="color_setting_btn" :class="{active:!color?.gradient?.gradientShow}">{{ $t('ColorboardUpload.Single') }}</div>
<a-switch :checked="color?.gradient?.gradientShow" @click="setOperate"/>
<div class="color_setting_btn" :class="{active:color?.gradient?.gradientShow}">{{ $t('ColorboardUpload.Gradual') }}</div>
</div>
<div class="color_setting_operate" v-if="color?.gradient?.gradientShow">
<div class="color_setting_operate_item color_setting_operate_control">
<div class="operate_item_box">
<div>{{ $t('ColorboardUpload.Alignment') }}</div>
</div>
<div class="operate_item_box operate_item_angle">
<div class="operate_item_angle_box" @mousedown="mousedownGradientAngle(getMousePosition($event,false))" @touchstart="mousedownGradientAngle(getMousePosition($event,true))">
<div :style="{'transform':`rotate(${color.gradient.angle}deg)`}"></div>
</div>
</div>
<div class="operate_item_box operate_item_delete">
<i class="fi fi-rr-trash" @click="deleteGradientItem"></i>
</div>
</div>
<div class="color_setting_operate_item color_setting_operate_input">
<div class="color_setting_operate_bg" @click="addGradient($event)" :style="{'background-image':color?.gradient?`linear-gradient(90deg,${setGradient(color.gradient)})`:'none'}">
</div>
<div v-for="item,index in color.gradient.gradientList" :key="item" class="color_setting_operate_btn" :class="{'active':index == color.gradient.selectIndex}" :style="{'left':item.left,'background-color':`rgba(${item.rgba.r},${item.rgba.g},${item.rgba.b},${item.rgba.a})`}" @mousedown="mousedownGradient(getMousePosition($event,false),item,index,)" @touchstart="mousedownGradient(getMousePosition($event,true),item,index,)"></div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,watch,nextTick,onMounted,toRefs, reactive} from 'vue'
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
import { message,Upload} from 'ant-design-vue';
import { Sketch, Chrome} from '@ans1998/vue3-color'
import { getMousePosition } from "@/tool/mdEvent";
import { rgbaToHex } from "@/tool/util"
import { color } from 'echarts/core';
export default defineComponent({
components:{
Chrome,
},
props:{
selectColor:{
type:Object,
default:()=>{}
},
},
emits:['selectUplpadColor'],
setup(props,{emit}) {
const {t} = useI18n()
const store = useStore();
const palletData = reactive({
palletShow:false,
palletList:[],
color_:{} as any,
color:{} as any,
updataSelectColorTime:null as any,
gradient:{
gradientList:[
{
rgba:{
r:117,
g:119,
b:255,
a:1,
},
left:'0%'
},{
rgba:{
r:0,
g:222,
b:152,
a:1,
},
left:'100%'
},
],
angle:45,
selectIndex:-1,
gradientShow:false,
},
setGradient:computed(()=>{
return (gradient:any)=>{
let gradientStr = ''
if(!gradient?.gradientList)return
gradient.gradientList.sort((a:any, b:any) => {
let aArr = a.left.split('%')[0]
let bArr = b.left.split('%')[0]
return aArr - bArr;
});
gradient.gradientList.forEach((item:any,index:any)=>{
let str = ','
if(gradient.gradientList.length == index+1)str = ''
let rgba = item.rgba?item.rgba:{r:255,g:255,b:255}
gradientStr += `rgba(${rgba.r},${rgba.g},${rgba.b},${rgba.a}) ${item.left}${str}`
})
return `${gradientStr}`
}
})
})
const getpalletListDom = reactive({
})
watch(()=>palletData.color_,(newVal:any)=>{
if(!newVal?.rgba?.r)return
if(palletData.color?.gradient?.gradientShow){
palletData.color.gradient.gradientList[palletData.color.gradient.selectIndex].rgba = {
r:newVal.rgba.r,
g:newVal.rgba.g,
b:newVal.rgba.b,
a:newVal.rgba.a,
}
}else{
palletData.color = newVal
}
})
watch(()=>palletData.color,(newVal:any)=>{
clearTimeout(palletData.updataSelectColorTime)
palletData.updataSelectColorTime = setTimeout(()=>{
if(JSON.stringify(props.selectColor) != JSON.stringify(newVal)){
newVal.name = ''
newVal.tcx = ''
let rgba = [newVal.rgba.r,newVal.rgba.g,newVal.rgba.b]
let hex = rgbaToHex(rgba)
newVal.hex = hex
emit('selectUplpadColor',newVal)
}
},400)
},{deep: true })
const setOperate = ()=>{
if(!palletData.color.rgba)return message.info(t('DesignDetailAlter.jsContent7'))
palletData.color.rgba = palletData.color?.rgba?.r?palletData.color.rgba:{r:0,g:0,b:0,a:1}
palletData.gradient.selectIndex = 0
palletData.gradient.gradientShow = true
if(!palletData.color.gradient){
if(palletData.color.rgba.r){
palletData.gradient.gradientList[palletData.gradient.selectIndex].rgba = {
r:palletData.color.rgba.r,
g:palletData.color.rgba.g,
b:palletData.color.rgba.b,
a:1,
}
}
palletData.color.gradient = JSON.parse(JSON.stringify(palletData.gradient))
}else{
palletData.color.rgba = palletData.color.gradient.gradientList[0].rgba
palletData.color.gradient = null
}
}
const deleteGradientItem = ()=>{
if(palletData.color.gradient.gradientList.length <= 2)return
palletData.color.gradient.gradientList.splice(palletData.color.gradient.selectIndex,1)
}
const addGradient = (event:any)=>{
let gradientWidth = event.target.clientWidth
let left:any = event.offsetX/gradientWidth
palletData.color.gradient.gradientList.push({
rgba:palletData.color_.rgba,
left:left.toFixed(2)*100+'%'
})
}
const mousedownGradientAngle = (event:any)=>{
// isMoible() true为移动端
let domPosition = event.target.getBoundingClientRect()
let position = {
x:domPosition.x+domPosition.width/2,
y:domPosition.y+domPosition.height/2,
}
let angle
let mousedown = function(event:any){
let e = getMousePosition(event,false)
mouseDownOperation(e)
}
let touchstart = function(event:any){
let e = getMousePosition(event,true)
mouseDownOperation(e)
}
let mouseDownOperation = (e:any)=>{
let X = position.x
let Y = position.y
let x = (e.clientX) - X
let y = Y -( e.clientY)
angle = Math.atan2(x,y)*(180 / Math.PI)
// this.colorList[this.selectIndex].gradient = JSON.parse(JSON.stringify(this.gradient))
palletData.color.gradient.angle = angle
}
let mouseupGradientAngle = ()=>{
window.removeEventListener('touchmove',touchstart)
window.removeEventListener('touchend',mouseupGradientAngle)
window.removeEventListener('mousemove',mousedown)
window.removeEventListener('mouseup',mouseupGradientAngle)
}
window.addEventListener('touchmove',touchstart)
window.addEventListener('touchend',mouseupGradientAngle)
window.addEventListener('mousemove',mousedown)
window.addEventListener('mouseup',mouseupGradientAngle)
}
const mousedownGradient = (event:any,item:any,index:number)=>{
palletData.color.gradient.selectIndex = index
// this.selectColor = {rgba:gradientRgba,hex:hex} //顔色选择器默认颜色
let gradientWidth = (document.querySelector('.pallet .color_setting_operate_bg') as any).clientWidth
let position = {
x:event.clientX,
left:event.target.style.left?event.target.style.left.split('%')[0]:0
}
let mousedown = function(event:any){
let e = getMousePosition(event,false)
mousedownGradient(e)
}
let touchstart = function(event:any){
let e = getMousePosition(event,true)
mousedownGradient(e)
}
let mousedownGradient = (e:any)=>{
let left = ((e.clientX) - position.x)/gradientWidth*100+Number(position.left)
left = (left<0?0:left>100?100:left)
item.left = left+'%'
}
let mouseupGradientAngle = ()=>{
window.removeEventListener('touchmove',touchstart)
window.removeEventListener('touchend',mouseupGradientAngle)
window.removeEventListener('mousemove',mousedown)
window.removeEventListener('mouseup',mouseupGradientAngle)
}
window.addEventListener('touchmove',touchstart)
window.addEventListener('touchend',mouseupGradientAngle)
window.addEventListener('mousemove',mousedown)
window.addEventListener('mouseup',mouseupGradientAngle)
}
const selectImgItem = ()=>{
}
const openPallet = ()=>{
palletData.palletShow = !palletData.palletShow
console.log(props.selectColor,palletData.palletShow)
if(palletData.palletShow && props.selectColor?.rgba?.r){
if(props.selectColor.gradient){
palletData.color_.rgba = props.selectColor.gradient.gradientList[0].rgba
}else{
palletData.color_ = JSON.parse(JSON.stringify(props.selectColor))
palletData.gradient.gradientShow = false
}
palletData.color = JSON.parse(JSON.stringify(props.selectColor))
}else{
}
}
onMounted(()=>{
nextTick().then(()=>{
const backIcon = document.createElement('div');
backIcon.classList.add('vc-sketch-color-wrap')
let dropperDom = document.getElementsByClassName("pallet")?.[0]?.getElementsByClassName('vc-chrome-fields-wrap')[0]
dropperDom.appendChild(backIcon);
backIcon.addEventListener('click',async ()=>{
try {
const dropper = new EyeDropper();
const result = await dropper.open();
let hex = result.sRGBHex.replace("#", "");
// 将十六进制颜色码拆分成红、绿、蓝三个部分
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
palletData.color = {rgba:{r:r,g:g,b:b,a:1},hex:result.sRGBHex}
// return `rgb(${r}, ${g}, ${b})`;
// box.style.backgroundColor = label.textContent = result.sRGBHex;
} catch (e) {
message.info(t('DesignDetailAlter.jsContent1'))
}
})
})
})
return{
...toRefs(palletData),
...toRefs(getpalletListDom),
openPallet,
selectImgItem,
setOperate,
deleteGradientItem,
addGradient,
mousedownGradientAngle,
mousedownGradient,
getMousePosition,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.pallet{
position: relative;
> .palletColo{
width: 100%;
height: 5.5rem;
border-radius: .5rem;
border: 1px solid #000;
padding: .5rem .6rem;
cursor: pointer;
> .palletBackColor{
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
> .palletBox{
position: absolute;
width: 100%;
z-index: 2;
> .color_setting_block{
margin: auto;
background: linear-gradient(70deg, #eee4f3, #f3f4e6);
width: 100%;
border-radius: calc(1rem*1.2);
overflow: hidden;
box-shadow: 2px 2px 8px rgba(0,0,0,.3);
.vc-chrome{
background: rgba(0,0,0,0);
box-shadow:none;
}
:deep(.chrome_color){
width: 100%;
overflow: hidden;
.vc-chrome-saturation-wrap{
width: 30rem;
height: 30rem;
margin: 2rem auto;
padding-bottom: 0;
}
.vc-chrome-body{
padding: 0;
width: 90%;
margin: 2 auto;
margin: 0 auto;
background: rgba(0,0,0,0);
margin-bottom: 3rem;
// display: none;
.vc-chrome-fields-wrap{
margin-top: 5%;
padding: 0;
position: relative;
.vc-chrome-toggle-btn{
width: calc(3.2rem*1.2);
.vc-chrome-toggle-icon{
height: auto;
margin-right: calc(-0.4rem*1.2);
margin-top: calc(0rem*1.2);
display: flex;
flex-direction: column;
align-items: center;
svg{
width: calc(2.4rem*1.2) !important;
height: calc(2.4rem*1.2) !important;
}
}
}
.vc-chrome-fields{
.vc-chrome-field{
padding-left: calc(.6rem*1.2);
}
.vc-input__label{
font-size: calc(1.6rem*1.2);
}
.vc-input__input{
font-size: 2rem;
height: 4rem;
}
}
.ant-upload-list{
}
.vc-sketch-color-wrap{
background-image: url(@../../../../../../assets/images/homePage/dropper.png);
background-size: 3rem;
background-repeat: no-repeat;
background-position: 50%;
cursor: pointer;
margin: 0;
width: 4rem;
height: 4rem;
padding: calc(.7rem*1.2);
border: 1px solid;
position: absolute;
bottom: -2rem;
right: 0rem;
border-radius: calc(.5rem*1.2);
}
.vc-chrome-fields{
.vc-input__label{
margin-top: calc(1rem*1.2);
}
}
.vc-chrome-fields:nth-child(2){
>:last-of-type {
display: none;
}
}
.vc-chrome-fields:nth-child(3){
>:last-of-type {
display: none;
}
}
}
.vc-chrome-controls{
align-items: center;
flex-direction: row-reverse;
.vc-chrome-color-wrap{
// width: 3.6rem*1.2);
margin-left: calc(2rem*1.2);
width: auto;
.vc-chrome-active-color{
border-radius: 50%;
}
.vc-chrome-active-color,.vc-checkerboard{
width: calc(3rem*1.2);
height: calc(3rem*1.2);
}
}
.vc-chrome-hue-wrap,.vc-chrome-alpha-wrap{
.vc-hue{
border-radius: 15px;
}
.vc-alpha{
border-radius: 15px;
overflow: hidden;
}
height: 2rem;
margin: 0;
.vc-hue-pointer{
transform: translateX(-1.25rem);
}
.vc-hue-picker{
width: 2.5rem;
height: 2.5rem;
border-radius: 50%;
transform: translate(0px,-3px);
}
}
.vc-chrome-alpha-wrap{
display: none;
}
}
}
.vc-chrome-saturation-wrap .vc-saturation-circle{
width: calc(1rem*1.2);
height: calc(1rem*1.2);
}
}
.color_block{
// margin-top: calc(1rem;
// display: flex;
// justify-content: space-between;
// font-size: calc(1.6rem;
width: 100%;
padding: 0 5%;
padding-bottom: 5%;
margin: calc(0.5rem*1.2) auto;
display: flex;
justify-content: space-between;
align-items: center;
.color_right{
width: 13rem;
font-size: calc(1.2rem*1.2);
color: #666666;
.color_rgb_block{
display: flex;
.rgb_item{
margin-left: calc(.2rem*1.2);
}
}
}
.color_left{
cursor: pointer;
color: rgb(153, 153, 153);
}
.color_right,.color_left{
>div{
display: flex;
align-items: center;
}
.color_HEX_block,.color_rgb_block{
padding: .25rem .6rem;
box-shadow: inset 0 0 0 1px #ccc;
border-radius: .5rem;
justify-content: space-around;
text-transform:uppercase;
.color_block_bg{
width: 1.8rem;
height: 2.5rem;
// margin-right: .5rem;
display: flex;
justify-content: space-between;
}
}
.color_block_bg{
}
}
}
.color_setting_operateSingle{
text-align: center;
margin: 1rem 0;
display: flex;
justify-content: center;
.color_setting_btn{
margin: 0 1rem;
color: rgba(0, 0, 0, 0.5);
&.active{
color: rgba(0, 0, 0, 0.7);
font-weight: 900;
}
}
}
.color_setting_operate{
*{
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none;
}
.color_setting_operate_item{
display: flex;
justify-content: space-around;
align-items: center;
.operate_item_box{
}
}
.color_setting_operate_control{
.operate_item_delete,.operate_item_angle{
cursor: pointer;
}
.operate_item_delete{
i{
display: flex;
font-size: 3rem;
}
}
.operate_item_angle{
.operate_item_angle_box{
border-radius: 50%;
width: 4rem;
height: 4rem;
border: solid 2px #000;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
>div{
height: 100%;
width: 1rem;
position: relative;
pointer-events:none;
}
>div::before{
position: absolute;
content: "";
top: 0.2rem;
width: 1rem;
height: 1rem;
border-radius: 50%;
background: #000;
}
}
}
}
.color_setting_operate_input{
width: 80%;
// padding: 0 10%;
margin: 1.2rem 10%;
border-radius: 10%;
position: relative;
height: 2.5rem;
.color_setting_operate_bg{
border-radius: .5rem;
width: 100%;
height: 2.5rem;
background: #fff;
position: absolute;
}
}
.color_setting_operate_btn{
position: absolute;
top: 50%;
transform: translate(-50%,-50%);
left: 0;
width: 1rem;
height: 110%;
border: .2rem solid;
border-radius: .5rem;
cursor: pointer;
box-sizing: content-box;
z-index: 2;
&.active{
border: .3rem solid;
}
}
.color_setting_operate_btn:hover{
border: .3rem solid;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,258 @@
<template>
<div class="upload">
<div class="successfullyUpload" v-show="uploadList?.[selectDetail.id]?.length >= 1">
<div class="img">
<div class="upload_file_item" v-for="(file) in uploadList?.[selectDetail.id]" :key="file">
<div class="upload_file_item_content" v-show="file.status !== 'done'">
<a-spin :indicator="indicator" tip="Uploading..."/>
</div>
<div class="upload_file_item_content" v-show="file.status === 'done'">
<img :src="file?.imgUrl" class="upload_img">
<div class="delete_file_block" @click="colorDeleteFile(index)">{{ $t('DesignDetailAlter.Delete') }}</div>
</div>
</div>
</div>
<div class="color">
<div v-for="item in colorList?.[selectDetail.id]" :key="item" @click="selectColor(item)" :style="{'background-color': item.hex}"></div>
</div>
</div>
<a-upload
:capture="null"
v-show="!uploadList?.[selectDetail.id] || uploadList?.[selectDetail.id]?.length < 1"
list-type="picture-card"
:customRequest="function(){}"
@change="fileUploadChange"
:before-upload="beforeUpload"
:action="null"
accept=".jpg,.png,.jpeg,.bmp"
>
<div class="upload_tip_block">
<i class="fi fi-br-upload"></i>
</div>
</a-upload>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,h,watch,nextTick,createVNode,toRefs, reactive} from 'vue'
import { message,Upload} from 'ant-design-vue';
import { useStore } from "vuex";
import GO from "@/tool/GO";
import { LoadingOutlined } from '@ant-design/icons-vue';
import { useI18n } from 'vue-i18n'
import { rgbaToHex } from "@/tool/util"
export default defineComponent({
components:{
},
emits:['selectUplpadColor'],
setup(props,{emit}) {
const {t} = useI18n();
const store = useStore();
const colorUpload = reactive({
selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
uploadList:{} as any,
indicator: h(LoadingOutlined, {
style: {
fontSize: "2.4rem",
},
spin: true,
}),
colorList:{} as any,
})
const fileUploadChange = (data:any)=>{
let file:any = data.file
let fileData = file.originFileObj
var reader = new FileReader();
reader.onload = (e:any) => {
let data_new;
if (typeof e.target.result === 'object') {
// 把Array Buffer转化为blob 如果是base64不需要
data_new = window.URL.createObjectURL(new Blob([e.target.result]));
} else {
data_new = e.target.result;
}
file.imgUrl = data_new
file.status = 'done'
if(!colorUpload.uploadList[colorUpload.selectDetail.id])colorUpload.uploadList[colorUpload.selectDetail.id]=[]
colorUpload.uploadList[colorUpload.selectDetail.id].push(file)
setTimeout(async ()=>{
const img = new Image();
// let colorImage = this.$refs.colorImage
img.src = file.imgUrl;
img.onload = async () => {
const colorThief = new ColorThief();
// let domImg = colorImage[0];
// let color = colorThief.getColor(img)
// let colorHex = this.rgbaToHex(color)
let selectColorList:any = [];
let selectColor = colorThief.getPalette(img,8)
//排序
let obj = {
max : 5,
min: 5,
}
let colorSort:any
await GO.setColor(selectColor,file.imgUrl,obj).then(
(rv:any) => {
if(rv){
colorSort = rv.ratio
}
}
)
colorSort.sort((a:any, b:any) => {
var a_num = a.ratio;
var b_num = b.ratio;
return b_num - a_num;
});
selectColor = []
colorSort.forEach((v:any)=>{
selectColor.push(v.rgb)
})
selectColor = selectColor.join('&')
selectColor = selectColor.split("&")
let color = selectColor[0].split(',')
let colorHex = rgbaToHex(color)
let colorLi:any = []
new Set(selectColor).forEach((item:any)=>{
colorLi.push(item.split(","))
})
colorLi.forEach((element:any) => {
let colorLiHex = rgbaToHex(element)
selectColorList.push(
{rgba:{r:element[0],g:element[1],b:element[2],a:1},hex:colorLiHex}
)
});
if(!colorUpload.colorList[colorUpload.selectDetail.id])colorUpload.colorList[colorUpload.selectDetail.id]=[]
colorUpload.colorList[colorUpload.selectDetail.id] = selectColorList
// this.getHsvColor(selectColorList)
// this.selectColor = {rgba:{r:color[0],g:color[1],b:color[2],a:1},hex:colorHex}
img.remove()
};
},100)
};
// 转化为base64S
reader.readAsDataURL(fileData)
}
const 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(t('DesignDetailAlter.jsContent4'));
}
const isLt2M = file.size / 1024 / 1024 < 5;
if (!isLt2M) {
message.info(t('DesignDetailAlter.jsContent5'));
}
return (isJpgOrPng && isLt2M) || Upload.LIST_IGNORE;
}
const selectColor = (color:any)=>{
emit('selectUplpadColor',color)
}
const colorDeleteFile = ()=>{
colorUpload.uploadList[colorUpload.selectDetail.id] = []
colorUpload.colorList[colorUpload.selectDetail.id] = []
}
return{
...toRefs(colorUpload),
fileUploadChange,
beforeUpload,
colorDeleteFile,
selectColor,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.upload{
// width: 34rem;
width: 100%;
height: 100%;
display: flex;
align-items: center;
:deep(.ant-upload-picture-card-wrapper){
height: 100%;
width: 100%;
.ant-upload-list{
height: 100%;
width: 100%;
.ant-upload-select-picture-card{
height: 100%;
width: 100%;
border: none;
margin: 0;
background: #fff;
&:hover{
border: none;
}
}
}
.upload_tip_block{
i{
font-size: 4rem;
display: flex;
}
}
}
> .successfullyUpload{
width: 100%;
display: flex;
> .color{
display: flex;
margin-left: 1rem;
flex-wrap: wrap;
align-items: center;
> div{
margin: .5rem;
width: 3rem;
height: 3rem;
cursor: pointer;
}
}
> .img{
> .upload_file_item{
> .upload_file_item_content{
width: 9rem;
height: 9rem;
position: relative;
&:hover{
> .delete_file_block{
display: block;
}
}
> .delete_file_block{
display: none;
cursor: pointer;
position: absolute;
bottom: 0;
line-height: 3rem;
background: rgba(0, 0, 0, 0.6);
color: #fff;
width: 100%;
text-align: center;
}
> img{
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,162 @@
<template>
<div class="element">
<div class="detailText">{{$t('DesignPrintOperation.CurrentElement')}}</div>
<div class="select_element">
<img :class="{active:elementList.length == 1}" v-for="item in elementList" @click="addElement(item)" :src="item.path" alt="">
<!-- <img :src="selectDetail.path" alt="">
{{ selectDetail }} -->
<div v-if="elementList.length == 0">
<i class="fi fi-rr-picture centent"></i>
</div>
</div>
<selectList @selectImgItem="selectImgItem" level1Type="DesignElements" type="element" :catecoryList="printCatecoryList"></selectList>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,watch,nextTick,createVNode,toRefs, reactive} from 'vue'
// import setDesignItem from '@/component/Detail/setDesignItem2.vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
// import sketchCategory from "@/component/HomePage/sketchCategory.vue";
import selectList from './module/selectList.vue'
export default defineComponent({
components:{
selectList,
},
setup(props,{emit}) {
const store = useStore();
const detailData = reactive({
selectTitle:'current',
selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
printCatecoryList:computed(()=>{
return store.state.UserHabit.designElementsType
}),
elementList:[],
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType)
})
watch(()=>detailData?.selectDetail?.trims?.prints,(newVal,oldVal)=>{
if(!newVal)return
detailData.elementList = newVal.reduce((acc:any, curr:any) => {
if (!acc.some((item:any) => item.minIOPath === curr.minIOPath)) {
acc.push(curr);
}
return acc;
}, []);
},{immediate: true})
const getDetailListData = reactive({
total:0,
pageSize:10,
currentPage:1,
})
const getDetailListDom = reactive({
libraryList:null as any,
})
const openCurrent = ()=>{
detailData.selectTitle = 'current'
}
const openUpload = ()=>{
detailData.selectTitle = 'upload'
}
const openLibrary = ()=>{
detailData.selectTitle = 'library'
getDetailListDom.libraryList.init()
}
const addElement = (data:any)=>{
let value = {
designType:data.designType,
level2Type:data.level2Type,
minIOPath:data.minIOPath,
url:data.path,
}
store.commit('DesignDetail/setCurrentPrintElement',value)
}
const selectImgItem = (data:any)=>{
let value = {
data,
}
if(detailData.currentDetailType != 'print' && detailData.currentDetailType != 'element'){
store.commit('DesignDetail/setNewDetail',value)
}else{
store.commit('DesignDetail/setCurrentPrintElement',null)
store.commit('DesignDetail/setCurrentPrintElement',data)
}
}
return{
...toRefs(detailData),
...toRefs(getDetailListData),
...toRefs(getDetailListDom),
openCurrent,
openUpload,
openLibrary,
selectImgItem,
addElement,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.element{
// width: 34rem;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
> .detailText{
margin-bottom: 1rem;
}
> .select_element{
width: 100%;
height: 23.5rem;
padding: 1rem;
text-align: center;
border-radius: .5rem;
// border: 1px dashed #202020;
border: 1px dashed transparent;
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
margin-bottom: 3rem;
display: flex;
flex-wrap: wrap;
overflow: hidden;
justify-content: space-between;
overflow-y: auto;
justify-content: flex-start;
> img{
object-fit: contain;
height: 9rem;
width: 9rem;
overflow-y: auto;
margin-bottom: 1rem;
margin: 1rem;
cursor: pointer;
}
> .active{
width: 100%;
height: 100%;
margin: 0;
margin-bottom: 0;
}
> div{
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
> i{
font-size: 10rem;
}
}
}
}
</style>

View File

@@ -0,0 +1,79 @@
<template>
<div class="detailLeft">
<sketch v-show="currentDetailType == 'sketch'" @addDetail="addDetail"></sketch>
<print v-show="currentDetailType == 'print'"></print>
<color v-if="currentDetailType == 'color'"></color>
<element v-show="currentDetailType == 'element'"></element>
<models v-show="currentDetailType == 'models'"></models>
<addDetails ref="addDetails" @setSloganData="setSloganData"></addDetails>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive} from 'vue'
// import setDesignItem from '@/component/Detail/setDesignItem2.vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
import sketch from './sketch.vue'
import print from './print.vue'
import color from './colorBox/index.vue'
import element from './element.vue'
import models from './models.vue'
import addDetails from '@/component/Detail/addDetails.vue'
export default defineComponent({
components:{
sketch,print,color,addDetails,element,models
},
setup(props,{emit}) {
const store = useStore();
const detailData = reactive({
selectTitle:'upload',
selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType),
})
const getDetailListData = reactive({
total:0,
pageSize:10,
currentPage:1,
})
const getDetailListDom = reactive({
addDetails:null as any,
})
const addDetail = () =>{
let addDetails:any = getDetailListDom.addDetails
addDetails.init(detailData.selectDetail,'')
}
const setSloganData = (data:any)=>{
detailData.selectDetail.sketchString = data
if(detailData.currentDetailType == 'sketch' && detailData.selectDetail?.newDetail?.sketch){
detailData.selectDetail.newDetail.sketch = null
}
}
return{
...toRefs(detailData),
...toRefs(getDetailListData),
...toRefs(getDetailListDom),
addDetail,
setSloganData,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.detailLeft{
width: 34rem;
// width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -0,0 +1,172 @@
<template>
<div class="sketch">
<div class="detailText">{{$t('DesignPrintOperation.CurrentModel')}}</div>
<div class="select_sketch">
<!-- <img :src="selectDetail?.sketchString?selectDetail?.sketchString:selectDetail.path" alt=""> -->
<img :src="frontBack.body.path || selectDetail.path" alt="">
</div>
<selectList @selectImgItem="selectImgItem" :isUpload="false" level1Type="Models" type="models" :catecoryList="sketchCatecoryList"></selectList>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive} from 'vue'
// import setDesignItem from '@/component/Detail/setDesignItem2.vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
// import sketchCategory from "@/component/HomePage/sketchCategory.vue";
import selectList from './module/selectList.vue'
export default defineComponent({
components:{
selectList,
},
emit:['addDetail'],
setup(props,{emit}) {
const store = useStore();
const detailData = reactive({
selectTitle:'current',
frontBack:computed(()=>store.state.DesignDetail.frontBack),
designDetail:computed(()=>store.state.DesignDetail.designDetail),
selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
sketchCatecoryList:computed(()=>{
return store.state.UserHabit.sex.value
}),
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType)
})
const getDetailListData = reactive({
total:0,
pageSize:10,
currentPage:1,
})
const getDetailListDom = reactive({
libraryList:null as any,
})
const openCurrent = ()=>{
detailData.selectTitle = 'current'
}
const openUpload = ()=>{
detailData.selectTitle = 'upload'
}
const openLibrary = ()=>{
detailData.selectTitle = 'library'
getDetailListDom.libraryList.init()
}
const selectImgItem = (data:any)=>{
if(data.presignedUrl)data.url = data.presignedUrl
let value = {
data,
}
store.commit('DesignDetail/setNewDetail',value)
}
const openAddDetail = ()=>{
emit('addDetail')
}
return{
...toRefs(detailData),
...toRefs(getDetailListData),
...toRefs(getDetailListDom),
openCurrent,
openUpload,
openLibrary,
selectImgItem,
openAddDetail,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.sketch{
// width: 34rem;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
> .detailText{
margin-bottom: 1rem;
text-align: left;
}
> .select_sketch{
width: 100%;
height: 23.5rem;
padding: 1rem 0;
text-align: center;
border-radius: .5rem;
// border: 1px dashed #202020;
border: 1px dashed transparent;
position: relative;
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
margin-bottom: 3rem;
> img{
width: 100%;
height: 100%;
object-fit: contain;
}
> i{
position: absolute;
left: auto;
right: 1rem;
top: 2rem;
font-size: 2rem;
cursor: pointer;
}
> div{
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
> i{
font-size: 10rem;
}
}
}
> .switch_type_list{
display: flex;
margin-bottom: 2.5rem;
> .switch_type_item:last-child{
margin-right: 0;
}
> .switch_type_item{
position: relative;
cursor: pointer;
margin-right: 6.5rem;
}
> .switch_type_item::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;
}
> .select_swtich {
color: #000;
font-weight: 600;
}
> .select_swtich::before {
width: 100%;
}
}
> .sketch_content_list{
flex: 1;
overflow: hidden;
> .content_item{
height: 100%;
margin-top: 1rem;
}
}
}
</style>

View File

@@ -0,0 +1,135 @@
<template>
<div class="uploadList">
<div class="uploadList_box">
<div class="content_img_item" v-for="(file) in currentList[type]" :key="file.id">
<div class="content_img_item_block" :class="{active:file?.checked}">
<img :src="file.imgUrl?file.imgUrl:file.url" :key="file.imgUrl || file.url" :alt="file.name" @click.stop="selectImgItem(file)"/>
<sketchCategory v-if="type != 'models'" v-model:disignTypeList="catecoryList" :generateList="allBoardData.sketchboardFiles" :item="file" :isSpread="true"></sketchCategory>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,watch,toRefs, reactive, onMounted} from 'vue'
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import sketchCategory from "@/component/HomePage/sketchCategory.vue";
import { getCookie } from "@/tool/cookie";
import { message,Upload} from 'ant-design-vue';
import {getMinioUrl} from '@/tool/util'
import { useI18n } from 'vue-i18n'
export default defineComponent({
components:{
sketchCategory
},
props:{
catecoryList:{
type:Object,
default:()=>[] as any,
required:true
},
type:{
type:String,
default:'' as any,
required:true
},
},
emits:['selectImgItem'],
setup(props,{emit}) {
const {t} = useI18n();
const store = useStore();
const detailData = reactive({
allBoardData:computed(()=>store.state.UploadFilesModule.allBoardData),
currentList:{
sketch:computed(()=>store.state.UploadFilesModule.allBoardData.sketchboardFiles),
print:computed(()=>store.state.UploadFilesModule.allBoardData.printboardFiles),
color:computed(()=>store.state.UploadFilesModule.allBoardData.colorBoards),
models:computed(()=>store.state.Workspace.probjects.model),
},
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType),
})
const getDetailListData = reactive({
})
const selectImgItem = (file:any)=>{
if(props.type != 'models'){
if(!file.resData.minIOPath){
file.minIOPath = getMinioUrl(file.resData.url)
}
if(!file.designType){
file.designType = file.resData.designType
}
}
// store.commit('DesignDetail/setNewDetail',file.resData)
emit('selectImgItem',file)
}
onMounted(()=>{
// detailData.currentList = {
// sketch:detailData.allBoardData.sketchboardFiles,
// print:detailData.allBoardData.printboardFiles,
// color:detailData.allBoardData.colorBoards,
// }
})
return{
...toRefs(detailData),
...toRefs(getDetailListData),
selectImgItem,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.uploadList{
height: 100%;
display: flex;
flex-direction: column;
> .uploadList_box{
width: 100%;
flex: 1;
overflow-y: auto;
display: flex;
flex-wrap: wrap;
margin-top: 1rem;
justify-content: space-between;
align-content: flex-start;
&::-webkit-scrollbar{display: none;}
> .content_img_item{
> .content_img_item_block{
width: calc((34rem - 2rem) / 2);
height: calc((34rem - 2rem) / 2);
position: relative;
margin-bottom: 2rem;
> img{
cursor: pointer;
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
> .material_content_list_loding{
width: 100%;
height: calc((34rem - 2rem) / 2);
}
> .upload_item{
width: calc((34rem - 2rem) / 2);
height: calc((34rem - 2rem) / 2);
align-items: center;
justify-content: center;
}
}
}
</style>

View File

@@ -0,0 +1,408 @@
<template>
<div class="libraryList">
<div class="generalModel_state">
<div class="generalModel_state_item" v-if="level1Type != 'Models' && catecoryList.length > 0" :style="{'width':(level1Type == 'DesignElements'?'100%':'40%')}">
<a-select
v-model:value="designType"
:options="(designTypeList)"
@change="handleChange"
style="width:100%"
size="large"
:fieldNames="{ label: 'name', value: 'value' }"
>
<template #suffixIcon
><span
class="icon iconfont icon-xiala"
style="color: #000"
></span
></template>
</a-select>
</div>
<div class="generalModel_state_item" v-if="level1Type == 'Models'" style="margin-bottom: 1rem;" :style="{'width':mannequinData.system == 'system'?'48%':'100%'}">
<a-select
v-model:value="mannequinData.system"
:options="systemList"
@change="handleChange"
style="width:100%"
size="large"
:fieldNames="{ label: 'name', value: 'value' }"
>
<template #suffixIcon
><span
class="icon iconfont icon-xiala"
style="color: #000"
></span
></template>
</a-select>
</div>
<div class="generalModel_state_item" v-if="level1Type == 'Models'" v-show="mannequinData.system == 'system'" style="width: 48%; margin-bottom: 1rem;">
<!-- {{ mannequinStyle }} -->
<a-select
v-model:value="mannequinData.style"
:options="mannequinStyle"
@change="handleChange"
style="width:100%"
size="large"
:fieldNames="{ label: 'name', value: 'value' }"
>
<template #suffixIcon
><span
class="icon iconfont icon-xiala"
style="color: #000"
></span
></template>
</a-select>
</div>
<div class="generalModel_state_item" v-if="level1Type == 'Models'" style="width: 39%;">
<a-select
v-model:value="mannequinData.ageGroup"
:options="ageGroupList"
@change="handleChange"
style="width:100%"
size="large"
:fieldNames="{ label: 'name', value: 'value' }"
>
<template #suffixIcon
><span
class="icon iconfont icon-xiala"
style="color: #000"
></span
></template>
</a-select>
</div>
<div class="generalModel_state_item" v-if="level1Type == 'Models'" style="width: 39%;">
<a-select
v-model:value="mannequinData.sex"
:options="sexList"
@change="handleChange"
style="width:100%"
size="large"
:fieldNames="{ label: 'name', value: 'value' }"
>
<template #suffixIcon
><span
class="icon iconfont icon-xiala"
style="color: #000"
></span
></template>
</a-select>
</div>
<div class="generalModel_state_item" style="width: 35%; flex: 1;margin-right: 2%;" v-if="level1Type != 'Models' && level1Type != 'DesignElements'">
<input class="search_input" style="width: 100%;" :placeholder="$t('DesignDetailAlter.inputContent1')" v-model="searchPictureName" @keydown.enter="getLibraryList()">
</div>
<div class="generalModel_state_item" style="width: auto;" v-show="level1Type != 'DesignElements'">
<div class="search_icon_block" @click.stop="getLibraryList()"><span class="icon iconfont icon-sousuo"></span></div>
</div>
<!-- clothesPrint -->
</div>
<div class="libraryList_box">
<div class="content_img_item" v-for="(file) in libraryList" :key="file.id">
<div class="content_img_item_block" :class="{active:file?.checked}">
<img :src="level1Type != 'Models'?file.url:file.presignedUrl" :key="level1Type != 'Models'?file.url:file.presignedUrl" :alt="file?.name" @click.stop="selectImgItem(file)"/>
<sketchCategory v-if="level1Type != 'Models' && level1Type != 'DesignElements'" :isSpread="catecoryList.length == 0" :disignTypeList="designTypeList" :generateList="libraryList" :item="file" :isSetSketchCategory="true"></sketchCategory>
</div>
</div>
<div v-show="total > libraryList.length" class="material_content_list_loding" v-observe>
<img src="@/assets/images/homePage/loading.gif" alt="">
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive, onMounted, watch} from 'vue'
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import sketchCategory from "@/component/HomePage/sketchCategory.vue";
import { useI18n } from 'vue-i18n'
export default defineComponent({
components:{
sketchCategory
},
props:{
catecoryList:{
type:Object,
default:()=>[] as any,
required:true
},
type:{
type:String,
default:'' as any,
required:true
},
randomId:{
type:Boolean,
default:true
},
level1Type:{
type:String,
default:'' as any,
required:true
},
isSegmentation:{
type:Boolean,
default:false as any,
required:true
},
},
emits:['selectImgItem'],
setup(props,{emit}) {
const store = useStore();
const {t} = useI18n()
const detailData = reactive({
isShowLoading:false,//懒加载,加载中
libraryList:[],
designTypeList:computed(()=>props.catecoryList) as any,
designType:'',
searchPictureName:'',
designDetail:computed(()=>store.state.DesignDetail.designDetail),
mannequinData:{
sex:'Female',
style:'',
system:'system',
ageGroup:'Adult',
systemList:[],
libraryList:[],
},
systemList:[{name:t('libraryList.System'),value:'system',},{name:t('libraryList.Library'),value:'library',}],//系统
mannequinStyle:computed(()=>store.state.UserHabit.mannequinStyle),//风格列表
sexList:computed(()=>store.state.UserHabit.sex.value),//风格列表
ageGroupList:computed(()=>store.state.UserHabit.ageGroup),//风格列表
selectObject:computed(()=>store.state.Workspace.probjects),//选择的项目
})
watch(()=>detailData.selectObject,(newValue,oldValue)=>{
detailData.mannequinData.sex = newValue.sex?newValue.sex:'Female'
detailData.mannequinData.style = newValue.style?newValue.style:''
detailData.mannequinData.ageGroup = newValue.ageGroup?newValue.ageGroup:''
},{immediate:true})
watch(()=>detailData.designTypeList.length,(newValue,oldValue)=>{
detailData.designType = detailData.designTypeList[0]?.value?detailData.designTypeList[0]?.value:''
getLibraryList()
})
const getDetailListData = reactive({
total:0,
pageSize:10,
currentPage:1,
})
const init = ()=>{
detailData.designType = detailData.designTypeList[0]?.value?detailData.designTypeList[0]?.value:''
getLibraryList()
}
const hasDuplicateId = (id:any)=>{
let arr = detailData.designDetail.clothes
for (let i = 0; i < arr.length; i++) {
if (arr[i].id === id) {
return true;
}
}
return false;
}
const selectImgItem = (file:any)=>{
let randomNum = Math.floor(100 + Math.random() * 900);
let type = props.type
// let type = store.state.DesignDetail.currentDetailType
let id = file.id
if(type == 'sketch'){
id = Number(file.id + (randomNum + ''))
if(props.randomId){
if(hasDuplicateId(id)){
selectImgItem(file)
return
}
}
}
let data = JSON.parse(JSON.stringify(file))
data.type = detailData.mannequinData.system == 'system'?'System':'Library'
if(!props.isSegmentation){
data.id = id
}
emit('selectImgItem',data)
// store.commit('DesignDetail/setNewDetail',data)
}
const getLibraryList = ()=>{
if(props.type == 'models'){
getModelList()
}else{
getList()
}
}
const getModelList = ()=>{
detailData.isShowLoading = true
let value = {
sex:detailData.mannequinData.sex,
style:detailData.mannequinData?.style,
ageGroup:store.state.Workspace.probjects.ageGroup,
}
Https.axiosGet(Https.httpUrls.getMannequins,{params:value}).then((rv: any) => {
if (rv) {
rv.forEach((item:any) => {
if(item.type == 'System'){
detailData.mannequinData.systemList = item.modelList
}else{
detailData.mannequinData.libraryList = item.modelList
}
});
setMannequinList()
}
detailData.isShowLoading = false
}).catch((res)=>{
detailData.isShowLoading = false
});
}
const setMannequinList = ()=>{
if(detailData.mannequinData.system == 'system'){
detailData.libraryList = detailData.mannequinData.systemList
}else{
detailData.libraryList = detailData.mannequinData.libraryList
}
}
const getList = ()=>{
detailData.isShowLoading = true
let level2Type = ''
let workspace = store.state.Workspace.probjects
// let type = store.state.DesignDetail.currentDetailType
let data = {
level1Type:props.level1Type,
// level2Type:'Pattern',
level2Type:detailData.designType,
modelSex:workspace?.sex,
page:getDetailListData.currentPage,
pictureName:detailData.searchPictureName,
size:getDetailListData.pageSize+detailData.libraryList.length,
}
Https.axiosPost(Https.httpUrls.queryLibraryPage,data).then(
(rv) => {
rv.content.forEach((vItem:any)=>{
if(props.catecoryList){
props.catecoryList.forEach((item:any) => {
if(item.value == vItem.level2Type){
vItem.categoryValue = item.value
vItem.category = item.name
}
});
}
})
detailData.libraryList = rv.content
detailData.isShowLoading = false
getDetailListData.total = rv.total
}
).catch((res)=>{
detailData.isShowLoading = false
});
}
const handleChange = ()=>{
getDetailListData.currentPage = 1
detailData.libraryList = []
getLibraryList()
}
onMounted(()=>{
})
return{
...toRefs(detailData),
...toRefs(getDetailListData),
init,
selectImgItem,
getLibraryList,
handleChange,
}
},
directives:{
observe:{
mounted (el,binding) {
// console.log(binding.instance);
let callback = (entries:any, observer:any)=> {
entries.forEach((entry:any) => {
if (entry.isIntersecting && !this_.isShowLoading) {
this_.getLibraryList()
} else {
}
});
}
const ob = new IntersectionObserver(callback,{
root:null,
threshold:[.5]
})
ob.observe(el)
// this.currentPage = +=1
// this.pageSize = 12
// currentPage
let this_:any = binding.instance
},
},
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.libraryList{
height: 100%;
display: flex;
flex-direction: column;
> .generalModel_state{
width: 100%;
display: flex;
justify-content: space-between;
> .generalModel_state_item{
width: 100%;
margin: 0;
position: relative;
> .search_icon_block{
// position: absolute;
// right: 5px;
width: calc(6rem - 4px);
height: calc(6rem - 4px);
color: #fff;
background: #000;
border-radius: 50%;
display: flex;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
}
> .generalModel_state_item:last-child{
// margin-top: 2rem;
}
}
> .libraryList_box{
width: 100%;
flex: 1;
overflow-y: auto;
display: flex;
flex-wrap: wrap;
margin-top: 1rem;
justify-content: space-between;
align-content: flex-start;
&::-webkit-scrollbar{display: none;}
> .content_img_item{
> .content_img_item_block{
width: calc((34rem - 2rem) / 2);
height: calc((34rem - 2rem) / 2);
position: relative;
margin-bottom: 2rem;
cursor: pointer;
> img{
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
> .material_content_list_loding{
width: 100%;
height: calc((34rem - 2rem) / 2);
overflow: hidden;
> img{
width: 100%;
}
}
}
}
</style>

View File

@@ -0,0 +1,207 @@
<template>
<div class="selectList">
<div class="selectList_header">
<div class="switch_type_list" v-if="type != 'element'">
<div
@click.stop="openCurrent()"
class="switch_type_item"
:class="[selectTitle == 'current' ? 'select_swtich' : '',]"
v-if="deReconstructionList.length == 0"
>
<span class="detailText">{{ $t('DesignDetailAlter.inProject') }}</span>
</div>
<div
v-if="isUpload"
@click.stop="openUpload()"
class="switch_type_item"
:class="[selectTitle == 'upload' ? 'select_swtich' : '',]"
>
<span class="detailText">{{ $t('DesignDetailAlter.Upload') }}</span>
</div>
<div
@click.stop="openLibrary()"
class="switch_type_item"
:class="[selectTitle == 'library' ? 'select_swtich' : '']"
>
<span class="detailText">{{ $t('DesignDetailAlter.Library') }}</span>
</div>
</div>
<slot name="selectSex"></slot>
</div>
<div class="print_content_list">
<div class="content_item" v-show="selectTitle == 'current'" v-if="type != 'element' && deReconstructionList.length == 0">
<currentList ref="currentList" :level1Type="level1Type" :type="type" @selectImgItem="selectImgItem" :catecoryList="catecoryList"></currentList>
</div>
<div class="content_item" v-show="selectTitle == 'upload'" v-if="type != 'element'">
<uploadList v-if="!isSegmentation" @selectImgItem="selectImgItem" :level1Type="level1Type" :catecoryList="catecoryList"></uploadList>
<uploadSegmentation v-if="isSegmentation" :segmentationType="segmentationType" :deReconstructionList=deReconstructionList @selectImgItem="selectImgItem" :level1Type="level1Type" :catecoryList="catecoryList"></uploadSegmentation>
</div>
<div class="content_item" v-show="selectTitle == 'library'">
<libraryList :isSegmentation="isSegmentation" @selectImgItem="selectImgItem" :randomId="randomId" :level1Type="level1Type" :type="type" ref="libraryList" :catecoryList="catecoryList"></libraryList>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,onMounted,watch,nextTick,createVNode,toRefs, reactive} from 'vue'
// import setDesignItem from '@/component/Detail/setDesignItem2.vue'
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
// import sketchCategory from "@/component/HomePage/sketchCategory.vue";
import libraryList from './libraryList.vue'
import uploadList from './uploadList.vue'
import uploadSegmentation from './uploadSegmentation.vue'
import currentList from './currentList.vue'
import { getMinioUrl } from '@/tool/util';
export default defineComponent({
components:{
currentList,
libraryList,
uploadList,
uploadSegmentation,
},
props:{
catecoryList:{
type:Array,
default:()=>[]
},
randomId:{
type:Boolean,
default:true,
required:false
},
isSegmentation:{//决定上传的入参,是否需要分割
type:Boolean,
default:false,
required:false
},
segmentationType:{//决定上传的入参,是否需要分割
type:String,
default:'',
required:false
},
type:{
type:String,
default:'' as any,
required:true
},
level1Type:{
type:String,
default:'' as any,
required:true
},
isUpload:{
type:Boolean,
default:true,
required:false
},
deReconstructionList:{
type:Array,
default:()=>[]
}
},
emits:['selectImgItem'],
setup(props,{emit}) {
const store = useStore();
const detailData = reactive({
selectTitle: props.type == 'element'?'library':'current',
printList:[]
})
const getDetailListDom = reactive({
libraryList:null as any,
})
const openCurrent = ()=>{
detailData.selectTitle = 'current'
}
const openUpload = ()=>{
detailData.selectTitle = 'upload'
}
const openLibrary = ()=>{
detailData.selectTitle = 'library'
getDetailListDom.libraryList.init()
}
const selectImgItem = (data:any)=>{
emit('selectImgItem',data)
}
onMounted(()=>{
if(props.type == 'element'){
openLibrary()
}
if(props.deReconstructionList.length > 0){
detailData.selectTitle = 'upload'
}
})
return{
...toRefs(detailData),
...toRefs(getDetailListDom),
openCurrent,
openUpload,
openLibrary,
selectImgItem,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.selectList{
// width: 34rem;
flex: 1;
overflow: hidden;
width: 100%;
height: auto;
display: flex;
flex-direction: column;
> .selectList_header{
margin-bottom: 2.5rem;
display: flex;
align-items: center;
> .switch_type_list{
display: flex;
> .switch_type_item:last-child{
margin-right: 0;
}
> .switch_type_item{
position: relative;
cursor: pointer;
margin-right: 6.5rem;
font-size: 1.8rem;
}
> .switch_type_item::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;
}
> .select_swtich {
color: #000;
font-weight: 600;
}
> .select_swtich::before {
width: 100%;
}
}
}
> .print_content_list{
flex: 1;
overflow: hidden;
> .content_item{
height: 100%;
margin-top: 1rem;
}
}
}
</style>

View File

@@ -0,0 +1,229 @@
<template>
<div class="uploadList">
<div class="uploadList_box">
<div class="content_img_item" v-for="(file) in uploadList" :key="file.id">
<div class="content_img_item_block" :class="{active:file?.checked}">
<img v-lazy="file.url" :key="file.url" :alt="file.name" @click.stop="selectImgItem(file)"/>
<sketchCategory :disignTypeList="catecoryList" :generateList="uploadList" :item="file" ></sketchCategory>
</div>
</div>
<div class="upload_item">
<div class="upload_file_item upload_component">
<a-upload
:action="uploadUrl + (upLoadHttpsUrl?upLoadHttpsUrl:'/api/element/upload')"
list-type="picture-card"
:capture="null"
:multiple="true"
:data="{
...upload,
}"
:headers="{ Authorization: token }"
v-model:file-list="uploadList"
:before-upload="beforeUpload"
:maxCount="8"
accept=".jpg,.png,.jpeg,.bmp"
@change="(file) => upFileUploadChange(file)"
>
<div
class="upload_tip_block"
v-show="uploadList.length != 8"
>
<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>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive, onMounted} from 'vue'
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import sketchCategory from "@/component/HomePage/sketchCategory.vue";
import { getCookie } from "@/tool/cookie";
import { message,Upload} from 'ant-design-vue';
import {getUploadUrl} from '@/tool/util'
import { useI18n } from 'vue-i18n'
export default defineComponent({
components:{
sketchCategory
},
props:{
catecoryList:{
type:Object,
default:()=>[] as any,
required:true
},
level1Type:{
type:String,
default:'' as any,
required:true
},
segmentation:{
type:Object,
default:null as any,
},
upLoadHttpsUrl:{//决定上传的入参,是否需要分割
type:String,
default:'' as any,
},
},
emits:['selectImgItem'],
setup(props,{emit}) {
const {t} = useI18n();
const store = useStore();
const detailData = reactive({
isShowLoading:false,//懒加载,加载中
uploadList:[],
upload:props.segmentation?
props.segmentation:{
isPin: 0,
level1Type: props.level1Type,
gender:store.state.Workspace.probjects.sex ,
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
ageGroup:store.state.Workspace.probjects.ageGroup,
},
token:getCookie("token"),
uploadUrl:getUploadUrl(),
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType)
})
const getDetailListData = reactive({
total:0,
pageSize:10,
currentPage:1,
})
const selectImgItem = (file:any)=>{
// let data = JSON.parse(JSON.stringify(file))
// store.commit('DesignDetail/setNewDetail',file)
emit('selectImgItem',file)
}
const upFileUploadChange = (data:any)=>{
let file = data.file;
let bor = true
if (file.status === "done") {
let res = JSON.parse(file.xhr.response);
if(res.errCode == 0){
file.id = res.data.id;
file.url = res.data.url;
file.resData = res.data;
let type
if(props?.catecoryList){
if(res.data.level2Type){
props?.catecoryList.forEach((item:any) => {
if(item.value == res.data.level2Type){
file.categoryValue = item?.value;
type = item.value
file.category = item?.name;
}
});
}else{
file.categoryValue = props?.catecoryList?.[0].value;
type = props.catecoryList[0].value
file.category = props.catecoryList[0].name;
}
}
file.designType = res.data.designType
file.level2Type = type;
file.minIOPath = file.resData.minIOPath
let fileList = detailData.uploadList.filter(
(v:any) => v.status === "done"
);
detailData.uploadList = fileList
// this.selectImgItem(detailData.uploadList[detailData.uploadList.length-1])
}else{
bor = false
}
} else if (file.status === "error") {
bor = false
}
if(!bor){
let res = JSON.parse(file.xhr.response);
let index = -1;
detailData.uploadList.forEach((ele:any, index1) => {
if (file.uid === ele.uid) {
index = index1;
}
});
if (index > -1) {
detailData.uploadList.splice(index, 1);
}
message.warning(res.errMsg);
}
}
const 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(t('DesignDetailAlter.jsContent4'));
}
const isLt2M = file.size / 1024 / 1024 < 5;
if (!isLt2M) {
message.info(t('DesignDetailAlter.jsContent5'));
}
return (isJpgOrPng && isLt2M) || Upload.LIST_IGNORE;
}
return{
...toRefs(detailData),
...toRefs(getDetailListData),
selectImgItem,
beforeUpload,
upFileUploadChange,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.uploadList{
height: 100%;
display: flex;
flex-direction: column;
> .uploadList_box{
width: 100%;
flex: 1;
overflow-y: auto;
display: flex;
flex-wrap: wrap;
margin-top: 1rem;
justify-content: space-between;
align-content: flex-start;
&::-webkit-scrollbar{display: none;}
> .content_img_item{
> .content_img_item_block{
width: calc((34rem - 2rem) / 2);
height: calc((34rem - 2rem) / 2);
position: relative;
margin-bottom: 2rem;
> img{
cursor: pointer;
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
> .material_content_list_loding{
width: 100%;
height: calc((34rem - 2rem) / 2);
}
> .upload_item{
width: calc((34rem - 2rem) / 2);
height: calc((34rem - 2rem) / 2);
align-items: center;
justify-content: center;
}
}
}
</style>

View File

@@ -0,0 +1,309 @@
<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="clearData()">
<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>Upload</div>
</div>
<div class="allUserPoeration_btn">
<div class="uploadList_box">
<div class="content_img_item" v-for="(file) in uploadList" :key="file.id">
<div class="content_img_item_block" :class="{active:file?.checked}">
<img v-lazy="file.url" :key="file.url" :alt="file.name"/>
<sketchCategory :disignTypeList="deReconstructionList" :generateList="uploadList" :item="file" :isSetSketchCategory="true" :upDataType="'element'"></sketchCategory>
</div>
</div>
<div class="upload_item">
<div class="upload" @click="upload">
<i class="fi fi-br-upload"></i>
</div>
</div>
<div class="mark_loading" v-show="isShowMark">
<a-spin size="large" />
</div>
</div>
<div class="gallery_btn" style="margin-left: auto;" @click="setOk">OK</div>
</div>
</a-modal>
</template>
<script lang="ts">
import {
defineComponent,
computed,
reactive,
watch,
onMounted,
h,
nextTick,
toRefs,
} from "vue";
import { LoadingOutlined } from "@ant-design/icons-vue";
import { Https } from "@/tool/https";
import { getCookie, setCookie } from "@/tool/cookie";
import { useStore } from "vuex";
import { useI18n } from "vue-i18n";
import { getMinioUrl } from "@/tool/util";
import sketchCategory from "@/component/HomePage/sketchCategory.vue";
export default defineComponent({
components: {sketchCategory},
props: {
deReconstructionList:{
type:Array,
default:()=>[]
}
},
emits: ["setUploadImgList"],
setup(props, { emit }) {
const store = useStore();
let operations = reactive({
operationsModal: false,
isShowMark:false,
uploadList:[],
});
let operationsData = reactive({
selectObject:computed(()=>store.state.Workspace.probjects),//选择的项目
});
const getUploadElement = () => {
};
let init = () => {
operations.operationsModal = true
};
const clearData = () => {
operations.operationsModal = false
emit('setUploadImgList',JSON.parse(JSON.stringify(operations.uploadList)))
operations.uploadList = []
};
let setOk = () => {
clearData()
};
const createProbject:any = inject('createProbject',()=>{}) as any
const upload = async ()=>{
if(!operationsData.selectObject?.id)await createProbject()
const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*'; // 只允许选择图片文件
input.multiple = true; // 允许多选
input.addEventListener('change', (event:any) => {
operations.isShowMark = true; // 显示加载状态
const files = event?.target?.files;
if (!files || files.length === 0) {
operations.isShowMark = false;
return;
}
let file = [...Array.from(files)];
let param = new FormData();
param.append('isPin', '0');
param.append('gender', store.state.Workspace.probjects.sex);
param.append('ageGroup',store.state.Workspace.probjects.ageGroup)
param.append('projectId', operationsData.selectObject.id);
param.append('level1Type', 'De/Reconstruction');
param.append('level2Type', props.deReconstructionList[0].value);
param.append('timeZone', Intl.DateTimeFormat().resolvedOptions().timeZone);
file.forEach((image:any) => {
param.append('file', image);
});
let config: any = {
headers: {
'Content-Type': 'multipart/form-data',
'Accept': '*/*'
}
};
Https.axiosPost(Https.httpUrls.elementUpload, param, config)
.then((rv: any) => {
rv.designType = 'Upload'
// rv.forEach((item:any)=>{
rv.category = props.deReconstructionList[0].name
rv.categoryValue = props.deReconstructionList[0].value
// })
operations.uploadList.unshift(rv);
operations.isShowMark = false;
})
.catch(rv => {
operations.isShowMark = false;
});
});
// 触发文件选择对话框
input.click();
}
return {
...toRefs(operations),
...toRefs(operationsData),
init,
setOk,
clearData,
upload,
};
},
data() {
return {
indicator: h(LoadingOutlined, {
style: {
fontSize: "2.4rem",
},
spin: true,
}),
};
},
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;
overflow-x: auto;
width: auto;
margin-bottom: 2rem;
flex-wrap: nowrap;
flex-direction: column;
width: 100%;
flex: 1;
> .uploadList_box{
width: 100%;
flex: 1;
overflow-y: auto;
display: flex;
flex-wrap: wrap;
margin-top: 1rem;
align-content: flex-start;
&::-webkit-scrollbar{display: none;}
> .content_img_item{
> .content_img_item_block{
width: calc((34rem - 2rem) / 2);
height: calc((34rem - 2rem) / 2);
position: relative;
margin-bottom: 2rem;
margin: 1rem;
> img{
cursor: pointer;
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
> .material_content_list_loding{
width: 100%;
height: calc((34rem - 2rem) / 2);
}
> .upload_item{
width: calc((34rem - 2rem) / 2);
height: calc((34rem - 2rem) / 2);
align-items: center;
justify-content: center;
.upload{
cursor: pointer;
width: calc(6rem * 1.2);
height: calc(6rem * 1.2);
border: calc(0.3rem * 1.2) solid #000;
border-radius: calc(1rem * 1.2);
display: flex;
align-items: center;
justify-content: center;
i{
font-size: 2rem;
display: flex;
color: #000;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,203 @@
<template>
<div class="uploadList">
<div class="uploadList_box">
<div class="content_img_item" v-for="(file,index) in uploadList" :key="file.id">
<div class="content_img_item_block" :class="{active:file?.checked}">
<img v-lazy="file.url" :key="file.url" :alt="file.name" @click.stop="selectImgItem(file)"/>
<sketchCategory :disignTypeList="deReconstructionList" :generateList="uploadList" :item="file" :isSetSketchCategory="true" :upDataType="'element'"></sketchCategory>
<i class="fi fi-rr-trash icon_delete" @click="deleteImgItem(file,index)"></i>
</div>
</div>
<div class="upload_item">
<div class="upload" @click="openUpload">
<i class="fi fi-br-upload"></i>
</div>
</div>
</div>
<uploadModel ref="uploadModel" @setUploadImgList="setUploadImgList" :deReconstructionList="deReconstructionList"></uploadModel>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive, onMounted} from 'vue'
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import sketchCategory from "@/component/HomePage/sketchCategory.vue";
import { getCookie } from "@/tool/cookie";
import { message,Upload} from 'ant-design-vue';
import {getUploadUrl} from '@/tool/util'
import { useI18n } from 'vue-i18n'
import uploadModel from "./uploadModel.vue"
export default defineComponent({
components:{
sketchCategory,uploadModel
},
props:{
catecoryList:{
type:Object,
default:()=>[] as any,
required:true
},
level1Type:{
type:String,
default:'' as any,
required:true
},
segmentation:{
type:Object,
default:null as any,
},
segmentationType:{
type:String,
default:'' as any,
},
upLoadHttpsUrl:{//决定上传的入参,是否需要分割
type:String,
default:'' as any,
},
deReconstructionList:{
type:Array,
default:()=>[]
}
},
emits:['selectImgItem'],
setup(props,{emit}) {
const {t} = useI18n();
const store = useStore();
const detailData = reactive({
isShowLoading:false,//懒加载,加载中
uploadList:computed(()=>store.state.HomeStoreModule.deReconstructionUploadImages) as any,
upload:props.segmentation?
props.segmentation:{
isPin: 0,
level1Type: props.level1Type,
gender:store.state.Workspace.probjects.sex ,
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
},
token:getCookie("token"),
uploadUrl:getUploadUrl(),
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType),
})
const dataDom = reactive({
uploadModel:null as any
})
const getDetailListData = reactive({
total:0,
pageSize:10,
currentPage:1,
})
const selectImgItem = (file:any)=>{
// let data = JSON.parse(JSON.stringify(file))
// store.commit('DesignDetail/setNewDetail',file)
emit('selectImgItem',file)
}
const setUploadImgList = (list:any)=>{
if(list.length>0){
detailData.uploadList.push(...list)
}
}
const openUpload = ()=>{
dataDom.uploadModel.init()
}
const deleteImgItem = (item:any,index)=>{
console.log(item)
Https.axiosPost(
Https.httpUrls.elementDelete,
{
id:item.id,
}
).then(res=>{
detailData.uploadList.splice(item.index,1)
})
}
return{
...toRefs(detailData),
...toRefs(dataDom),
...toRefs(getDetailListData),
selectImgItem,
openUpload,
setUploadImgList,
deleteImgItem,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.uploadList{
height: 100%;
display: flex;
flex-direction: column;
> .uploadList_box{
width: 100%;
flex: 1;
overflow-y: auto;
display: flex;
flex-wrap: wrap;
margin-top: 1rem;
justify-content: space-between;
align-content: flex-start;
&::-webkit-scrollbar{display: none;}
> .content_img_item{
> .content_img_item_block{
width: calc((34rem - 2rem) / 2);
height: calc((34rem - 2rem) / 2);
position: relative;
margin-bottom: 2rem;
> img{
cursor: pointer;
width: 100%;
height: 100%;
object-fit: contain;
}
&:hover{
> .icon_delete{
opacity: 1;
}
}
> .icon_delete{
position: absolute;
right: 1rem;
top: 1rem;
font-size: 1.8rem;
cursor: pointer;
opacity: 0;
}
}
}
> .material_content_list_loding{
width: 100%;
height: calc((34rem - 2rem) / 2);
}
> .upload_item{
width: calc((34rem - 2rem) / 2);
height: calc((34rem - 2rem) / 2);
align-items: center;
justify-content: center;
.upload{
cursor: pointer;
width: calc(6rem * 1.2);
height: calc(6rem * 1.2);
border: calc(0.3rem * 1.2) solid #000;
border-radius: calc(1rem * 1.2);
display: flex;
align-items: center;
justify-content: center;
i{
font-size: 2rem;
display: flex;
color: #000;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,161 @@
<template>
<div class="print">
<div class="detailText">{{$t('DesignPrintOperation.CurrentPrint')}}</div>
<div class="select_print">
<img :class="{active:printList.length == 1}" v-for="item in printList" @click="addElement(item)" :src="item.path" alt="">
<!-- <img :src="selectDetail.path" alt="">
{{ selectDetail }} -->
<div v-if="printList.length == 0">
<i class="fi fi-rr-picture centent"></i>
</div>
</div>
<selectList @selectImgItem="selectImgItem" level1Type="Printboard" type="print" :catecoryList="printCatecoryList"></selectList>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,watch,nextTick,createVNode,toRefs, reactive} from 'vue'
// import setDesignItem from '@/component/Detail/setDesignItem2.vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
// import sketchCategory from "@/component/HomePage/sketchCategory.vue";
import selectList from './module/selectList.vue'
export default defineComponent({
components:{
selectList,
},
setup(props,{emit}) {
const store = useStore();
const detailData = reactive({
selectTitle:'current',
selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
printCatecoryList:computed(()=>{
return store.state.UserHabit.printType
}),
printList:[],
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType)
})
watch(()=>detailData?.selectDetail?.printObject?.prints,(newVal,oldVal)=>{
if(!newVal)return
detailData.printList = newVal.reduce((acc:any, curr:any) => {
if (!acc.some((item:any) => item.minIOPath === curr.minIOPath)) {
acc.push(curr);
}
return acc;
}, []);
},{immediate: true})
const getDetailListData = reactive({
total:0,
pageSize:10,
currentPage:1,
})
const getDetailListDom = reactive({
libraryList:null as any,
})
const openCurrent = ()=>{
detailData.selectTitle = 'current'
}
const openUpload = ()=>{
detailData.selectTitle = 'upload'
}
const openLibrary = ()=>{
detailData.selectTitle = 'library'
getDetailListDom.libraryList.init()
}
const addElement = (data:any)=>{
let value = {
designType:data.designType,
level2Type:data.level2Type,
minIOPath:data.minIOPath,
url:data.path,
}
store.commit('DesignDetail/setCurrentPrintElement',value)
}
const selectImgItem = (data:any)=>{
let value = {
data,
}
if(detailData.currentDetailType != 'print' && detailData.currentDetailType != 'element'){
store.commit('DesignDetail/setNewDetail',value)
}else{
store.commit('DesignDetail/setCurrentPrintElement',null)
store.commit('DesignDetail/setCurrentPrintElement',data)
}
}
return{
...toRefs(detailData),
...toRefs(getDetailListData),
...toRefs(getDetailListDom),
openCurrent,
openUpload,
openLibrary,
selectImgItem,
addElement,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.print{
// width: 34rem;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
> .detailText{
margin-bottom: 1rem;
}
> .select_print{
width: 100%;
height: 23.5rem;
padding: 1rem;
text-align: center;
border-radius: .5rem;
// border: 1px dashed #202020;
border: 1px dashed transparent;
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
margin-bottom: 3rem;
display: flex;
flex-wrap: wrap;
overflow: hidden;
justify-content: space-between;
overflow-y: auto;
justify-content: flex-start;
> img{
object-fit: contain;
height: 9rem;
width: 9rem;
overflow-y: auto;
margin-bottom: 1rem;
margin: 1rem;
cursor: pointer;
}
> .active{
width: 100%;
height: 100%;
margin: 0;
margin-bottom: 0;
}
> div{
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
> i{
font-size: 10rem;
}
}
}
}
</style>

View File

@@ -0,0 +1,181 @@
<template>
<div class="sketch">
<div class="detailText">{{$t('DesignPrintOperation.CurrentSketch')}}</div>
<div class="select_sketch" v-if="selectDetail.id">
<!-- <img :src="selectDetail?.sketchString?selectDetail?.sketchString:selectDetail.path" alt=""> -->
<img :src="selectDetail.path" alt="">
<!-- <img :src="selectDetail.sketchString || selectDetail.path" alt=""> -->
<i :title="$t('DesignDetail.editSketchTitle')" class="fi fi-rs-pencil-paintbrush" @click.stop="openAddDetail"></i>
</div>
<div class="select_sketch" v-else>
<div>
<i class="fi fi-rr-picture centent"></i>
</div>
</div>
<selectList @selectImgItem="selectImgItem" source="detail" level1Type="Sketchboard" type="sketch" :catecoryList="sketchCatecoryList"></selectList>
</div>
</template>
<script lang="ts">
import { defineComponent,computed,ref,provide,nextTick,createVNode,toRefs, reactive} from 'vue'
// import setDesignItem from '@/component/Detail/setDesignItem2.vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https";
import { useStore } from "vuex";
import { useI18n } from 'vue-i18n'
// import sketchCategory from "@/component/HomePage/sketchCategory.vue";
import selectList from './module/selectList.vue'
export default defineComponent({
components:{
selectList,
},
emit:['addDetail'],
setup(props,{emit}) {
const store = useStore();
const detailData = reactive({
selectTitle:'current',
selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
sketchCatecoryList:computed(()=>{
return store.state.Workspace.probjects.positionList
}),
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType)
})
const getDetailListData = reactive({
total:0,
pageSize:10,
currentPage:1,
})
const getDetailListDom = reactive({
libraryList:null as any,
})
const openCurrent = ()=>{
detailData.selectTitle = 'current'
}
const openUpload = ()=>{
detailData.selectTitle = 'upload'
}
const openLibrary = ()=>{
detailData.selectTitle = 'library'
getDetailListDom.libraryList.init()
}
const selectImgItem = (data:any)=>{
console.log(data)
if(data?.imgUrl)data.url = data.imgUrl
let value = {
data,
}
if(detailData.currentDetailType == 'sketch'){
detailData.selectDetail.sketchString = ''
}
store.commit('DesignDetail/setNewDetail',value)
}
const openAddDetail = ()=>{
emit('addDetail')
}
return{
...toRefs(detailData),
...toRefs(getDetailListData),
...toRefs(getDetailListDom),
openCurrent,
openUpload,
openLibrary,
selectImgItem,
openAddDetail,
}
},
provide() {
return {
}
},
})
</script>
<style lang="less" scoped>
.sketch{
// width: 34rem;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
> .detailText{
margin-bottom: 1rem;
text-align: left;
}
> .select_sketch{
width: 100%;
height: 23.5rem;
padding: 1rem 0;
text-align: center;
border-radius: .5rem;
// border: 1px dashed #202020;
border: 1px dashed transparent;
position: relative;
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
margin-bottom: 3rem;
> img{
width: 100%;
height: 100%;
object-fit: contain;
}
> i{
position: absolute;
left: auto;
right: 1rem;
top: 2rem;
font-size: 2rem;
cursor: pointer;
}
> div{
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
> i{
font-size: 10rem;
}
}
}
> .switch_type_list{
display: flex;
margin-bottom: 2.5rem;
> .switch_type_item:last-child{
margin-right: 0;
}
> .switch_type_item{
position: relative;
cursor: pointer;
margin-right: 6.5rem;
}
> .switch_type_item::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;
}
> .select_swtich {
color: #000;
font-weight: 600;
}
> .select_swtich::before {
width: 100%;
}
}
> .sketch_content_list{
flex: 1;
overflow: hidden;
> .content_item{
height: 100%;
margin-top: 1rem;
}
}
}
</style>