digital item页面

This commit is contained in:
X1627315083@163.com
2026-05-22 11:11:38 +08:00
parent 2d95c3c976
commit 3ae774bc6b
7 changed files with 278 additions and 127 deletions

View File

@@ -6,34 +6,42 @@ const props = defineProps({
default:()=>[] default:()=>[]
}, },
selected:{ selected:{
type:String, type:Array,
default:()=>'' default:()=>[]
} }
}) })
const emit = defineEmits([ const emit = defineEmits([
'update:selected','change' 'update:selected','change'
]) ])
const checkList = computed(()=>{ const checkList = computed(()=>{
if(props.selected[0] === ''){ if(props.selected[0] === 'all'){
return props.list.map(item => item.value) return props.list.map(item => item.value)
}else{ }else{
return [...props.selected] return [...props.selected]
} }
}) })
const handleChange = (val) => { const handleChange = (val) => {
emit('update:selected', val) let data = val.filter(item => item !== 'all')
emit('change', val) if(val.length == 0)return
if(data.length == props.list.length){
data = ['all']
}else{
data = [...val]
}
emit('update:selected', data)
emit('change', data)
} }
const checkAll = computed(()=>{ const checkAll = computed(()=>{
return checkList.value.length === props.list.length return checkList.value.length === props.list.length
}) })
const handleCheckAllChange = (val) => { const handleCheckAllChange = (val) => {
let data = [] let data = []
if(val){ if(val && props.selected[0] !== 'all'){
data = props.list.map(item => item.value) data = ['all']
} // data = props.list.map(item => item.value)
emit('update:selected', data) emit('update:selected', data)
emit('change', data) emit('change', data)
}
} }
let data = reactive({ let data = reactive({
}) })

View File

@@ -6,8 +6,6 @@ import scListNull from '@/views/shoppingCart/sc-list-null.vue'
import brandItem from '@/views/brand/brand-item.vue' import brandItem from '@/views/brand/brand-item.vue'
import { getDesignerList } from '@/api/brand' import { getDesignerList } from '@/api/brand'
import img from '@/assets/images/collectionStory/Rectangle.png'
//const props = defineProps({ //const props = defineProps({
//}) //})
//const emit = defineEmits([ //const emit = defineEmits([

View File

