Files
砂糖 8015759c65 init
2026-02-07 18:01:13 +08:00

588 lines
16 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<!--店铺切换-->
<Location v-if="storeInfo" :storeInfo="storeInfo"/>
<!-- 搜索框 -->
<Search tips="请输入搜索关键字..." @event="$navTo('pages/search/index')" />
<view class="cate-content dis-flex" v-if="list.length > 0">
<!-- 左侧 分类 -->
<scroll-view class="cate-left f-28" :scroll-y="true" :style="{ height: `${scrollHeight}px` }">
<view v-for="(item, index) in list" :key="index">
<text class="cart-badge" v-if="item.total">{{ item.total }}</text>
<view class="type-nav" :class="{ selected: curIndex == index }" @click="handleSelectNav(index)">
<image class="logo" lazy-load :lazy-load-margin="0" v-if="item.logo" :src="item.logo"></image>
<view class="name">{{ item.name }}</view>
</view>
</view>
</scroll-view>
<!-- 右侧 商品 -->
<scroll-view class="cate-right b-f" :scroll-top="scrollTop" :scroll-y="true" :style="{ height: `${scrollHeight}px` }">
<view v-if="list[curIndex]">
<view class="cate-right-cont">
<view class="cate-two-box">
<view v-if="list[curIndex].goodsList.length" class="cate-cont-box">
<view class="flex-five item" v-for="(item, idx) in list[curIndex].goodsList" :key="idx">
<view class="cate-img">
<image v-if="item.logo" lazy-load :lazy-load-margin="0" :src="item.logo" @click="onTargetGoods(item.id)"></image>
</view>
<view class="cate-info">
<view class="base">
<text class="name text">{{ item.name }}</text>
<text class="stock text">库存:{{ item.stock ? item.stock : 0 }} 已售:{{ item.initSale ? item.initSale : 0 }}</text>
</view>
<view class="action">
<text class="price">{{ item.price ? item.price : 0 }}</text>
<view class="cart">
<view v-if="item.isSingleSpec === 'Y'" class="singleSpec">
<view class="ii do-minus" v-if="item.buyNum" @click="onSaveCart(item.id, '-')"></view>
<view class="ii num" v-if="item.buyNum">{{ (item.buyNum != undefined) ? item.buyNum : 0 }}</view>
<view class="ii do-add" v-if="item.stock > 0" @click="onSaveCart(item.id, '+')"></view>
</view>
<view v-if="item.isSingleSpec === 'N'" class="multiSpec">
<text class="num-badge" v-if="item.buyNum">{{ item.buyNum }}</text>
<view class="select-spec" @click="onShowSkuPopup(2, item.id)">选规格</view>
</view>
</view>
</view>
</view>
</view>
</view>
<empty v-if="!list[curIndex].goodsList.length" :isLoading="isLoading" tips="暂无商品~"></empty>
</view>
</view>
</view>
</scroll-view>
</view>
<!-- 商品SKU弹窗 -->
<SkuPopup v-if="!isLoading" v-model="showSkuPopup" :skuMode="skuMode" :goods="goods" @addCart="onAddCart"/>
<view class="flow-fixed-footer b-f m-top10">
<view class="dis-flex chackout-box">
<view class="chackout-left pl-12">
<view class="col-amount-do">总金额<text class="amount">{{ totalPrice.toFixed(2) }}</text></view>
<view class="col-amount-view">共计{{ totalNum }} </view>
</view>
<view class="chackout-right" @click="doSubmit()">
<view class="flow-btn f-32">去结算</view>
</view>
</view>
</view>
<empty v-if="!list.length" :isLoading="isLoading" />
</view>
</template>
<script>
import { setCartTabBadge, setCartTotalNum } from '@/utils/app'
import * as CartApi from '@/api/cart'
import * as GoodsApi from '@/api/goods'
import * as settingApi from '@/api/setting'
import Search from '@/components/search'
import Empty from '@/components/empty'
import SkuPopup from './components/SkuPopup'
import Location from '@/components/page/location'
const App = getApp()
export default {
components: {
Search,
SkuPopup,
Empty,
Location
},
data() {
return {
goodsCart: [],
totalNum: 0,
totalPrice: 0.00,
// 列表高度
scrollHeight: 500,
// 一级分类:指针
curIndex: 0,
// 内容区竖向滚动条位置
scrollTop: 0,
// 分类列表
list: [],
// 正在加载中
isLoading: true,
showSkuPopup: false,
skuMode: 1,
goods: {},
storeInfo: null
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad() {
const app = this
// 设置分类列表高度
app.setListHeight()
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
const app = this;
// 获取页面数据
app.getPageData();
app.onGetStoreInfo();
uni.getLocation({
type: 'gcj02',
success(res){
uni.setStorageSync('latitude', res.latitude);
uni.setStorageSync('longitude', res.longitude);
app.onGetStoreInfo();
},
fail(e) {
// empty
}
})
},
methods: {
/**
* 获取页面数据
*/
getPageData() {
const app = this
app.isLoading = true
Promise.all([
// 获取分类列表
GoodsApi.cateList(),
// 获取购物车列表
CartApi.list()
])
.then(result => {
// 初始化分类列表数据
app.list = result[0].data;
app.totalNum = result[1].data.totalNum;
app.goodsCart = result[1].data.list;
setCartTotalNum(app.totalNum);
setCartTabBadge();
})
.finally(() => {
app.isLoading = false
app.totalPrice = 0
app.list.forEach(function(item, index) {
let total = 0
item.goodsList.forEach(function(goods, key) {
let totalBuyNum = 0
app.goodsCart.forEach(function(cart){
if (goods.id == cart.goodsId) {
total = total + cart.num
totalBuyNum = totalBuyNum + cart.num
app.totalPrice = app.totalPrice + (cart.goodsInfo.price * cart.num)
}
})
app.$set(app.list[index].goodsList[key], 'buyNum', totalBuyNum)
})
app.$set(app.list[index], 'total', total)
})
})
},
/**
* 获取默认店铺
* */
onGetStoreInfo() {
const app = this
settingApi.systemConfig()
.then(result => {
app.storeInfo = result.data.storeInfo
})
},
/**
* 跳转商品详情
*/
onTargetGoods(goodsId) {
this.$navTo(`pages/goods/detail`, { goodsId })
},
/**
* 设置分类列表高度
*/
setListHeight() {
const app = this
uni.getSystemInfo({
success(res) {
app.scrollHeight = res.windowHeight - 120
}
})
},
// 一级分类:选中分类
handleSelectNav(index) {
const app = this;
app.curIndex = index;
app.scrollTop = 0;
},
// 更新购物车
onSaveCart(goodsId, action) {
const app = this
return new Promise((resolve, reject) => {
CartApi.save(goodsId, action)
.then(result => {
app.getPageData();
resolve(result);
})
.catch(err => {
console.log(err);
})
})
},
// 更新购物车数量
onAddCart(total) {
this.getPageData();
this.$toast("添加购物车成功");
},
// 结算
doSubmit() {
if (this.totalPrice > 0) {
this.$navTo('pages/cart/index')
} else {
this.$error("请先选择商品")
}
},
onShowSkuPopup(skuMode, goodsId) {
const app = this
app.isLoading = true
return new Promise((resolve, reject) => {
GoodsApi.detail(goodsId)
.then(result => {
const goodsData = result.data
if (goodsData.skuList) {
goodsData.skuList.forEach(function(sku, index) {
goodsData.skuList[index].specIds = sku.specIds.split('-')
goodsData.skuList[index].skuId = sku.id
})
}
app.goods = goodsData
app.skuMode = skuMode
app.showSkuPopup = !app.showSkuPopup
console.log(app.skuMode)
app.isLoading = false
resolve(result)
})
.catch(err => reject(err))
})
},
},
/**
* 设置分享内容
*/
onShareAppMessage() {
const app = this
return {
title: _this.templet.shareTitle,
path: '/pages/category/index?' + app.$getShareUrlParams()
}
},
/**
* 分享到朋友圈
* 本接口为 Beta 版本,暂只在 Android 平台支持,详见分享到朋友圈 (Beta)
* https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share-timeline.html
*/
onShareTimeline() {
const app = this
return {
title: _this.templet.shareTitle,
path: '/pages/category/index?' + app.$getShareUrlParams()
}
}
}
</script>
<style>
page {
background: #fff;
}
</style>
<style lang="scss" scoped>
.cate-content {
background: #fff;
margin-top: 118rpx;
/* #ifdef H5 */
margin-top: 124rpx;
/* #endif */
}
.cate-wrapper {
padding: 0 20rpx 20rpx 20rpx;
box-sizing: border-box;
}
/* 分类内容 */
.cate-content {
width: 100%;
}
.cate-left {
flex-direction: column;
display: flex;
width: 200rpx;
color: #444;
height: 100%;
background: #f8f8f8;
margin-bottom: 120rpx;
.cart-badge {
position: absolute;
right: 1rpx;
margin-top: 10rpx;
margin-right: 5rpx;
font-size: 18rpx;
background: #fa5151;
z-index: 999;
text-align: center;
line-height: 28rpx;
color: #ffffff;
border-radius: 50%;
min-width: 32rpx;
padding: 5rpx 13rpx 5rpx 13rpx;
}
}
.cate-right {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
overflow: hidden;
margin-bottom: 80rpx;
}
.cate-right-cont {
width: 100%;
display: flex;
flex-flow: row wrap;
align-content: flex-start;
padding-top: 10rpx;
}
.type-nav {
position: relative;
height: 140rpx;
text-align: center;
z-index: 10;
display: block;
font-size: 26rpx;
padding: 20rpx 0rpx 126rpx 0rpx;
.logo {
width: 60rpx;
height: 60rpx;
border-radius: 60rpx;
margin: 0rpx;
padding: 0rpx;
}
.name {
margin-top: 2rpx;
width: 100%;
overflow-x: hidden;
height: 40rpx;
line-height: 40rpx;
text-align: center;
}
}
.type-nav.selected {
color: #666666;
background: #ffffff;
border-right: none;
border-left: solid 10rpx #f03c3c;
font-weight: bold;
font-size: 28rpx;
}
.cate-cont-box {
margin-bottom: 10rpx;
padding-bottom: 10rpx;
overflow: hidden;
height: auto;
display: block;
.item {
height: 220rpx;
display: block;
padding-top: 5rpx;
border-radius: 3rpx;
margin-bottom: 5rpx;
}
}
.cate-cont-box .cate-img {
padding: 13rpx 10rpx 4rpx 10rpx;
display: block;
}
.cate-cont-box .cate-img image {
width: 160rpx;
height: 150rpx;
float: left;
border-radius: 5rpx;
display: block;
margin-top: 5rpx;
}
.cate-cont-box .cate-info {
text-align: left;
display: flex;
flex-direction: column;
font-size: 26rpx;
margin-left: 168rpx;
padding-bottom: 14rpx;
color: #444;
padding: 0 15rpx 30rpx 15rpx;
.base {
height: 100%;
display: block;
.text {
display: block;
float: left;
width: 100%;
}
.name {
font-weight: bold;
width: 100%;
font-size: 26rpx;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.stock {
margin-top: 10rpx;
color: #999;
}
}
.action {
display: block;
height: 50rpx;
.price {
margin-top: 20rpx;
color: #f03c3c;
float: left;
font-size: 32rpx;
font-weight: bold;
}
.cart {
margin-top: 20rpx;
float: right;
font-size: 30rpx;
height: 60rpx;
.ii {
float: left;
text-align: center;
width: 60rpx;
cursor: pointer;
}
.do-add {
background: url('~@/static/icon/add.png') no-repeat;
background-size: 100% 100%;
width: 45rpx;
height: 45rpx;
}
.do-minus {
background-image: url('~@/static/icon/minus.png');
background-size: 100% 100%;
width: 45rpx;
height: 45rpx;
}
.multiSpec {
.num-badge {
position: absolute;
margin-top: 10rpx;
margin-right: 25rpx;
font-size: 18rpx;
background: #f03c3c;
text-align: center;
line-height: 36rpx;
color: #ffffff;
border-radius: 50%;
min-width: 36rpx;
padding: 2rpx;
}
.select-spec {
border: solid 1rpx $fuint-theme;
padding: 10rpx 20rpx 10rpx 36rpx;
font-size: 25rpx;
border-radius: 5rpx;
color: #ffffff;
background: $fuint-theme;
}
}
}
}
}
.cate-two-box {
width: 100%;
padding: 0 2px;
}
// 底部操作栏
.flow-fixed-footer {
position: fixed;
bottom: var(--window-bottom);
width: 100%;
background: #fff;
border-top: 1px solid #eee;
z-index: 11;
padding-top: 8rpx;
.chackout-left {
font-size: 28rpx;
height: 98rpx;
color: #777;
flex: 4;
padding-left: 12px;
text-align: right;
padding-right: 40rpx;
.col-amount-do {
font-size: 35rpx;
margin-top: 5rpx;
margin-bottom:5rpx;
.amount {
color: #f03c3c;
font-weight: bold;
}
}
}
.chackout-right {
font-size: 34rpx;
flex: 2;
}
// 提交按钮
.flow-btn {
background: linear-gradient(to right, $fuint-theme, $fuint-theme);
color: #fff;
text-align: center;
line-height: 92rpx;
display: block;
font-size: 28rpx;
border-radius: 5rpx;
margin-right: 20rpx;
// 禁用按钮
&.disabled {
background: #ff9779;
}
}
}
</style>