【新增】前端【分类】模块集成仿点餐模式,并添加了可后台选择。

This commit is contained in:
大灰灰
2022-09-27 00:08:31 +08:00
parent 2d7001c58c
commit a5688502bf
4 changed files with 434 additions and 13 deletions

View File

@@ -17,3 +17,95 @@
}
}
}
.main { width: 100%; height: 100%; position: relative; display: flex; flex-direction: column; }
.nav { width: 100%; height: 212rpx; flex-shrink: 0; display: flex; flex-direction: column;
.header { width: 100%; display: flex; align-items: center; justify-content: space-between; padding: 20rpx; background-color: #ffffff; height: 140rpx;
.left { flex: 1; display: flex; flex-direction: column;
.store-name { display: flex; justify-content: flex-start; align-items: center; font-size: 32rpx; margin-bottom: 10rpx;
.iconfont { margin-left: 10rpx; line-height: 100%; }
}
.store-location { display: flex; justify-content: flex-start; align-items: center; color: #919293; font-size: 24rpx;
.iconfont { vertical-align: middle; display: table-cell; color: #ADB838; line-height: 100%; }
}
}
.right { background-color: #F5F5F5; border-radius: 38rpx; display: flex; align-items: center; font-size: 24rpx; padding: 0 38rpx; color: #919293;
.dinein, .takeout { position: relative; display: flex; align-items: center;
&.active { padding: 14rpx 38rpx; color: #ffffff; background-color: #E8EACF; border-radius: 38rpx; }
}
.takeout { margin-left: 20rpx; height: 100%; flex: 1; padding: 14rpx 0; }
.dinein.active { margin-left: -38rpx; }
.takeout.active { margin-right: -38rpx; }
}
}
.coupon { flex: 1; width: 100%; background-color: #E8EACF; font-size: 28rpx; color: #ADB838; padding: 0 20rpx; display: flex; align-items: center; overflow: hidden;
.title { flex: 1; margin-left: 10rpx; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.iconfont { line-height: 100%; }
}
}
.content { flex: 1; overflow: hidden; width: 100%; display: flex;
.menus { width: 200rpx; overflow: hidden; background-color: #F5F5F5;
.wrapper { width: 100%; height: 100%;
.menu { display: flex; align-items: center; justify-content: flex-start; padding: 30rpx 20rpx; font-size: 26rpx; color: #919293; position: relative;
&:nth-last-child(1) { margin-bottom: 130rpx; }
&.current { background-color: #ffffff; color: #5A5B5C; }
.dot { position: absolute; width: 34rpx; height: 34rpx; line-height: 34rpx; font-size: 22rpx; background-color: #ADB838; color: #ffffff; top: 16rpx; right: 10rpx; border-radius: 100%; text-align: center; }
}
}
}
.goods { flex: 1; overflow: hidden; background-color: #ffffff;
.wrapper { width: 100%; height: 100%; padding: 20rpx;
.ads { height: calc(300 / 550 * 510rpx);
image { width: 100%; height: 100%; border-radius: 8rpx; }
}
.list { width: 100%; font-size: 28rpx; padding-bottom: 30rpx;
.category { width: 100%;
.title { padding: 30rpx 0; display: flex; align-items: center; color: #5A5B5C;
.icon { width: 38rpx; height: 38rpx; margin-left: 10rpx; }
}
}
.items { display: flex; flex-direction: column; padding-bottom: -30rpx;
.good { display: flex; align-items: center; margin-bottom: 30rpx;
.image { width: 160rpx; height: 160rpx; margin-right: 20rpx; border-radius: 8rpx; }
.right { flex: 1; height: 160rpx; overflow: hidden; display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; padding-right: 14rpx;
.name { font-size: 28rpx; margin-bottom: 10rpx; }
.tips { width: 100%; height: 40rpx; line-height: 40rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 24rpx; color: #919293; margin-bottom: 10rpx; }
.price_and_action { width: 100%; display: flex; justify-content: space-between; align-items: center;
.price { font-size: 28rpx; font-weight: 600; }
.btn-group { display: flex; justify-content: space-between; align-items: center; position: relative;
.btn { padding: 0 20rpx; box-sizing: border-box; font-size: 24rpx; height: 44rpx; line-height: 44rpx;
&.property_btn { border-radius: 24rpx; }
&.add_btn,
&.reduce_btn { padding: 0; width: 44rpx; border-radius: 44rpx; }
}
.dot { position: absolute; background-color: #ffffff; border: 1px solid #ADB838; color: #ADB838; font-size: 24rpx; width: 36rpx; height: 36rpx; line-height: 36rpx; text-align: center; border-radius: 100%; right: -12rpx; top: -10rpx; }
.number { width: 44rpx; height: 44rpx; line-height: 44rpx; text-align: center; }
}
}
}
}
}
}
}
}
}
.cart-box { position: fixed; bottom: 30rpx; left: 30rpx; right: 30rpx; height: 96rpx; border-radius: 48rpx; box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.2); background-color: #FFFFFF; display: flex; align-items: center; justify-content: space-between; z-index: 10;
.cart-img { width: 96rpx; height: 96rpx; position: relative; margin-top: -48rpx; }
.pay-btn { height: 100%; padding: 0 30rpx; color: #FFFFFF; border-radius: 0 50rpx 50rpx 0; display: flex; align-items: center; font-size: 28rpx; }
.mark { padding-left: 46rpx; margin-right: 30rpx; position: relative;
.tag { background-color: #FAB714; color: #ffffff; display: flex; justify-content: center; align-items: center; font-size: 24rpx; position: absolute; right: -10rpx; top: -50rpx; border-radius: 100%; padding: 4rpx; width: 40rpx; height: 40rpx; opacity: .9; }
}
.price { flex: 1; color: #5A5B5C; }
}
.text-color-base { color: #5A5B5C; }
text-color-assist { color: #919293; }
.overflow-hidden { overflow: hidden !important; }
.text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

View File

@@ -52,13 +52,75 @@
</scroll-view>
</block>
</view>
<view class="u-menu-wrap coreshop-flex-direction-row" v-if="CateStyle==4">
<view class="main" :style="'height:' + scorllH+'px;'">
<view class="content" :style="'height:' + scorllH+'px;'">
<scroll-view class="menus" scroll-with-animation scroll-y :scroll-top="headerH" :style="'height:' + scorllH+'px;'">
<view class="wrapper">
<view class="menu" :id="`menu-${item.id}`" :class="{'current': item.id === currentCateId}" v-for="(item, index) in menus"
:key="index" @tap="handleMenuTap(item.id)">
<text>{{ item.name }}</text>
<!--<view class="dot" v-show="menuCartNum(item.id)">{{ menuCartNum(item.id) }}</view>-->
</view>
</view>
</scroll-view>
<scroll-view class="goods" scroll-with-animation scroll-y :scroll-top="headerH" :style="'height:' + scorllH+'px;'">
<view class="wrapper">
<view class="list">
<view class="category" v-for="(good, key) in goodsList" :key="key" :id="`cate-${good.id}`">
<view class="items">
<view class="good">
<image :src="good.images" class="image" @tap="goGoodsDetail(good.id)"></image>
<view class="right">
<text class="name u-line-1" @tap="goGoodsDetail(good.id)">{{ good.name }}</text>
<text class="tips u-line-1" @tap="goGoodsDetail(good.id)">{{ good.brief }}</text>
<view class="price_and_action">
<text class="price">{{ good.price }}</text>
<view class="btn-group">
<button type="primary" class="btn property_btn" hover-class="none" size="mini" @tap="showGoodSkuModal(good)">
选规格
</button>
<!--<view class="dot">111</view>-->
</view>
</view>
</view>
</view>
</view>
</view>
<u-loadmore :status="status" :icon-type="iconType" :load-text="loadText" margin-top="20" margin-bottom="20" />
</view>
</view>
</scroll-view>
</view>
<!-- 购物车栏 end -->
</view>
<vk-data-goods-sku-popup ref="skuPopup"
v-model="skuKey"
border-radius="20"
:amount-type="0"
:localdata="goodsSkuInfo"
:mode="skuMode"
@open="onOpenSkuPopup"
@close="onCloseSkuPopup"
@add-cart="addCart"
@buy-now="buyNow"></vk-data-goods-sku-popup>
</view>
<!-- 购物车栏 begin -->
<view class="cart-box">
<view class="mark">
<image src="https://files.cdn.coreshop.cn/static/template/diancan/images/cart.png" class="cart-img"></image>
<view class="tag">{{cartNums}}</view>
</view>
<view class="price">{{cartMoney}}</view>
<button type="primary" class="pay-btn" @tap="redirectCart" :disabled="cartNums<=0">去结算</button>
</view>
<!-- 登录提示 -->
<coreshop-login-modal></coreshop-login-modal>
</view>
</template>
<script>
import { mapMutations, mapActions, mapState } from 'vuex';
export default {
data() {
@@ -70,28 +132,89 @@
menuItemHeight: 0, // 左边菜单item的高度,
beans: [],
isChild: false,
searchKey: ''
searchKey: '',
headerH: 0,
scorllH: 0, //滚动区域全屏
cartNums: 0, // 购物车数量
cartMoney: 0, // 购物车数量
menus: [],//所有分类
goodsList: [], //所有商品
menuScrollIntoView: '',
good: {},
currentCateId: 0,//默认分类
scrollTop: 0,
loadStatus: 'loadmore',
loadIconType: 'flower',
loadText: {
loadmore: '轻轻上拉',
loading: '努力加载中',
nomore: '实在没有了'
},
type: 2, // 1加入购物车 2购买
cartType: this.$globalConstVars.paymentType.common,
page: 1,
limit: 10,
// 是否打开SKU弹窗
skuKey: false,
// SKU弹窗模式
skuMode: 1,
// 后端返回的商品信息
goodsSkuInfo: {},
}
},
computed: {
...mapState({
hasLogin: state => state.hasLogin,
userInfo: state => state.userInfo,
}),
hasLogin: {
get() {
return this.$store.state.hasLogin;
},
set(val) {
this.$store.commit('hasLogin', val);
}
},
userInfo: {
get() {
return this.$store.state.userInfo;
},
set(val) {
this.$store.commit('userInfo', val);
}
},
CateStyle() {
return this.$store.state.config.cateStyle ? this.$store.state.config.cateStyle : 3;
}
},
onShow() {
uni.getSystemInfo({
success: (e) => {
// #ifndef MP
this.StatusBar = e.statusBarHeight;
if (e.platform == 'android') {
this.headerH = e.statusBarHeight + 50;
} else {
this.headerH = e.statusBarHeight + 45;
};
// #endif
this.scorllH = e.windowHeight - e.statusBarHeight - 50;
}
})
this.categories();
// 获取购物车数量
if (this.$store.state.config.cateStyle == 4) {
this.getCartNums();
}
},
onReachBottom() {
if (this.loadStatus != 'nomore') {
this.getGoods();
}
},
methods: {
categories() {
this.$u.api.categories().then(res => {
if (res.status) {
this.tabbar = res.data;
}
});
},
getImg() {
return Math.floor(Math.random() * 35);
},
// 点击左边的栏目切换
async swichMenu(index) {
if (index == this.current) return;
@@ -131,7 +254,209 @@
} else {
this.$refs.uToast.show({ message: '请输入查询关键字', type: 'warning', })
}
}
},
categories() {
this.$u.api.categories().then(res => {
if (res.status) {
this.tabbar = res.data;
if (this.$store.state.config.cateStyle == 4) {
this.menus = res.data;
if (res.data.length > 0) {
this.currentCateId = res.data[0].id;
}
this.getGoods();
}
}
});
},
// 打开sku弹出
openSkuPopup() {
this.skuKey = true;
},
closeSkuPopup() {
this.skuKey = false;
},
// sku组件监听
onOpenSkuPopup() {
//console.log("监听 - 打开sku组件");
},
onCloseSkuPopup() {
//console.log("监听 - 关闭sku组件");
},
showGoodSkuModal(item) {
console.log(item);
if (item.id) {
this.getGoodsDetail(item.id);
}
},
// 获取商品详情
getGoodsDetail(goodsId) {
uni.showLoading({
title: '加载中'
});
let _this = this;
let data = {
id: goodsId,
data: true
}
// 如果用户已经登录 要传用户token
let userToken = this.$db.get("userToken");
if (userToken) {
this.$u.api.goodsDetailByToken(data).then(res => {
if (res.status == true) {
_this.goodsSkuInfo = res.data.skuList;
_this.openSkuPopup();
uni.hideLoading();
} else {
_this.$refs.uToast.show({
message: res.msg, type: 'error', complete: function () {
uni.navigateBack({
delta: 1
});
}
})
uni.hideLoading();
}
})
} else {
this.$u.api.goodsDetail(data).then(res => {
if (res.status == true) {
_this.goodsSkuInfo = res.data.skuList;
_this.openSkuPopup();
uni.hideLoading();
} else {
_this.$refs.uToast.show({
message: res.msg, type: 'error', complete: function () {
uni.navigateBack({
delta: 1
});
}
})
uni.hideLoading();
}
})
}
},
// 加入购物车按钮
addCart(selectShop) {
//console.log("监听 - 加入购物车");
//console.log(selectShop);
var that = this;
uni.showLoading({
title: '加载中'
});
if (!this.hasLogin) {
uni.hideLoading();
this.$store.commit('showLoginTip', true);
return false;
}
if (selectShop.buy_num > 0) {
let data = {
productId: selectShop._id,
nums: selectShop.buy_num,
type: 1,
}
this.$u.api.addCart(data).then(res => {
if (res.status) {
uni.hideLoading();
that.getCartNums(); // 获取购物车数量
that.$refs.uToast.show({ message: res.msg, type: 'success' });
} else {
that.$u.toast(res.msg);
uni.hideLoading();
}
});
}
that.closeSkuPopup();
},
// 立即购买
buyNow(selectShop) {
//console.log("监听 - 立即购买");
//console.log(selectShop);
var that = this;
uni.showLoading({
title: '加载中'
});
if (!this.hasLogin) {
uni.hideLoading();
this.$store.commit('showLoginTip', true);
return false;
}
if (selectShop.buy_num > 0) {
let data = {
productId: selectShop._id,
nums: selectShop.buy_num,
type: 2,
cartType: this.cartType
}
this.$u.api.addCart(data).then(res => {
if (res.status) {
let cartIds = res.data;
that.$u.route('/pages/placeOrder/index/index?cartIds=' + JSON.stringify(cartIds));
uni.hideLoading();
} else {
this.$u.toast(res.msg);
uni.hideLoading();
}
});
}
that.closeSkuPopup();
},
handleMenuTap(id) {
this.currentCateId = id
this.page = 1;
this.goodsList = [];
this.getGoods();
//this.$nextTick(() => this.cateScrollTop = this.goods.find(item => item.id == id).top)
},
//取得商品数据
getGoods: function () {
uni.showLoading({
title: '加载中'
});
var _this = this;
let data = {
page: this.page,
limit: this.limit,
};
var where = {
catId: this.currentCateId,
};
data.where = JSON.stringify(where);
_this.$u.api.goodsList(data).then(res => {
if (res.status) {
const _list = res.data.list;
_this.goodsList = [..._this.goodsList, ..._list];
if (res.data.totalCount > _this.goodsList.length) {
_this.loadStatus = 'loadmore';
_this.page++;
} else {
// 数据已加载完毕
_this.loadStatus = 'nomore';
}
uni.hideLoading();
} else {
// 接口请求出错了
uni.hideLoading();
this.$u.toast(res.msg);
}
});
},
// 获取购物车数量
getCartNums() {
let userToken = this.$db.get("userToken");
if (userToken && userToken != '') {
// 获取购物车数量
this.$u.api.getCartNumAndMoney().then(res => {
if (res.status) {
this.cartNums = res.data.count;
this.cartMoney = res.data.money;
}
})
}
},
}
}
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

View File

@@ -253,6 +253,10 @@
<input type="radio" lay-filter="cateStyle" name="cateStyle" value="3" title="二级小图" {{d.data.configs['cateStyle']['sValue']==="3" ? 'checked':''}}>
<img src="/static/images/common/two-small.png" onclick="layui.coreHelper.viewImage('/static/images/common/two-small.png')">
</div>
<div class="classifyimg-item">
<input type="radio" lay-filter="cateStyle" name="cateStyle" value="4" title="仿点餐模式" {{d.data.configs['cateStyle']['sValue']==="4" ? 'checked':''}}>
<img src="/static/images/common/diancan.png" onclick="layui.coreHelper.viewImage('/static/images/common/diancan.png')">
</div>
<div class="layui-form-mid layui-word-aux list-tag">
1一级大图分类图标尺寸建议350px*150px<br />
2一级小图分类图标尺寸建议105px*105px<br />