@@ -1,6 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue"; import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
import img from "@/assets/images/collectionStory/Rectangle.png";
import { getlistingListApi } from "@/api/listing"; import { getlistingListApi } from "@/api/listing";
const props = defineProps({ const props = defineProps({
@@ -150,10 +149,9 @@ defineExpose({})
// align-content: start; // align-content: start;
// grid-template-columns: repeat(3, 1fr); // grid-template-columns: repeat(3, 1fr);
overflow: hidden; overflow: hidden;
display: grid; display: grid;
align-content: start; align-content: start;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 28rem), 1fr)); grid-template-columns: repeat(auto-fill, minmax(min(100%, 28rem), 1fr));
border-top: 0.5px solid #585858; border-top: 0.5px solid #585858;
padding: .5px 0 0 .5px; padding: .5px 0 0 .5px;
/* 垂直线(右边框) */ /* 垂直线(右边框) */

View File

@@ -5,6 +5,8 @@ import img from "@/assets/images/collectionStory/Rectangle.png";
import myEvent from '@/utils/myEvent' import myEvent from '@/utils/myEvent'
import { getListingDetailApi } from '@/api/listing' import { getListingDetailApi } from '@/api/listing'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
//const props = defineProps({ //const props = defineProps({
//}) //})
@@ -21,8 +23,40 @@ let detail:any = ref({
updateTime: '', updateTime: '',
gender: '', gender: '',
}) })
const addShopping = (item) => { const sketchList = ref([])
myEvent.emit('addShopping', item) const illustrationList = ref([])
const productList = ref([])
const editorialVisualList = ref([])
const addShopping = () => {
console.log(detail.value)
if(!detail.value.price) return ElMessage.warning('Please log in first.')
let data = {
cover: detail.value.images.cover[0],
price: detail.value.price,
shopName: detail.value.shopName,
title: detail.value.title,
}
myEvent.emit('addShopping', data)
}
const goShopping = () => {
if(!detail.value.price) return ElMessage.warning('Please log in first.')
router.push({path: '/shoppingCart'})
}
const setImgList = (list)=>{
sketchList.value = list.apparel.map((item:any) => {return {imgUrl:item}})
illustrationList.value = list.sketch.map((item:any) => {return {imgUrl:item}})
productList.value = list.main_product.map((item:any) => {return {imgUrl:item}})
editorialVisualList.value = list.product.map((item:any) => {return {imgUrl:item}})
if(list.firstFrame){
list.firstFrame.forEach((item:any,index) => {
editorialVisualList.value.push({
imgUrl:item,
gif: list.gif[index],
video: list.video[index],
})
})
}
} }
const getListingDetail = ()=>{ const getListingDetail = ()=>{
getListingDetailApi({ getListingDetailApi({
@@ -30,8 +64,15 @@ const getListingDetail = ()=>{
}).then((res)=>{ }).then((res)=>{
console.log(res) console.log(res)
if(res)detail.value = res if(res)detail.value = res
setImgList(res.images)
}) })
} }
// const vObserve = {
// mounted (el,binding) {
// },
// unmounted (el,binding) {
// }
// }
onMounted(()=>{ onMounted(()=>{
getListingDetail() getListingDetail()
}) })
@@ -43,23 +84,38 @@ defineExpose({})
<div class="digitalItemDetail"> <div class="digitalItemDetail">
<div class="center"> <div class="center">
<div class="img-list"> <div class="img-list">
<div class="title"> <div class="left">
<div>Sketch</div> <div class="title">Sketch</div>
<div>Illustration</div> <div class="box sketch">
<div>Product</div> <div class="imgBox">
</div> <img :src="item?.imgUrl" v-for="item in sketchList" :key="item" alt="">
<div class="img"> </div>
<div class="sketch"> </div>
<img :src="img" v-for="item in 4" :key="item" alt=""> </div>
</div> <div class="right">
<div class="illustration"> <div class="top">
<img :src="img" v-for="item in 4" :key="item" alt=""> <div class="box">
</div> <div class="title">Illustration</div>
<div class="product"> <div class="imgBox">
<img :src="img" v-for="item in 4" :key="item" alt=""> <img :src="item?.imgUrl" v-for="item in illustrationList" :key="item" alt="">
</div>
</div>
<div class="box">
<div class="title">Product</div>
<div class="imgBox">
<img :src="item?.imgUrl" v-for="item in productList" :key="item" alt="">
</div>
</div>
</div>
<div class="bottom">
<div class="box aa">
<div class="title">Editorial Visual</div>
<div class="imgBox">
<img :src="item?.gif||item?.imgUrl" v-for="item in editorialVisualList" :key="item" alt="">
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="img-detail"> <div class="img-detail">
<div class="back" @click="router.back()"> <div class="back" @click="router.back()">
@@ -69,13 +125,13 @@ defineExpose({})
<span>Back</span> <span>Back</span>
</div> </div>
<div class="img-info"> <div class="img-info">
<div class="img-type">{{ detail.gender.toUpperCase() }} / skirt, blouse, Outwear</div> <div class="img-type">{{ detail.designFor?.toUpperCase() || ''}} / {{ detail.productCategory?.join(',')?.toUpperCase() || '' }}</div>
<div class="img-name">{{ detail.title }}</div> <div class="img-name">{{ detail.title }}</div>
<div class="img-price" v-if="detail.price">¥{{ detail.price }} <span class="mini-scrollbar">HKD</span></div> <div class="img-price" v-if="detail.price">¥{{ detail.price }} <span class="mini-scrollbar">HKD</span></div>
</div> </div>
<div class="commodity"> <div class="commodity">
<div class="info"> <div class="info">
<img class="profile" :src="img" alt=""> <img class="profile" :src="detail.avatar" alt="">
<div class="detail"> <div class="detail">
<div class="name">{{ detail.shopName }}</div> <div class="name">{{ detail.shopName }}</div>
<div class="release-time"> <div class="release-time">
@@ -102,8 +158,8 @@ defineExpose({})
</div> </div>
</div> </div>
<div class="button"> <div class="button">
<div class="buy-now">Buy Now</div> <div class="buy-now" @click="goShopping">Buy Now</div>
<div class="add-cart" @click="addShopping(item)"> <div class="add-cart" @click="addShopping()">
<div class="icon"> <div class="icon">
<svg-icon name="cart_0" size="24"></svg-icon> <svg-icon name="cart_0" size="24"></svg-icon>
</div> </div>
@@ -130,42 +186,66 @@ defineExpose({})
display: flex; display: flex;
overflow: hidden; overflow: hidden;
.img-list{ .img-list{
display: flex;
flex: 1; flex: 1;
flex-direction: column; display: grid;
grid-template-columns: 1fr 2fr;
--row-width: 33.333%; --row-width: 33.333%;
align-items: stretch;
// --row-width: 29.3rem; // --row-width: 29.3rem;
overflow-y: auto; overflow-y: auto;
position: relative;
&::-webkit-scrollbar{ &::-webkit-scrollbar{
display: none; display: none;
} }
> .title{ .title{
display: flex; width: 100%;
position: sticky;
top: 0;
> div{
width: var(--row-width);
line-height: 8.6rem; line-height: 8.6rem;
padding-left: 2.4rem; padding-left: 2.4rem;
border-right: 0.5px solid #C4C4C4;
font-weight: 500; font-weight: 500;
font-size: 1.6rem; font-size: 1.6rem;
background-color: #f5f5f5; background-color: #f5f5f5;
&:last-child{ position: sticky;
border: none; top: 0;
} }
} .box{
} flex: 1;
> .img{ .imgBox{
display: flex; display: flex;
flex-direction: row;
flex-wrap: wrap;
img{
width: 100%;
}
}
> div{ }
display: flex; > .left{
width: var(--row-width);
border-right: 0.5px solid #C4C4C4; border-right: 0.5px solid #C4C4C4;
flex-direction: column; .imgBox{
&:last-child{ padding: 0 30px;
border: none; }
}
> .right{
position: relative;
&::after{
content: '';
display: block;
border-right: 0.5px solid #C4C4C4;
position: absolute;
height: 100%;
left: 50%;
top: 0;
z-index: 2;
}
> .top{
display: flex;
}
> .bottom{
.imgBox{
display: flex;
img{
width: 50%;
}
} }
} }
} }

View File

@@ -1,68 +1,103 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue"; import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
import img from "@/assets/images/collectionStory/Rectangle.png"; import { getListingMallListApi } from '@/api/listing'
//const props = defineProps({
//}) const props = defineProps({
getListData: {
type: Object,
default: () => ({
designFor: '',
categories: [],
sortField: '',
})
}
})
const emit = defineEmits([ const emit = defineEmits([
'addShopping', 'addShopping',
'openDetail' 'openDetail',
'getListingMallList'
]) ])
let data = reactive({ let data = reactive({
}) })
const list = ref([
{
url: img,
title: "Windswept Burden",
price: "$100.00",
},{
url: img,
title: "Windswept Burden",
price: "$100.00",
},{
url: img,
title: "Windswept Burden",
price: "$100.00",
},{
url: img,
title: "Windswept Burden",
price: "$100.00",
},{
url: img,
title: "Windswept Burden",
price: "$100.00",
},{
url: img,
title: "Windswept Burden",
price: "$100.00",
},{
url: img,
title: "Windswept Burden",
price: "$100.00",
},{
url: img,
title: "Windswept Burden",
price: "$100.00",
},
])
const type = ref('All')
const addShopping = (item) => { const addShopping = (item) => {
emit('addShopping', item) emit('addShopping', item)
} }
const openDetail = (item) => { const openDetail = (item) => {
emit('openDetail', item) emit('openDetail', item)
} }
const commodityList = ref([])
const getListingListData = reactive({
pageSize: 10,
pageNum: 1,
isShowMark:false,
isNoData:false,
})
const reset = () => {
commodityList.value = []
getListingListData.pageNum = 1
getListingListData.isShowMark = false
getListingListData.isNoData = false
}
const getListingMallList = ()=>{
getListingListData.isShowMark = true
getListingListData.isNoData = false
let data = {
designFor: props.getListData.designFor,
// categories: [all],
categories: props.getListData.categories[0] == 'all' ? [] : props.getListData.categories,
sortField: props.getListData.sortField,
sortOrder: 'desc',
pageSize: getListingListData.pageSize,
pageNum: getListingListData.pageNum,
}
getListingMallListApi(data).then(res => {
if(res.content.length == 0)getListingListData.isNoData = true
commodityList.value.push(...res.content)
getListingListData.isShowMark = false
}).catch(()=>{
getListingListData.isNoData = true
getListingListData.isShowMark = false
})
}
const vObserve = {
mounted (el,binding) {
getListingListData.isShowMark = false
getListingListData.isNoData = false
new IntersectionObserver(
(entries, observer) => {
// 如果不是相交,则直接返回
// console.log(entries[0]);
if (!entries[0].intersectionRatio) return;
binding.value()
getListingListData.pageNum += 1
},
// { root:worksPage }
).observe(el);
}
}
onMounted(()=>{ onMounted(()=>{
}) })
onUnmounted(()=>{ onUnmounted(()=>{
}) })
defineExpose({}) defineExpose({reset,commodityList,getListingListData})
const {} = toRefs(data); const {} = toRefs(data);
</script> </script>
<template> <template>
<div class="commodityList"> <div class="commodityList">
<div class="list"> <div class="list">
<div class="item" v-for="item in list" :key="item.url"> <div class="item" v-for="item in commodityList" :key="item.url">
<CommodityItem :url="item.url" :name="item.title" :price="item.price" @addShopping="addShopping(item)" @openDetail="openDetail(item)"></CommodityItem> <CommodityItem :url="item.cover" :name="item.title" :price="item.price" @addShopping="addShopping(item)" @openDetail="openDetail(item)"></CommodityItem>
</div>
<div v-show="!getListingListData.isNoData" class="material_content_list_loding">
<span class="page_loading" v-show="!getListingListData.isShowMark" v-observe="getListingMallList"></span>
<img v-if="getListingListData.isShowMark" src="@/assets/images/brand/brandLoading.gif" alt="">
</div> </div>
</div> </div>
</div> </div>
@@ -81,12 +116,12 @@ const {} = toRefs(data);
// align-content: start; // align-content: start;
// grid-template-columns: repeat(3, 1fr); // grid-template-columns: repeat(3, 1fr);
overflow: hidden; overflow: hidden;
display: grid; display: grid;
align-content: start; align-content: start;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 28rem), 1fr)); grid-template-columns: repeat(auto-fill, minmax(min(100%, 28rem), 1fr));
border-top: 0.5px solid #585858; border-top: 0.5px solid #585858;
padding: .5px 0 0 .5px; padding: .5px 0 0 .5px;
/* 垂直线(右边框) */ /* 垂直线(右边框) */
.item{ .item{
position: relative; position: relative;
@@ -96,6 +131,25 @@ const {} = toRefs(data);
margin-right: -1px; margin-right: -1px;
margin-bottom: -1px; margin-bottom: -1px;
} }
> .material_content_list_loding{
width: 100%;
height: 5rem;
aspect-ratio: 1/1;
grid-column: 1 / -1;
overflow: hidden;
display: flex;
flex-shrink: 0;
justify-content: center;
> .page_loading{
width: 5rem;
height: 5rem;
}
> img{
width: 5rem;
height: 5rem;
object-fit: contain;
}
}
} }
} }
</style> </style>

