2632 lines
69 KiB
Vue
2632 lines
69 KiB
Vue
<template>
|
||
<view>
|
||
<Nav />
|
||
<!-- 顶部面板 -->
|
||
<view class="top--panel" :class="{ 'grayscale':!isBusinessTime }">
|
||
<image class="panelimgbackground"
|
||
:src="shopExtend?shopExtend.value:'https://czg-qr-order.oss-cn-beijing.aliyuncs.com/shopDetails/topBanner.png'"
|
||
mode="aspectFill">
|
||
</image>
|
||
<view class="panelone flex-start">
|
||
<view class="u-flex u-flex-y-center">
|
||
<text>
|
||
{{ shopInfo.shopName }}
|
||
</text>
|
||
<view class="u-flex u-flex-y-center u-m-t-4">
|
||
<up-icon name="arrow-right" color="#999999" size="14"></up-icon>
|
||
</view>
|
||
</view>
|
||
<!-- <up-icon name="arrow-right" color="#999999" size="14"></up-icon> -->
|
||
</view>
|
||
<view class="paneltow" v-if="distance">
|
||
距离您{{ distance }}
|
||
</view>
|
||
<view class="panelthere flex-between">
|
||
<view class="paneltheretext">
|
||
营业时间:{{ (shopInfo.businessStartDay || '--') +' 至 '+ (shopInfo.businessEndDay || '--')}}
|
||
{{endTimeref.startTime}} -
|
||
{{endTimeref.endTime < '05'?` 凌晨${endTimeref.endTime}`:endTimeref.endTime}}
|
||
</view>
|
||
<view class="flex-start" @click="callChildMethod">
|
||
<view style="margin-right: 14rpx;">查看</view>
|
||
<up-icon name="arrow-down" color="#999999" size="14"></up-icon>
|
||
</view>
|
||
</view>
|
||
<!-- 本店招牌菜 -->
|
||
<view class="panelfour" v-if="shopProductList.hots && shopProductList.hots.length > 0">
|
||
本店招牌菜
|
||
</view>
|
||
<view class="panelfive ">
|
||
|
||
<scroll-view :scroll-x="true" :scroll-with-animation="false">
|
||
<view class="panelfive_list">
|
||
<view class="panelfiveitem" @click="clickspecifications(item,index,index,'热销')"
|
||
v-for="(item,index) in shopProductList.hots" :key="index">
|
||
<image class="panelfiveitemimage" :src="item.coverImg" mode="aspectFill"></image>
|
||
<view class="vifgoodsImg flex-center"
|
||
v-if="item.isSale == 0 || (item.isSaleTime == 0 && !item.isSaleTimeshow) || item.isSoldStock == 1 || (item.isStock == 1 && item.stockNumber <= 0)">
|
||
<image v-if="item.isSale == 0" src="@/static/ztt/icon_goods_yxj.svg"
|
||
style="width:200rpx; height: 100%;" mode=""></image>
|
||
<image v-else-if="(item.isSaleTime == 0 && !item.isSaleTimeshow)"
|
||
src="@/static/ztt/icon_goods_wks.svg" style="width:200rpx; height: 100%;" mode="">
|
||
</image>
|
||
<image v-else-if="item.isSoldStock == 1" src="@/static/ztt/icon_goods_sq.svg"
|
||
style="width:200rpx; height: 100%;" mode=""></image>
|
||
<image v-else-if="item.isStock == 1 && item.stockNumber <= 0"
|
||
src="@/static/ztt/icon_goods_kcbz.svg" style="width:200rpx; height: 100%;" mode="">
|
||
</image>
|
||
</view>
|
||
<view class="panelfiveitemone">
|
||
{{ item.name }}
|
||
</view>
|
||
<view class="panelfiveitemtow">
|
||
本店回头客第{{index+1}}名
|
||
</view>
|
||
<view class="panelfiveitemthere flex-between">
|
||
<text>招牌</text>
|
||
<view class="describe" v-if="item.suitNum>1 && item.type!= 'sku'"
|
||
style="font-size: 20rpx;margin-top: 10rpx;">
|
||
「{{item.suitNum}}{{item.unitName}}起点」
|
||
</view>
|
||
</view>
|
||
|
||
<!-- <view class="panelfiveitemfour">
|
||
{{item.shortTitle?item.shortTitle:''}}
|
||
</view>
|
||
<view class="panelfiveitemfive">
|
||
月售{{item.stockNumber}}
|
||
</view> -->
|
||
<view v-if="item.isSoldStock == 1 || (item.isSaleTime == 0 && !item.isSaleTimeshow)"
|
||
class="flex-between" style="margin-top: 32rpx;margin-bottom: 48rpx;">
|
||
<view class="panelfiveitemsex flex-between">
|
||
<view class="panelfiveitemsex_oen">
|
||
<text class="tips"
|
||
:class="shopInfo.isVip == 0 || shopInfo.isMemberPrice==0?'lineThrough':''">¥</text>
|
||
<!-- 会员价与价格 -->
|
||
<text class="price">
|
||
{{shopInfo.isVip ==1 && shopInfo.isMemberPrice==1?(item.memberPrice||item.salePrice):item.salePrice}}
|
||
</text>
|
||
<!-- 单位 -->
|
||
<text class="unit" v-if="item.unitName">/{{item.unitName}}</text>
|
||
</view>
|
||
</view>
|
||
<view class="panelfiveitemNum">
|
||
<view class="sku-wrap flex-center" style="background-color: #CECECE;">
|
||
<text class="t" v-if="(item.isSaleTime == 0 && !item.isSaleTimeshow)">未开售</text>
|
||
<text class="t" v-if="item.isSoldStock == 1">已售罄</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-else class="flex-between"
|
||
style="margin-top: 32rpx;margin-bottom: 48rpx; flex-wrap: inherit">
|
||
<view class="panelfiveitemsex flex-between">
|
||
<view class="panelfiveitemsex_oen">
|
||
<text class="tips"
|
||
:class="shopInfo.isVip ==0 || shopInfo.isMemberPrice==0?'lineThrough':''">¥</text>
|
||
<!-- 会员价与价格 -->
|
||
<text class="price">
|
||
{{shopInfo.isVip ==1 && shopInfo.isMemberPrice==1?(item.memberPrice|| item.salePrice):item.salePrice}}
|
||
</text>
|
||
<text class="unit" v-if="item.unitName">/{{item.unitName}}</text>
|
||
<!-- <text v-if="item.suitNum>1 && item.type!= 'sku'"
|
||
style="font-size: 16rpx;">「{{item.suitNum}}{{item.unitName}}起点」</text> -->
|
||
</view>
|
||
</view>
|
||
<!-- single-单规格商品 sku-多规格商品 package-套餐商品 weight-称重商品 coupon-团购券 -->
|
||
<view class="panelfiveitemNum">
|
||
<!-- v-if="item.type == 'single'|| item.type == 'weight' || item.type == 'coupon' || (item.type == 'package' && item.groupType=='0')" -->
|
||
<view class="sku-wrap flex-center"
|
||
v-if="item.type == 'sku' || (item.type == 'package' && item.groupType == '1')"
|
||
@click.stop="clickspecifications(item,index,index1)">
|
||
<text class="t" v-if="item.groupType == '1'">选择套餐</text>
|
||
<text class="t" v-else>选规格</text>
|
||
<text class="dot num"
|
||
v-if="item.cartNumber >0">{{ ifcartNumber(item) <99?ifcartNumber(item):'99+'}}</text>
|
||
</view>
|
||
<view class="Controls" v-else>
|
||
<view class="btn" v-if="item.cartNumber != '0'">
|
||
<up-icon name="minus-circle-fill" color="#E9AB7A" size="25"></up-icon>
|
||
<view class="btnClick"
|
||
@tap.stop="$u.throttle(() => singleclick(item, '-'), 500)">
|
||
</view>
|
||
</view>
|
||
<text class="num"> {{ ifcartNumber(item) }} </text>
|
||
<view class="btn">
|
||
<up-icon name="plus-circle-fill" color="#E9AB7A" size="25"></up-icon>
|
||
<view class="btnClick"
|
||
@tap.stop="$u.throttle(() => singleclick(item, '+'), 500)">
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 滚动区域 -->
|
||
<view class="scroll-panel " id="scroll-panel" :class="{ 'grayscale':!isBusinessTime }">
|
||
<view class="list-box">
|
||
<view class="left" :style="{top: `${store.height}px`}">
|
||
<scroll-view :scroll-into-view="leftIntoView" :scroll-with-animation="false" :scroll-y="true"
|
||
:style="{height:`${store.screenHeight - store.height}px`}" style="padding-bottom: 200rpx;">
|
||
<view class="item" v-for="(item,index) in shopProductList.productInfo" :key="index"
|
||
:class="{ 'active':index==leftIndex }" :id="'left-'+index" :data-index="index"
|
||
@click="leftTap(index)"><text>{{item.name}}</text></view>
|
||
</scroll-view>
|
||
</view>
|
||
<view class="main">
|
||
<view>
|
||
<view class="item main-item" v-for="(item,index) in shopProductList.productInfo" :key="index"
|
||
:id="'item-'+index">
|
||
<view class="title">
|
||
<view>{{item.name}}</view>
|
||
</view>
|
||
<view class="goods" @click="clickspecifications(item1,index,index1)"
|
||
v-for="(item1,index1) in item.productList" :key="index1">
|
||
<image class="goodsImg" v-if="item1.coverImg!=null" :lazy-load="true"
|
||
@load="imageLoaded(item1,index,index1)"
|
||
:src="`${item1.coverImg}${!item1.imgLoad?'?x-oss-process=image/resize,m_lfit,w_150,h_150':''}`"
|
||
mode="aspectFill"></image>
|
||
<image class="goodsImg"
|
||
src="https://czg-qr-order.oss-cn-beijing.aliyuncs.com/index/1.gif" mode="" v-else
|
||
:lazy-load="true">
|
||
</image>
|
||
<view class="vifgoodsImg"
|
||
v-if="item1.isSale == 0 || (item1.isSaleTime == 0 && !item1.isSaleTimeshow) || item1.isSoldStock == 1 || (item1.isStock == 1 && item1.stockNumber <= 0)">
|
||
<image v-if="item1.isSale == 0" src="@/static/ztt/icon_goods_yxj.svg"
|
||
style="width:200rpx; height: 100%;" mode=""></image>
|
||
<image v-else-if="(item1.isSaleTime == 0 && !item1.isSaleTimeshow)"
|
||
src="@/static/ztt/icon_goods_wks.svg" style="width:200rpx; height: 100%;"
|
||
mode=""></image>
|
||
<image v-else-if="item1.isSoldStock == 1" src="@/static/ztt/icon_goods_sq.svg"
|
||
style="width:200rpx; height: 100%;" mode=""></image>
|
||
<image v-else-if="item1.isStock == 1 && item1.stockNumber <= 0"
|
||
src="@/static/ztt/icon_goods_kcbz.svg" style="width:200rpx; height: 100%;"
|
||
mode=""></image>
|
||
</view>
|
||
<view v-if="index=='0'" class="topSort" :class="'c'+(index1+1)">TOP{{index1+1}}</view>
|
||
<view class="goods_right" style="overflow: hidden;">
|
||
<view class="name">{{ item1.name }}</view>
|
||
<!-- <view class="lookBack" v-if="index=='0'">本店销量第{{index1+1}}名</view>-->
|
||
<view class="lookBack" v-if="specifications.item.isHot == 1">热销</view>
|
||
<view class="describe"> {{item1.shortTitle?item1.shortTitle:''}} </view>
|
||
|
||
<view class="describe" v-if="item1.suitNum>1 && item1.type!= 'sku'"
|
||
style="font-size: 20rpx;">
|
||
「{{item1.suitNum}}{{item1.unitName}}起点」
|
||
</view>
|
||
<view
|
||
v-if="item1.isSoldStock == 1 || (item1.isSaleTime == 0 && !item1.isSaleTimeshow)"
|
||
class="flex-between">
|
||
<view class="money">
|
||
<view>¥</view>
|
||
<text class="money_num" style="margin-right: 10rpx;">
|
||
{{shopInfo.isVip ==1 && shopInfo.isMemberPrice==1 ?(item1.memberPrice||item1.salePrice):item1.salePrice}}
|
||
</text>
|
||
<text v-if="item1.unitName">/{{item1.unitName}}</text>
|
||
</view>
|
||
<view class="flex-end">
|
||
<view class="sku-wrap flex-center" style="background-color: #CECECE;">
|
||
<text class="t"
|
||
v-if="(item1.isSaleTime == 0 && !item1.isSaleTimeshow)">未开售</text>
|
||
<text class="t" v-else-if="item1.isSoldStock == 1">已售罄</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view v-else class="flex-between" style="flex-wrap: inherit;">
|
||
<view class="money">
|
||
<view>¥</view>
|
||
<text class="money_num">
|
||
{{shopInfo.isVip ==1 && shopInfo.isMemberPrice==1?(item1.memberPrice||item1.salePrice):item1.salePrice}}
|
||
</text>
|
||
<text class="money_num" v-if="item1.unitName">/{{item1.unitName}}</text>
|
||
<!-- <text v-if="item1.suitNum>1 && item1.type!= 'sku'"
|
||
style="font-size: 14rpx;">
|
||
「{{item1.suitNum}}{{item1.unitName}}起点」
|
||
</text> -->
|
||
</view>
|
||
<view class="flex-end"
|
||
v-if="item1.type == 'sku' || (item1.type == 'package' && item1.groupType == '1')">
|
||
<view class="sku-wrap flex-center"
|
||
@click.stop="clickspecifications(item1,index,index1)">
|
||
<text class="t" v-if="item1.groupType == '1'">选择套餐</text>
|
||
<text class="t" v-else>选规格</text>
|
||
<text class="dot num"
|
||
v-if="item1.cartNumber >0">{{ ifcartNumber(item1) <99?ifcartNumber(item1):'99+'}}</text>
|
||
</view>
|
||
</view>
|
||
<view class="Controls" v-else>
|
||
<view class="btn" v-if="item1.cartNumber != '0'">
|
||
<up-icon name="minus-circle-fill" color="#E9AB7A" size="25"></up-icon>
|
||
<view class="btnClick"
|
||
@tap.stop="$u.throttle(() => singleclick(item1, '-'), 500)">
|
||
</view>
|
||
</view>
|
||
|
||
<text class="num"> {{ ifcartNumber(item1) }} </text>
|
||
<view class="btn">
|
||
<up-icon name="plus-circle-fill" color="#E9AB7A" size="25"></up-icon>
|
||
<view class="btnClick"
|
||
@tap.stop="$u.throttle(() => singleclick(item1, '+'), 500)">
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="fill-last" :style="{ 'height':fillHeight + 'px' }"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
|
||
</view>
|
||
|
||
<confirmorder ref="confirmorderref" :cartLists_count="cartLists_count" :cartList="matchedProducts"
|
||
:totalPrices='totalPrices' :confirmordershow="confirmordershow"
|
||
@close="confirmordershow = !confirmordershow" @customevent='websocketsendMessage' :orderinfo="orderinfo">
|
||
</confirmorder>
|
||
|
||
<!-- 店铺详情 -->
|
||
<shopindex ref="showShopInfoRef"></shopindex>
|
||
<!-- 购物车 -->
|
||
<shoppingCartes :cartLists_count="cartLists_count" :cartList="matchedProducts" :showCart="showCart"
|
||
@customevent='websocketsendMessage' @close="showCart = !showCart" :orderinfo="orderinfo"
|
||
@clickcancelOrder='clickcancelOrder' v-if="cartLists_count > 0">
|
||
</shoppingCartes>
|
||
|
||
<!-- 显示购物车栏 -->
|
||
<view class="cart-wrap" v-if="cartLists_count > 0 && !confirmordershow && isBusinessTime">
|
||
<view class="cart-content">
|
||
<view class="left">
|
||
<view class="iconBox">
|
||
<image class="icon"
|
||
src="https://czg-qr-order.oss-cn-beijing.aliyuncs.com/shopDetails/shopIcon.png"
|
||
mode="aspectFill" @click="Historicalorders(true)">
|
||
</image>
|
||
<text class="u-badge"> {{cartLists_count<99?cartLists_count:'99+'}} </text>
|
||
</view>
|
||
|
||
<text class="i">¥</text>
|
||
<text class="num">{{totalPrices}}</text>
|
||
</view>
|
||
<view class="btn" @tap="$u.debounce(orderdetail, 500)">
|
||
<text class="t">结算</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 规格 -->
|
||
<up-popup :show="showShopsku" :round="20" mode="bottom" @close="showShopsku = false,pagemetashow = false">
|
||
<view class="shop_sku">
|
||
<scroll-view scroll-y style="max-height:60vh;width: 100%;">
|
||
<view class="positionabsolute">
|
||
<up-icon name="close-circle" @click="showShopsku = false;pagemetashow=false" color="#000"
|
||
size="25"></up-icon>
|
||
</view>
|
||
<up-swiper :list="specifications.item.images" height="250"></up-swiper>
|
||
<view class="shop_sku_name"> {{specifications.item.name}} </view>
|
||
<view class="shop_sku_description">
|
||
{{specifications.item.shortTitle?specifications.item.shortTitle:''}}
|
||
</view>
|
||
<view v-if="specifications.item.type != 'package'">
|
||
<view class="shop_sku_box" v-for="(specOptions,specType) in specifications.item.selectSpecInfo"
|
||
:key="specType">
|
||
<view class="shop_sku_box_name">
|
||
{{specType }}
|
||
</view>
|
||
<view class="flex-start">
|
||
<view class="shop_sku_box_item" v-for="option in specOptions" :key="option"
|
||
@click="selectSpec(specType, option)"
|
||
:class="{ shop_sku_box_item_selected: selectedSpecs[specType] === option }">
|
||
{{option}}
|
||
<view class="shop_sku_box_item_tip"
|
||
v-if="specifications.item.result&& specifications.item.result.isSoldStock== 1 && selectedSpecs[specType] === option">
|
||
<view>售罄</view>
|
||
</view>
|
||
<view class="shop_sku_box_item_tip"
|
||
v-if="specifications.item.result == 'kong' && canSubmit == false && selectedSpecs[specType] === option">
|
||
<view>已下架</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- 套餐 -->
|
||
<view v-else>
|
||
<view class="shop_sku_box">
|
||
<view v-for="(setmenu, setmenuindex) in specifications.item.groupSnap" :key='setmenuindex'>
|
||
<view class="shop_sku_box_name">
|
||
{{setmenu.title}} {{setmenu.count }} 选{{setmenu.number }}
|
||
</view>
|
||
<view class="flex-start">
|
||
<view class="shop_sku_box_item" v-for="(option, goodsid) in setmenu.goods"
|
||
:key="goodsid" @click="goodsidClick(setmenuindex, option, goodsid)"
|
||
:class="{ shop_sku_box_item_selected: isOptionSelected(setmenuindex, option)}"
|
||
:disabled="isMaxSelected(setmenuindex) &&!isOptionSelected(setmenuindex, option)">
|
||
{{option.proName}}
|
||
<text v-if="option.unitName">/{{option.unitName}}</text>
|
||
<view class="shop_sku_box_item_tip" v-if="specifications.item.isSoldStock == 1">
|
||
<view>售罄</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
<view class="shop_bottom">
|
||
<view class="flex-between">
|
||
|
||
<view class="price" v-if="specifications.item.type != 'package' && specifications.item.result">
|
||
<text class="i">¥</text>
|
||
<text
|
||
class="num">{{shopInfo.isVip ==1 && shopInfo.isMemberPrice==1? (specifications.item.result.memberPrice||specifications.item.result.salePrice):specifications.item.result.salePrice}}</text>
|
||
<text class="i" v-if="specifications.item.unitName">/{{specifications.item.unitName}}</text>
|
||
<text v-if="specifications.item.result.suitNum>1">
|
||
「{{specifications.item.result.suitNum}}{{specifications.item.result.unitName}}起点」
|
||
</text>
|
||
</view>
|
||
<view class="price" v-else>
|
||
<text class="i">¥</text>
|
||
<text class="num">
|
||
{{shopInfo.isVip ==1 && shopInfo.isMemberPrice==1? (specifications.item.memberPrice||specifications.item.salePrice):specifications.item.salePrice}}
|
||
</text>
|
||
<text class="i" v-if="specifications.item.unitName">
|
||
/{{specifications.item.unitName}}
|
||
</text>
|
||
<text v-if="specifications.item.suitNum>1">
|
||
「{{specifications.item.suitNum}}{{specifications.item.unitName}}起点」
|
||
</text>
|
||
</view>
|
||
|
||
<view class="operation-wrap" v-if="specifications.item.type != 'package'">
|
||
<view class="btn">
|
||
<up-icon name="minus-circle-fill" color="#E9AB7A" size="25"
|
||
v-if="shopCartNumber>0"></up-icon>
|
||
<view class="btnClick" @click="shopCart('-')">
|
||
</view>
|
||
</view>
|
||
<text class="num">{{ shopCartNumber }}</text>
|
||
<view class="btn">
|
||
<up-icon name="plus-circle-fill" color="#E9AB7A" size="25"></up-icon>
|
||
<view class="btnClick" @click="shopCart('+')">
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="shop_skuselect flex-start" v-if="selectedSpecsStr">
|
||
<view class="shop_skuselectname">{{selectedSpecsStr }}</view>
|
||
</view>
|
||
<view v-if="specifications.item.type == 'package'" class="addShopping"
|
||
:class="shopCartNumber>0&&allConditionsSatisfied?'active':''" @click="submitSelection()">
|
||
{{skuBtnText}}
|
||
</view>
|
||
<view v-else class="addShopping" :class="shopCartNumber>0&&canSubmit?'active':''"
|
||
@click="submitSelection()">
|
||
{{skuBtnText}}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</up-popup>
|
||
<view class="history_order" @click="toHistory" v-if="shopInfo&&shopInfo.registerType == 'after'&&orderinfo.id">
|
||
<image class="img" src="@/static/history.png" mode=""></image>
|
||
<text>已下单菜品</text>
|
||
</view>
|
||
<Loading :isLoading="isLoading" />
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {
|
||
ref,
|
||
reactive,
|
||
onMounted,
|
||
watchEffect,
|
||
getCurrentInstance,
|
||
computed,
|
||
watch
|
||
} from "vue";
|
||
|
||
import {
|
||
onLoad,
|
||
onReady,
|
||
onShow,
|
||
onHide,
|
||
onPageScroll
|
||
} from '@dcloudio/uni-app'
|
||
|
||
//导航栏
|
||
import Nav from '@/components/CustomNavbar.vue';
|
||
import shopindex from './components/shopindex.vue'
|
||
import shoppingCartes from './components/shoppingCartes.vue'
|
||
import confirmorder from './components/confirmorder.vue'
|
||
import Loading from '@/components/Loading.vue';
|
||
import dayjs from 'dayjs';
|
||
import isBetween from 'dayjs/plugin/isBetween'
|
||
dayjs.extend(isBetween)
|
||
|
||
// 获取全局属性
|
||
const {
|
||
proxy
|
||
} = getCurrentInstance();
|
||
|
||
//接口引入
|
||
import {
|
||
productminiApphotsquery,
|
||
APIgroupquery,
|
||
APIminiAppinfo,
|
||
APIminiAppskuinfo
|
||
} from "@/common/api/product/product.js";
|
||
|
||
import {
|
||
APIhistoryOrder,
|
||
APIcancelOrder,
|
||
APIrmPlaceOrder
|
||
} from "@/common/api/order/index.js";
|
||
|
||
// websocket
|
||
// import useWebSocket from '@/common/js/websocket.js';
|
||
import useWebSocket from '@/common/js/carts-websocket.js';
|
||
|
||
// pinia管理
|
||
import {
|
||
useNavbarStore
|
||
} from '@/stores/navbarStore';
|
||
|
||
// 结账管理
|
||
import {
|
||
Memberpay
|
||
} from '@/stores/pay.js';
|
||
|
||
const storeMemberpay = Memberpay();
|
||
const store = useNavbarStore();
|
||
|
||
import {
|
||
productStore
|
||
} from '@/stores/user.js';
|
||
|
||
const userStore = productStore();
|
||
|
||
// 金额管理
|
||
import {
|
||
useCartStore
|
||
} from '@/stores/order.js';
|
||
const cartStore = useCartStore()
|
||
|
||
// 动态更新导航栏配置
|
||
store.updateNavbarConfig({
|
||
showBack: true, //左边返回键
|
||
rightText: '', //右边文字
|
||
showSearch: false, //true是标题其他事文字
|
||
title: '',
|
||
isTransparent: false,
|
||
hasPlaceholder: false //是否要占位符
|
||
});
|
||
|
||
const shopInfo = uni.cache.get('shopInfo')
|
||
const shopTable = uni.cache.get('shopTable')
|
||
const distance = uni.cache.get('distance') //距离
|
||
|
||
|
||
//店铺详情
|
||
const showShopInfoRef = ref(null)
|
||
|
||
// 初始加载中
|
||
const isLoading = ref(true);
|
||
|
||
//调用shop组件
|
||
const callChildMethod = () => {
|
||
if (showShopInfoRef.value) {
|
||
showShopInfoRef.value.childMethod();
|
||
}
|
||
}
|
||
|
||
try {
|
||
const shopExtend = uni.cache.get('shopTable').shopExtendMap.shopinfo_bg
|
||
} catch (error) {}
|
||
|
||
// 计算高度
|
||
const navScroll = ref(null)
|
||
|
||
// 获取商品数据
|
||
const shopProductList = reactive({
|
||
hots: [],
|
||
productInfo: [],
|
||
})
|
||
|
||
// * 图片加载
|
||
const imageLoaded = (item, index, index1) => {
|
||
// shopProductList.productInfo[index].products[index1]['imgLoad'] = true;
|
||
}
|
||
|
||
// 计算左侧位置
|
||
const leftIndex = ref(0)
|
||
|
||
//距离顶部的高度
|
||
const scrollTopSiz = ref(0)
|
||
|
||
//元素最低端的距离
|
||
const lastbottom = ref('')
|
||
|
||
//储存元素的下标
|
||
const topArr = ref([])
|
||
|
||
// 填充高度,用于最后一项低于滚动区域时使用
|
||
const fillHeight = ref(200)
|
||
|
||
//距离顶部的高度
|
||
const scrollTopSize = ref(0)
|
||
|
||
//左侧导航点击
|
||
const leftTap = (index) => {
|
||
uni.pageScrollTo({
|
||
scrollTop: topArr.value[index] - store.height,
|
||
duration: 0
|
||
});
|
||
leftIndex.value = index
|
||
}
|
||
|
||
/* 计算左侧滚动位置定位 */
|
||
const leftIntoView = computed(() => {
|
||
return `left-${leftIndex.value? leftIndex.value:0}`
|
||
})
|
||
|
||
/* 获取元素顶部信息 */
|
||
const getElementTop = () => {
|
||
new Promise((resolve, reject) => {
|
||
let view = uni.createSelectorQuery().selectAll('.main-item');
|
||
view.boundingClientRect(async data => {
|
||
resolve(data);
|
||
}).exec();
|
||
proxy.$uGetRect('.scroll-panel').then(res => {
|
||
scrollTopSize.value = res.top; //元素距离顶部的距离
|
||
})
|
||
}).then((res) => {
|
||
try {
|
||
topArr.value = res.map((item) => {
|
||
return item.top; /* 减去滚动容器距离顶部的距离 加导航栏高度*/
|
||
});
|
||
|
||
// 获取最后一个元素最低端的盒子到顶点的距离
|
||
for (let i = 0; i <= (topArr.value.length - 1); i++) {
|
||
if ((store.screenHeight - 200) >= (topArr.value[topArr.value.length - 1] - topArr.value[
|
||
i])) {
|
||
// 获取距离最后一个index
|
||
lastbottom.value = i;
|
||
break;
|
||
}
|
||
}
|
||
/* 获取最后一项的高度,设置填充高度。判断和填充时做了 +-20 的操作,是为了滚动时更好的定位 */
|
||
let last = res[res.length - 1].height;
|
||
if (last - 20 < store.screenHeight) {
|
||
fillHeight.value = 200;
|
||
}
|
||
} catch (error) {
|
||
//TODO handle the exception
|
||
}
|
||
});
|
||
}
|
||
|
||
// 定时器
|
||
const mainThrottle = ref(null)
|
||
|
||
/* 主区域滚动监听 */
|
||
const mainScroll = (e) => {
|
||
// 节流方法
|
||
clearTimeout(mainThrottle.value);
|
||
mainThrottle.value = setTimeout(() => {
|
||
scrollFn();
|
||
}, 10);
|
||
let scrollFn = () => {
|
||
let top = e.scrollTop;
|
||
let index = 0;
|
||
// 判断左边是否可以滑动
|
||
|
||
for (let i = (topArr.value.length - 1); i >= 0; i--) {
|
||
/* 在部分安卓设备上,因手机逻辑分辨率与rpx单位计算不是整数,滚动距离与有误差,增加2px来完善该问题 */
|
||
if ((top + 2) >= topArr.value[i] - store.height) {
|
||
index = i;
|
||
break;
|
||
}
|
||
}
|
||
/* 查找当前滚动距离 */
|
||
if (index >= lastbottom.value) { //
|
||
leftIndex.value = index > leftIndex.value ? index : leftIndex.value
|
||
// this.leftIndex = this.leftIndex
|
||
} else {
|
||
leftIndex.value = (index < 0 ? 0 : index);
|
||
}
|
||
}
|
||
}
|
||
|
||
//动态导航栏滑动距离
|
||
onPageScroll((res) => {
|
||
uni.$u.debounce(store.scrollTop = res.scrollTop, 500)
|
||
uni.$u.debounce(navScroll.value = res.scrollTop, 500)
|
||
uni.$u.debounce(mainScroll(res), 500)
|
||
});
|
||
|
||
// 点击详情
|
||
const showShopsku = ref(false)
|
||
|
||
// 规格信息
|
||
const specifications = reactive({
|
||
item: {},
|
||
index: '',
|
||
inedxs: '',
|
||
type: '',
|
||
product_id: '',
|
||
sku_id: '',
|
||
groupSnap: {},
|
||
item: {
|
||
groupSnap: [],
|
||
result: {
|
||
isSoldStock: 0
|
||
}
|
||
},
|
||
|
||
})
|
||
// 用于判断接口数据是否加载完成
|
||
const isDataLoaded = ref(false);
|
||
|
||
// 存储用户当前选择的规格,初始为空对象
|
||
const selectedSpecs = ref({});
|
||
|
||
// 能否提交的状态
|
||
const canSubmit = ref(false);
|
||
|
||
//字形判断
|
||
const skuBtnText = ref('添加到购物车')
|
||
|
||
// 计算属性,判断是否所有规格类型都有选中项
|
||
const allSpecsSelected = computed(() => {
|
||
// 获取所有规格类型的键
|
||
const specKeys = Object.keys(specifications.item.selectSpecInfo);
|
||
// skuBtnText.value = selectedSpecsStr.value ? `您还没选择${specKeys[1]}哦` : ``
|
||
// 检查每个规格类型是否都在 selectedSpecs 中有对应的选中值
|
||
return specKeys.every(key => selectedSpecs.value[key]);
|
||
});
|
||
|
||
// 处理规格选择的方法
|
||
const selectSpec = async (specType, option) => {
|
||
// 规格清零
|
||
shopCartNumber.value = 0
|
||
|
||
// 更新 selectedSpecs 对象,将当前规格类型的选中值设置为用户点击的选项
|
||
const newSelectedSpecs = {};
|
||
const specKeys = Object.keys(specifications.item.selectSpecInfo);
|
||
for (const key of specKeys) {
|
||
if (key === specType) {
|
||
newSelectedSpecs[key] = option;
|
||
} else {
|
||
newSelectedSpecs[key] = selectedSpecs.value[key];
|
||
}
|
||
}
|
||
selectedSpecs.value = newSelectedSpecs;
|
||
if (allSpecsSelected.value) {
|
||
// try {
|
||
let result = await APIminiAppskuinfo({
|
||
specInfo: selectedSpecsStr.value,
|
||
id: specifications.item.id
|
||
});
|
||
// skuList
|
||
if (result != true) {
|
||
specifications.sku_id = result.id
|
||
specifications.product_id = result.productId
|
||
// 添加多规格分组
|
||
specifications.item.result = result
|
||
if (result.isSoldStock == 0) {
|
||
canSubmit.value = true;
|
||
} else {
|
||
canSubmit.value = false;
|
||
}
|
||
} else {
|
||
specifications.item.result = 'kong'
|
||
canSubmit.value = false;
|
||
}
|
||
|
||
} else {
|
||
canSubmit.value = false;
|
||
}
|
||
};
|
||
|
||
// 监听 specifications 的变化
|
||
watch(
|
||
() => specifications.item.groupSnap,
|
||
(newGroupSnap) => {
|
||
if (Array.isArray(newGroupSnap)) {
|
||
selectedOptions.value = newGroupSnap.map(() => []);
|
||
}
|
||
}
|
||
);
|
||
|
||
// 存储选中的选项,二维数组
|
||
const selectedOptions = ref(
|
||
specifications.item.groupSnap.map(() => [])
|
||
);
|
||
|
||
// / 选择规格的方法
|
||
const goodsidClick = (setmenuindex, option, goodsid) => {
|
||
if (!selectedOptions.value[setmenuindex]) {
|
||
// 如果 selectedOptions.value[setmenuindex] 不存在,初始化一个空数组
|
||
selectedOptions.value[setmenuindex] = [];
|
||
}
|
||
if (isOptionSelected(setmenuindex, option)) {
|
||
// 如果已经选中,取消选中
|
||
selectedOptions.value[setmenuindex] = selectedOptions.value[setmenuindex].filter(item => item.proId !==
|
||
option.proId);
|
||
} else if (!isMaxSelected(setmenuindex)) {
|
||
// 如果未达到最大选择数量,添加到选中列表
|
||
selectedOptions.value[setmenuindex].push(option);
|
||
}
|
||
};
|
||
|
||
// 判断选项是否已选中
|
||
const isOptionSelected = (setmenuindex, option) => {
|
||
// 确保 selectedOptions.value[setmenuindex] 存在
|
||
if (selectedOptions.value[setmenuindex]) {
|
||
return selectedOptions.value[setmenuindex].some(item => item.proId === option.proId);
|
||
}
|
||
return false;
|
||
};
|
||
|
||
// 判断是否达到最大选择数量
|
||
const isMaxSelected = (setmenuindex) => {
|
||
// 确保 selectedOptions.value[setmenuindex] 存在
|
||
if (selectedOptions.value[setmenuindex]) {
|
||
return selectedOptions.value[setmenuindex].length >= specifications.item.groupSnap[setmenuindex]
|
||
.number;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
// 计算所有选中条件是否都符合
|
||
const allConditionsSatisfied = computed(() => {
|
||
// 检查 specifications.item.groupSnap 是否存在
|
||
if (!specifications.item?.groupSnap) {
|
||
return false;
|
||
}
|
||
return specifications.item.groupSnap.every((optionGroup, index) => {
|
||
// 获取当前索引对应的已选选项,如果不存在则默认为空数组
|
||
const selected = selectedOptions.value[index] || [];
|
||
// 检查是否达到最大选择数量
|
||
const hasEnoughSelection = selected.length === optionGroup.number;
|
||
return hasEnoughSelection;
|
||
});
|
||
});
|
||
|
||
// 提交选择,套餐选中最后处理的数据
|
||
const selectedGroupSnap = ref([]);
|
||
|
||
// 计算属性,将 selectedSpecs 转换为字符串形式
|
||
const selectedSpecsStr = computed(() => {
|
||
const values = Object.values(selectedSpecs.value);
|
||
return values.join(',');
|
||
});
|
||
|
||
//添加购物车数量
|
||
const shopCartNumber = ref(0)
|
||
|
||
// 多规格 套餐添加数量
|
||
const shopCart = async (i) => {
|
||
if (i == '-' && shopCartNumber.value >= 0) {
|
||
shopCartNumber.value = 0
|
||
return false;
|
||
}
|
||
let res = await shoppingcart()
|
||
if (i == '-') {
|
||
if (!res && shopCartNumber.value == specifications.item.suitNum) {
|
||
uni.showToast({
|
||
title: `起点${specifications.item.suitNum}个`,
|
||
icon: 'none'
|
||
})
|
||
return false;
|
||
} else {
|
||
shopCartNumber.value--;
|
||
}
|
||
} else {
|
||
if (!res && shopCartNumber.value < 1) {
|
||
console.log(res, specifications)
|
||
if (specifications.type == 'sku') {
|
||
shopCartNumber.value = parseFloat(specifications.item.result.suitNum);
|
||
} else {
|
||
shopCartNumber.value = parseFloat(specifications.item.suitNum);
|
||
}
|
||
} else {
|
||
shopCartNumber.value++;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 套餐比较两个对象是否相等
|
||
function isObjectEqual(obj1, obj2) {
|
||
if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {
|
||
return obj1 === obj2;
|
||
}
|
||
const keys1 = Object.keys(obj1);
|
||
const keys2 = Object.keys(obj2);
|
||
if (keys1.length !== keys2.length) {
|
||
return false;
|
||
}
|
||
for (const key of keys1) {
|
||
if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) {
|
||
if (!isArrayEqual(obj1[key], obj2[key])) {
|
||
return false;
|
||
}
|
||
} else if (!isObjectEqual(obj1[key], obj2[key])) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 比较两个数组是否相等(忽略顺序)
|
||
function isArrayEqual(arr1, arr2) {
|
||
if (arr1.length !== arr2.length) {
|
||
return false;
|
||
}
|
||
const usedIndices = new Array(arr2.length).fill(false);
|
||
for (const item1 of arr1) {
|
||
let found = false;
|
||
for (let i = 0; i < arr2.length; i++) {
|
||
if (!usedIndices[i] && isObjectEqual(item1, arr2[i])) {
|
||
usedIndices[i] = true;
|
||
found = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!found) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 根据购物车的数据匹配选中的商品查找是否有匹配的数组
|
||
const matchingProduct = async (data) => {
|
||
return matchedProducts.value.find((product, index) => {
|
||
if (specifications.type == 'package') {
|
||
// 套餐
|
||
let result = false;
|
||
try {
|
||
if (product.type == "package") {
|
||
let res = JSON.parse(product.cartListinfo.pro_group_info);
|
||
result = isArrayEqual(res, selectedGroupSnap.value);
|
||
}
|
||
} catch (error) {
|
||
//TODO handle the exception
|
||
}
|
||
// 直接返回布尔值
|
||
return result;
|
||
} else if (specifications.item.type == 'sku') {
|
||
// 多规格
|
||
return product.cartListinfo.sku_id == data.id && product.cartListinfo.product_id == data
|
||
.productId
|
||
} else {
|
||
// 其他
|
||
return product.skuId == data.skuId && product.id == data.id
|
||
}
|
||
});
|
||
}
|
||
|
||
// 判断多规格和套餐 商品是否在购物车有数据
|
||
const shoppingcart = async () => {
|
||
let res = null
|
||
if (specifications.item.type == "package") {
|
||
if (!allConditionsSatisfied.value) {
|
||
return false
|
||
}
|
||
// 是否是套餐package
|
||
selectedGroupSnap.value = specifications.item.groupSnap.map((setmenu, index) => {
|
||
return {
|
||
...setmenu,
|
||
goods: selectedOptions.value[index]
|
||
};
|
||
});
|
||
res = await matchingProduct(selectedGroupSnap.value)
|
||
} else {
|
||
if (!canSubmit.value) {
|
||
return false
|
||
}
|
||
res = await matchingProduct(specifications.item.result)
|
||
}
|
||
return res;
|
||
}
|
||
|
||
|
||
// 提交选择并执行下一步操作的方法
|
||
const submitSelection = async () => {
|
||
if (!isProductAvailable(specifications.productListitem.days, specifications.productListitem.startTime,
|
||
specifications.productListitem.endTime)) {
|
||
uni.showToast({
|
||
title: '不在可售时间内'
|
||
})
|
||
return false;
|
||
}
|
||
// 判断购物车是否有该选中商品
|
||
// 数量不能少于0
|
||
if (shopCartNumber.value <= 0) {
|
||
return;
|
||
}
|
||
if ((specifications.item.type == 'package' && allConditionsSatisfied.value) || (specifications.item.type ==
|
||
'sku' && canSubmit.value)) {
|
||
let res = await shoppingcart()
|
||
|
||
// 是否是套餐 有就传
|
||
if (specifications.item.type == "package") {
|
||
// 需求更改:所所有商品套餐都是add,没有修改
|
||
res = null
|
||
} else {
|
||
selectedGroupSnap.value = []
|
||
}
|
||
|
||
websocketsendMessage({
|
||
id: res ? res.cartListId : '',
|
||
type: 'shopping',
|
||
suitNum: specifications.productListitem.suitNum,
|
||
table_code: uni.cache.get('tableCode'),
|
||
shop_id: uni.cache.get('shopId'),
|
||
operate_type: res ? 'edit' : 'add',
|
||
product_id: specifications.product_id,
|
||
sku_id: specifications.sku_id,
|
||
number: res ? await calculateValue(res.cartNumber, '+', shopCartNumber.value) :
|
||
shopCartNumber
|
||
.value,
|
||
pro_group_info: selectedGroupSnap.value,
|
||
goods_type: specifications.item.type == "package" ? 'package' : '',
|
||
is_print: 1,
|
||
product_type: specifications.item.type
|
||
})
|
||
// 清空套餐选中
|
||
selectedGroupSnap.value = []
|
||
showShopsku.value = false
|
||
} else {
|
||
return;
|
||
}
|
||
}
|
||
|
||
//获取多规格数据
|
||
const clickspecifications = async (item, index, indexs, type) => {
|
||
console.log(item)
|
||
// 商品类型 single-单规格商品 sku-多规格商品 package-套餐商品 weight-称重商品 coupon-团购券
|
||
if (item.isSoldStock == 1 || (item.isSaleTime == 0 && !item.isSaleTimeshow) || item.type == 'single' ||
|
||
item
|
||
.type == 'weight' || (
|
||
item.type == 'package' && item.groupType == '0')) {
|
||
return false;
|
||
}
|
||
// 数量清零
|
||
shopCartNumber.value = 0
|
||
// 初始化
|
||
let data = {
|
||
item: item,
|
||
productListitem: item,
|
||
type: '',
|
||
product_id: '',
|
||
sku_id: ''
|
||
}
|
||
Object.assign(specifications, data);
|
||
// 初始化 多规格选中
|
||
selectedSpecs.value = {}
|
||
canSubmit.value = false
|
||
// skuBtnText.value = '请选择规格'
|
||
// single-单规格商品 sku-多规格商品 package-套餐商品 weight-称重商品 coupon-团购券
|
||
let res = await APIminiAppinfo(item.id)
|
||
specifications.item = res
|
||
if (specifications.item.type == "package") {
|
||
selectedOptions.value = []
|
||
specifications.product_id = res.id
|
||
specifications.sku_id = item.skuId
|
||
shopCartNumber.value = 1
|
||
}
|
||
// 购物车是否有商品
|
||
specifications.type = res.type
|
||
specifications.item.selectSpecInfo = Object.fromEntries(
|
||
Object.entries(specifications.item.selectSpecInfo).filter(([_, value]) => value.length > 0)
|
||
);
|
||
// 给默认数量
|
||
specifications.item.amountcartNumber = 0
|
||
showShopsku.value = true
|
||
}
|
||
// 判断商品是否在可售时间内
|
||
const isProductAvailable = async (sellDaysStr, startTimeStr, endTimeStr) => {
|
||
// 将后端返回的字符串转换为数组
|
||
const sellDays = sellDaysStr.split(',');
|
||
const now = dayjs();
|
||
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
||
const currentDay = days[now.day()];
|
||
|
||
// console.log('当前日期:', currentDay);
|
||
// console.log('可售日期列表:', sellDays);
|
||
|
||
// 检查当前周几是否在可售周几列表中
|
||
if (!sellDays.includes(currentDay)) {
|
||
// console.log('当前日期不在可售日期列表中');
|
||
return false;
|
||
}
|
||
|
||
const startTime = dayjs(`${now.format('YYYY-MM-DD')} ${startTimeStr}`);
|
||
let endTime = dayjs(`${now.format('YYYY-MM-DD')} ${endTimeStr}`);
|
||
|
||
// 处理跨天情况
|
||
if (endTime.isBefore(startTime)) {
|
||
endTime = endTime.add(1, 'day');
|
||
}
|
||
|
||
// console.log('当前时间:', now.format('YYYY-MM-DD HH:mm:ss'));
|
||
// console.log('开始时间:', startTime.format('YYYY-MM-DD HH:mm:ss'));
|
||
// console.log('结束时间:', endTime.format('YYYY-MM-DD HH:mm:ss'));
|
||
|
||
const isInRange = now.isBetween(startTime, endTime, null, '[)');
|
||
// console.log('当前时间是否在可售时间范围内:', isInRange);
|
||
|
||
return isInRange;
|
||
}
|
||
|
||
// 单规格
|
||
const singleclick = async (item, i) => {
|
||
if (!isProductAvailable(item.days, item.startTime, item.endTime)) {
|
||
uni.showToast({
|
||
title: '不在可售时间内'
|
||
})
|
||
return false;
|
||
}
|
||
// 判断购物车是否有该选中商品
|
||
let res = null
|
||
try {
|
||
res = matchedProducts.value.find((product, index) => {
|
||
return product.skuId == item.skuId && product.id == item.id
|
||
});
|
||
} catch (error) {
|
||
//TODO handle the exception
|
||
}
|
||
|
||
// 保存这次点击的
|
||
specifications.productListitem = item
|
||
|
||
// 是否起售 如果小于或者大于都是1
|
||
let suitNum = 1;
|
||
const cartNumberFloat = parseFloat(item.cartNumber);
|
||
if (!res && item.suitNum > cartNumberFloat) {
|
||
suitNum = item.suitNum;
|
||
} else if (item.suitNum >= cartNumberFloat && i === '-') {
|
||
suitNum = item.cartNumber;
|
||
}
|
||
websocketsendMessage({
|
||
id: res ? item.cartListId : '',
|
||
type: 'shopping',
|
||
suitNum: item.suitNum,
|
||
table_code: uni.cache.get('tableCode'),
|
||
shop_id: uni.cache.get('shopId'),
|
||
operate_type: await calculateValue(item.cartNumber, i, suitNum) == 'del' ? 'del' : res ?
|
||
'edit' : 'add',
|
||
product_id: item.id,
|
||
sku_id: item.skuId,
|
||
number: await calculateValue(item.cartNumber, i, suitNum),
|
||
is_print: 1,
|
||
product_type: item.type
|
||
})
|
||
}
|
||
|
||
|
||
const calculateValue = (cartNumber, i, step = 1) => {
|
||
if (i == '+') {
|
||
const result = parseFloat(cartNumber) + parseFloat(step);
|
||
return result.toFixed(2);
|
||
} else {
|
||
// 当减到0返回del
|
||
const result = parseFloat(cartNumber) - parseFloat(step);
|
||
return result == 0 ? 'del' : result.toFixed(2);
|
||
}
|
||
}
|
||
|
||
// WebSocket处理 // 初始化配置
|
||
const options = {
|
||
initMessage: {
|
||
type: 'shopping',
|
||
operate_type: 'init',
|
||
table_code: uni.cache.get('tableCode'),
|
||
shop_id: uni.cache.get('shopId')
|
||
}
|
||
}
|
||
const {
|
||
isConnected,
|
||
sendMessage,
|
||
closeSocket: manualClose,
|
||
receivedMessages,
|
||
closeExistingConnection,
|
||
onShowconnect,
|
||
initNetworkListener
|
||
} = useWebSocket(options);
|
||
|
||
//购物车显示
|
||
const showCart = ref(false)
|
||
|
||
// 提交订单显示
|
||
const confirmordershow = ref(false)
|
||
|
||
|
||
// 更新商品数量的方法
|
||
const updateProductQuantities = () => {
|
||
// 先将所有商品的 cartNumber 初始化为 0
|
||
shopProductList.hots.forEach((i) => {
|
||
i.cartNumber = 0
|
||
})
|
||
// 遍历商品列表二维数组
|
||
shopProductList.productInfo.forEach((group) => {
|
||
group.productList.forEach((product) => {
|
||
product.cartNumber = 0
|
||
});
|
||
});
|
||
|
||
// 再去更新数组的值
|
||
cartListFilter.value.forEach((cartItem) => {
|
||
shopProductList.productInfo.forEach((group) => {
|
||
group.productList.forEach((product) => {
|
||
if (product.id == cartItem.product_id && product.skuId == cartItem
|
||
.sku_id) {
|
||
product.cartNumber = cartItem.number
|
||
product.cartListId = cartItem.id
|
||
}
|
||
});
|
||
});
|
||
});
|
||
// 遍历购物车数组
|
||
cartListFilter.value.forEach((cartItem) => {
|
||
// 遍历商品列表二维数组
|
||
shopProductList.hots.forEach((group) => {
|
||
// 商品 id 匹配
|
||
if (group.id == cartItem.product_id) {
|
||
// 更新商品的数量
|
||
group.cartListId = cartItem.id
|
||
group.cartNumber = cartItem.number
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
//websocket产值
|
||
const websocketsendMessage = (data) => {
|
||
uni.$u.debounce(sendMessage(data), 500)
|
||
}
|
||
|
||
// 用于记录已经处理过的消息的 msg_id
|
||
const processedMessageIds = new Set();
|
||
|
||
// 监听接收到的消息变化
|
||
watchEffect(async () => {
|
||
if (isDataLoaded.value && receivedMessages.value) {
|
||
const Message = receivedMessages.value
|
||
if (Message) {
|
||
console.log(Message.data);
|
||
// 心跳返回 过滤
|
||
if (Message.type == "ping_interval" || Message.msg_id == "ping_interval") {
|
||
isLoading.value = false;
|
||
return false
|
||
}
|
||
// 检查消息是否已经处理过
|
||
if (processedMessageIds.has(Message.msg_id)) {
|
||
return;
|
||
}
|
||
processedMessageIds.add(Message.msg_id);
|
||
|
||
// 初始化
|
||
if (Message.operate_type == "init") {
|
||
cartStore.carts = Message.data
|
||
uni.hideLoading();
|
||
isLoading.value = false;
|
||
}
|
||
|
||
// 清空购物车
|
||
if (Message.operate_type == 'cleanup') {
|
||
cartStore.carts = []
|
||
setTimeout(() => {
|
||
Historicalorders()
|
||
}, 400)
|
||
showCart.value = false
|
||
}
|
||
|
||
// 删除除购物车
|
||
if (Message.operate_type == 'del' && Message.status == 1) {
|
||
// 优化:使用可选链操作符避免报错
|
||
cartStore.carts = cartStore.carts.filter(item => item.id !== Message.data?.id);
|
||
// cartStore.carts = cartStore.carts.filter(item => item.id != Message.data.id);
|
||
}
|
||
|
||
// 添加或者减少购物后返回
|
||
if (Message.operate_type == 'add' || Message.operate_type == 'edit') {
|
||
[Message.data].forEach((objA) => {
|
||
const index = cartStore.carts.findIndex((objB) => objB.id == objA.id);
|
||
if (index !== -1) {
|
||
cartStore.carts[index] = objA;
|
||
} else {
|
||
cartStore.carts.push(objA);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 历史订单
|
||
if (Message.operate_type == 'clearOrder') {
|
||
Historicalorders()
|
||
}
|
||
|
||
// 购物车数据更新从新请求
|
||
if (Message.type == 'product' && Message.data_type == 'product_update' && Message
|
||
.operate_type == 'product_update') {
|
||
isDataLoaded.value = false;
|
||
productqueryProduct()
|
||
}
|
||
|
||
// 提示
|
||
if (Message.status == 0 && Message.type != 'no_suit_num') {
|
||
uni.showToast({
|
||
title: Message.msg,
|
||
icon: "none"
|
||
})
|
||
}
|
||
|
||
if (Message.type == 'no_suit_num') {
|
||
// console.log(specifications)
|
||
uni.showModal({
|
||
title: '提示',
|
||
showCancel: false,
|
||
content: '此商品库存不足起售数量!',
|
||
success: async (data) => {
|
||
await websocketsendMessage({
|
||
id: Message.id,
|
||
type: 'shopping',
|
||
table_code: uni.cache.get('tableCode'),
|
||
shop_id: uni.cache.get('shopId'),
|
||
operate_type: 'del',
|
||
is_print: 1,
|
||
})
|
||
}
|
||
});
|
||
}
|
||
|
||
//除去p 每次返回都回执消息
|
||
await websocketsendMessage({
|
||
type: 'receipt',
|
||
msg_id: Message.msg_id
|
||
})
|
||
|
||
// 初始化商品数量
|
||
await updateProductQuantities()
|
||
|
||
}
|
||
}
|
||
})
|
||
|
||
// 更新购物车数据shopProductList.hots
|
||
const matchedProducts = computed(() => {
|
||
if (cartStore.carts.length > 0) {
|
||
let Specialstop = null
|
||
|
||
try {
|
||
Specialstop = [...[{
|
||
id: "",
|
||
name: "",
|
||
productList: shopProductList.hots
|
||
}], ...shopProductList.productInfo]
|
||
} catch (error) {
|
||
Specialstop = shopProductList.productInfo
|
||
//TODO handle the exception
|
||
}
|
||
return cartStore.carts.flatMap((cartItem) => {
|
||
for (const group of Specialstop) {
|
||
for (const product of group.productList) {
|
||
if (product.id == cartItem.product_id) {
|
||
return {
|
||
...product,
|
||
cartListinfo: cartItem,
|
||
cartListId: cartItem.id, //购物车id
|
||
cartNumber: cartItem.number //增加一个数量算法
|
||
// cartNumberToAdd: cartItem.number //增加一个数量算法
|
||
};
|
||
|
||
}
|
||
}
|
||
}
|
||
if (cartItem.is_temporary === 1) {
|
||
return [{
|
||
...cartItem,
|
||
memberPrice: cartItem.discount_sale_amount,
|
||
salePrice: cartItem.discount_sale_amount,
|
||
cartListinfo: cartItem,
|
||
cartListId: cartItem.id, // 购物车id
|
||
cartNumber: cartItem.number // 增加一个数量算法
|
||
}];
|
||
}
|
||
// 如果没找到匹配的商品,返回 null 或者其他默认值,这里返回 null
|
||
return null;
|
||
}).filter(item => item !== null);
|
||
} else {
|
||
return []
|
||
}
|
||
|
||
})
|
||
|
||
//删除某一个待支付订单
|
||
const clickcancelOrder = async (data) => {
|
||
if (data.i == 'all') {
|
||
await APIcancelOrder({
|
||
shopId: uni.cache.get('shopId'),
|
||
orderId: orderinfo.value.id,
|
||
})
|
||
} else {
|
||
await APIrmPlaceOrder({
|
||
shopId: uni.cache.get('shopId'),
|
||
orderId: orderinfo.value.id,
|
||
placeNum: data.key
|
||
})
|
||
}
|
||
Historicalorders()
|
||
}
|
||
|
||
// 储存是否存在多次下单
|
||
const orderinfo = ref({})
|
||
const confirmorderref = ref(null)
|
||
|
||
// 结账
|
||
const orderdetail = async () => {
|
||
uni.navigateTo({
|
||
url: '/pages/order/confirm-order?tableCode=' + uni.cache.get('tableCode') + '&shopId=' + uni
|
||
.cache.get(
|
||
'shopId')
|
||
})
|
||
return
|
||
try {
|
||
await Historicalorders()
|
||
} catch (error) {}
|
||
confirmordershow.value = true
|
||
showCart.value = false
|
||
}
|
||
|
||
// 历史订单
|
||
const Historicalorders = async (W) => {
|
||
|
||
if (W===true) {
|
||
showCart.value = !showCart.value
|
||
} else {
|
||
let res = await APIhistoryOrder({
|
||
tableCode: uni.cache.get('tableCode'),
|
||
})
|
||
orderinfo.value = {
|
||
id: res.id,
|
||
detailMap: res.detailMap,
|
||
placeNum: res.placeNum
|
||
}
|
||
}
|
||
}
|
||
|
||
// 提取合并 orderinfo.detailMap 数组的逻辑
|
||
function combineOrderInfoDetailMap(orderinfo) {
|
||
if (!orderinfo) return [];
|
||
let combinedArray = [];
|
||
for (const key in orderinfo.detailMap) {
|
||
if (orderinfo.detailMap.hasOwnProperty(key)) {
|
||
let subArray = orderinfo.detailMap[key];
|
||
combinedArray = [...combinedArray, ...subArray];
|
||
}
|
||
}
|
||
return combinedArray;
|
||
}
|
||
|
||
// 计算购物车商品费用
|
||
const totalPrices = computed(() => {
|
||
// 待支付订单
|
||
let cartone = 0
|
||
if (orderinfo.value) {
|
||
let combinedArray = [];
|
||
for (const key in orderinfo.value.detailMap) {
|
||
if (orderinfo.value.detailMap.hasOwnProperty(key)) {
|
||
let subArray = orderinfo.value.detailMap[key];
|
||
combinedArray = [...combinedArray, ...subArray]
|
||
}
|
||
}
|
||
// 购物车总数价格
|
||
cartone = combinedArray.reduce((total, item) => {
|
||
// 是否启用会员价 0否1是
|
||
if (shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1) {
|
||
// memberPrice会员价
|
||
return total + (parseFloat(item.memberPrice || item.price) * parseFloat(item.num - item
|
||
.returnNum));
|
||
} else {
|
||
// salePrice销售价
|
||
return total + (parseFloat(item.price || 0) * parseFloat(item.num - item.returnNum));
|
||
}
|
||
}, 0);
|
||
}
|
||
// 购物车总数价格
|
||
let cart = 0
|
||
if (matchedProducts.value.length > 0) {
|
||
// 购物车总数价格
|
||
cart = matchedProducts.value.reduce((total, item) => {
|
||
if (item.type == 'sku') {
|
||
item.skuList.forEach((i, t) => {
|
||
if (item.cartListinfo.sku_id == i.id) {
|
||
item.memberPrice = i.memberPrice
|
||
item.salePrice = i.salePrice
|
||
}
|
||
})
|
||
}
|
||
// 是否启用会员价 0否1是
|
||
if (shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1) {
|
||
// memberPrice会员价
|
||
return total + parseFloat(item.memberPrice || item.salePrice) * parseFloat(item
|
||
.cartNumber);
|
||
} else {
|
||
// salePrice销售价
|
||
return total + parseFloat(item.salePrice || 0) * parseFloat(item.cartNumber);
|
||
}
|
||
}, 0);
|
||
}
|
||
cart = parseFloat(cart)
|
||
// 向上取整并保留两位小数
|
||
return parseFloat(cart.toFixed(2));
|
||
});
|
||
|
||
// 计算购物车商品总数量
|
||
const cartLists_count = computed(() => {
|
||
const combinedOrderInfo = combineOrderInfoDetailMap(orderinfo.value);
|
||
const orderInfoCount = combinedOrderInfo.reduce((sum, item) => {
|
||
return sum + parseFloat(item.num);
|
||
}, 0);
|
||
|
||
const matchedProductsCount = matchedProducts.value.reduce((sum, item) => {
|
||
const num = typeof item.cartNumber === 'string' ? parseFloat(item.cartNumber) : item
|
||
.cartNumber;
|
||
return sum + num;
|
||
}, 0);
|
||
|
||
const totalCount = matchedProductsCount;
|
||
return parseFloat(totalCount.toFixed(2));
|
||
});
|
||
|
||
// 定义 ifcartNumber 计算属性方法 展示数量
|
||
const ifcartNumber = computed(() => {
|
||
return (item) => {
|
||
// 如果 item 为空或者 cartNumber 不是字符串类型,返回 0
|
||
if (!item || typeof item.cartNumber !== 'string') {
|
||
return 0;
|
||
}
|
||
let numValue = parseFloat(item.cartNumber);
|
||
if (isNaN(numValue)) {
|
||
// 如果转换结果是 NaN,说明 cartNumber 不是有效的数字字符串,返回 0
|
||
return 0;
|
||
}
|
||
// type string 商品类型 single-单规格商品 sku-多规格商品 package-套餐商品 weight-称重商品 coupon-团购券
|
||
if (item.type === 'weight') {
|
||
// 如果类型是称重重量,将值保留两位小数
|
||
return parseFloat(numValue.toFixed(2));
|
||
} else {
|
||
// 如果类型是整数,将值转换为整数
|
||
return Math.round(numValue);
|
||
}
|
||
// 如果类型不匹配,返回原始值
|
||
return item.cartNumber;
|
||
};
|
||
})
|
||
|
||
// 计算处理后的购物车列表 // 用于筛选后的购物车数组
|
||
const cartListFilter = computed(() => {
|
||
// 使用 reduce 方法对 cartList 进行处理
|
||
const grouped = cartStore.carts.reduce((acc, item) => {
|
||
const productId = item.product_id;
|
||
const num = parseFloat(item.number);
|
||
|
||
if (!acc[productId]) {
|
||
// 如果 acc 中还没有该 product_id 的记录,创建一个新对象
|
||
acc[productId] = {
|
||
...item,
|
||
number: num
|
||
};
|
||
} else {
|
||
// 如果已经有该 product_id 的记录,将当前对象的 number 值累加到已有记录的 number 属性上
|
||
acc[productId].number += num;
|
||
}
|
||
return acc;
|
||
}, {});
|
||
// 将累加结果保留两位小数,并将对象转换为数组
|
||
return Object.values(grouped).map(item => ({
|
||
...item,
|
||
number: item.number.toFixed(2)
|
||
}));
|
||
})
|
||
|
||
const endTimeref = reactive({
|
||
startTime: '',
|
||
endTime: ''
|
||
})
|
||
|
||
// 获取当前时间
|
||
const getCurrentTime = () => {
|
||
const now = new Date();
|
||
const hours = now.getHours().toString().padStart(2, '0');
|
||
const minutes = now.getMinutes().toString().padStart(2, '0');
|
||
return `${hours}:${minutes}`;
|
||
};
|
||
|
||
// 计算是否在营业时间内
|
||
const isBusinessTime = computed(() => {
|
||
if (!shopInfo.businessTime) {
|
||
return true;
|
||
}
|
||
const currentTime = getCurrentTime();
|
||
const [startTime, endTime] = shopInfo.businessTime.split('-');
|
||
endTimeref.startTime = startTime
|
||
endTimeref.endTime = endTime
|
||
// 如果开始时间大于结束时间,说明是跨天的营业时间
|
||
if (startTime > endTime) {
|
||
return currentTime >= startTime || currentTime <= endTime;
|
||
}
|
||
return currentTime >= startTime && currentTime <= endTime;
|
||
});
|
||
|
||
|
||
// 列表请求
|
||
const productqueryProduct = async () => {
|
||
cartStore.goodsIsloading = false;
|
||
try {
|
||
shopProductList.hots = await productminiApphotsquery()
|
||
shopProductList.productInfo = await APIgroupquery()
|
||
} catch (error) {
|
||
uni.showToast({
|
||
title: '网络不稳定,请重新扫码进入',
|
||
icon: 'none'
|
||
})
|
||
setTimeout(() => {
|
||
uni.pro.switchTab('index/index')
|
||
}, 1000)
|
||
}
|
||
if (shopProductList.productInfo.length > 0 || shopProductList.hots.length > 0) {
|
||
//TODO handle the exception
|
||
//第一步:将所有商品的 cartNumber 初始化为 0
|
||
shopProductList.productInfo.forEach((group) => {
|
||
group.productList.forEach(async (product) => {
|
||
product.cartNumber = 0;
|
||
product.isSaleTimeshow = await isProductAvailable(product.days, product
|
||
.startTime, product.endTime)
|
||
cartStore.setGoodsMap(product.id, product)
|
||
});
|
||
});
|
||
shopProductList.hots.forEach(async (i) => {
|
||
i.cartNumber = 0
|
||
i.isSaleTimeshow = await isProductAvailable(i.days, i.startTime, i.endTime)
|
||
cartStore.setGoodsMap(i.id, i)
|
||
})
|
||
cartStore.goodsIsloading = true;
|
||
scrollTopSize.value = 0
|
||
topArr.value = []
|
||
// userStore.actionsAPIuser()
|
||
// 数据可以更新
|
||
isDataLoaded.value = true;
|
||
// 历史订单
|
||
Historicalorders()
|
||
} else {
|
||
uni.showToast({
|
||
title: '暂无列表数据,请重新扫码',
|
||
icon: "none"
|
||
});
|
||
isDataLoaded.value = false;
|
||
setTimeout(() => {
|
||
uni.pro.switchTab('index/index')
|
||
}, 1000)
|
||
return false;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
onLoad(async (e) => {
|
||
await proxy.$onLaunched;
|
||
})
|
||
|
||
onShow(async() => {
|
||
// 监听页面显示和隐藏
|
||
onShowconnect()
|
||
let res = await APIhistoryOrder({
|
||
tableCode: uni.cache.get('tableCode'),
|
||
})
|
||
if(res){
|
||
orderinfo.value = {
|
||
id: res.id,
|
||
detailMap: res.detailMap,
|
||
placeNum: res.placeNum
|
||
}
|
||
}else{
|
||
orderinfo.value = {
|
||
id:''
|
||
}
|
||
}
|
||
})
|
||
|
||
onHide(() => {
|
||
closeExistingConnection()
|
||
})
|
||
|
||
onMounted(async () => {
|
||
await proxy.$onLaunched;
|
||
// 获取当前页面栈
|
||
const pages = getCurrentPages();
|
||
// 获取当前页面实例
|
||
const currentPage = pages[pages.length - 1];
|
||
// 获取页面参数
|
||
const options = currentPage.options;
|
||
let res = await APIhistoryOrder({
|
||
tableCode: uni.cache.get('tableCode'),
|
||
})
|
||
|
||
await productqueryProduct()
|
||
if (res && res.id && shopInfo.registerType == "after") {
|
||
toHistory()
|
||
return
|
||
}
|
||
setTimeout(() => {
|
||
// 启动网络监听
|
||
initNetworkListener()
|
||
getElementTop()
|
||
}, 500)
|
||
})
|
||
|
||
|
||
//跳转历史订单
|
||
function toHistory() {
|
||
uni.navigateTo({
|
||
url: '/pages/order/confirm-order?tableCode=' + uni.cache.get('tableCode') + '&shopId=' + uni
|
||
.cache.get(
|
||
'shopId')
|
||
})
|
||
// uni.navigateTo({
|
||
// url: '/pages/order/confirm-order?orderId=' + orderinfo.id + '&shopId=' + uni.cache.get('shopId')+'&tableCode='+uni.cache.get('tableCode')
|
||
// })
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.grayscale {
|
||
filter: grayscale(100%);
|
||
pointer-events: none;
|
||
}
|
||
|
||
.top--panel {
|
||
// padding: 0 20rpx;
|
||
background-color: #fff;
|
||
|
||
.panelimgbackground {
|
||
width: 100%;
|
||
height: 272rpx;
|
||
}
|
||
|
||
.panelone {
|
||
padding: 20rpx 20rpx 0 20rpx;
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 500;
|
||
font-size: 32rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
.paneltow {
|
||
padding: 0 20rpx;
|
||
margin-top: 16rpx;
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.panelthere {
|
||
margin-top: 32rpx;
|
||
margin-bottom: 50rpx;
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
padding: 0 20rpx;
|
||
|
||
.paneltheretext {
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.flex-start {
|
||
view {
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
}
|
||
}
|
||
}
|
||
|
||
.panelfour {
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: bold;
|
||
font-size: 32rpx;
|
||
color: #333333;
|
||
padding: 0 20rpx;
|
||
}
|
||
|
||
.panelfive {
|
||
width: 100%;
|
||
padding: 0 20rpx;
|
||
|
||
.panelfive_list {
|
||
display: flex;
|
||
}
|
||
|
||
.panelfiveitem {
|
||
margin-top: 16rpx;
|
||
width: 340rpx;
|
||
margin-right: 30rpx;
|
||
position: relative;
|
||
flex-shrink: 0;
|
||
|
||
.panelfiveitemimage {
|
||
border-radius: 20rpx 20rpx 0rpx 0rpx;
|
||
width: 100%;
|
||
height: 204rpx;
|
||
}
|
||
|
||
.vifgoodsImg {
|
||
width: 100%;
|
||
height: 204rpx;
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
z-index: 9;
|
||
background-color: rgb(0, 0, 0, 0.5);
|
||
|
||
image {
|
||
padding: 30rpx;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
|
||
.panelfiveitemone {
|
||
margin-top: 32rpx;
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 500;
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
overflow: hidden; //超出的文本隐藏
|
||
text-overflow: ellipsis; //溢出用省略号显示
|
||
white-space: nowrap; //溢出不换行
|
||
}
|
||
|
||
.panelfiveitemtow {
|
||
margin-top: 16rpx;
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #FF534B;
|
||
}
|
||
|
||
.panelfiveitemthere {
|
||
margin-top: 12rpx;
|
||
// text:nth-child(1) {
|
||
// margin-left: 0;
|
||
// }
|
||
|
||
text {
|
||
padding: 4rpx 24rpx;
|
||
background: #F6F6F6;
|
||
border-radius: 8rpx 8rpx 8rpx 8rpx;
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 20rpx;
|
||
color: #999999;
|
||
}
|
||
}
|
||
|
||
.panelfiveitemfour {
|
||
margin-top: 12rpx;
|
||
width: 100%;
|
||
height: 36rpx;
|
||
line-height: 36rpx;
|
||
overflow: hidden; //超出的文本隐藏
|
||
text-overflow: ellipsis; //溢出用省略号显示
|
||
white-space: nowrap; //溢出不换行
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.panelfiveitemfive {
|
||
margin-top: 8rpx;
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.panelfiveitemsex {
|
||
|
||
.panelfiveitemsex_oen {
|
||
.tips {
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
.price {
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: bold;
|
||
font-size: 36rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
.originalprice {
|
||
margin-left: 10rpx;
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 20rpx;
|
||
text-decoration: line-through;
|
||
}
|
||
|
||
.unit {
|
||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||
font-weight: 400;
|
||
font-size: 36rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
.panelfiveitemNum {
|
||
// position: absolute;
|
||
// bottom: 82rpx;
|
||
// right: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
|
||
.sku-wrap {
|
||
padding: 10rpx 20rpx;
|
||
background: #E3AD7F;
|
||
border-radius: 32rpx;
|
||
position: relative;
|
||
align-items: center;
|
||
|
||
.t {
|
||
font-size: 28rpx;
|
||
color: #fff;
|
||
}
|
||
|
||
.dot {
|
||
position: absolute;
|
||
top: -15rpx;
|
||
right: -10rpx;
|
||
background-color: #FF4B33;
|
||
color: #fff;
|
||
border-radius: 58rpx;
|
||
padding: 5rpx 14rpx;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 20rpx;
|
||
}
|
||
}
|
||
|
||
.Controls {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.num {
|
||
margin: 8rpx 8rpx 0 8rpx;
|
||
}
|
||
|
||
.btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
|
||
.btnClick {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
position: absolute;
|
||
// bottom: 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.scroll-panel {
|
||
position: relative;
|
||
|
||
.list-box {
|
||
display: flex;
|
||
flex-direction: row;
|
||
flex-wrap: nowrap;
|
||
justify-content: flex-start;
|
||
align-items: flex-start;
|
||
align-content: flex-start;
|
||
font-size: 28rpx;
|
||
position: relative;
|
||
|
||
.left {
|
||
width: 200rpx;
|
||
background-color: #f6f6f6;
|
||
line-height: normal;
|
||
box-sizing: border-box;
|
||
font-size: 32rpx;
|
||
position: sticky;
|
||
top: 0;
|
||
|
||
// padding-bottom: 200rpx;
|
||
.item {
|
||
padding: 30rpx 30rpx;
|
||
// height: 92rpx;
|
||
// line-height: 92rpx;
|
||
position: relative;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #333333;
|
||
display: flex;
|
||
align-items: center;
|
||
// overflow: hidden;
|
||
// text-overflow: ellipsis;
|
||
// white-space: nowrap;
|
||
|
||
&+.item {
|
||
margin-top: 1px;
|
||
|
||
&::after {
|
||
// content: '';
|
||
// display: block;
|
||
// height: 0;
|
||
// border-top: #d6d6d6 solid 1px;
|
||
// width: 620upx;
|
||
// position: absolute;
|
||
// top: -1px;
|
||
// right: 0;
|
||
// transform: scaleY(0.5);
|
||
/* 1px像素 */
|
||
}
|
||
}
|
||
|
||
&.active {
|
||
color: #333;
|
||
background-color: #fff;
|
||
position: relative;
|
||
|
||
&::before {
|
||
content: '';
|
||
display: block;
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
border-left: #7E5C23 solid 4px;
|
||
height: 100%;
|
||
width: 0;
|
||
}
|
||
|
||
&::after {
|
||
content: '';
|
||
display: block;
|
||
position: absolute;
|
||
top: 0;
|
||
left: -15rpx;
|
||
bottom: 0;
|
||
margin: auto;
|
||
height: 30rpx;
|
||
width: 30rpx;
|
||
border-radius: 50%;
|
||
background-color: #7E5C23;
|
||
}
|
||
}
|
||
}
|
||
|
||
.items {
|
||
height: 90px;
|
||
position: relative;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
.fill-last {
|
||
height: 0;
|
||
width: 100%;
|
||
background: none;
|
||
}
|
||
}
|
||
|
||
.main {
|
||
background-color: #fff;
|
||
padding-left: 20rpx;
|
||
width: 0;
|
||
flex-grow: 1;
|
||
box-sizing: border-box;
|
||
position: relative;
|
||
|
||
|
||
.title {
|
||
line-height: normal;
|
||
padding: 30rpx 0;
|
||
font-size: 24rpx;
|
||
font-weight: bold;
|
||
color: #666;
|
||
background-color: #fff;
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 19;
|
||
}
|
||
|
||
.item {
|
||
padding-bottom: 16rpx;
|
||
border-bottom: #eee solid 1px;
|
||
}
|
||
|
||
.goods {
|
||
display: flex;
|
||
flex-direction: row;
|
||
flex-wrap: nowrap;
|
||
justify-content: flex-start;
|
||
align-content: center;
|
||
position: relative;
|
||
|
||
&+.goods {
|
||
margin-top: 16rpx;
|
||
}
|
||
|
||
&>image {
|
||
width: 120rpx;
|
||
height: 120rpx;
|
||
margin-right: 18rpx;
|
||
}
|
||
|
||
.goodsImg {
|
||
position: relative;
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
border-radius: 18rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.vifgoodsImg {
|
||
width: 200rpx;
|
||
height: 100%;
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
z-index: 9;
|
||
background-color: rgb(0, 0, 0, 0.5);
|
||
|
||
image {
|
||
padding: 30rpx;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.topSort {
|
||
width: 92rpx;
|
||
height: 38rpx;
|
||
text-align: center;
|
||
line-height: 38rpx;
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #FFFFFF;
|
||
border-radius: 20rpx 0rpx 20rpx 0rpx;
|
||
|
||
}
|
||
|
||
.topSort.c1 {
|
||
background: #FC5C2E;
|
||
}
|
||
|
||
.topSort.c2 {
|
||
background: #EF994E;
|
||
}
|
||
|
||
.topSort.c3 {
|
||
background: #F4B951;
|
||
}
|
||
|
||
.goods_right {
|
||
width: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-around;
|
||
position: relative;
|
||
padding-top: 5rpx;
|
||
padding-right: 20rpx;
|
||
box-sizing: border-box;
|
||
|
||
.name {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: bold;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.describe,
|
||
.monthlySale,
|
||
.lookBack {
|
||
font-weight: 400;
|
||
font-size: 20rpx;
|
||
color: #999999;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.describe,
|
||
.name {
|
||
width: 270rpx;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
|
||
.lookBack {
|
||
color: #FF534B;
|
||
}
|
||
|
||
.money {
|
||
font-weight: bold;
|
||
font-size: 24rpx;
|
||
color: #333;
|
||
display: flex;
|
||
align-items: flex-end;
|
||
|
||
.money_num {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
|
||
.suit {
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
}
|
||
|
||
.sku-wrap {
|
||
padding: 10rpx 20rpx;
|
||
background: #E3AD7F;
|
||
border-radius: 32rpx;
|
||
// position: absolute;
|
||
// bottom: 10rpx;
|
||
// right: 20rpx;
|
||
align-items: center;
|
||
position: relative;
|
||
|
||
.t {
|
||
font-size: 24rpx;
|
||
color: #fff;
|
||
}
|
||
|
||
.dot {
|
||
position: absolute;
|
||
top: -15rpx;
|
||
right: -10rpx;
|
||
background-color: #FF4B33;
|
||
color: #fff;
|
||
border-radius: 58rpx;
|
||
padding: 5rpx 14rpx;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 20rpx;
|
||
}
|
||
}
|
||
|
||
.Controls {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
|
||
// position: absolute;
|
||
// bottom: 10rpx;
|
||
// right: 20rpx;
|
||
.num {
|
||
margin: auto 16rpx;
|
||
}
|
||
|
||
.btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
|
||
.btnClick {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
position: absolute;
|
||
// bottom: 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
.lineThrough {
|
||
font-weight: normal;
|
||
text-decoration: line-through;
|
||
color: #999 !important;
|
||
font-size: 24rpx !important;
|
||
}
|
||
|
||
.money_num.lineThrough {}
|
||
}
|
||
|
||
|
||
.shop_sku {
|
||
width: 100%;
|
||
position: relative;
|
||
border-radius: 20rpx;
|
||
background: #fff;
|
||
box-sizing: border-box;
|
||
padding-bottom: 250rpx;
|
||
|
||
.positionabsolute {
|
||
position: absolute;
|
||
top: 30rpx;
|
||
z-index: 999;
|
||
right: 30rpx;
|
||
}
|
||
|
||
|
||
.shop_sku_name {
|
||
padding: 0 28rpx;
|
||
margin-top: 20rpx;
|
||
font-weight: bold;
|
||
font-size: 32upx;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.shop_sku_returned {
|
||
padding: 0 28rpx;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #FF534B;
|
||
}
|
||
|
||
.shop_sku_description {
|
||
padding: 0 28rpx;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
margin-top: 16rpx;
|
||
padding-bottom: 32rpx;
|
||
box-sizing: border-box;
|
||
border-bottom: 2rpx solid #F0F0F0;
|
||
}
|
||
|
||
.shop_sku_box:last-child {
|
||
padding-bottom: 60rpx;
|
||
}
|
||
|
||
.shop_sku_box {
|
||
padding: 20rpx;
|
||
|
||
.shop_sku_box_name {
|
||
margin-top: 20rpx;
|
||
font-weight: 500;
|
||
font-size: 28upx;
|
||
color: #333;
|
||
}
|
||
|
||
.flex-start {
|
||
.shop_sku_box_item {
|
||
margin-top: 16rpx;
|
||
padding: 12rpx 28rpx;
|
||
border-radius: 8rpx;
|
||
font-size: 24upx;
|
||
margin-right: 56rpx;
|
||
background: #EFEFEF;
|
||
border: 2rpx solid #EFEFEF;
|
||
position: relative;
|
||
color: #666666;
|
||
|
||
.shop_sku_box_item_tip {
|
||
width: 62rpx;
|
||
height: 47rpx;
|
||
text-align: right;
|
||
position: absolute;
|
||
top: 0;
|
||
right: 0;
|
||
background: linear-gradient(45deg, transparent, transparent 50%, #CECECE 50%, #CECECE 100%);
|
||
|
||
view {
|
||
font-size: 18rpx;
|
||
color: #666666;
|
||
transform: rotate(45deg);
|
||
position: absolute;
|
||
top: 5rpx;
|
||
right: 3rpx;
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
.shop_sku_box_item:nth-child(1) {
|
||
margin-left: 0;
|
||
}
|
||
|
||
.disabled {
|
||
color: #999;
|
||
background-color: #F5F5F5;
|
||
border: 2rpx solid #F5F5F5;
|
||
}
|
||
|
||
.shop_sku_box_item_noselected {
|
||
color: #666;
|
||
}
|
||
|
||
.shop_sku_box_item_selected {
|
||
background: #FEFAF7;
|
||
border-radius: 8rpx;
|
||
border: 2rpx solid #E8AD7B;
|
||
color: #E8AD7B;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
.shop_skuselect {
|
||
margin-top: 16rpx;
|
||
width: 100%;
|
||
// background: #f7f7f7;
|
||
color: #999;
|
||
font-size: 24upx;
|
||
|
||
.shop_skuselectname {
|
||
color: #000;
|
||
font-size: 26upx;
|
||
}
|
||
}
|
||
|
||
.shop_bottom {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
padding: 30rpx 28rpx;
|
||
background-color: #fff;
|
||
box-shadow: 0rpx -6rpx 14rpx 2rpx rgba(0, 0, 0, 0.1);
|
||
position: fixed;
|
||
left: 0;
|
||
bottom: 0;
|
||
|
||
.price {
|
||
display: flex;
|
||
align-items: flex-end;
|
||
|
||
.i {
|
||
font-size: 28rpx;
|
||
color: #E8AD7B;
|
||
position: relative;
|
||
bottom: 4upx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.num {
|
||
font-size: 42rpx;
|
||
color: #E8AD7B;
|
||
position: relative;
|
||
top: 6upx;
|
||
padding: 0 4upx;
|
||
}
|
||
}
|
||
|
||
.operation-wrap {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.num {
|
||
font-size: 32upx;
|
||
padding: 0 16upx;
|
||
}
|
||
|
||
.btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
|
||
.btnClick {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
position: absolute;
|
||
// bottom: 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.addShopping {
|
||
width: 100%;
|
||
height: 96rpx;
|
||
line-height: 96rpx;
|
||
text-align: center;
|
||
background: #ccc;
|
||
border-radius: 48rpx;
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
color: #FFFFFF;
|
||
margin-top: 36rpx;
|
||
}
|
||
|
||
.addShopping.active {
|
||
background: #E8AD7B;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
.shop-info-wrap {
|
||
padding: 0 30rpx 50rpx;
|
||
box-sizing: border-box;
|
||
|
||
.info-wrap {
|
||
padding: 30rpx 0;
|
||
box-sizing: border-box;
|
||
|
||
.shopName {
|
||
align-self: center;
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
|
||
.info-wrap-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
}
|
||
|
||
.row {
|
||
.col {
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.l,
|
||
.t {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
|
||
.cart-wrap {
|
||
width: 100%;
|
||
padding: 0 20rpx;
|
||
box-sizing: border-box;
|
||
position: fixed;
|
||
bottom: 40rpx;
|
||
left: 0;
|
||
z-index: 99;
|
||
|
||
.cart-content {
|
||
display: flex;
|
||
align-items: center;
|
||
height: 128rpx;
|
||
background: #FFFFFF;
|
||
box-shadow: 0rpx 0rpx 20rpx 2rpx rgba(0, 0, 0, 0.15);
|
||
border-radius: 58rpx;
|
||
padding: 0 36rpx;
|
||
box-sizing: border-box;
|
||
|
||
.left {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
position: relative;
|
||
|
||
.iconBox {
|
||
position: relative;
|
||
}
|
||
|
||
.icon {
|
||
width: 76rpx;
|
||
height: 88rpx;
|
||
margin-left: 22rpx;
|
||
}
|
||
|
||
.u-badge {
|
||
position: absolute;
|
||
top: -30rpx;
|
||
right: -30rpx;
|
||
background-color: #FF4B33;
|
||
color: #fff;
|
||
border-radius: 58rpx;
|
||
padding: 5rpx 14rpx;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 20rpx;
|
||
}
|
||
|
||
.i,
|
||
.num {
|
||
color: #333;
|
||
}
|
||
|
||
.i {
|
||
font-size: 20upx;
|
||
position: relative;
|
||
top: 4upx;
|
||
margin-left: 64rpx;
|
||
}
|
||
|
||
.num {
|
||
font-size: 42upx;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
|
||
.btn {
|
||
height: 100%;
|
||
width: 40%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
|
||
.t {
|
||
width: 160rpx;
|
||
height: 64rpx;
|
||
line-height: 64rpx;
|
||
text-align: center;
|
||
background: #FEFAF7;
|
||
border-radius: 36rpx 36rpx 36rpx 36rpx;
|
||
border: 2rpx solid $my-main-color;
|
||
font-weight: bold;
|
||
font-size: 28rpx;
|
||
color: $my-main-color;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.history_order {
|
||
background-color: #fff;
|
||
padding: 12rpx 16rpx;
|
||
font-size: 24rpx;
|
||
color: #333;
|
||
display: flex;
|
||
align-items: center;
|
||
box-shadow: 0rpx 6rpx 12rpx 2rpx rgba(0, 0, 0, 0.16);
|
||
position: fixed;
|
||
top: 50%;
|
||
right: 0;
|
||
transform: translateY(-50%);
|
||
border-radius: 100px 0 0 100px;
|
||
z-index: 20;
|
||
|
||
.img {
|
||
width: 36rpx;
|
||
margin-right: 8rpx;
|
||
height: 36rpx;
|
||
}
|
||
}
|
||
</style> |