| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621 |
- <template>
- <layout>
- <!-- #ifdef MP-WEIXIN -->
- <uv-navbar
- :fixed="false"
- :title="title"
- left-arrow
- @leftClick="$onClickLeft"
- />
- <!-- #endif -->
- <view class="container" v-if="!loading">
- <view class="main">
- <view class="nav">
- <view class="header" v-if="isScan">
- <view class="mr-1">
- <image :src="store.image" class="rounded-circle" style="width:80rpx ; height: 80rpx; "></image>
- </view>
- <view class="left" style="">
- <view class="store-name" @click="selectShop()">
- <text style="font-size: 26rpx;">{{ store.name }}</text>
- </view>
- <view class="store-location">
- <text>{{ store.address }}</text>
- </view>
- </view>
- <view class="right flex flex-column" style="background-color: #ffffff;color: black;" >
- <view>桌位号:{{ desk.number }}</view>
- <view class="mt-1"> 人数:{{ desk.people }}人</view>
- </view>
- </view>
- <view class="header" v-else>
- <view class="mr-1"><image :src="store.image" class="rounded-circle" style="width:80rpx ; height: 80rpx; "></image></view>
- <view class="left" v-if="orderType == 'takein'" style="">
- <view class="store-name" @click="selectShop()">
- <text>{{ store.name }}</text>
- <view class="iconfont iconarrow-right"></view>
- </view>
- <view class="store-location">
- <text class="font-weight-bold">自取</text> <text class="px-1">|</text><text>距离:{{kmUnit(store.dis)}}</text>
- </view>
- </view>
- <view class="left overflow-hidden" v-else>
- <view class="store-name" @click="selectShop()">
- <view class="flex flex-column">
- <view class="flex align-center">
- <text>{{ store.name }}</text>
- <view class="iconfont iconarrow-right"></view>
- </view>
- <view class="store-location">
- <text class="font-weight-bold">外卖</text> <text class="px-1">|</text><text>配送距离:{{store.distance}}km</text>
- </view>
- </view>
-
- </view>
- </view>
- </view>
- <view v-if="isShowAd" class="pl-1 pr-2">
- <uv-swiper height="150" imgMode="aspectFill" :list="toArrImgs(store.images)" indicatorMode="dot" indicatorStyle="bottom"></uv-swiper>
- </view>
- </view>
-
- <!-- #ifdef H5 -->
- <view class="content"
- :style="{height: 'calc(100vh - 300rpx + '+(store.notice ? '0rpx':'60rpx')+')'}">
- <!-- #endif -->
- <!-- #ifndef H5 -->
- <view class="content" :style="{height: 'calc(100vh - 350rpx + '+(store.notice ? '0rpx':'60rpx')+')'}">
- <!-- #endif -->
- <scroll-view class="menus" :scroll-into-view="menuScrollIntoView" scroll-with-animation scroll-y>
- <view class="wrapper">
- <view class="menu" :id="`menu-${item.id}`" :class="{'current': item.id === currentCateId}"
- v-for="(item, index) in goods" :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>
- <!-- goods list begin -->
- <scroll-view class="goods" scroll-with-animation scroll-y :scroll-top="cateScrollTop"
- @scroll="handleGoodsScroll" @scrolltoupper="goBotttom">
- <view class="wrapper">
- <view class="list">
- <!-- category begin -->
- <view class="category" v-for="(item, index) in goods" :key="index"
- :id="`cate-${item.id}`">
- <view class="title">
- <text>{{ item.name }}</text>
- <image mode="aspectFill" :src="item.picUrl" class="icon"></image>
- </view>
- <view class="items">
- <!-- 商品 begin -->
- <view class="good" v-for="(good, key) in item.goodsList" :key="key"
- :class="{'backgroud-grey': good.stock <= 0}">
- <image mode="aspectFill" :src="good.image" class="image"
- @tap="goDetail(good.id)"></image>
- <view class="right">
- <text class="name" @tap="goDetail(good.id)">{{ good.storeName }}</text>
- <text class="tips">{{ good.storeInfo }}</text>
- <view class="price_and_action">
- <text class="price">¥{{ good.price }}</text>
- <view class="btn-group" v-if="good.stock > 0 && good.productAttr.length >= 1 && good.productAttr[0].attrValues != '默认'">
- <button type="primary" class="btn property_btn"
- hover-class="none" size="mini"
- @tap="showGoodDetailModal(item, good)">
- 选规格
- </button>
- <view class="dot" v-show="goodCartNum(good.id)">
- {{ goodCartNum(good.id) }}</view>
- </view>
- <view class="btn-group" v-if="good.stock > 0 && good.productAttr.length == 1 && good.productAttr[0].attrValues == '默认'">
- <button type="default" v-show="goodCartNum(good.id)" plain class="btn reduce_btn"
- size="mini" hover-class="none" @tap="handleReduceFromCart(item, good)">
- <view class="iconfont iconsami-select"></view>
- </button>
- <view class="number" v-show="goodCartNum(good.id)">{{ goodCartNum(good.id) }}</view>
- <button type="primary" class="btn add_btn" size="min" hover-class="none"
- @tap="handleAddToCart(item, good, 1)">
- <view class="iconfont iconadd-select"></view>
- </button>
- </view>
- <view v-if="good.stock == 0">已售罄</view>
- </view>
- </view>
- </view>
- <!-- 商品 end -->
- </view>
- </view>
- <!-- category end -->
- <view style="height: 110rpx;"></view>
- </view>
- </view>
- </scroll-view>
- <!-- goods list end -->
- </view>
- <!-- content end -->
- <!-- 购物车栏 begin -->
- <view class="cart-box" v-if="cart.length > 0 && isCartShow">
- <view class="mark">
- <image src="/static/images/cart.png" class="cart-img" @tap="isScan ? toPay() : openCartPopup()"></image>
- <view class="tag">{{ getCartGoodsNumber }}</view>
- </view>
- <view class="price">¥{{ getCartGoodsPrice }}</view>
- <button type="primary" class="pay-btn" @tap="toPay" :disabled="disabledPay">
- {{ disabledPay ? `差${spread}元起送` : '去结算' }}
- </button>
- </view>
- <!-- 购物车栏 end -->
- </view>
- <!-- 商品详情模态框 begin -->
- <modal :show="goodDetailModalVisible" class="good-detail-modal" color="#5A5B5C" width="90%" custom
- padding="0rpx" radius="12rpx">
- <view class="cover">
- <view class="btn-group">
- <image src="/static/images/menu/close.png" @tap="closeGoodDetailModal"></image>
- </view>
- </view>
- <scroll-view class="detail" scroll-y>
- <view v-if="good.image" class="image">
- <image :src="good.image"></image>
- </view>
- <view class="wrapper">
- <view class="basic">
- <view class="name">{{ good.storeName }}</view>
- <view class="tips flex justify-between">{{ good.storeInfo }}</view>
- </view>
- <view class="properties">
- <view class="property" v-for="(item, index) in good.productAttr" :key="index">
- <view class="title">
- <text class="name">{{ item.attrName }}</text>
- </view>
- <view class="values">
- <view class="value" v-for="(value, key) in item.attrValueArr" :key="key"
- :class="{'default': value == newValue[index]}"
- @tap="changePropertyDefault(index, key,false)">
- {{ value }}
- </view>
- </view>
- </view>
- </view>
- </view>
- </scroll-view>
- <view class="action">
- <view class="left">
- <view class="price">¥{{ good.price }}</view>
- <view class="props">
- {{ good.valueStr }}
- </view>
- </view>
- <view class="btn-group">
- <text style="margin-right: 20rpx;">库存:{{good.stock}} </text>
- <button type="default" plain class="btn" size="mini" hover-class="none"
- @tap="handlePropertyReduce">
- <view class="iconfont iconsami-select"></view>
- </button>
- <view class="number">{{ good.number }}</view>
- <button type="primary" class="btn" size="min" hover-class="none" @tap="handlePropertyAdd">
- <view class="iconfont iconadd-select"></view>
- </button>
- </view>
- </view>
- <view class="add-to-cart-btn" @tap="handleAddToCartInModal">
- <view>加入购物车</view>
- </view>
- </modal>
- <!-- 商品详情模态框 end -->
- <!-- 购物车详情popup -->
- <uv-popup ref="popup" mode="bottom" class="cart-popup" :customStyle="customStyle">
- <template #default>
- <view class="cart-popup">
- <view class="top flex justify-between">
- <text>购物车({{ getCartGoodsNumber }}份)</text>
- <view class="flex align-center"><uv-icon name="trash" size="20"></uv-icon><text @tap="handleCartClear">清空购物车</text></view>
- </view>
- <scroll-view class="cart-list" scroll-y>
- <view class="wrapper">
- <view class="item" v-for="(item, index) in cart" :key="index">
- <view class="left">
- <view class="flex align-center">
- <view>
- <image mode="aspectFill" :src="item.image" style="width: 100rpx;height: 100rpx;"></image>
- </view>
- <view class="ml-2">
- <view class="name">{{ item.name }}</view>
- <view class="props">{{ item.valueStr }}</view>
- <text class="price"><text class="font-size:16rpx">¥</text>{{ item.price }}</text>
- </view>
- </view>
- </view>
- <!-- <view class="center">
- <text>¥{{ item.price }}</text>
- </view> -->
- <view class="right">
- <button type="default" plain size="mini" class="btn" hover-class="none"
- @tap="handleCartItemReduce(index)">
- <view class="iconfont iconsami-select"></view>
- </button>
- <view class="number">{{ item.number }}</view>
- <button type="primary" class="btn" size="min" hover-class="none"
- @tap="handleCartItemAdd(index)">
- <view class="iconfont iconadd-select"></view>
- </button>
- </view>
- </view>
-
- </view>
- </scroll-view>
- </view>
- </template>
- </uv-popup>
- <!-- 购物车详情popup -->
- <uv-toast ref="uToast"></uv-toast>
- </view>
- <!--轻提示-->
- <view class="loading" v-else>
- <!-- <uv-loading-icon color="#DA5650" size=40 mode="circle" ></uv-loading-icon> -->
- <button type="primary" style="z-index: 3001;position: absolute;top: 650rpx;" @click="init"
- >定位最近的门店</button>
- <!-- <uv-toast ref="uToast"></uv-toast> -->
- </view>
- </layout>
- </template>
- <script setup>
- import {
- ref,
- toRefs,
- computed,
- nextTick
- } from 'vue'
- import { useMainStore } from '@/store/store'
- import { storeToRefs } from 'pinia'
- import { onLoad,onShow ,onPullDownRefresh,onHide,onUnload} from '@dcloudio/uni-app'
- import { formatDateTime,kmUnit } from '@/utils/util'
- import {
- shopNearby,
- menuGoods
- } from '@/api/goods'
- import {
- syncCart
- } from '@/api/order'
- import { useWebSocket } from '@/hooks/useWebSocket'
- const main = useMainStore()
- const { orderType,address, store,location,isLogin,desk,isScan } = storeToRefs(main)
- const title = ref('点餐')
- const text = ref('滚动通知')
- const goods = ref([])
- const ads = ref([])
- const loading = ref(true)
- const currentCateId = ref(0)
- const cateScrollTop = ref(0)
- const menuScrollIntoView = ref('')
- const cart = ref([])
- const goodDetailModalVisible = ref(false)
- const good= ref({})
- const category = ref({})
- const cartPopupVisible = ref(false)
- const sizeCalcState = ref(false)
- const newValue = ref([])
- const shopAd = ref('')
- const isCartShow = ref(true)
- const isClick = ref(false)
- const popup = ref()
- const isShowAd = ref(true)
- const customStyle = computed(() =>{
- // #ifdef H5
- return {
- bottom:'120rpx'
- }
- // #endif
-
- // #ifdef MP-WEIXIN
- return {
- bottom:'0rpx'
- }
- // #endif
- })
- const goodCartNum = computed(() => { //计算单个饮品添加到购物车的数量
- return (id) => cart.value.reduce((acc, cur) => {
- if (cur.id === id) {
- return acc += cur.number
- }
- return acc
- }, 0)
- })
- const menuCartNum = computed(() =>{
- return (id) => cart.value.reduce((acc, cur) => {
- if (cur.cate_id === id) {
- return acc += cur.number
- }
- return acc
- }, 0)
- })
- const getCartGoodsNumber = computed(() => { //计算购物车总数
- return cart.value.reduce((acc, cur) => acc + cur.number, 0)
- })
- const getCartGoodsPrice = computed(() =>{ //计算购物车总价
- let price = cart.value.reduce((acc, cur) => acc + cur.number * cur.price, 0);
- return parseFloat(price).toFixed(2);
- })
- const disabledPay = computed(() => { //是否达到起送价
- console.log('store.value.minPrice:',store.value.minPrice)
- console.log('orderType.value:',orderType.value)
- console.log('getCartGoodsPrice:',getCartGoodsPrice)
- return orderType.value == 'takeout' && (getCartGoodsPrice.value < parseFloat(store.value.minPrice)) ? true :
- false
- })
- const spread = computed(() => { //差多少元起送
- if (orderType.value != 'takeout') return
- return parseFloat((store.value.minPrice - getCartGoodsPrice.value).toFixed(2))
- })
- // 监听自定义事件
- uni.$on('refreshMenu', () => {
- // 在这里执行onLoad逻辑
- init()
- })
- onPullDownRefresh(() => {
- init()
- })
- onLoad(() => {
- if(isScan.value){
- getProducts()
- }else{
- init();
- }
- refreshCart()
-
-
- })
- onHide(() => {
- // 重新进入要重新计算页面高度,否则有问题
- sizeCalcState.value = false;
- })
- onShow(() => {
- //init();
- refreshCart()
-
- })
- const goDetail = (id) => {
- uni.navigateTo({
- url: '/pages/components/pages/menudetail/menudetail?id=' + id
- })
- }
- const openCartShow = () =>{
- isCartShow.value = false
- }
- const in_array = (search, array) => {
- for (var i in array) {
- if (array[i] == search) {
- return true;
- }
- }
- return false;
- }
- const selectShop = () => {
- uni.navigateTo({
- url: '/pages/components/pages/shop/shop?type=1'
- })
- }
- const uToast = ref()
- const getProducts = async() => {
- let shop = store.value
- if (shop) {
- shop.notice = shop.status == 1 ? shop.notice : '店铺营业时间为:' + formatDateTime(shop.startTime,'hh:mm')+' - '+formatDateTime(shop.endTime,'hh:mm') +
- ',不在营业时间内无法下单';
- // 设置店铺信息
- main.SET_STORE(shop);
- let mygoods = await menuGoods({
- shopId: shop.id
- });
- if (mygoods) {
- goods.value = mygoods;
- currentCateId.value = mygoods[0].id
- refreshCart();
- }
- loading.value = false;
- uni.stopPullDownRefresh();
- }
- }
- const init = async() => { //页面初始化
- loading.value = true;
-
- let error = {},
- result = location.value
- if (!location.value.hasOwnProperty('latitude')) {
- uni.getLocation(({
- type: 'wgs84',
- success: function (res) {
-
- result = {
- latitude: res.latitude,
- longitude: res.longitude
- };
- getShopList(result)
- },
- fail: function (res) {
- uni.showToast({
- title: '获取位置失败,请检查是否开启相关权限',
- duration: 2000,
- icon: 'error'
- });
- // 默认地为你为北京地址
- result = {
- latitude: 39.919990,
- longitude: 116.456270
- };
- getShopList(result)
- },
- complete: function (res) {
- }
- }));
-
-
- return
- }
-
- getShopList(result)
-
-
- }
- const getShopList = async(res) => {
- if (res) {
- main.SET_LOCATION(res);
-
- let shop_id = 0;
- console.log('store.value:',store.value.id)
- if (store.value.id) {
- shop_id = store.value.id;
- }
-
- let shop = await shopNearby({
- lat: res.latitude,
- lng: res.longitude,
- shop_id: shop_id,
- kw: ''
- });
- if (shop) {
- shop.notice = shop.status == 1 ? shop.notice : '店铺营业时间为:' + formatDateTime(shop.startTime,'hh:mm')+' - '+formatDateTime(shop.endTime,'hh:mm') +
- ',不在营业时间内无法下单';
- // 设置店铺信息
- main.SET_STORE(shop);
- let mygoods = await menuGoods({
- shopId: shop.id
- });
- if (mygoods.length > 0) {
- goods.value = mygoods;
- currentCateId.value = mygoods[0].id
- refreshCart();
- }else{
- goods.value = [];
- refreshCart();
- }
- loading.value = false;
- uni.stopPullDownRefresh();
- }
- }
- }
- const refreshCart = () =>{
- if (goods.value && goods.value.length > 0) {
- let newGoods = goods.value;
- cart.value = [];
- let newCart = uni.getStorageSync('cart') || [];
- let tmpCart = [];
- if (newCart) {
- for (let i in newCart) {
- for (let ii in newGoods) {
- for (let iii in newGoods[ii].goodsList) {
- if (newCart[i].id == newGoods[ii].goodsList[iii].id) {
- tmpCart.push(newCart[i]);
- }
- }
- }
- }
- cart.value = tmpCart;
- cartPopupVisible.value = false;
- }
- }
- }
- const openCartPopup = () => { //打开/关闭购物车列表popup
- popup.value.open()
- }
- const takout = (force = false) => {
- if (orderType.value == 'takeout' && force == false) return
- main.SET_ORDER_TYPE('takeout');
- if (!isLogin.value) {
- uni.navigateTo({
- url: '/pages/components/pages/login/login'
- })
- return
- }
- }
- const takein = (force = false) => {
- if (orderType.value == 'takein' && force == false) return
- main.SET_ORDER_TYPE('takein');
- if (!isLogin.value) {
- uni.navigateTo({
- url: '/pages/components/pages/login/login'
- })
- return
- }
- }
- const handleMenuTap = (id) => { //点击菜单项事件
- if (!sizeCalcState.value) {
- calcSize()
- }
- setTimeout(() => {
- cateScrollTop.value = goods.value.find(item => {
- return item.id == id
- }).top
- }, 100);
- currentCateId.value = id
- isClick.value = true
- }
- const goBotttom = () => {
- isShowAd.value = true
- }
- const handleGoodsScroll = ({ detail }) => { //商品列表滚动事件
- isShowAd.value = false
- if (!sizeCalcState.value) {
- calcSize()
- }
- const {
- scrollTop
- } = detail
- let tabs = goods.value.filter(item => item.top <= scrollTop).reverse()
- if (tabs.length > 0) {
- if(isClick.value ){
- //currentCateId.value = tabs[0].id
- }else{
- currentCateId.value = tabs[0].id
- }
- isClick.value = false
- }
- }
- const calcSize = () => {
- let h = 10
- goods.value.forEach(item => {
- let view = uni.createSelectorQuery().select(`#cate-${item.id}`)
-
- view.fields({
- size: true
- }, data => {
- item.top = h
- h += data.height
- item.bottom = h
- }).exec()
- })
- sizeCalcState.value = true
- }
- const handleAddToCart = (cate, newGood, num) =>{ //添加到购物车
- if(store.value.status == 0) {
- uToast.value.show({message:'店铺已经歇业',type: 'error'});
- return;
- }
- const index = cart.value.findIndex(item => {
- if (newGood) {
- return (item.id === newGood.id) && (item.valueStr === good.value.valueStr)
- } else {
- return item.id === newGood.id
- }
- })
- if (index > -1) {
- cart.value[index].number += num
- } else {
- cart.value.push({
- id: newGood.id,
- cate_id: cate.id,
- name: newGood.storeName,
- price: newGood.price,
- number: num,
- image: newGood.image,
- valueStr: good.value.valueStr
- })
- }
- if(isScan.value){
- noticeCartInfo({shopId: store.value.id,deskId:desk.value.id,content: cart.value})
- }
- uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
- }
- const noticeCartInfo = async(cart) => {
- await syncCart(cart)
- }
- const handleReduceFromCart = (item, good) => {
- const index = cart.value.findIndex(item => item.id === good.id)
- cart.value[index].number -= 1
- if (cart.value[index].number <= 0) {
- cart.value.splice(index, 1)
- }
- uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
- }
- const showGoodDetailModal = (item, newGood) => {
- isCartShow.value = true
- good.value = JSON.parse(JSON.stringify({
- ...newGood,
- number: 1
- }))
- category.value = JSON.parse(JSON.stringify(item))
- goodDetailModalVisible.value = true;
- changePropertyDefault(0, 0,true);
- }
- const closeGoodDetailModal = () => { //关闭饮品详情模态框
- goodDetailModalVisible.value = false
- category.value = {}
- good.value = {}
- }
- const changePropertyDefault = (index, key, isDefault) => { //改变默认属性值
- let valueStr = ''
- if(isDefault){
- newValue.value = []
- for(let i = 0;i < good.value.productAttr.length;i++){
- newValue.value[i] = good.value.productAttr[i].attrValueArr[0]
- }
- }else{
- newValue.value[index] = good.value.productAttr[index].attrValueArr[key]
- }
-
- valueStr = newValue.value.join(',')
-
- let productValue = good.value.productValue[valueStr]
- //console.log('productValue:',productValue)
- if(!productValue) {
- let skukey = JSON.parse(JSON.stringify(newValue.value))
- skukey.sort((a, b) => a.localeCompare(b))
- //console.log('skukey:',skukey)
- valueStr = skukey.join(',')
- productValue = good.value.productValue[valueStr]
- }
- good.value.number = 1;
- good.value.price = parseFloat(productValue.price).toFixed(2);
- good.value.stock = productValue.stock;
- good.value.image = productValue.image ? productValue.image : good.value.image;
- good.value.valueStr = valueStr
- }
- const handlePropertyAdd = () => {
- good.value.number += 1
- }
- const handlePropertyReduce = () => {
- if (good.value.number === 1) return
- good.value.number -= 1
- }
- const handleAddToCartInModal = () => {
- if(store.value.status == 0) {
- uToast.value.show({message:'店铺已经歇业',type: 'error'});
- return;
- }
- if (good.value.stock <= 0) {
- uToast.value.show({message:'商品库存不足',type: 'error'});
- return;
- }
- handleAddToCart(category.value, good.value, good.value.number)
- closeGoodDetailModal()
- }
- const handleCartClear = () => { //清空购物车
- uni.showModal({
- title: '提示',
- content: '确定清空购物车么',
- success: ({
- confirm
- }) => {
- if (confirm) {
- popup.value.close()
- cart.value = []
- uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
- }
- }
- })
- }
- const handleCartItemAdd = (index) => {
- cart.value[index].number += 1
- uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
- }
- const handleCartItemReduce = (index) => {
- if (cart.value[index].number === 1) {
- cart.value.splice(index, 1)
- } else {
- cart.value[index].number -= 1
- }
- if (!cart.value.length) {
- cartPopupVisible.value = false
- }
- uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
- }
- const toPay = () => {
- if (!isLogin.value) {
- uni.navigateTo({
- url: '/pages/components/pages/login/login'
- })
- return
- } else {
- if(cart.value.length == 0){
- uToast.value.show({message:'请先去点餐哦',type: 'error'});
- return;
- }
- if(store.value.status == 0) {
- uToast.value.show({message:'店铺已经歇业',type: 'error'});
- return;
- }
- if (store.value.status == 0) {
- uToast.value.show({message:'不在店铺营业时间内',type: 'error'});
- return;
- }
- if(orderType.value == 'takeout' && store.value.distance <= 0){
- uToast.value.show({message:'本店不支持外卖',type: 'error'});
- return;
- }
- // 判断当前是否在配送范围内
- if (orderType.value == 'takeout' && store.value.distance < store.value.far) {
- uToast.value.show({message:'选中的地址不在配送范围',type: 'error'});
- return;
- }
- uni.showLoading({
- title: '加载中'
- })
- uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
-
- if(orderType.value == 'desk'){
- uni.navigateTo({
- url: '/pages/components/pages/cart/cart'
- })
- }else{
- uni.navigateTo({
- url: '/pages/components/pages/pay/pay'
- })
- }
-
- }
- uni.hideLoading()
- }
- const toArrImgs = (str) => {
- return str.split(",");
- }
- function removeCharByReplace(str, char) {
- const regex = new RegExp(char, 'g');
- return str.replace(regex, '');
- }
- </script>
- <style lang="scss" scoped>
- /* #ifdef H5 */
- page {
- height: auto;
- min-height: 100%;
- }
- /* #endif */
-
- .container {
- overflow: hidden;
- position: relative;
- }
-
- .loading {
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
-
- image {
- width: 260rpx;
- height: 260rpx;
- position: relative;
- margin-top: -200rpx;
- /* #ifdef h5 */
- margin-top: 0;
- /* #endif */
- }
- }
-
- .stores {
- width: 100%;
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- margin-bottom: -40rpx;
- .store {
- width: 100%;
- background-color: $bg-color-grey;
- padding: 20rpx;
- display: flex;
- align-items: center;
- margin-bottom: 20rpx;
- border-radius: 6rpx;
-
- .iconfont {
- font-size: 50rpx;
- margin-right: 15rpx;
-
- &.iconradio-button-off {
- color: $text-color-assist;
- }
-
- &.iconradio-button-on {
- color: $color-primary;
- }
- }
-
- .infos {
- flex: 1;
- display: flex;
- flex-direction: column;
- color: $text-color-base;
- overflow: hidden;
-
- .name_and_distance {
- width: 100%;
- display: flex;
- justify-content: space-between;
- margin-bottom: 10rpx;
- overflow: hidden;
-
- .name {
- flex: 1;
- flex-shrink: 0;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- font-size: $font-size-lg;
- }
-
- .distance {
- flex-shrink: 0;
- font-size: $font-size-lg;
- font-weight: bold;
- margin-left: 20rpx;
- }
- }
-
- .street {
- color: $text-color-assist;
- font-size: $font-size-sm;
- }
- }
- }
- }
-
- .main {
- width: 100%;
- height: 100%;
- position: relative;
- }
-
- .nav {
- width: 100%;
- //height: 212rpx;
- //height: 140rpx;
- 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: $font-size-lg;
- margin-bottom: 10rpx;
- .small {
- font-size: $font-size-sm;
- color: $text-color-assist;
- }
- .iconfont {
- margin-left: 10rpx;
- line-height: 100%;
- }
- }
-
- .store-location {
- display: flex;
- justify-content: flex-start;
- align-items: center;
- color: $text-color-assist;
- font-size: $font-size-sm;
-
- .iconfont {
- vertical-align: middle;
- display: table-cell;
- color: $color-primary;
- line-height: 100%;
- }
- }
- }
-
- .right {
- background-color: $bg-color-grey;
- border-radius: 38rpx;
- display: flex;
- align-items: center;
- font-size: $font-size-sm;
- padding: 0 38rpx;
- color: $text-color-assist;
-
- .dinein,
- .takeout {
- position: relative;
- display: flex;
- align-items: center;
- &.active {
- padding: 14rpx 38rpx;
- color: #ffffff;
- background-color: $color-primary;
- //background-color: #5A5B5C;
- 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: $bg-color-primary;
- font-size: $font-size-base;
- color: $color-primary;
- 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 {
- width: 100%;
- height: calc(100vh - 212rpx);
- /* #ifdef H5 */
- height: calc(100vh - 212rpx - 140rpx);
- /* #endif */
- display: flex;
-
- .menus {
- width: 200rpx;
- height: 100%;
- overflow: hidden;
- background-color: $bg-color-grey;
-
- .wrapper {
- width: 100%;
- height: 100%;
-
- .menu {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- padding: 30rpx 20rpx;
- font-size: 26rpx;
- color: $text-color-assist;
- position: relative;
-
- &.current {
- background-color: #ffffff;
- //background-color: red;
- //color: $color-primary;
- font-weight: bold;
- }
-
- .dot {
- position: absolute;
- width: 34rpx;
- height: 34rpx;
- line-height: 34rpx;
- font-size: 22rpx;
- background-color: #e45656;
- //background-color: #5A5B5C;
- color: #ffffff;
- top: 16rpx;
- right: 10rpx;
- border-radius: 100%;
- text-align: center;
- }
- }
- .menu:last-child {
- margin-bottom: 200rpx;
- }
- }
- }
-
- .goods {
- flex: 1;
- height: 100%;
- 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: $font-size-base;
-
- .category {
- width: 100%;
-
- .title {
- padding: 30rpx 0;
- display: flex;
- align-items: center;
- color: $text-color-base;
-
- .icon {
- width: 38rpx;
- height: 38rpx;
- margin-left: 10rpx;
- }
- }
- }
- .category:last-child {
- margin-bottom: 200rpx;
- }
-
- .items {
- display: flex;
- flex-direction: column;
- padding-bottom: -30rpx;
-
- .good {
- display: flex;
- align-items: center;
- //margin-bottom: 30rpx;
- padding: 15rpx 0;
- .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: $font-size-base;
- margin-bottom: 10rpx;
- width: 100%;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- .tips {
- width: 100%;
- height: 40rpx;
- line-height: 40rpx;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- font-size: $font-size-sm;
- color: $text-color-assist;
- margin-bottom: 10rpx;
- }
-
- .price_and_action {
- width: 100%;
- display: flex;
- justify-content: space-between;
- align-items: center;
-
- .price {
- font-size: $font-size-base;
- 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: $font-size-sm;
- 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 $color-primary;
- color: $color-primary;
- font-size: $font-size-sm;
- 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;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- .modal-box {
- max-height: 90vh;
- }
-
- .good-detail-modal {
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: column;
-
- .cover {
- height: 20rpx;
- display: flex;
- justify-content: center;
- align-items: center;
-
- .btn-group {
- position: absolute;
- right: 10rpx;
- top: 0rpx;
- display: flex;
- align-items: center;
- justify-content: space-around;
- z-index: 210;
-
- image {
- width: 80rpx;
- height: 80rpx;
- }
- }
- }
-
- .detail {
- width: 100%;
- min-height: 1vh;
- max-height: calc(90vh - 320rpx - 80rpx - 120rpx);
- position: relative;
-
- .image {
- display: flex;
- justify-content: center;
- align-items: center;
- image {
- width: 260rpx;
- height: 260rpx;
- }
- }
- .wrapper {
- width: 100%;
- height: 100%;
- overflow: hidden;
-
- .basic {
- padding: 0 20rpx 30rpx;
- display: flex;
- flex-direction: column;
- .name {
- font-size: $font-size-base;
- color: $text-color-base;
- margin-bottom: 10rpx;
- }
- .tips {
- font-size: $font-size-sm;
- color: $text-color-grey;
- }
- }
-
- .properties {
- width: 100%;
- border-top: 2rpx solid $bg-color-grey;
- padding: 10rpx 30rpx 0;
- display: flex;
- flex-direction: column;
-
- .property {
- width: 100%;
- display: flex;
- flex-direction: column;
- margin-bottom: 30rpx;
- padding-bottom: -16rpx;
-
- .title {
- width: 100%;
- display: flex;
- justify-content: flex-start;
- align-items: center;
- margin-bottom: 20rpx;
-
- .name {
- font-size: 26rpx;
- color: $text-color-base;
- margin-right: 20rpx;
- }
-
- .desc {
- flex: 1;
- font-size: $font-size-sm;
- color: $color-primary;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- }
-
- .values {
- width: 100%;
- display: flex;
- flex-wrap: wrap;
-
- .value {
- border-radius: 8rpx;
- //background-color: $bg-color-grey;
- border: solid 1rpx;
- padding: 10rpx 35rpx;
- font-size: 26rpx;
- color: $text-color-assist;
- margin-right: 16rpx;
- margin-bottom: 16rpx;
-
- &.default {
- border: solid 2rpx;
- border-color: $color-primary;
- //background-color: $color-primary;
- color: $text-color-base;
- }
- }
- }
- }
- }
- }
- }
-
- .action {
- display: flex;
- align-items: center;
- justify-content: space-between;
- background-color: $bg-color-grey;
- height: 120rpx;
- padding: 0 26rpx;
-
- .left {
- flex: 1;
- display: flex;
- flex-direction: column;
- justify-content: center;
- margin-right: 20rpx;
- overflow: hidden;
-
- .price {
- font-size: $font-size-lg;
- color: $text-color-base;
- }
-
- .props {
- color: $text-color-assist;
- font-size: 24rpx;
- width: 100%;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- }
- .btn-group {
- display: flex;
- align-items: center;
- justify-content: space-around;
-
- .number {
- font-size: $font-size-base;
- width: 44rpx;
- height: 44rpx;
- line-height: 44rpx;
- text-align: center;
- }
-
- .btn {
- padding: 0;
- font-size: $font-size-base;
- width: 44rpx;
- height: 44rpx;
- line-height: 44rpx;
- border-radius: 100%;
- }
- }
- }
-
- .add-to-cart-btn {
- display: flex;
- justify-content: center;
- align-items: center;
- background-color: $color-primary;
- color: $text-color-white;
- font-size: $font-size-base;
- height: 80rpx;
- border-radius: 0 0 12rpx 12rpx;
- }
- }
-
- .cart-box {
- position: fixed;
- bottom: 5rpx;
- /* #ifdef H5 */
- bottom:var(--window-bottom);
- //bottom: 100rpx;
- /* #endif */
- left: 30rpx;
- right: 30rpx;
- height: 80rpx;
- border-radius: 48rpx;
- box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.2);
- background-color: #000;
- display: flex;
- align-items: center;
- justify-content: space-between;
- z-index: 99;
-
- .cart-img {
- width: 83rpx;
- height: 83rpx;
- position: relative;
- //margin-top: -8rpx;
- }
-
- .pay-btn {
- height: 100%;
- padding: 0 30rpx;
- color: #ffffff;
- border-radius: 0 50rpx 50rpx 0;
- display: flex;
- align-items: center;
- font-size: $font-size-base;
- }
-
- .mark {
- padding-left: 46rpx;
- margin-right: 30rpx;
- position: relative;
-
- .tag {
- //background-color: $color-warning;
- background-color: #e45656;;
- color: $text-color-white;
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: $font-size-sm;
- position: absolute;
- right: -10rpx;
- top: 10rpx;
- border-radius: 100%;
- padding: 4rpx;
- width: 35rpx;
- height: 35rpx;
- opacity: 0.9;
- }
- }
-
- .price {
- flex: 1;
- color: #fff;
- }
- }
-
- .cart-popup {
- .top {
- background-color: $bg-color-primary;
- //color: $color-primary;
- color: #5A5B5C;
- padding: 10rpx 30rpx;
- font-size: 24rpx;
- text-align: right;
- }
- .cart-list {
- background-color: #ffffff;
- width: 100%;
- overflow: hidden;
- min-height: 1vh;
- max-height: 60vh;
-
- .wrapper {
- height: 100%;
- display: flex;
- flex-direction: column;
- padding: 0 30rpx;
- //margin-bottom: 10rpx;
-
- .item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 30rpx 0;
- position: relative;
-
- &::after {
- content: ' ';
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- background-color: $border-color;
- height: 2rpx;
- transform: scaleY(0.6);
- }
-
- .left {
- flex: 1;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- margin-right: 30rpx;
-
- .name {
- font-weight: bolder;
- font-size: $font-size-sm;
- color: $text-color-base;
- }
- .props {
- color: $text-color-assist;
- font-size: 24rpx;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .price{
- font-size: $font-size-sm;
- color: #e45656;
- }
- }
-
- .center {
- margin-right: 120rpx;
- font-size: $font-size-base;
- }
-
- .right {
- display: flex;
- align-items: center;
- justify-content: space-between;
-
- .btn {
- width: 46rpx;
- height: 46rpx;
- border-radius: 100%;
- padding: 0;
- text-align: center;
- line-height: 46rpx;
- }
-
- .number {
- font-size: $font-size-base;
- width: 46rpx;
- height: 46rpx;
- text-align: center;
- line-height: 46rpx;
- }
- }
- }
- }
- }
- }
-
- .backgroud-grey {
- background-color: #e1e4e4;
- padding: 15rpx !important;
- }
- </style>
|