feat: 楼层装修新增绑定分类功能

master
学习很差啦 2022-10-19 11:56:42 +08:00
parent f08d166c86
commit d01edbdfe2
4 changed files with 385 additions and 209 deletions

View File

@ -1,198 +1,276 @@
<template> <template>
<div> <div>
<div v-for="(item, index) in res" :key="index" class="goods-row"> <!-- 一行两列商品展示 -->
<div class="flex goods-col"> <view class="goods-list" v-if="type == 'twoColumns'">
<div class="goods-img" @click="navigateToDetailPage(item)"> <view v-for="(item, index) in res" :key="index" class="goods-item">
<u-image width="230rpx" border-radius='16' height="230rpx" :src="item.goodsImage || item.thumbnail"> <view class="image-wrapper" @click="navigateToDetailPage(item)">
<u-loading slot="loading"></u-loading> <u-image
</u-image> :src="item.thumbnail"
</div> width="100%"
<div class="goods-detail"> height="330rpx"
<div class="title clamp3" @click="navigateToDetailPage(item)">{{ item.goodsName }}</div> mode="aspectFill"
<view class="price-box" @click="navigateToDetailPage(item)"> >
<div class="price" v-if="item.price!=undefined"> <u-loading slot="loading"></u-loading>
¥<span>{{ $options.filters.goodsFormatPrice(item.price )[0] }} </span>.{{ </u-image>
$options.filters.goodsFormatPrice(item.price )[1] </view>
}} <view class="goods-detail">
</div> <div
</view> class="title clamp"
<div class="promotion" @click="navigateToDetailPage(item)"> v-html="lightSearchStr(keyword, item.goodsName)"
<div v-if="item.salesModel == 'WHOLESALE'"> @click="navigateToDetailPage(item)"
<span></span> ></div>
</div> <view class="price-box" @click="navigateToDetailPage(item)">
<div v-for="(promotionItem,promotionIndex) in getPromotion(item)" :key="promotionIndex"> <div class="price" v-if="item.price != undefined">
<span v-if="promotionItem.indexOf('COUPON') != -1"></span> ¥<span
<span v-if="promotionItem.indexOf('FULL_DISCOUNT') != -1"></span> >{{
<span v-if="promotionItem.indexOf('SECKILL') != -1"></span> $options.filters.goodsFormatPrice(item.price)[0]
</div> }} </span
</div> >.{{ $options.filters.goodsFormatPrice(item.price)[1] }}
<div style="overflow: hidden" @click="navigateToDetailPage(item)" class="count-config"> </div>
<span style="float: left; font-size: 22rpx">已售 {{ item.buyCount || '0' }}</span> </view>
<span style="float: right; font-size: 22rpx">{{ item.commentNum || '0' }}条评论</span> <div class="count-config" @click="navigateToDetailPage(item)">
</div> <span>已售 {{ item.buyCount || "0" }}</span>
<span>{{ item.commentNum || "0" }}条评论</span>
</div> </div>
</div> <div
class="store-seller-name"
</div> v-if="storeName"
</div> @click="navigateToStoreDetailPage(item)"
>
<div class="text-hidden">
<u-tag
style="margin-right: 10rpx"
size="mini"
mode="dark"
v-if="item.selfOperated"
text="自营"
type="error"
/>
<span>{{ item.storeName || "暂无" }}</span>
</div>
<span>
<u-icon name="arrow-right"></u-icon>
</span>
</div>
</view>
</view>
</view>
<!-- 一行一列商品展示 -->
<div v-if="type == 'oneColumns'">
<div v-for="(item, index) in res" :key="index" class="goods-row">
<div class="flex goods-col">
<div class="goods-img" @click="navigateToDetailPage(item)">
<u-image
width="230rpx"
border-radius="16"
height="230rpx"
:src="item.goodsImage || item.thumbnail"
>
<u-loading slot="loading"></u-loading>
</u-image>
</div>
<div class="goods-detail">
<div class="title clamp3" @click="navigateToDetailPage(item)">
{{ item.goodsName }}
</div>
<view class="price-box" @click="navigateToDetailPage(item)">
<div class="price" v-if="item.price != undefined">
¥<span
>{{ $options.filters.goodsFormatPrice(item.price)[0] }} </span
>.{{ $options.filters.goodsFormatPrice(item.price)[1] }}
</div>
</view>
<div class="promotion" @click="navigateToDetailPage(item)">
<div v-if="item.salesModel == 'WHOLESALE'">
<span></span>
</div>
<div
v-for="(promotionItem, promotionIndex) in getPromotion(item)"
:key="promotionIndex"
>
<span v-if="promotionItem.indexOf('COUPON') != -1"></span>
<span v-if="promotionItem.indexOf('FULL_DISCOUNT') != -1"
>满减</span
>
<span v-if="promotionItem.indexOf('SECKILL') != -1"></span>
</div>
</div>
<div
style="overflow: hidden"
@click="navigateToDetailPage(item)"
class="count-config"
>
<span style="float: left; font-size: 22rpx"
>已售 {{ item.buyCount || "0" }}</span
>
<span style="float: right; font-size: 22rpx"
>{{ item.commentNum || "0" }}条评论</span
>
</div>
</div>
</div>
</div>
</div>
</div>
</template> </template>
<script> <script>
import commonTpl from '@/components/m-goods-list/common' import commonTpl from "@/components/m-goods-list/common";
export default { export default {
data() { data() {
return { return {
lightColor: this.$mainColor lightColor: this.$mainColor,
} };
}, },
mixins: [commonTpl], mixins: [commonTpl],
props: { props: {
// //
res: { type:{
type: Array, type:String,
default: () => { default:"oneColumns"
return [] },
} //
}, res: {
}, type: Array,
methods:{ default: () => {
// return [];
navigateToDetailPage(item) { },
uni.navigateTo({ },
url: `/pages/product/goods?id=${item.id}&goodsId=${item.goodsId}`, },
}); methods: {
}, //
} navigateToDetailPage(item) {
} uni.navigateTo({
url: `/pages/product/goods?id=${item.id}&goodsId=${item.goodsId}`,
});
},
},
};
</script> </script>
<style lang='scss' scoped> <style lang="scss" scoped>
.goods-list { .goods-list {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
margin: 10rpx 20rpx 284rpx; margin: 10rpx 20rpx 284rpx;
width: 100%; width: 100%;
>.goods-item { > .goods-item {
background-color: #ffffff; background-color: #ffffff;
display: flex; display: flex;
border-radius: 16rpx; border-radius: 16rpx;
flex-direction: column; flex-direction: column;
width: calc(50% - 30rpx); width: calc(50% - 30rpx);
margin-bottom: 20rpx; margin-bottom: 20rpx;
padding-bottom: 20rpx; padding-bottom: 20rpx;
&:nth-child(2n + 1) { &:nth-child(2n + 1) {
margin-right: 20rpx; margin-right: 20rpx;
} }
.image-wrapper {
.image-wrapper { width: 100%;
width: 100%; height: 330rpx;
height: 330rpx; border-radius: 16rpx 16rpx 0 0;
border-radius: 16rpx 16rpx 0 0; overflow: hidden;
overflow: hidden; padding: 0;
padding: 0; }
} }
}
.count-config,
.count-config, .store-seller-name {
.store-seller-name { font-size: $font-sm;
font-size: $font-sm; }
}
.text-hidden {
.text-hidden { overflow: hidden;
overflow: hidden; text-overflow: ellipsis;
text-overflow: ellipsis; white-space: nowrap;
white-space: nowrap; }
} }
}
.goods-row {
background: #fff;
.goods-row { padding: 16rpx;
background: #fff;
padding: 16rpx; > .goods-col {
display: flex;
>.goods-col {
display: flex; > .goods-img {
overflow: hidden;
>.goods-img { flex: 4;
overflow: hidden; }
flex: 4;
} > .goods-detail {
flex: 7;
>.goods-detail { }
flex: 7; }
} }
}
} .goods-detail {
margin: 0 20rpx;
.goods-detail {
margin: 0 20rpx; > .title {
font-size: $font-base;
>.title { color: $font-color-dark;
font-size: $font-base; line-height: 1.5;
color: $font-color-dark; height: 86rpx;
line-height: 1.5; padding: 10rpx 0 0;
height: 86rpx; display: -webkit-box;
padding: 10rpx 0 0; -webkit-box-orient: vertical;
display: -webkit-box; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; overflow: hidden;
-webkit-line-clamp: 2; }
overflow: hidden;
} .promotion {
margin-top: 4rpx;
.promotion { display: flex;
margin-top: 4rpx;
display: flex; div {
span {
div { font-size: 24rpx;
span { color: $light-color;
font-size: 24rpx; margin-right: 10rpx;
color: $light-color; padding: 0 4rpx;
margin-right: 10rpx; border-radius: 2rpx;
padding: 0 4rpx; }
border-radius: 2rpx; }
} }
}
} .store-seller-name {
color: #666;
.store-seller-name { overflow: hidden;
color: #666; display: flex;
overflow: hidden; justify-content: space-between;
display: flex; }
justify-content: space-between;
} .count-config {
padding: 5rpx 0;
.count-config { color: #666;
padding: 5rpx 0; display: flex;
color: #666; font-size: 24rpx;
display: flex; justify-content: space-between;
font-size: 24rpx; }
justify-content: space-between;
} > .price-box {
margin-top: 10rpx;
>.price-box { display: flex;
margin-top: 10rpx; align-items: center;
display: flex; justify-content: space-between;
align-items: center; padding-right: 10rpx;
justify-content: space-between; font-size: 24rpx;
padding-right: 10rpx; color: $font-color-light;
font-size: 24rpx;
color: $font-color-light; > .price {
font-size: 26rpx;
>.price { line-height: 1;
font-size: 26rpx; color: $main-color;
line-height: 1; font-weight: bold;
color: $main-color;
font-weight: bold; /deep/ span:nth-of-type(1) {
font-size: 38rpx;
/deep/ span:nth-of-type(1) { }
font-size: 38rpx; }
} }
} }
}
}
</style> </style>

