This commit is contained in:
X1627315083@163.com
2026-04-10 14:40:48 +08:00
parent 5e77348913
commit 3b70ed2830
11 changed files with 1039 additions and 43 deletions

View File

@@ -1,6 +1,9 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
import { VueDraggable } from "vue-draggable-plus"
import contentItem from "./contentItem.vue"
import selectMenu from '@/component/modules/selectMenu.vue'
//const props = defineProps({
//})
@@ -54,9 +57,75 @@ const config = ref({
"scroll-speed": 10,
onEnd: (e) => {}
})
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
}
onMounted(()=>{
// 创建观察器
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)
})
})
onUnmounted(()=>{
// 停止监听
if(listingsBoxRef?.value)resizeObserver?.unobserve(listingsBoxRef?.value)
})
defineExpose({})
const { showDrafts } = toRefs(data);
@@ -64,19 +133,62 @@ const { showDrafts } = toRefs(data);
<template>
<div class="listings">
<div class="listingsBox listingsBox1">
<div class="box">
<div class="box" :class="domSize" ref="listingsBoxRef">
<div class="title">
<div class="left">
<i class="fi fi-rs-comments"></i>
<span>Active Listings</span>
</div>
<div class="right">
<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>
</div>
</div>
<VueDraggable
v-model="list"
class="list"
:style="{gap: gap[domSize] || '1.6rem'}"
v-bind="config"
:group="{
name: 'sortable',
@@ -84,20 +196,25 @@ const { showDrafts } = toRefs(data);
put: true
}"
>
<div class="item" v-for="v in list" :key="v.id" :draging="true">
{{ v.id }}
</div>
<contentItem v-for="v in list" :key="v.id" type="listings" :domSize="domSize"/>
</VueDraggable>
</div>
<div class="openOrCloseDrafts" :class="{'active': showDrafts}" @click="showDrafts = !showDrafts">
<div class="openOrCloseDrafts" :class="{'active': showDrafts}" @click="unfoldDrafits">
<span class="icon iconfont icon-xiala"></span>
</div>
</div>
<!-- <div class="listingsBox listingsBox2" :class="{'active': showDrafts}">
<div class="box">
<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>
<VueDraggable
v-model="list2"
class="list"
class="list2"
v-bind="config"
:group="{
name: 'sortable',
@@ -105,12 +222,10 @@ const { showDrafts } = toRefs(data);
put: true
}"
>
<div class="item" v-for="v in list" :key="v.id" :draging="true">
{{ v.id }}
</div>
<contentItem v-for="v in list2" :key="v.id" domSize="Small" type="drafts"/>
</VueDraggable>
</div>
</div> -->
</div>
</div>
</template>
<style lang="less" scoped>
@@ -123,16 +238,19 @@ const { showDrafts } = toRefs(data);
.listingsBox{
background-color: #f9fafa;
border-radius: 2rem;
flex: 1;
position: relative;
// overflow: hidden;
display: flex;
transition: all .3s;
.box{
width: 100%;
padding: 2.4rem 4rem;
padding: 2.4rem 0;
padding-bottom: 0;
flex-direction: column;
overflow: hidden;
display: flex;
flex: 1;
padding: 2.4rem 4rem;
> .title{
display: flex;
justify-content: space-between;
@@ -148,6 +266,7 @@ const { showDrafts } = toRefs(data);
line-height: 130%;
letter-spacing: 0%;
gap: 1.2rem;
align-content: flex-start;
> i{
display: flex;
justify-content: space-between;
@@ -156,34 +275,30 @@ const { showDrafts } = toRefs(data);
}
}
}
.list{
.list2{
gap: 1.6rem;
.item{
width: 19.2rem;
}
}
.list,.list2{
display: flex;
flex-wrap: wrap;
gap: 20px;
.item{
width: 197px;
height: 249px;
border-radius: 20px;
border: 1.5px solid #C7C7C7;
&:hover{
border: 2px solid #000000;
}
// flex: 1;
margin: auto;
overflow: auto;
&::-webkit-scrollbar {
display: none;
}
}
}
}
.listingsBox1{
width: 100%;
flex: 1;
.box{
.list{
justify-content: center;
}
}
}
.listingsBox2{
width: 48.8rem;
transition: all .3s;
overflow: hidden;
&.active{
width: 0;

View File

@@ -0,0 +1,216 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
const props = defineProps({
domSize: {
type: String,
default: 'Small'
},
type: {
type: String,
default: 'listings'
}
})
//const emit = defineEmits([
//])
let data = reactive({
})
onMounted(()=>{
})
onUnmounted(()=>{
})
defineExpose({})
const {} = toRefs(data);
</script>
<template>
<div class="item" :draging="true" :class="domSize">
<div class="imgBox">
<img src="" alt="">
<div class="maskBtn">
<div>
<svgIcon name="seller-edit" :size="domSize == 'Small'?32:domSize == 'Medium'?40:48" />
<div>Edit</div>
</div>
<div v-if="type == 'listings'">
<svgIcon name="seller-draft" :size="domSize == 'Small'?32:domSize == 'Medium'?40:48" />
<div>Draft</div>
</div>
<div v-else-if="type == 'drafts'">
<svgIcon name="seller-share" :size="domSize == 'Small'?32:domSize == 'Medium'?40:48" />
<div>Publish</div>
</div>
</div>
</div>
<div class="detail">
<div class="left">
<div class="name">item name</div>
<div class="price">$1123</div>
</div>
<div class="right">
<div class="detailItem" v-if="type == 'listings'">
<div class="shopping1">
<i class="fi fi-rr-shopping-bag-add"></i>
</div>
<span>123</span>
</div>
<div class="detailItem" v-if="type == 'listings'">
<div class="eye1">
<i class="fi fi-rs-eye"></i>
</div>
<span>123</span>
</div>
<div class="detailItem drafts" v-if="type == 'drafts'">
<div class="">
<i class="fi fi-rr-trash"></i>
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.item{
// height: 30.2rem;
&.Small{
--itemWidth: 19.7rem;
--itemImgHeight: 24.9rem;
--maskBtnGap: .8rem;
--maskBtnWidth: 6rem;
--maskBtnFS: 1.6rem;
--detailPadding: .8rem 1.2rem;
--detailLeftNameSize: 1.4rem;
--detailLeftPriceSize: 1.2rem;
--detailRightGap: .8rem;
--detailRightItemGap: .4rem;
--detailRightItemIcon: 1.6rem;
--detailRightItemDraftsIcon: 2rem;
}
&.Medium{
--itemWidth: 25.4rem;
--itemImgHeight: 32.2rem;
--maskBtnGap: 1rem;
--maskBtnWidth: 7.6rem;
--maskBtnFS: 2.07rem;
--detailPadding: 1.2rem 1.4rem;
--detailLeftNameSize: 1.6rem;
--detailLeftPriceSize: 1.4rem;
--detailRightGap: 1rem;
--detailRightItemGap: .4rem;
--detailRightItemIcon: 2rem;
--detailRightItemDraftsIcon: 2rem;
}
&.Large{
--itemWidth: 31.4rem;
--itemImgHeight: 39.8rem;
--maskBtnGap: 1.2rem;
--maskBtnWidth: 7.6rem;
--maskBtnFS: 2.56rem;
--detailPadding: 1.2rem 1.6rem;
--detailLeftNameSize: 1.98rem;
--detailLeftPriceSize: 1.73rem;
--detailRightGap: 1.2rem;
--detailRightItemGap: .4rem;
--detailRightItemIcon: 2.6rem;
--detailRightItemDraftsIcon: 2rem;
}
width: var(--itemWidth);
border-radius: 2rem;
border: 1.5px solid #C7C7C7;
overflow: hidden;
.imgBox{
position: relative;
height: var(--itemImgHeight);
width: 100%;
> .maskBtn{
position: absolute;
width: 100%;
height: 100%;
background: #00000066;
opacity: 0;
transition: all .3s;
top: 0;
display: flex;
justify-content: center;
align-items: center;
gap: var(--maskBtnGap);
> div{
font-family: pingfang_bold;
font-weight: 400;
font-size: var(--maskBtnFS);
line-height: 150%;
color: #fff;
cursor: pointer;
width: var(--maskBtnWidth);
text-align: center;
> div{
margin-top: .8rem;
}
}
}
}
.detail{
padding: var(--detailPadding);
display: flex;
justify-content: space-between;
--rightColor: #979797;
.left{
gap: var(--detailRightItemGap);
.name{
font-weight: 500;
font-size: var(--detailLeftNameSize);
line-height: 150%;
}
.price{
font-family: pingfang_regular;
font-weight: 400;
font-size: var(--detailLeftPriceSize);
line-height: 150%;
}
}
.right{
display: flex;
gap: var(--detailRightGap);
.detailItem{
display: flex;
gap: var(--detailRightItemGap);
flex-direction: column;
justify-content: space-between;
> div{
color: var(--rightColor);
display: flex;
justify-content: center;
> i{
font-size: var(--detailRightItemIcon);
display: flex;
}
}
> span{
color: var(--rightColor);
font-family: pingfang_regular;
font-weight: 400;
font-size: var(--detailLeftPriceSize);
line-height: 150%;
}
&.drafts{
justify-content: center;
> div{
> i{
font-size: var(--detailRightItemDraftsIcon);
}
}
}
}
}
}
&:hover{
border: 1.5px solid #000000;
.imgBox{
> .maskBtn{
opacity: 1;
}
}
.detail{
--rightColor: #000000;
}
}
}
</style>

View File

@@ -2,6 +2,7 @@
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
import sellerHeader from "../../seller-header.vue"
import sellerContent from "./content.vue"
import myEvent from "@/tool/myEvents.js"
//const props = defineProps({
//})
@@ -9,6 +10,9 @@ import sellerContent from "./content.vue"
//])
let data = reactive({
})
const newListing = ()=>{
myEvent.emit('newListing')
}
onMounted(()=>{
})
onUnmounted(()=>{
@@ -23,7 +27,7 @@ const {} = toRefs(data);
tip="Active listings and unpublished inventory."
>
<template #right>
<div class="button">
<div class="button" @click="newListing">
<span>New Listing</span>
<div class="icon">
<i class="fi fi-br-plus"></i>