Files
aida_front/src/component/HomePage/generalMenu.vue

404 lines
9.7 KiB
Vue
Raw Normal View History

2024-05-28 16:00:26 +08:00
<template>
2025-09-08 14:50:59 +08:00
<div class="generalMenu_printModel" ref="containerRef">
2025-04-09 14:09:19 +08:00
<div @click.stop="openPrintModel" :class="driverClass.class1" :style="{...$props.style_,'width':selectWidth}">
2024-09-27 16:31:33 +08:00
<a-popover v-if="isCanvas">
<template #content>
<img style="width: 10rem;height: 10rem;object-fit: contain;" :src="item.img" alt="">
2024-10-20 15:58:29 +08:00
<span style="text-align: center;">{{ $t('Generate.referenceImage') }}</span>
</template>
<span v-if="item?.label">{{ item?.label }}</span>
2025-04-01 15:25:15 +08:00
<span v-else>{{ item?.name }}</span>
</a-popover>
2024-09-27 16:31:33 +08:00
<div v-else>
2025-09-08 14:50:59 +08:00
<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>
2024-09-27 16:31:33 +08:00
</div>
2025-02-05 10:09:59 +08:00
<div class="icon iconfont icon-xiala" :class="{active:openClick}"></div>
</div>
2025-09-08 14:50:59 +08:00
<ul
:class="driverClass.class2"
v-show="openClick"
:style="{
'width': selectWidth,
...ulStyle,
...dropdownPositionStyle
}"
ref="dropdownRef"
>
2025-07-19 14:04:48 +08:00
<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>
2025-09-08 14:50:59 +08:00
<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>
2025-07-19 14:04:48 +08:00
</div>
</li>
</div>
2024-05-28 16:00:26 +08:00
</ul>
</div>
</template>
<script lang="ts">
2025-09-09 11:47:38 +08:00
import { defineComponent, ref, nextTick, onMounted, onUnmounted, getCurrentInstance } from "vue";
import { useStore } from "vuex";
import { Https } from "@/tool/https";
2024-05-28 16:00:26 +08:00
import { openGuide,driverObj__ } from "@/tool/guide";
import { getUploadUrl } from "@/tool/util";
import { message, Upload, Modal } from "ant-design-vue";
2024-05-28 16:00:26 +08:00
export default defineComponent({
name:'filterComponent',
props:{
item:{
type:Object
},
dataList:{
type:Array
},
driver__:{
type:Boolean,
default:false,
},
2024-09-27 16:31:33 +08:00
isCanvas:{
type:Boolean,
default:false,
},
2025-09-08 14:50:59 +08:00
isFontType:{
type:Boolean,
default:true,
},
selectSize:{
type:String,
default:'1.8rem'
},
2024-05-28 16:00:26 +08:00
deleteItem:{
type:Number,
default:-1
},
driverClass:{
type:Object,
default:{class1:'',class2:'',classList:{item1:'',item2:'',item3:''}},
2025-01-07 17:15:28 +08:00
},
style_:{
type:Object,
default:{}
2025-04-09 14:09:19 +08:00
},
2025-07-19 14:04:48 +08:00
ulStyle:{
type:Object,
default:{}
},
2025-04-09 14:09:19 +08:00
selectWidth:{
type:String,
default:'20rem'
2024-05-28 16:00:26 +08:00
}
},
emits:['setprintModel'],
setup(props:any,{emit}){
let selectIndex = ref(0)
let openClick = ref(false)
2025-09-08 14:50:59 +08:00
let containerRef = ref<HTMLElement | null>(null)
let dropdownRef = ref<HTMLElement | null>(null)
let dropdownPositionStyle = ref({})
let store = useStore();
2025-09-09 11:47:38 +08:00
const instance = getCurrentInstance()
2025-09-08 14:50:59 +08:00
// 计算元素到屏幕底部的距离
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()
}
2024-05-28 16:00:26 +08:00
let openPrintModel = ()=>{
2025-09-09 11:47:38 +08:00
instance.appContext.config.globalProperties.$dropdownEvents.closeAll()
2025-09-08 14:50:59 +08:00
window.addEventListener('resize', handleResize)
2024-05-28 16:00:26 +08:00
openClick.value = true
nextTick().then(()=>{
2025-09-08 14:50:59 +08:00
adjustDropdownPosition() // 打开时计算位置
2024-05-28 16:00:26 +08:00
if(props.driver__.driver){
driverObj__.moveNext()
}
})
}
2025-09-08 14:50:59 +08:00
2024-05-28 16:00:26 +08:00
let setprintModel = (item:any,index:any)=>{
if(props.deleteItem == index) return
if(item.img == -1) return
2024-05-28 16:00:26 +08:00
openClick.value = false
selectIndex = index
nextTick().then(()=>{
if(props.driver__.driver){
driverObj__.moveNext()
}
})
emit('setprintModel',item)
}
2025-09-08 14:50:59 +08:00
2024-05-28 16:00:26 +08:00
let removePrintModel = ()=>{
openClick.value = false
2025-09-08 14:50:59 +08:00
window.removeEventListener('resize', handleResize)
}
// 窗口 resize 处理
const handleResize = () => {
if (openClick.value) {
adjustDropdownPosition()
}
}
// 滚动处理
const handleScroll = () => {
if (openClick.value) {
adjustDropdownPosition()
}
2024-05-28 16:00:26 +08:00
}
2025-09-08 14:50:59 +08:00
onMounted(() => {
2025-09-09 11:47:38 +08:00
instance.appContext.config.globalProperties.$dropdownEvents.onClose(removePrintModel)
2025-09-08 14:50:59 +08:00
window.addEventListener('scroll', handleScroll, true)
2025-09-09 11:47:38 +08:00
console.log(instance,)
2025-09-08 14:50:59 +08:00
})
onUnmounted(() => {
instance.appContext.config.globalProperties.$dropdownEvents.offClose(removePrintModel)
2025-09-08 14:50:59 +08:00
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){
2025-09-08 14:50:59 +08:00
// 错误处理
}
}
2025-09-08 14:50:59 +08:00
2024-09-27 17:45:11 +08:00
let deleteFile = (item:any)=>{
item.img = -1
emit('setprintModel',props.dataList[0])
}
2025-09-08 14:50:59 +08:00
2024-05-28 16:00:26 +08:00
return {
selectIndex,
openClick,
store,
2024-05-28 16:00:26 +08:00
setprintModel,
openPrintModel,
fileUploadChange,
2024-09-27 17:45:11 +08:00
deleteFile,
2025-09-08 14:50:59 +08:00
containerRef,
dropdownRef,
dropdownPositionStyle
2024-05-28 16:00:26 +08:00
}
},
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();
2025-04-01 15:25:15 +08:00
this.upload.gender = this.store.state.Workspace.probjects.sex
}
2024-05-28 16:00:26 +08:00
});
</script>
2025-09-08 14:50:59 +08:00
2024-10-13 22:20:59 +08:00
<style lang="less">
2024-10-13 16:14:38 +08:00
.ant-popover-inner-content{
display: flex;
flex-direction: column;
2024-10-14 16:08:24 +08:00
align-items: center;
2024-10-13 16:14:38 +08:00
}
</style>
2025-09-08 14:50:59 +08:00
2024-05-28 16:00:26 +08:00
<style lang="less">
//衣服类型下拉菜单
.generalMenu_printModel{
2025-09-08 14:50:59 +08:00
position: relative;
2024-05-28 16:00:26 +08:00
margin-right: 2rem;
2025-04-09 14:09:19 +08:00
height: 5rem;
2025-09-08 14:50:59 +08:00
2025-02-05 10:09:59 +08:00
.icon-xiala{
margin-left: auto;
transition: all .3s;
&.active{
transform: rotate(180deg);
}
}
2025-09-08 14:50:59 +08:00
2024-05-28 16:00:26 +08:00
>div{
display: block;
2024-12-31 11:40:40 +08:00
width: 20rem;
2025-04-09 14:09:19 +08:00
border-radius: 1rem;
2024-05-28 16:00:26 +08:00
margin: 0;
2024-12-31 11:40:40 +08:00
border: 1px solid;
2024-05-28 16:00:26 +08:00
cursor: pointer;
2025-04-09 14:09:19 +08:00
padding: 1rem;
2024-05-28 16:00:26 +08:00
text-align: center;
2024-10-20 15:58:29 +08:00
display: flex;
2024-12-31 11:40:40 +08:00
font-size: 1.8rem;
2024-10-20 15:58:29 +08:00
justify-content: space-around;
2025-02-06 10:06:12 +08:00
height: 100%;
box-sizing: border-box;
align-items: center;
2025-03-10 16:51:12 +08:00
background: #fff;
2025-09-08 14:50:59 +08:00
> div{
display: flex;
align-items: center;
}
2024-10-20 15:58:29 +08:00
> span{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
2025-09-08 14:50:59 +08:00
2024-10-20 15:58:29 +08:00
>i{
justify-content: center;
position: relative;
}
2024-05-28 16:00:26 +08:00
}
2025-09-08 14:50:59 +08:00
2024-05-28 16:00:26 +08:00
ul{
position: absolute;
2025-09-08 14:50:59 +08:00
left: 0;
2024-12-31 11:40:40 +08:00
width: 20rem;
2025-09-08 14:50:59 +08:00
margin-top: 0.36rem;
z-index: 1000;
2024-05-28 16:00:26 +08:00
overflow: hidden;
2025-09-08 14:50:59 +08:00
border-radius: 1.2rem;
background: #fff;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
transition: all 0.3s ease;
2025-07-19 14:04:48 +08:00
> div{
overflow-y: auto;
2025-09-08 14:50:59 +08:00
max-height: 300px;
2025-07-19 14:04:48 +08:00
}
2025-09-08 14:50:59 +08:00
2024-05-28 16:00:26 +08:00
li{
2024-12-31 11:40:40 +08:00
background: #fff;
2024-05-28 16:00:26 +08:00
line-height: 2;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
2025-09-08 14:50:59 +08:00
padding: 0 1.2rem;
transition: all 0.2s ease;
position: relative;
2024-10-13 22:20:59 +08:00
span{
display: block;
width: 100%;
}
2025-09-08 14:50:59 +08:00
2024-05-28 16:00:26 +08:00
&.active{
2024-10-04 12:07:37 +08:00
pointer-events: none;
2024-05-28 16:00:26 +08:00
color: #a4a4a4 !important;
background: #ebebeb !important;
cursor: not-allowed;
}
2025-09-08 14:50:59 +08:00
2025-04-09 14:09:19 +08:00
&.hover{
background: #f3f3f6;
color: #000;
}
2024-09-27 17:45:11 +08:00
:deep(.icon-shanchu){
cursor: pointer;
position: absolute;
right: 10px;
top: 10px;
2025-09-08 14:50:59 +08:00
z-index: 2;
2024-09-27 17:45:11 +08:00
}
2024-05-28 16:00:26 +08:00
}
.printModel_item:hover{
2024-12-31 11:40:40 +08:00
background: #f3f3f6;
2024-05-28 16:00:26 +08:00
color: #000;
}
}
}
</style>