404 lines
9.7 KiB
Vue
404 lines
9.7 KiB
Vue
<template>
|
|
<div class="generalMenu_printModel" ref="containerRef">
|
|
<div @click.stop="openPrintModel" :class="driverClass.class1" :style="{...$props.style_,'width':selectWidth}">
|
|
<a-popover v-if="isCanvas">
|
|
<template #content>
|
|
<img style="width: 10rem;height: 10rem;object-fit: contain;" :src="item.img" alt="">
|
|
<span style="text-align: center;">{{ $t('Generate.referenceImage') }}</span>
|
|
</template>
|
|
<span v-if="item?.label">{{ item?.label }}</span>
|
|
<span v-else>{{ item?.name }}</span>
|
|
</a-popover>
|
|
<div v-else>
|
|
<span v-if="item?.label" :style="{'font-family': isFontType?item?.value:'',fontSize:selectSize}">{{ item?.label }}</span>
|
|
<span v-else :style="{'font-family': isFontType?item?.value:'',fontSize:selectSize}">{{ item?.name }}</span>
|
|
</div>
|
|
<div class="icon iconfont icon-xiala" :class="{active:openClick}"></div>
|
|
</div>
|
|
<ul
|
|
:class="driverClass.class2"
|
|
v-show="openClick"
|
|
:style="{
|
|
'width': selectWidth,
|
|
...ulStyle,
|
|
...dropdownPositionStyle
|
|
}"
|
|
ref="dropdownRef"
|
|
>
|
|
<div>
|
|
<li v-for="listItem,index in dataList" :class="{active:deleteItem == index,hover:((item?.label && item?.label == listItem?.label) || (item?.name && item?.name == listItem?.name))}" class="printModel_item" @click="setprintModel(listItem,index)">
|
|
<a-popover placement="right" v-if="isCanvas">
|
|
<template #content>
|
|
<img v-if="listItem.img != -1" style="width: 10rem;height: 10rem;object-fit: contain;" :src="item.img" alt="">
|
|
<span style="text-align: center;">{{ $t('Generate.referenceImage') }}</span>
|
|
</template>
|
|
<span v-if="listItem?.label">{{ listItem?.label }}</span>
|
|
<span v-else>{{ listItem?.name }}</span>
|
|
</a-popover>
|
|
<div v-else>
|
|
<span v-if="listItem?.label" :style="{'font-family': isFontType?listItem?.value:''}">{{ listItem?.label }}</span>
|
|
<span v-else :style="{'font-family': isFontType?listItem?.value:''}">{{ listItem?.name }}</span>
|
|
</div>
|
|
</li>
|
|
</div>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, ref, nextTick, onMounted, onUnmounted, getCurrentInstance } from "vue";
|
|
import { useStore } from "vuex";
|
|
import { Https } from "@/tool/https";
|
|
import { openGuide,driverObj__ } from "@/tool/guide";
|
|
import { getUploadUrl } from "@/tool/util";
|
|
import { message, Upload, Modal } from "ant-design-vue";
|
|
export default defineComponent({
|
|
name:'filterComponent',
|
|
props:{
|
|
item:{
|
|
type:Object
|
|
},
|
|
dataList:{
|
|
type:Array
|
|
},
|
|
driver__:{
|
|
type:Boolean,
|
|
default:false,
|
|
},
|
|
isCanvas:{
|
|
type:Boolean,
|
|
default:false,
|
|
},
|
|
isFontType:{
|
|
type:Boolean,
|
|
default:false,
|
|
},
|
|
selectSize:{
|
|
type:String,
|
|
default:'1.8rem'
|
|
},
|
|
deleteItem:{
|
|
type:Number,
|
|
default:-1
|
|
},
|
|
driverClass:{
|
|
type:Object,
|
|
default:{class1:'',class2:'',classList:{item1:'',item2:'',item3:''}},
|
|
},
|
|
style_:{
|
|
type:Object,
|
|
default:{}
|
|
},
|
|
ulStyle:{
|
|
type:Object,
|
|
default:{}
|
|
},
|
|
selectWidth:{
|
|
type:String,
|
|
default:'20rem'
|
|
}
|
|
},
|
|
emits:['setprintModel'],
|
|
setup(props:any,{emit}){
|
|
let selectIndex = ref(0)
|
|
let openClick = ref(false)
|
|
let containerRef = ref<HTMLElement | null>(null)
|
|
let dropdownRef = ref<HTMLElement | null>(null)
|
|
let dropdownPositionStyle = ref({})
|
|
let store = useStore();
|
|
const instance = getCurrentInstance()
|
|
|
|
// 计算元素到屏幕底部的距离
|
|
const getDistanceToBottom = (element: HTMLElement) => {
|
|
const rect = element.getBoundingClientRect()
|
|
return window.innerHeight - rect.bottom
|
|
}
|
|
|
|
// 计算元素到屏幕顶部的距离
|
|
const getDistanceToTop = (element: HTMLElement) => {
|
|
const rect = element.getBoundingClientRect()
|
|
return rect.top
|
|
}
|
|
|
|
// 智能计算下拉菜单位置
|
|
const calculateDropdownPosition = () => {
|
|
if (!containerRef.value || !dropdownRef.value) return {}
|
|
|
|
const trigger = containerRef.value
|
|
const dropdown = dropdownRef.value
|
|
|
|
const distanceToBottom = getDistanceToBottom(trigger)
|
|
const distanceToTop = getDistanceToTop(trigger)
|
|
const dropdownHeight = dropdown.offsetHeight || 200 // 默认高度
|
|
|
|
// 如果下方空间足够,正常向下展开
|
|
if (distanceToBottom >= dropdownHeight) {
|
|
return {
|
|
top: '100%',
|
|
bottom: 'auto',
|
|
maxHeight: 'none',
|
|
transformOrigin: 'top center'
|
|
}
|
|
}
|
|
// 如果下方空间不足但上方空间足够,向上展开
|
|
else if (distanceToTop >= dropdownHeight) {
|
|
return {
|
|
top: 'auto',
|
|
bottom: '100%',
|
|
maxHeight: 'none',
|
|
transformOrigin: 'bottom center'
|
|
}
|
|
}
|
|
// 如果上下空间都不足,向上展开并限制高度
|
|
else {
|
|
return {
|
|
top: 'auto',
|
|
bottom: '100%',
|
|
maxHeight: `${distanceToTop - 20}px`, // 留出一些边距
|
|
overflowY: 'auto',
|
|
transformOrigin: 'bottom center'
|
|
}
|
|
}
|
|
}
|
|
|
|
// 调整下拉菜单位置
|
|
const adjustDropdownPosition = () => {
|
|
dropdownPositionStyle.value = calculateDropdownPosition()
|
|
}
|
|
|
|
let openPrintModel = ()=>{
|
|
instance.appContext.config.globalProperties.$dropdownEvents.closeAll()
|
|
window.addEventListener('resize', handleResize)
|
|
openClick.value = true
|
|
nextTick().then(()=>{
|
|
adjustDropdownPosition() // 打开时计算位置
|
|
if(props.driver__.driver){
|
|
driverObj__.moveNext()
|
|
}
|
|
})
|
|
}
|
|
|
|
let setprintModel = (item:any,index:any)=>{
|
|
if(props.deleteItem == index) return
|
|
if(item.img == -1) return
|
|
openClick.value = false
|
|
selectIndex = index
|
|
nextTick().then(()=>{
|
|
if(props.driver__.driver){
|
|
driverObj__.moveNext()
|
|
}
|
|
})
|
|
emit('setprintModel',item)
|
|
}
|
|
|
|
let removePrintModel = ()=>{
|
|
openClick.value = false
|
|
window.removeEventListener('resize', handleResize)
|
|
}
|
|
|
|
// 窗口 resize 处理
|
|
const handleResize = () => {
|
|
if (openClick.value) {
|
|
adjustDropdownPosition()
|
|
}
|
|
}
|
|
|
|
// 滚动处理
|
|
const handleScroll = () => {
|
|
if (openClick.value) {
|
|
adjustDropdownPosition()
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
instance.appContext.config.globalProperties.$dropdownEvents.onClose(removePrintModel)
|
|
window.addEventListener('scroll', handleScroll, true)
|
|
console.log(instance,)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
instance.appContext.config.globalProperties.$dropdownEvents.offClose(removePrintModel)
|
|
window.removeEventListener('scroll', handleScroll, true)
|
|
window.removeEventListener('resize', handleResize)
|
|
})
|
|
|
|
let fileUploadChange = (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.type_ = "upload";
|
|
props.dataList.forEach((item:any)=>{
|
|
if(item.img == -1){
|
|
item.img = res.data.url
|
|
item.id = res.data.id
|
|
}
|
|
})
|
|
}else{
|
|
bor = false
|
|
}
|
|
} else if (file.status === "error") {
|
|
bor = false
|
|
}
|
|
if(!bor){
|
|
// 错误处理
|
|
}
|
|
}
|
|
|
|
let deleteFile = (item:any)=>{
|
|
item.img = -1
|
|
emit('setprintModel',props.dataList[0])
|
|
}
|
|
|
|
return {
|
|
selectIndex,
|
|
openClick,
|
|
store,
|
|
setprintModel,
|
|
openPrintModel,
|
|
fileUploadChange,
|
|
deleteFile,
|
|
containerRef,
|
|
dropdownRef,
|
|
dropdownPositionStyle
|
|
}
|
|
},
|
|
data(prop) {
|
|
return {
|
|
upload: {
|
|
isPin: 0,
|
|
gender:'',
|
|
level1Type: 'Sketchboard',
|
|
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
},
|
|
uploadUrl: "",
|
|
type_: {
|
|
type1: "generate",
|
|
type2: 'Sketchboard',
|
|
},
|
|
isTextarea:false,
|
|
isInputFocus:false,
|
|
};
|
|
},
|
|
mounted() {
|
|
this.uploadUrl = getUploadUrl();
|
|
this.upload.gender = this.store.state.Workspace.probjects.sex
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style lang="less">
|
|
.ant-popover-inner-content{
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
</style>
|
|
|
|
<style lang="less">
|
|
//衣服类型下拉菜单
|
|
.generalMenu_printModel{
|
|
position: relative;
|
|
margin-right: 2rem;
|
|
height: 5rem;
|
|
|
|
.icon-xiala{
|
|
margin-left: auto;
|
|
transition: all .3s;
|
|
&.active{
|
|
transform: rotate(180deg);
|
|
}
|
|
}
|
|
|
|
>div{
|
|
display: block;
|
|
width: 20rem;
|
|
border-radius: 1rem;
|
|
margin: 0;
|
|
border: 1px solid;
|
|
cursor: pointer;
|
|
padding: 1rem;
|
|
text-align: center;
|
|
display: flex;
|
|
font-size: 1.8rem;
|
|
justify-content: space-around;
|
|
height: 100%;
|
|
box-sizing: border-box;
|
|
align-items: center;
|
|
background: #fff;
|
|
> div{
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
> span{
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
>i{
|
|
justify-content: center;
|
|
position: relative;
|
|
}
|
|
}
|
|
|
|
ul{
|
|
position: absolute;
|
|
left: 0;
|
|
width: 20rem;
|
|
margin-top: 0.36rem;
|
|
z-index: 1000;
|
|
overflow: hidden;
|
|
border-radius: 1.2rem;
|
|
background: #fff;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
transition: all 0.3s ease;
|
|
|
|
> div{
|
|
overflow-y: auto;
|
|
max-height: 300px;
|
|
}
|
|
|
|
li{
|
|
background: #fff;
|
|
line-height: 2;
|
|
cursor: pointer;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
padding: 0 1.2rem;
|
|
transition: all 0.2s ease;
|
|
position: relative;
|
|
|
|
span{
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
|
|
&.active{
|
|
pointer-events: none;
|
|
color: #a4a4a4 !important;
|
|
background: #ebebeb !important;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
&.hover{
|
|
background: #f3f3f6;
|
|
color: #000;
|
|
}
|
|
:deep(.icon-shanchu){
|
|
cursor: pointer;
|
|
position: absolute;
|
|
right: 10px;
|
|
top: 10px;
|
|
z-index: 2;
|
|
}
|
|
}
|
|
.printModel_item:hover{
|
|
background: #f3f3f6;
|
|
color: #000;
|
|
}
|
|
}
|
|
}
|
|
</style> |