Files
aida_front/src/views/SellerDashboard/MyListings/main/content.vue

344 lines
7.6 KiB
Vue
Raw Normal View History

2026-04-09 13:36:03 +08:00
<script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
import { VueDraggable } from "vue-draggable-plus"
2026-04-10 14:40:48 +08:00
import contentItem from "./contentItem.vue"
import selectMenu from '@/component/modules/selectMenu.vue'
2026-04-09 13:36:03 +08:00
//const props = defineProps({
//})
//const emit = defineEmits([
//])
let data = reactive({
showDrafts: false,
})
const list = ref([
{ id: "1" },
{ id: "2" },
{ id: "3" },
{ id: "4" },
{ id: "5" },
{ id: "6" },
{ id: "7" },
{ id: "8" },
{ id: "9" },
{ id: "9" },
{ id: "9" },
{ id: "9" },
{ id: "9" },
{ id: "9" },
{ id: "10" }
])
const list2 = ref([
{ id: "1" },
{ id: "2" },
{ id: "3" },
{ id: "4" },
{ id: "5" },
{ id: "6" },
{ id: "7" },
{ id: "8" },
{ id: "9" },
{ id: "10" }
])
const config = ref({
"data-container-type": "root",
"data-parent-id": "null",
animation: 250,
handle: ".item", // 可拖动的元素
"ghost-class": "ghost", // 拖动时的类名
"chosen-class": "chosen", // 选中时的类名
"drag-class": "drag", // 拖动时的类名
"swap-threshold": 0.5,
"empty-insert-threshold": 5,
"force-fallback": false,
"fallback-tolerance": 3,
"scroll-sensitivity": 100,
"scroll-speed": 10,
onEnd: (e) => {}
})
2026-04-10 14:40:48 +08:00
const domSize = ref('Small')
const domSizeList = ref([
{
label:'Small',
value:'Small',
},
{
label:'Medium',
value:'Medium',
},
{
label:'Large',
value:'Large',
},
])
const listingsBoxRef = ref(null) as any
let resizeObserver = null as any
const gap = ref({
Small: '16px',
Medium: '24px',
Large: '30px',
})
//根据宽度设置列表宽度
let upDataDomWidthTime = null
const setDomSize = (width: number)=>{
if(!listingsBoxRef.value)return
let listDom = listingsBoxRef.value.querySelector('.list')
let listItemDom = listDom.querySelector('.item')
let offsetWidth = listItemDom.getBoundingClientRect().width
let lineNum = Math.floor(width / offsetWidth)
let itemNum = Math.floor((width - (lineNum - 1) * parseInt(gap.value[domSize.value])) / offsetWidth)
listDom.style.maxWidth = ((itemNum - 1) * parseInt(gap.value[domSize.value]) + itemNum * (offsetWidth)) + 'px'
}
const changeDomSize = ()=>{
setTimeout(()=>{
setDomSize(listingsBoxRef.value.clientWidth)
},350)
}
const unfoldDrafits = ()=>{
data.showDrafts = !data.showDrafts
}
2026-04-09 13:36:03 +08:00
onMounted(()=>{
2026-04-10 14:40:48 +08:00
// 创建观察器
nextTick(()=>{
resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
// 获取元素尺寸
const width = entry.contentRect.width
const height = entry.contentRect.height
const borderBoxSize = entry.borderBoxSize[0] // 包含边框
const contentBoxSize = entry.contentBoxSize[0] // 内容区域
if(upDataDomWidthTime)clearTimeout(upDataDomWidthTime)
upDataDomWidthTime = setTimeout(()=>{
setDomSize(width)
},200)
}
})
// 开始监听
if(resizeObserver)resizeObserver.observe(listingsBoxRef.value)
})
2026-04-09 13:36:03 +08:00
})
onUnmounted(()=>{
2026-04-10 14:40:48 +08:00
// 停止监听
if(listingsBoxRef?.value)resizeObserver?.unobserve(listingsBoxRef?.value)
2026-04-09 13:36:03 +08:00
})
defineExpose({})
const { showDrafts } = toRefs(data);
</script>
<template>
<div class="listings">
<div class="listingsBox listingsBox1">
2026-04-10 14:40:48 +08:00
<div class="box" :class="domSize" ref="listingsBoxRef">
2026-04-09 13:36:03 +08:00
<div class="title">
<div class="left">
<i class="fi fi-rs-comments"></i>
<span>Active Listings</span>
</div>
<div class="right">
2026-04-10 14:40:48 +08:00
<div class="generalModel_state">
<div>
<selectMenu
:selectList="domSizeList"
@change="changeDomSize"
:isBtnOpen='true'
:style="{
'border-radius':'0rem',
'border':'none',
'font-weight': '900',
'border-right':'2px solid rgba(0,0,0,.2)',
'line-height': '3rem',
'height': '3rem',
'background': 'rgba(0,0,0,0)',
}"
v-model:select="domSize"
>
<template v-slot:btnText>
{{ $t('Header.Filter') }}
</template>
</selectMenu>
</div>
<div>
<selectMenu
:selectList="domSizeList"
@change="changeDomSize"
:isBtnOpen='true'
:style="{
'border-radius':'0rem',
'border':'none',
'font-weight': '900',
'line-height': '3rem',
'height': '3rem',
'background': 'rgba(0,0,0,0)',
}"
v-model:select="domSize"
>
<template v-slot:btnText>
{{ $t('Header.Size') }}
</template>
</selectMenu>
</div>
</div>
2026-04-09 13:36:03 +08:00
</div>
</div>
<VueDraggable
v-model="list"
class="list"
2026-04-10 14:40:48 +08:00
:style="{gap: gap[domSize] || '1.6rem'}"
2026-04-09 13:36:03 +08:00
v-bind="config"
:group="{
name: 'sortable',
pull: false,
put: true
}"
>
2026-04-10 14:40:48 +08:00
<contentItem v-for="v in list" :key="v.id" type="listings" :domSize="domSize"/>
2026-04-09 13:36:03 +08:00
</VueDraggable>
</div>
2026-04-10 14:40:48 +08:00
<div class="openOrCloseDrafts" :class="{'active': showDrafts}" @click="unfoldDrafits">
2026-04-09 13:36:03 +08:00
<span class="icon iconfont icon-xiala"></span>
</div>
</div>
2026-04-10 14:40:48 +08:00
<div class="listingsBox listingsBox2" :class="{'active': showDrafts}">
<div class="box Small">
<div class="title">
<div class="left">
<i class="fi fi-rs-comments"></i>
<span>Drafts</span>
</div>
</div>
2026-04-09 13:36:03 +08:00
<VueDraggable
v-model="list2"
2026-04-10 14:40:48 +08:00
class="list2"
2026-04-09 13:36:03 +08:00
v-bind="config"
:group="{
name: 'sortable',
pull: true,
put: true
}"
>
2026-04-10 14:40:48 +08:00
<contentItem v-for="v in list2" :key="v.id" domSize="Small" type="drafts"/>
2026-04-09 13:36:03 +08:00
</VueDraggable>
</div>
2026-04-10 14:40:48 +08:00
</div>
2026-04-09 13:36:03 +08:00
</div>
</template>
<style lang="less" scoped>
.listings{
2026-04-09 13:48:46 +08:00
position: absolute;
width: 100%;
height: 100%;
2026-04-09 13:36:03 +08:00
display: flex;
gap: 2rem;
.listingsBox{
background-color: #f9fafa;
border-radius: 2rem;
position: relative;
2026-04-09 13:48:46 +08:00
// overflow: hidden;
2026-04-09 13:36:03 +08:00
display: flex;
2026-04-10 14:40:48 +08:00
transition: all .3s;
2026-04-09 13:36:03 +08:00
.box{
width: 100%;
2026-04-10 14:40:48 +08:00
padding: 2.4rem 0;
2026-04-09 13:36:03 +08:00
padding-bottom: 0;
flex-direction: column;
2026-04-10 14:40:48 +08:00
overflow: hidden;
display: flex;
2026-04-09 13:36:03 +08:00
flex: 1;
2026-04-10 14:40:48 +08:00
padding: 2.4rem 4rem;
2026-04-09 13:36:03 +08:00
> .title{
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 3rem;
> .left{
display: flex;
justify-content: space-between;
align-items: center;
font-family: pingfang_heavy;
font-weight: 400;
font-size: 1.8rem;
line-height: 130%;
letter-spacing: 0%;
gap: 1.2rem;
2026-04-10 14:40:48 +08:00
align-content: flex-start;
2026-04-09 13:36:03 +08:00
> i{
display: flex;
justify-content: space-between;
align-items: center;
font-size: 2.4rem;
}
}
}
2026-04-10 14:40:48 +08:00
.list2{
gap: 1.6rem;
.item{
width: 19.2rem;
}
}
.list,.list2{
2026-04-09 13:36:03 +08:00
display: flex;
flex-wrap: wrap;
2026-04-10 14:40:48 +08:00
// flex: 1;
margin: auto;
overflow: auto;
&::-webkit-scrollbar {
display: none;
2026-04-09 13:36:03 +08:00
}
}
}
}
.listingsBox1{
2026-04-10 14:40:48 +08:00
width: 100%;
2026-04-09 13:36:03 +08:00
flex: 1;
}
.listingsBox2{
width: 48.8rem;
overflow: hidden;
&.active{
width: 0;
}
.box{
width: 48.8rem;
}
}
.openOrCloseDrafts{
position: absolute;
width: 3.4rem;
height: 8rem;
border-top-right-radius: 2rem;
border-bottom-right-radius: 2rem;
border-width: 1.5px, 1.5px, 1.5px, 0px;
border-style: solid;
border-color: #000000;
right: 1.5px;
top: 50%;
transform: translate(100%,-50%);
cursor: pointer;
transition: all 0.3s ease-in-out;
border-left: none;
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
z-index: 2;
> span{
transform: rotate(-90deg);
transition: all .3s;
}
&.active{
> span{
transform: rotate(90deg);
}
}
&:hover{
width: 4.5rem;
}
}
}
</style>