View File

@ -15,6 +15,11 @@ export default {
}, },
}; };
}, },
onReachBottom(){
//
uni.$emit('onReachBottom',true)
},
onPullDownRefresh() { onPullDownRefresh() {
this.$refs.tpl.init(); this.$refs.tpl.init();

View File

@ -1,21 +1,38 @@
<template> <template>
<div class="layout"> <div class="layout">
<u-sticky> <u-sticky>
<div class="goods-cell-title"> <div class="goods-cell-title">
<div class="goods-item-title" :class="{ 'selected-title': selected.index == index }" <div
@click="handleClickTitle(title, index)" v-for="(title, index) in res.list[0].titleWay" :key="index"> class="goods-item-title"
:class="{ 'selected-title': selected.index == index }"
@click="handleClickTitle(title, index)"
v-for="(title, index) in res.list[0].titleWay"
:key="index"
>
<h4 class="h4">{{ title.title }}</h4> <h4 class="h4">{{ title.title }}</h4>
<div>{{ title.desc }}</div> <div>{{ title.desc }}</div>
</div> </div>
</div> </div>
</u-sticky> </u-sticky>
<div class="goods-list"> <div class="goods-list">
<div v-if="item.___index != undefined ? (selected.index == item.___index) : ( selected.val == item.type)" <div
@click="handleClick(item)" class="goods-item" v-for="(item, item_index) in res.list[0].listWay" v-if="
:key="item_index"> item.___index != undefined
? selected.index == item.___index
: selected.val == item.type
"
@click="handleClick(item)"
class="goods-item"
v-for="(item, item_index) in res.list[0].listWay"
:key="item_index"
>
<div class="goods-img"> <div class="goods-img">
<u-image :src="item.img" height="350rpx" mode="aspectFit" width="100%"> <u-image
:src="item.img"
height="350rpx"
mode="aspectFit"
width="100%"
>
<u-loading slot="loading"></u-loading> <u-loading slot="loading"></u-loading>
</u-image> </u-image>
</div> </div>
@ -24,9 +41,42 @@
{{ item.title }} {{ item.title }}
</div> </div>
<div class="goods-bottom"> <div class="goods-bottom">
<div class="goods-price"> ¥<span>{{ $options.filters.goodsFormatPrice(item.price )[0] }} </span>.{{ <div class="goods-price">
$options.filters.goodsFormatPrice(item.price)[1] ¥<span
}}</div> >{{ $options.filters.goodsFormatPrice(item.price)[0] }} </span
>.{{ $options.filters.goodsFormatPrice(item.price)[1] }}
</div>
</div>
</div>
</div>
<div
v-if="res.list[0].titleWay[selected.index].bindCategory && goodsData.length"
v-for="(item, index) in goodsData"
:key="index"
class="goods-item"
@click="handleClick(item)"
>
<div class="goods-img">
<u-image
:src="item.thumbnail"
height="350rpx"
mode="aspectFit"
width="100%"
>
<u-loading slot="loading"></u-loading>
</u-image>
</div>
<div class="goods-desc">
<div class="goods-title">
{{ item.goodsName }}
</div>
<div class="goods-bottom">
<div class="goods-price">
¥<span
>{{ $options.filters.goodsFormatPrice(item.price)[0] }} </span
>.{{ $options.filters.goodsFormatPrice(item.price)[1] }}
</div>
</div> </div>
</div> </div>
</div> </div>
@ -34,6 +84,7 @@
</div> </div>
</template> </template>
<script> <script>
import { getGoodsList } from "@/api/goods.js";
export default { export default {
title: "商品分类以及商品", title: "商品分类以及商品",
data() { data() {
@ -42,21 +93,43 @@ export default {
index: 0, index: 0,
val: "", val: "",
}, },
params: {
pageNumber: 1,
pageSize: 100,
categoryId: "",
},
goodsData: [], //
goodsResult:"", //es
}; };
}, },
props: ["res"], props: ["res","enableBottomLoad"],
watch: { watch: {
res: { res: {
handler(val) { handler(val) {
// selected // selected
if (val) { if (val) {
this.selected.val = this.res.list[0].listWay[0].type; console.log(val)
//
this.selected.val = this.res.list[0].listWay[0] ? this.res.list[0].listWay[0].type: '';
//
this.res.list[0].titleWay[0].bindCategory ? this.initGoods(this.res.list[0].titleWay[0]) : ''
} }
}, },
immediate: true, immediate: true,
}, },
}, },
mounted() {}, mounted() {
uni.$on('onReachBottom',()=>{
if(this.enableBottomLoad && this.goodsResult.totalElements >= this.params.pageNumber * this.params.pageSize){
this.params.pageNumber++
this.initGoods(this.res.list[0].titleWay[this.selected.index])
}
})
},
destroyed(){
uni.$off('onReachBottom')
},
methods: { methods: {
handleClick(item) { handleClick(item) {
uni.navigateTo({ uni.navigateTo({
@ -66,9 +139,25 @@ export default {
closeGoods(val, index) { closeGoods(val, index) {
this.res.list[0].listWay.splice(index, 1); this.res.list[0].listWay.splice(index, 1);
}, },
async initGoods(val) {
if(this.enableBottomLoad) this.params.pageSize = 20
val ? this.params.categoryId = val.bindCategory.id : '';
const res = await getGoodsList(this.params);
if (res.data.success) {
this.goodsResult = res.data.result
const result = res.data.result.content.map(item=>item.content)
this.goodsData.push(...result);
console.log(this.goodsData)
}
},
handleClickTitle(val, index) { handleClickTitle(val, index) {
this.selected.index = index; this.selected.index = index;
this.selected.val = val.title; this.selected.val = val.title;
if (val.bindCategory) {
this.params.pageNumber = 1
this.goodsData = []
this.initGoods(val);
}
}, },
}, },
}; };
@ -151,7 +240,7 @@ $w_94: 94%;
margin: 0 auto; margin: 0 auto;
> .goods-title { > .goods-title {
font-size: 24rpx; font-size: 24rpx;
height: 70rpx; height: 67rpx;
display: -webkit-box; display: -webkit-box;
font-weight: 500; font-weight: 500;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
@ -165,11 +254,10 @@ $w_94: 94%;
> .goods-price { > .goods-price {
line-height: 2; line-height: 2;
color: $main-color; color: $main-color;
>span{ > span {
font-size: 42rpx; font-size: 42rpx;
} }
} }
} }
} }
</style> </style>

View File

@ -42,7 +42,7 @@
<textPicture v-if="item.type == 'textPicture'" :res="item.options" /> <textPicture v-if="item.type == 'textPicture'" :res="item.options" />
<menuLayout v-if="item.type == 'menu'" :res="item.options" /> <menuLayout v-if="item.type == 'menu'" :res="item.options" />
<flexOne v-if="item.type == 'flexOne'" :res="item.options" /> <flexOne v-if="item.type == 'flexOne'" :res="item.options" />
<goods v-if="item.type == 'goods'" :res="item.options" /> <goods :enableBottomLoad="enableLoad" v-if="item.type == 'goods'" :res="item.options" />
<group v-if="item.type == 'group'" :res="item.options" /> <group v-if="item.type == 'group'" :res="item.options" />
<notice v-if="item.type == 'notice'" :res="item.options" /> <notice v-if="item.type == 'notice'" :res="item.options" />
<promotions v-if="item.type == 'promotionDetail'" :res="item.options" /> <promotions v-if="item.type == 'promotionDetail'" :res="item.options" />
@ -85,6 +85,7 @@ export default {
config, config,
pageData: "", // pageData: "", //
isIos: "", isIos: "",
enableLoad:false, //
}; };
}, },
components: { components: {
@ -124,8 +125,12 @@ export default {
this.pageData = ""; this.pageData = "";
getFloorData().then((res) => { getFloorData().then((res) => {
if (res.data.success) { if (res.data.success) {
this.pageData = JSON.parse(res.data.result.pageData); const result = JSON.parse(res.data.result.pageData)
console.log(this.pageData); this.pageData = result;
if(result.list.length){
//
result.list[result.list.length-1] ? result.list[result.list.length-1].model == 'goods' ? this.enableLoad = true : '' : ''
}
} }
}); });
}, },