glhcp/uniapp/pages/store_index/store_index.vue

393 lines
9.7 KiB
Vue

<template>
<view class="store-index">
<view class="store-header" :style="{ 'background-image': `url(${shopInfo.background})`}">
<u-navbar :border-bottom="false" :background="{ 'background-image': `url(${shopInfo.background})`, 'background-repeat': 'no-repeat', 'background-size': '100% auto'}"
:back-bg="'rgba(255, 255, 255, 0.45)'" :back-icon-color="'rgb(255,255,255)'" :is-fixed="true">
<view class="store-search flex-1">
<u-search v-model="keyword" bg-color="white" shape="round" placeholder="搜索店内商品" wrap-bg-color="transparent" @search="refresh">
</u-search>
</view>
</u-navbar>
<view class="store-info m-t-20">
<view class="flex row-between">
<view class="flex">
<u-image width="100rpx" height="100rpx" border-radius="50%" :src="shopInfo.logo" />
<view class="m-l-20 flex-col col-top">
<router-link :to="{path: '/pages/store_detail/store_detail', query: {id: shopInfo.id}}">
<view class="lg white line-1 bold" style="width: 420rpx;">
{{shopInfo.name}}
<u-icon name="arrow-right"></u-icon>
</view>
</router-link>
<view class="store-tag xxs m-t-10 white" v-if="shopInfo.type == 1">
自营
</view>
</view>
</view>
<view class="flex row-center white br60 sm flex-none subscribe-btn" :class="{'gray': shopInfo.shop_follow_status === 1}" @tap="changeShopFollowFun">
{{shopInfo.shop_follow_status === 1 ? '已关注' : '+ 关注'}}
</view>
</view>
<view class="sale-info flex row-between m-t-10">
<view class="flex">
<view style="width: 100rpx;" />
<view class="white m-l-20 xs">
在售商品:{{shopInfo.on_sale_count}}件
</view>
</view>
<view class="white xs">
{{shopInfo.visited_num}}人进店
</view>
</view>
</view>
</view>
<view class="content">
<view class="content-wrap">
<view>
<get-coupon :wrap-style="{'border-bottom': '1px solid #E5E5E5'}" :shop-id="shopInfo.id"></get-coupon>
</view>
<view class="store-hot-goods bg-white m-b-20" v-if="shopInfo.goods_list.length">
<view class="store-hot-header flex">
<view class="column-line m-r-20" />
<view class="md" style="font-weight: 500;">
店铺推荐
</view>
</view>
<view class="store-hot-content">
<scroll-view :scroll-x="true">
<view class="goods p-l-20 p-r-20">
<goods-list :list="shopInfo.goods_list" type="row"></goods-list>
</view>
</scroll-view>
</view>
</view>
</view>
<view class="goods-display flex bg-body">
<view class="category-aside">
<u-sticky bg-color="rgba(255, 255, 255, 0)" :enable="enableFix" :offset-top="navHeight" :h5-nav-height="0">
<scroll-view :scroll-y="true" :style="{'height': aslideH + 'px'}">
<view class="aside-item flex row-center" :class="{active: active == -1}" @click="changeActive(-1)">
<view class="xs text-center" style="width: 60rpx" :class="{primary: active == -1}">全部商品</view>
</view>
<view class="aside-item flex row-center" :class="{active: active == index}"
v-for="(item, index) in category" :key="index" @click="changeActive(index)">
<view class="xs text-center" style="width: 60rpx" :class="{primary: active == index}">{{item.name}}</view>
</view>
</scroll-view>
</u-sticky>
</view>
<view class="category-row flex-1">
<u-sticky bg-color="rgba(255, 255, 255, 0)" :enable="enableFix" :offset-top="navHeight" :h5-nav-height="0">
<sort-nav v-model="sortConfig" :show-type="false"></sort-nav>
</u-sticky>
<mescroll-body ref="mescrollRef" @init="mescrollInit" :height="meScrollH" @down="downCallback" @up="upCallback"
:up="upOption" :down="{use: false}">
<view class="bg-white">
<goods-list :list="goodsList" width="285rpx"></goods-list>
</view>
</mescroll-body>
</view>
</view>
</view>
<loading-view v-if="isFirstLoading"></loading-view>
</view>
</template>
<script>
import {
mapGetters
} from 'vuex'
import {
getShopInfo,
getShopGoodsCategory,
changeShopFollow
} from '@/api/shop'
import {getGoodsList} from '@/api/store'
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
export default {
mixins: [MescrollMixin], // 使用mixin
data() {
return {
isFirstLoading: true,
navOpacity: 0,
shopInfo: {
goods_list: []
},
category: [],
active: -1,
upOption: {
auto: false,
empty: {
icon: '/static/images/goods_null.png',
tip: "暂无商品",
}
},
goodsList: [],
sortConfig: {
priceSort: '',
saleSort: '',
},
keyword: '',
sys: {},
enableFix: true,
id: ''
}
},
async onLoad() {
this.id = this.$Route.query.id
this.sys = uni.getSystemInfoSync()
await this.getShopInfoFun()
await this.getShopGoodsCategoryFun()
this.isFirstLoading = false
this.mescroll.resetUpScroll();
},
onHide() {
// #ifdef H5
this.enableFix = false
// #endif
},
onShow() {
// #ifdef H5
this.enableFix = true
// #endif
},
onShareAppMessage() {
return {
title: this.shopInfo.name,
path: `pages/store_index/store_index?invite_code=${this.inviteCode}&id=${this.id}`
};
},
methods: {
async changeShopFollowFun() {
if (!this.isLogin) return this.$Router.push('/pages/login/login')
const {code, msg} = await changeShopFollow({
shop_id: this.id
})
if(code == 1) {
this.$toast({
title: msg
})
this.getShopInfoFun()
}
},
async getShopInfoFun() {
const {
data,
code
} = await getShopInfo({
shop_id: this.id
})
if (code == 1) {
this.shopInfo = data
}
},
async getShopGoodsCategoryFun() {
const {
data,
code
} = await getShopGoodsCategory({
shop_id: this.id
})
if (code == 1) {
this.category = data
}
},
changeActive(index) {
this.active = index
this.refresh()
},
refresh() {
this.goodsList = []
this.mescroll.resetUpScroll();
},
/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
upCallback(page) {
//联网加载数据
let {
goodsList,
keyword,
sortConfig: {
priceSort,
saleSort,
},
active,
category
} = this;
const pageNum = page.num; // 页码, 默认从1开始
const pageSize = page.size; // 页长, 默认每页10条
const cateId = active == -1 ? '' : category[active].id
getGoodsList({
page_size: pageSize,
page_no: pageNum,
shop_id: this.id,
shop_cate_id: cateId,
sort_by_price: priceSort,
sort_by_sales: saleSort,
keyword
}).then(({
data
}) => {
let curPageData = data.lists;
let curPageLen = curPageData.length;
let hasNext = !!data.more;
if (page.num == 1) this.goodsList = [];
this.goodsList = this.goodsList.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
})
},
},
computed: {
...mapGetters(['sysInfo']),
navHeight() {
return this.sysInfo.navHeight + 'px'
},
aslideH() {
const {
windowHeight,
navHeight,
safeArea
} = this.sys
if(!safeArea) return 0
return windowHeight - this.sysInfo.navHeight
},
meScrollH() {
return this.aslideH - uni.upx2px(80) + 'px'
}
},
watch:{
sortConfig: {
deep: true,
handler(val) {
console.log(val)
this.refresh()
}
}
}
}
</script>
<style lang="scss">
page {
padding: 0;
}
.store-index {
.store-header {
padding-bottom: 60rpx;
background-repeat: no-repeat;
background-size: 100% auto;
.store-info {
padding-right: 30rpx;
padding-left: 24rpx;
.store-tag {
background: linear-gradient(267deg, #FF2C3C 0%, #F52E99 100%);
border-radius: 6rpx;
padding: 4rpx 9rpx;
}
.subscribe-btn {
background: linear-gradient(97deg, #FF5784 0%, #FF2C3C 100%);
height: 52rpx;
width: 128rpx;
&.gray {
background: #ccc;
}
}
}
}
.content {
margin-top: -30rpx;
.content-wrap {
border-radius: 20rpx 20rpx 0px 0px;
overflow: hidden;
}
.store-hot-goods {
overflow: hidden;
.store-hot-header {
padding: 20rpx;
.column-line {
width: 6rpx;
height: 32rpx;
background-color: $-color-primary;
}
}
.store-hot-content {
.goods {
display: inline-block;
}
.hot-goods-item {
width: 200rpx;
.hot-goods-info {
.hot-goods-price {
margin-top: 5rpx;
}
}
}
}
}
.goods-display {
.category-aside {
width: 120rpx;
align-self: flex-start;
.aside-item {
width: 120rpx;
padding: 20rpx 0;
&.active {
position: relative;
background-color: $-color-white;
&::before {
content: '';
width: 3rpx;
height: 80rpx;
background-color: $-color-primary;
position: absolute;
left: 0;
}
}
}
}
.category-row {
align-self: flex-start;
width: 630rpx;
.sort-tool-bar {
.sort-item {
flex: 1;
height: 80rpx;
}
}
.goods-lists {
padding: 20rpx;
.item {
width: 285rpx;
border-radius: 10rpx;
overflow: hidden;
&:nth-of-type(2n) {
margin-left: 20rpx;
}
.goods-info {
padding: 10rpx;
}
}
}
}
}
}
}
</style>