View File

@@ -10,47 +10,45 @@ import { getListingMallListApi } from '@/api/listing'
defineOptions({ defineOptions({
name: 'digitalItem' name: 'digitalItem'
}) })
const categories = ref([''])
const gender = ref([''])
//const props = defineProps({ //const props = defineProps({
//}) //})
//const emit = defineEmits([ //const emit = defineEmits([
//]) //])
const categories = ref(['all'])
const gender = ref(['all'])
const digitalItemRef = ref(null) const digitalItemRef = ref(null)
const scrollTop = ref(0) const scrollTop = ref(0)
const router = useRouter() const router = useRouter()
const commodityListRef = ref(null)
const searechTypeList = ref([ const searechTypeList = ref([
{ {
value:'Best Selling', value:'salesVolume',
label:'Best Selling' label:'Best Selling'
},{ },{
value:'Price: Low to High', value:'price',
label:'Price: Low to High' label:'Price: Low to High'
},{ },{
value:'Newest First', value:'updateTime',
label:'Newest First' label:'Newest First'
}, },
]) ])
const searechType = ref('Newest First')
const searechType = ref('updateTime')
const addShopping = (item) => {} const addShopping = (item) => {}
const openDetail = (item) => { const openDetail = (item) => {
scrollTop.value = digitalItemRef.value.scrollTop scrollTop.value = digitalItemRef.value.scrollTop
router.push({ router.push({
path: '/digitalItem/' + 123, path: '/digitalItem/' + item.id,
}) })
} }
const handleChange = (val) => { const handleChange = (val) => {
categories.value = val.categories
gender.value = val.gender
commodityListRef.value.reset()
} }
const getListingMallList = ()=>{ const updateSort = () => {
let data = { commodityListRef.value.reset()
// designFor
}
// getListingMallListApi().then(res => {
// })
} }
onActivated(()=>{ onActivated(()=>{
digitalItemRef.value.scrollTop = scrollTop.value digitalItemRef.value.scrollTop = scrollTop.value
@@ -72,13 +70,13 @@ defineExpose({})
</div> </div>
<div class="filters"> <div class="filters">
<div class="filter-item"> <div class="filter-item">
<el-select v-model="categories" placeholder="Sort By" :teleported="false"> <el-select v-model="searechType" @change="updateSort" placeholder="Sort By" :teleported="false">
<template #label="{ label }"> <template #label="{ label }">
<span class="header-label">Sort By</span> <span class="header-label">Sort By</span>
<span class="header-value">{{ label }}</span> <span class="header-value">{{ label }}</span>
</template> </template>
<el-option <el-option
v-for="item in categoriesList" v-for="item in searechTypeList"
:key="item.label" :key="item.label"
:value="item.value" :value="item.value"
:label="item.label" :label="item.label"
@@ -91,8 +89,17 @@ defineExpose({})
<MerchantInfo @change="handleChange"></MerchantInfo> <MerchantInfo @change="handleChange"></MerchantInfo>
</div> </div>
<div class="commodity-list"> <div class="commodity-list">
<CommodityList v-if="true" @addShopping="addShopping" @openDetail="openDetail"></CommodityList> <CommodityList
<div v-else class="null"> v-show="commodityListRef?.commodityList?.length > 0 || !commodityListRef?.getListingListData.isNoData"
ref="commodityListRef"
:getListData="{
designFor: gender[0],
categories: categories,
sortField: searechType,
}"
@addShopping="addShopping"
@openDetail="openDetail"></CommodityList>
<div v-show="commodityListRef?.commodityList?.length == 0" class="null">
<sc-list-null <sc-list-null
nullImage="shopping-cart" nullImage="shopping-cart"
:showButton="false" :showButton="false"
@@ -100,6 +107,7 @@ defineExpose({})
tip="Try adjusting your filters or refreshing the page." tip="Try adjusting your filters or refreshing the page."
/> />
</div> </div>
</div> </div>
</div> </div>
<Footer></Footer> <Footer></Footer>
@@ -220,8 +228,13 @@ defineExpose({})
border-right: 0.5px solid #585858; border-right: 0.5px solid #585858;
margin-right: 9rem; margin-right: 9rem;
display: flex; display: flex;
position: relative;
.null{ .null{
flex: 1; flex: 1;
position: absolute;
width: 100%;
height: 100%;
background-color: #fff;
} }
} }
} }

View File

@@ -16,12 +16,12 @@ const genderList = computed(() => [
{ label: t('Wardrobe.assets.genders.male'), value: 'male' }, { label: t('Wardrobe.assets.genders.male'), value: 'male' },
{ label: t('Wardrobe.assets.genders.female'), value: 'female' } { label: t('Wardrobe.assets.genders.female'), value: 'female' }
]) ])
const categories = ref(['']) const categories = ref(['all'])
const gender = ref(['']) const gender = ref(['all'])
const clearFilters = () => { const clearFilters = () => {
categories.value = [''] categories.value = ['all']
gender.value = [''] gender.value = ['all']
handleChange() handleChange()
} }
const handleChange = () => { const handleChange = () => {