menu.vue 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621
  1. <template>
  2. <layout>
  3. <!-- #ifdef MP-WEIXIN -->
  4. <uv-navbar
  5. :fixed="false"
  6. :title="title"
  7. left-arrow
  8. @leftClick="$onClickLeft"
  9. />
  10. <!-- #endif -->
  11. <view class="container" v-if="!loading">
  12. <view class="main">
  13. <view class="nav">
  14. <view class="header" v-if="isScan">
  15. <view class="mr-1">
  16. <image :src="store.image" class="rounded-circle" style="width:80rpx ; height: 80rpx; "></image>
  17. </view>
  18. <view class="left" style="">
  19. <view class="store-name" @click="selectShop()">
  20. <text style="font-size: 26rpx;">{{ store.name }}</text>
  21. </view>
  22. <view class="store-location">
  23. <text>{{ store.address }}</text>
  24. </view>
  25. </view>
  26. <view class="right flex flex-column" style="background-color: #ffffff;color: black;" >
  27. <view>桌位号:{{ desk.number }}</view>
  28. <view class="mt-1"> 人数:{{ desk.people }}人</view>
  29. </view>
  30. </view>
  31. <view class="header" v-else>
  32. <view class="mr-1"><image :src="store.image" class="rounded-circle" style="width:80rpx ; height: 80rpx; "></image></view>
  33. <view class="left" v-if="orderType == 'takein'" style="">
  34. <view class="store-name" @click="selectShop()">
  35. <text>{{ store.name }}</text>
  36. <view class="iconfont iconarrow-right"></view>
  37. </view>
  38. <view class="store-location">
  39. <text class="font-weight-bold">自取</text> <text class="px-1">|</text><text>距离:{{kmUnit(store.dis)}}</text>
  40. </view>
  41. </view>
  42. <view class="left overflow-hidden" v-else>
  43. <view class="store-name" @click="selectShop()">
  44. <view class="flex flex-column">
  45. <view class="flex align-center">
  46. <text>{{ store.name }}</text>
  47. <view class="iconfont iconarrow-right"></view>
  48. </view>
  49. <view class="store-location">
  50. <text class="font-weight-bold">外卖</text> <text class="px-1">|</text><text>配送距离:{{store.distance}}km</text>
  51. </view>
  52. </view>
  53. </view>
  54. </view>
  55. </view>
  56. <view v-if="isShowAd" class="pl-1 pr-2">
  57. <uv-swiper height="150" imgMode="aspectFill" :list="toArrImgs(store.images)" indicatorMode="dot" indicatorStyle="bottom"></uv-swiper>
  58. </view>
  59. </view>
  60. <!-- #ifdef H5 -->
  61. <view class="content"
  62. :style="{height: 'calc(100vh - 300rpx + '+(store.notice ? '0rpx':'60rpx')+')'}">
  63. <!-- #endif -->
  64. <!-- #ifndef H5 -->
  65. <view class="content" :style="{height: 'calc(100vh - 350rpx + '+(store.notice ? '0rpx':'60rpx')+')'}">
  66. <!-- #endif -->
  67. <scroll-view class="menus" :scroll-into-view="menuScrollIntoView" scroll-with-animation scroll-y>
  68. <view class="wrapper">
  69. <view class="menu" :id="`menu-${item.id}`" :class="{'current': item.id === currentCateId}"
  70. v-for="(item, index) in goods" :key="index" @tap="handleMenuTap(item.id)">
  71. <text>{{ item.name }}</text>
  72. <view class="dot" v-show="menuCartNum(item.id)">{{ menuCartNum(item.id) }}</view>
  73. </view>
  74. </view>
  75. </scroll-view>
  76. <!-- goods list begin -->
  77. <scroll-view class="goods" scroll-with-animation scroll-y :scroll-top="cateScrollTop"
  78. @scroll="handleGoodsScroll" @scrolltoupper="goBotttom">
  79. <view class="wrapper">
  80. <view class="list">
  81. <!-- category begin -->
  82. <view class="category" v-for="(item, index) in goods" :key="index"
  83. :id="`cate-${item.id}`">
  84. <view class="title">
  85. <text>{{ item.name }}</text>
  86. <image mode="aspectFill" :src="item.picUrl" class="icon"></image>
  87. </view>
  88. <view class="items">
  89. <!-- 商品 begin -->
  90. <view class="good" v-for="(good, key) in item.goodsList" :key="key"
  91. :class="{'backgroud-grey': good.stock <= 0}">
  92. <image mode="aspectFill" :src="good.image" class="image"
  93. @tap="goDetail(good.id)"></image>
  94. <view class="right">
  95. <text class="name" @tap="goDetail(good.id)">{{ good.storeName }}</text>
  96. <text class="tips">{{ good.storeInfo }}</text>
  97. <view class="price_and_action">
  98. <text class="price">¥{{ good.price }}</text>
  99. <view class="btn-group" v-if="good.stock > 0 && good.productAttr.length >= 1 && good.productAttr[0].attrValues != '默认'">
  100. <button type="primary" class="btn property_btn"
  101. hover-class="none" size="mini"
  102. @tap="showGoodDetailModal(item, good)">
  103. 选规格
  104. </button>
  105. <view class="dot" v-show="goodCartNum(good.id)">
  106. {{ goodCartNum(good.id) }}</view>
  107. </view>
  108. <view class="btn-group" v-if="good.stock > 0 && good.productAttr.length == 1 && good.productAttr[0].attrValues == '默认'">
  109. <button type="default" v-show="goodCartNum(good.id)" plain class="btn reduce_btn"
  110. size="mini" hover-class="none" @tap="handleReduceFromCart(item, good)">
  111. <view class="iconfont iconsami-select"></view>
  112. </button>
  113. <view class="number" v-show="goodCartNum(good.id)">{{ goodCartNum(good.id) }}</view>
  114. <button type="primary" class="btn add_btn" size="min" hover-class="none"
  115. @tap="handleAddToCart(item, good, 1)">
  116. <view class="iconfont iconadd-select"></view>
  117. </button>
  118. </view>
  119. <view v-if="good.stock == 0">已售罄</view>
  120. </view>
  121. </view>
  122. </view>
  123. <!-- 商品 end -->
  124. </view>
  125. </view>
  126. <!-- category end -->
  127. <view style="height: 110rpx;"></view>
  128. </view>
  129. </view>
  130. </scroll-view>
  131. <!-- goods list end -->
  132. </view>
  133. <!-- content end -->
  134. <!-- 购物车栏 begin -->
  135. <view class="cart-box" v-if="cart.length > 0 && isCartShow">
  136. <view class="mark">
  137. <image src="/static/images/cart.png" class="cart-img" @tap="isScan ? toPay() : openCartPopup()"></image>
  138. <view class="tag">{{ getCartGoodsNumber }}</view>
  139. </view>
  140. <view class="price">¥{{ getCartGoodsPrice }}</view>
  141. <button type="primary" class="pay-btn" @tap="toPay" :disabled="disabledPay">
  142. {{ disabledPay ? `差${spread}元起送` : '去结算' }}
  143. </button>
  144. </view>
  145. <!-- 购物车栏 end -->
  146. </view>
  147. <!-- 商品详情模态框 begin -->
  148. <modal :show="goodDetailModalVisible" class="good-detail-modal" color="#5A5B5C" width="90%" custom
  149. padding="0rpx" radius="12rpx">
  150. <view class="cover">
  151. <view class="btn-group">
  152. <image src="/static/images/menu/close.png" @tap="closeGoodDetailModal"></image>
  153. </view>
  154. </view>
  155. <scroll-view class="detail" scroll-y>
  156. <view v-if="good.image" class="image">
  157. <image :src="good.image"></image>
  158. </view>
  159. <view class="wrapper">
  160. <view class="basic">
  161. <view class="name">{{ good.storeName }}</view>
  162. <view class="tips flex justify-between">{{ good.storeInfo }}</view>
  163. </view>
  164. <view class="properties">
  165. <view class="property" v-for="(item, index) in good.productAttr" :key="index">
  166. <view class="title">
  167. <text class="name">{{ item.attrName }}</text>
  168. </view>
  169. <view class="values">
  170. <view class="value" v-for="(value, key) in item.attrValueArr" :key="key"
  171. :class="{'default': value == newValue[index]}"
  172. @tap="changePropertyDefault(index, key,false)">
  173. {{ value }}
  174. </view>
  175. </view>
  176. </view>
  177. </view>
  178. </view>
  179. </scroll-view>
  180. <view class="action">
  181. <view class="left">
  182. <view class="price">¥{{ good.price }}</view>
  183. <view class="props">
  184. {{ good.valueStr }}
  185. </view>
  186. </view>
  187. <view class="btn-group">
  188. <text style="margin-right: 20rpx;">库存:{{good.stock}} </text>
  189. <button type="default" plain class="btn" size="mini" hover-class="none"
  190. @tap="handlePropertyReduce">
  191. <view class="iconfont iconsami-select"></view>
  192. </button>
  193. <view class="number">{{ good.number }}</view>
  194. <button type="primary" class="btn" size="min" hover-class="none" @tap="handlePropertyAdd">
  195. <view class="iconfont iconadd-select"></view>
  196. </button>
  197. </view>
  198. </view>
  199. <view class="add-to-cart-btn" @tap="handleAddToCartInModal">
  200. <view>加入购物车</view>
  201. </view>
  202. </modal>
  203. <!-- 商品详情模态框 end -->
  204. <!-- 购物车详情popup -->
  205. <uv-popup ref="popup" mode="bottom" class="cart-popup" :customStyle="customStyle">
  206. <template #default>
  207. <view class="cart-popup">
  208. <view class="top flex justify-between">
  209. <text>购物车({{ getCartGoodsNumber }}份)</text>
  210. <view class="flex align-center"><uv-icon name="trash" size="20"></uv-icon><text @tap="handleCartClear">清空购物车</text></view>
  211. </view>
  212. <scroll-view class="cart-list" scroll-y>
  213. <view class="wrapper">
  214. <view class="item" v-for="(item, index) in cart" :key="index">
  215. <view class="left">
  216. <view class="flex align-center">
  217. <view>
  218. <image mode="aspectFill" :src="item.image" style="width: 100rpx;height: 100rpx;"></image>
  219. </view>
  220. <view class="ml-2">
  221. <view class="name">{{ item.name }}</view>
  222. <view class="props">{{ item.valueStr }}</view>
  223. <text class="price"><text class="font-size:16rpx">¥</text>{{ item.price }}</text>
  224. </view>
  225. </view>
  226. </view>
  227. <!-- <view class="center">
  228. <text>¥{{ item.price }}</text>
  229. </view> -->
  230. <view class="right">
  231. <button type="default" plain size="mini" class="btn" hover-class="none"
  232. @tap="handleCartItemReduce(index)">
  233. <view class="iconfont iconsami-select"></view>
  234. </button>
  235. <view class="number">{{ item.number }}</view>
  236. <button type="primary" class="btn" size="min" hover-class="none"
  237. @tap="handleCartItemAdd(index)">
  238. <view class="iconfont iconadd-select"></view>
  239. </button>
  240. </view>
  241. </view>
  242. </view>
  243. </scroll-view>
  244. </view>
  245. </template>
  246. </uv-popup>
  247. <!-- 购物车详情popup -->
  248. <uv-toast ref="uToast"></uv-toast>
  249. </view>
  250. <!--轻提示-->
  251. <view class="loading" v-else>
  252. <!-- <uv-loading-icon color="#DA5650" size=40 mode="circle" ></uv-loading-icon> -->
  253. <button type="primary" style="z-index: 3001;position: absolute;top: 650rpx;" @click="init"
  254. >定位最近的门店</button>
  255. <!-- <uv-toast ref="uToast"></uv-toast> -->
  256. </view>
  257. </layout>
  258. </template>
  259. <script setup>
  260. import {
  261. ref,
  262. toRefs,
  263. computed,
  264. nextTick
  265. } from 'vue'
  266. import { useMainStore } from '@/store/store'
  267. import { storeToRefs } from 'pinia'
  268. import { onLoad,onShow ,onPullDownRefresh,onHide,onUnload} from '@dcloudio/uni-app'
  269. import { formatDateTime,kmUnit } from '@/utils/util'
  270. import {
  271. shopNearby,
  272. menuGoods
  273. } from '@/api/goods'
  274. import {
  275. syncCart
  276. } from '@/api/order'
  277. import { useWebSocket } from '@/hooks/useWebSocket'
  278. const main = useMainStore()
  279. const { orderType,address, store,location,isLogin,desk,isScan } = storeToRefs(main)
  280. const title = ref('点餐')
  281. const text = ref('滚动通知')
  282. const goods = ref([])
  283. const ads = ref([])
  284. const loading = ref(true)
  285. const currentCateId = ref(0)
  286. const cateScrollTop = ref(0)
  287. const menuScrollIntoView = ref('')
  288. const cart = ref([])
  289. const goodDetailModalVisible = ref(false)
  290. const good= ref({})
  291. const category = ref({})
  292. const cartPopupVisible = ref(false)
  293. const sizeCalcState = ref(false)
  294. const newValue = ref([])
  295. const shopAd = ref('')
  296. const isCartShow = ref(true)
  297. const isClick = ref(false)
  298. const popup = ref()
  299. const isShowAd = ref(true)
  300. const customStyle = computed(() =>{
  301. // #ifdef H5
  302. return {
  303. bottom:'120rpx'
  304. }
  305. // #endif
  306. // #ifdef MP-WEIXIN
  307. return {
  308. bottom:'0rpx'
  309. }
  310. // #endif
  311. })
  312. const goodCartNum = computed(() => { //计算单个饮品添加到购物车的数量
  313. return (id) => cart.value.reduce((acc, cur) => {
  314. if (cur.id === id) {
  315. return acc += cur.number
  316. }
  317. return acc
  318. }, 0)
  319. })
  320. const menuCartNum = computed(() =>{
  321. return (id) => cart.value.reduce((acc, cur) => {
  322. if (cur.cate_id === id) {
  323. return acc += cur.number
  324. }
  325. return acc
  326. }, 0)
  327. })
  328. const getCartGoodsNumber = computed(() => { //计算购物车总数
  329. return cart.value.reduce((acc, cur) => acc + cur.number, 0)
  330. })
  331. const getCartGoodsPrice = computed(() =>{ //计算购物车总价
  332. let price = cart.value.reduce((acc, cur) => acc + cur.number * cur.price, 0);
  333. return parseFloat(price).toFixed(2);
  334. })
  335. const disabledPay = computed(() => { //是否达到起送价
  336. console.log('store.value.minPrice:',store.value.minPrice)
  337. console.log('orderType.value:',orderType.value)
  338. console.log('getCartGoodsPrice:',getCartGoodsPrice)
  339. return orderType.value == 'takeout' && (getCartGoodsPrice.value < parseFloat(store.value.minPrice)) ? true :
  340. false
  341. })
  342. const spread = computed(() => { //差多少元起送
  343. if (orderType.value != 'takeout') return
  344. return parseFloat((store.value.minPrice - getCartGoodsPrice.value).toFixed(2))
  345. })
  346. // 监听自定义事件
  347. uni.$on('refreshMenu', () => {
  348. // 在这里执行onLoad逻辑
  349. init()
  350. })
  351. onPullDownRefresh(() => {
  352. init()
  353. })
  354. onLoad(() => {
  355. if(isScan.value){
  356. getProducts()
  357. }else{
  358. init();
  359. }
  360. refreshCart()
  361. })
  362. onHide(() => {
  363. // 重新进入要重新计算页面高度,否则有问题
  364. sizeCalcState.value = false;
  365. })
  366. onShow(() => {
  367. //init();
  368. refreshCart()
  369. })
  370. const goDetail = (id) => {
  371. uni.navigateTo({
  372. url: '/pages/components/pages/menudetail/menudetail?id=' + id
  373. })
  374. }
  375. const openCartShow = () =>{
  376. isCartShow.value = false
  377. }
  378. const in_array = (search, array) => {
  379. for (var i in array) {
  380. if (array[i] == search) {
  381. return true;
  382. }
  383. }
  384. return false;
  385. }
  386. const selectShop = () => {
  387. uni.navigateTo({
  388. url: '/pages/components/pages/shop/shop?type=1'
  389. })
  390. }
  391. const uToast = ref()
  392. const getProducts = async() => {
  393. let shop = store.value
  394. if (shop) {
  395. shop.notice = shop.status == 1 ? shop.notice : '店铺营业时间为:' + formatDateTime(shop.startTime,'hh:mm')+' - '+formatDateTime(shop.endTime,'hh:mm') +
  396. ',不在营业时间内无法下单';
  397. // 设置店铺信息
  398. main.SET_STORE(shop);
  399. let mygoods = await menuGoods({
  400. shopId: shop.id
  401. });
  402. if (mygoods) {
  403. goods.value = mygoods;
  404. currentCateId.value = mygoods[0].id
  405. refreshCart();
  406. }
  407. loading.value = false;
  408. uni.stopPullDownRefresh();
  409. }
  410. }
  411. const init = async() => { //页面初始化
  412. loading.value = true;
  413. let error = {},
  414. result = location.value
  415. if (!location.value.hasOwnProperty('latitude')) {
  416. uni.getLocation(({
  417. type: 'wgs84',
  418. success: function (res) {
  419. result = {
  420. latitude: res.latitude,
  421. longitude: res.longitude
  422. };
  423. getShopList(result)
  424. },
  425. fail: function (res) {
  426. uni.showToast({
  427. title: '获取位置失败,请检查是否开启相关权限',
  428. duration: 2000,
  429. icon: 'error'
  430. });
  431. // 默认地为你为北京地址
  432. result = {
  433. latitude: 39.919990,
  434. longitude: 116.456270
  435. };
  436. getShopList(result)
  437. },
  438. complete: function (res) {
  439. }
  440. }));
  441. return
  442. }
  443. getShopList(result)
  444. }
  445. const getShopList = async(res) => {
  446. if (res) {
  447. main.SET_LOCATION(res);
  448. let shop_id = 0;
  449. console.log('store.value:',store.value.id)
  450. if (store.value.id) {
  451. shop_id = store.value.id;
  452. }
  453. let shop = await shopNearby({
  454. lat: res.latitude,
  455. lng: res.longitude,
  456. shop_id: shop_id,
  457. kw: ''
  458. });
  459. if (shop) {
  460. shop.notice = shop.status == 1 ? shop.notice : '店铺营业时间为:' + formatDateTime(shop.startTime,'hh:mm')+' - '+formatDateTime(shop.endTime,'hh:mm') +
  461. ',不在营业时间内无法下单';
  462. // 设置店铺信息
  463. main.SET_STORE(shop);
  464. let mygoods = await menuGoods({
  465. shopId: shop.id
  466. });
  467. if (mygoods.length > 0) {
  468. goods.value = mygoods;
  469. currentCateId.value = mygoods[0].id
  470. refreshCart();
  471. }else{
  472. goods.value = [];
  473. refreshCart();
  474. }
  475. loading.value = false;
  476. uni.stopPullDownRefresh();
  477. }
  478. }
  479. }
  480. const refreshCart = () =>{
  481. if (goods.value && goods.value.length > 0) {
  482. let newGoods = goods.value;
  483. cart.value = [];
  484. let newCart = uni.getStorageSync('cart') || [];
  485. let tmpCart = [];
  486. if (newCart) {
  487. for (let i in newCart) {
  488. for (let ii in newGoods) {
  489. for (let iii in newGoods[ii].goodsList) {
  490. if (newCart[i].id == newGoods[ii].goodsList[iii].id) {
  491. tmpCart.push(newCart[i]);
  492. }
  493. }
  494. }
  495. }
  496. cart.value = tmpCart;
  497. cartPopupVisible.value = false;
  498. }
  499. }
  500. }
  501. const openCartPopup = () => { //打开/关闭购物车列表popup
  502. popup.value.open()
  503. }
  504. const takout = (force = false) => {
  505. if (orderType.value == 'takeout' && force == false) return
  506. main.SET_ORDER_TYPE('takeout');
  507. if (!isLogin.value) {
  508. uni.navigateTo({
  509. url: '/pages/components/pages/login/login'
  510. })
  511. return
  512. }
  513. }
  514. const takein = (force = false) => {
  515. if (orderType.value == 'takein' && force == false) return
  516. main.SET_ORDER_TYPE('takein');
  517. if (!isLogin.value) {
  518. uni.navigateTo({
  519. url: '/pages/components/pages/login/login'
  520. })
  521. return
  522. }
  523. }
  524. const handleMenuTap = (id) => { //点击菜单项事件
  525. if (!sizeCalcState.value) {
  526. calcSize()
  527. }
  528. setTimeout(() => {
  529. cateScrollTop.value = goods.value.find(item => {
  530. return item.id == id
  531. }).top
  532. }, 100);
  533. currentCateId.value = id
  534. isClick.value = true
  535. }
  536. const goBotttom = () => {
  537. isShowAd.value = true
  538. }
  539. const handleGoodsScroll = ({ detail }) => { //商品列表滚动事件
  540. isShowAd.value = false
  541. if (!sizeCalcState.value) {
  542. calcSize()
  543. }
  544. const {
  545. scrollTop
  546. } = detail
  547. let tabs = goods.value.filter(item => item.top <= scrollTop).reverse()
  548. if (tabs.length > 0) {
  549. if(isClick.value ){
  550. //currentCateId.value = tabs[0].id
  551. }else{
  552. currentCateId.value = tabs[0].id
  553. }
  554. isClick.value = false
  555. }
  556. }
  557. const calcSize = () => {
  558. let h = 10
  559. goods.value.forEach(item => {
  560. let view = uni.createSelectorQuery().select(`#cate-${item.id}`)
  561. view.fields({
  562. size: true
  563. }, data => {
  564. item.top = h
  565. h += data.height
  566. item.bottom = h
  567. }).exec()
  568. })
  569. sizeCalcState.value = true
  570. }
  571. const handleAddToCart = (cate, newGood, num) =>{ //添加到购物车
  572. if(store.value.status == 0) {
  573. uToast.value.show({message:'店铺已经歇业',type: 'error'});
  574. return;
  575. }
  576. const index = cart.value.findIndex(item => {
  577. if (newGood) {
  578. return (item.id === newGood.id) && (item.valueStr === good.value.valueStr)
  579. } else {
  580. return item.id === newGood.id
  581. }
  582. })
  583. if (index > -1) {
  584. cart.value[index].number += num
  585. } else {
  586. cart.value.push({
  587. id: newGood.id,
  588. cate_id: cate.id,
  589. name: newGood.storeName,
  590. price: newGood.price,
  591. number: num,
  592. image: newGood.image,
  593. valueStr: good.value.valueStr
  594. })
  595. }
  596. if(isScan.value){
  597. noticeCartInfo({shopId: store.value.id,deskId:desk.value.id,content: cart.value})
  598. }
  599. uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
  600. }
  601. const noticeCartInfo = async(cart) => {
  602. await syncCart(cart)
  603. }
  604. const handleReduceFromCart = (item, good) => {
  605. const index = cart.value.findIndex(item => item.id === good.id)
  606. cart.value[index].number -= 1
  607. if (cart.value[index].number <= 0) {
  608. cart.value.splice(index, 1)
  609. }
  610. uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
  611. }
  612. const showGoodDetailModal = (item, newGood) => {
  613. isCartShow.value = true
  614. good.value = JSON.parse(JSON.stringify({
  615. ...newGood,
  616. number: 1
  617. }))
  618. category.value = JSON.parse(JSON.stringify(item))
  619. goodDetailModalVisible.value = true;
  620. changePropertyDefault(0, 0,true);
  621. }
  622. const closeGoodDetailModal = () => { //关闭饮品详情模态框
  623. goodDetailModalVisible.value = false
  624. category.value = {}
  625. good.value = {}
  626. }
  627. const changePropertyDefault = (index, key, isDefault) => { //改变默认属性值
  628. let valueStr = ''
  629. if(isDefault){
  630. newValue.value = []
  631. for(let i = 0;i < good.value.productAttr.length;i++){
  632. newValue.value[i] = good.value.productAttr[i].attrValueArr[0]
  633. }
  634. }else{
  635. newValue.value[index] = good.value.productAttr[index].attrValueArr[key]
  636. }
  637. valueStr = newValue.value.join(',')
  638. let productValue = good.value.productValue[valueStr]
  639. //console.log('productValue:',productValue)
  640. if(!productValue) {
  641. let skukey = JSON.parse(JSON.stringify(newValue.value))
  642. skukey.sort((a, b) => a.localeCompare(b))
  643. //console.log('skukey:',skukey)
  644. valueStr = skukey.join(',')
  645. productValue = good.value.productValue[valueStr]
  646. }
  647. good.value.number = 1;
  648. good.value.price = parseFloat(productValue.price).toFixed(2);
  649. good.value.stock = productValue.stock;
  650. good.value.image = productValue.image ? productValue.image : good.value.image;
  651. good.value.valueStr = valueStr
  652. }
  653. const handlePropertyAdd = () => {
  654. good.value.number += 1
  655. }
  656. const handlePropertyReduce = () => {
  657. if (good.value.number === 1) return
  658. good.value.number -= 1
  659. }
  660. const handleAddToCartInModal = () => {
  661. if(store.value.status == 0) {
  662. uToast.value.show({message:'店铺已经歇业',type: 'error'});
  663. return;
  664. }
  665. if (good.value.stock <= 0) {
  666. uToast.value.show({message:'商品库存不足',type: 'error'});
  667. return;
  668. }
  669. handleAddToCart(category.value, good.value, good.value.number)
  670. closeGoodDetailModal()
  671. }
  672. const handleCartClear = () => { //清空购物车
  673. uni.showModal({
  674. title: '提示',
  675. content: '确定清空购物车么',
  676. success: ({
  677. confirm
  678. }) => {
  679. if (confirm) {
  680. popup.value.close()
  681. cart.value = []
  682. uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
  683. }
  684. }
  685. })
  686. }
  687. const handleCartItemAdd = (index) => {
  688. cart.value[index].number += 1
  689. uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
  690. }
  691. const handleCartItemReduce = (index) => {
  692. if (cart.value[index].number === 1) {
  693. cart.value.splice(index, 1)
  694. } else {
  695. cart.value[index].number -= 1
  696. }
  697. if (!cart.value.length) {
  698. cartPopupVisible.value = false
  699. }
  700. uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
  701. }
  702. const toPay = () => {
  703. if (!isLogin.value) {
  704. uni.navigateTo({
  705. url: '/pages/components/pages/login/login'
  706. })
  707. return
  708. } else {
  709. if(cart.value.length == 0){
  710. uToast.value.show({message:'请先去点餐哦',type: 'error'});
  711. return;
  712. }
  713. if(store.value.status == 0) {
  714. uToast.value.show({message:'店铺已经歇业',type: 'error'});
  715. return;
  716. }
  717. if (store.value.status == 0) {
  718. uToast.value.show({message:'不在店铺营业时间内',type: 'error'});
  719. return;
  720. }
  721. if(orderType.value == 'takeout' && store.value.distance <= 0){
  722. uToast.value.show({message:'本店不支持外卖',type: 'error'});
  723. return;
  724. }
  725. // 判断当前是否在配送范围内
  726. if (orderType.value == 'takeout' && store.value.distance < store.value.far) {
  727. uToast.value.show({message:'选中的地址不在配送范围',type: 'error'});
  728. return;
  729. }
  730. uni.showLoading({
  731. title: '加载中'
  732. })
  733. uni.setStorageSync('cart', JSON.parse(JSON.stringify(cart.value)))
  734. if(orderType.value == 'desk'){
  735. uni.navigateTo({
  736. url: '/pages/components/pages/cart/cart'
  737. })
  738. }else{
  739. uni.navigateTo({
  740. url: '/pages/components/pages/pay/pay'
  741. })
  742. }
  743. }
  744. uni.hideLoading()
  745. }
  746. const toArrImgs = (str) => {
  747. return str.split(",");
  748. }
  749. function removeCharByReplace(str, char) {
  750. const regex = new RegExp(char, 'g');
  751. return str.replace(regex, '');
  752. }
  753. </script>
  754. <style lang="scss" scoped>
  755. /* #ifdef H5 */
  756. page {
  757. height: auto;
  758. min-height: 100%;
  759. }
  760. /* #endif */
  761. .container {
  762. overflow: hidden;
  763. position: relative;
  764. }
  765. .loading {
  766. width: 100%;
  767. height: 100%;
  768. display: flex;
  769. align-items: center;
  770. justify-content: center;
  771. image {
  772. width: 260rpx;
  773. height: 260rpx;
  774. position: relative;
  775. margin-top: -200rpx;
  776. /* #ifdef h5 */
  777. margin-top: 0;
  778. /* #endif */
  779. }
  780. }
  781. .stores {
  782. width: 100%;
  783. display: flex;
  784. flex-direction: column;
  785. justify-content: flex-start;
  786. margin-bottom: -40rpx;
  787. .store {
  788. width: 100%;
  789. background-color: $bg-color-grey;
  790. padding: 20rpx;
  791. display: flex;
  792. align-items: center;
  793. margin-bottom: 20rpx;
  794. border-radius: 6rpx;
  795. .iconfont {
  796. font-size: 50rpx;
  797. margin-right: 15rpx;
  798. &.iconradio-button-off {
  799. color: $text-color-assist;
  800. }
  801. &.iconradio-button-on {
  802. color: $color-primary;
  803. }
  804. }
  805. .infos {
  806. flex: 1;
  807. display: flex;
  808. flex-direction: column;
  809. color: $text-color-base;
  810. overflow: hidden;
  811. .name_and_distance {
  812. width: 100%;
  813. display: flex;
  814. justify-content: space-between;
  815. margin-bottom: 10rpx;
  816. overflow: hidden;
  817. .name {
  818. flex: 1;
  819. flex-shrink: 0;
  820. overflow: hidden;
  821. text-overflow: ellipsis;
  822. white-space: nowrap;
  823. font-size: $font-size-lg;
  824. }
  825. .distance {
  826. flex-shrink: 0;
  827. font-size: $font-size-lg;
  828. font-weight: bold;
  829. margin-left: 20rpx;
  830. }
  831. }
  832. .street {
  833. color: $text-color-assist;
  834. font-size: $font-size-sm;
  835. }
  836. }
  837. }
  838. }
  839. .main {
  840. width: 100%;
  841. height: 100%;
  842. position: relative;
  843. }
  844. .nav {
  845. width: 100%;
  846. //height: 212rpx;
  847. //height: 140rpx;
  848. display: flex;
  849. flex-direction: column;
  850. .header {
  851. width: 100%;
  852. display: flex;
  853. align-items: center;
  854. justify-content: space-between;
  855. padding: 20rpx;
  856. background-color: #ffffff;
  857. height: 140rpx;
  858. .left {
  859. flex: 1;
  860. display: flex;
  861. flex-direction: column;
  862. .store-name {
  863. display: flex;
  864. justify-content: flex-start;
  865. align-items: center;
  866. font-size: $font-size-lg;
  867. margin-bottom: 10rpx;
  868. .small {
  869. font-size: $font-size-sm;
  870. color: $text-color-assist;
  871. }
  872. .iconfont {
  873. margin-left: 10rpx;
  874. line-height: 100%;
  875. }
  876. }
  877. .store-location {
  878. display: flex;
  879. justify-content: flex-start;
  880. align-items: center;
  881. color: $text-color-assist;
  882. font-size: $font-size-sm;
  883. .iconfont {
  884. vertical-align: middle;
  885. display: table-cell;
  886. color: $color-primary;
  887. line-height: 100%;
  888. }
  889. }
  890. }
  891. .right {
  892. background-color: $bg-color-grey;
  893. border-radius: 38rpx;
  894. display: flex;
  895. align-items: center;
  896. font-size: $font-size-sm;
  897. padding: 0 38rpx;
  898. color: $text-color-assist;
  899. .dinein,
  900. .takeout {
  901. position: relative;
  902. display: flex;
  903. align-items: center;
  904. &.active {
  905. padding: 14rpx 38rpx;
  906. color: #ffffff;
  907. background-color: $color-primary;
  908. //background-color: #5A5B5C;
  909. border-radius: 38rpx;
  910. }
  911. }
  912. .takeout {
  913. margin-left: 20rpx;
  914. height: 100%;
  915. flex: 1;
  916. padding: 14rpx 0;
  917. }
  918. .dinein.active {
  919. margin-left: -38rpx;
  920. }
  921. .takeout.active {
  922. margin-right: -38rpx;
  923. }
  924. }
  925. }
  926. .coupon {
  927. flex: 1;
  928. width: 100%;
  929. background-color: $bg-color-primary;
  930. font-size: $font-size-base;
  931. color: $color-primary;
  932. padding: 0 20rpx;
  933. display: flex;
  934. align-items: center;
  935. overflow: hidden;
  936. .title {
  937. flex: 1;
  938. margin-left: 10rpx;
  939. overflow: hidden;
  940. white-space: nowrap;
  941. text-overflow: ellipsis;
  942. }
  943. .iconfont {
  944. line-height: 100%;
  945. }
  946. }
  947. }
  948. .content {
  949. width: 100%;
  950. height: calc(100vh - 212rpx);
  951. /* #ifdef H5 */
  952. height: calc(100vh - 212rpx - 140rpx);
  953. /* #endif */
  954. display: flex;
  955. .menus {
  956. width: 200rpx;
  957. height: 100%;
  958. overflow: hidden;
  959. background-color: $bg-color-grey;
  960. .wrapper {
  961. width: 100%;
  962. height: 100%;
  963. .menu {
  964. display: flex;
  965. align-items: center;
  966. justify-content: flex-start;
  967. padding: 30rpx 20rpx;
  968. font-size: 26rpx;
  969. color: $text-color-assist;
  970. position: relative;
  971. &.current {
  972. background-color: #ffffff;
  973. //background-color: red;
  974. //color: $color-primary;
  975. font-weight: bold;
  976. }
  977. .dot {
  978. position: absolute;
  979. width: 34rpx;
  980. height: 34rpx;
  981. line-height: 34rpx;
  982. font-size: 22rpx;
  983. background-color: #e45656;
  984. //background-color: #5A5B5C;
  985. color: #ffffff;
  986. top: 16rpx;
  987. right: 10rpx;
  988. border-radius: 100%;
  989. text-align: center;
  990. }
  991. }
  992. .menu:last-child {
  993. margin-bottom: 200rpx;
  994. }
  995. }
  996. }
  997. .goods {
  998. flex: 1;
  999. height: 100%;
  1000. overflow: hidden;
  1001. background-color: #ffffff;
  1002. .wrapper {
  1003. width: 100%;
  1004. height: 100%;
  1005. padding: 20rpx;
  1006. .ads {
  1007. height: calc(300 / 550 * 510rpx);
  1008. image {
  1009. width: 100%;
  1010. height: 100%;
  1011. border-radius: 8rpx;
  1012. }
  1013. }
  1014. .list {
  1015. width: 100%;
  1016. font-size: $font-size-base;
  1017. .category {
  1018. width: 100%;
  1019. .title {
  1020. padding: 30rpx 0;
  1021. display: flex;
  1022. align-items: center;
  1023. color: $text-color-base;
  1024. .icon {
  1025. width: 38rpx;
  1026. height: 38rpx;
  1027. margin-left: 10rpx;
  1028. }
  1029. }
  1030. }
  1031. .category:last-child {
  1032. margin-bottom: 200rpx;
  1033. }
  1034. .items {
  1035. display: flex;
  1036. flex-direction: column;
  1037. padding-bottom: -30rpx;
  1038. .good {
  1039. display: flex;
  1040. align-items: center;
  1041. //margin-bottom: 30rpx;
  1042. padding: 15rpx 0;
  1043. .image {
  1044. width: 160rpx;
  1045. height: 160rpx;
  1046. margin-right: 20rpx;
  1047. border-radius: 8rpx;
  1048. }
  1049. .right {
  1050. flex: 1;
  1051. height: 160rpx;
  1052. overflow: hidden;
  1053. display: flex;
  1054. flex-direction: column;
  1055. align-items: flex-start;
  1056. justify-content: space-between;
  1057. padding-right: 14rpx;
  1058. .name {
  1059. font-size: $font-size-base;
  1060. margin-bottom: 10rpx;
  1061. width: 100%;
  1062. overflow: hidden;
  1063. text-overflow: ellipsis;
  1064. white-space: nowrap;
  1065. }
  1066. .tips {
  1067. width: 100%;
  1068. height: 40rpx;
  1069. line-height: 40rpx;
  1070. overflow: hidden;
  1071. text-overflow: ellipsis;
  1072. white-space: nowrap;
  1073. font-size: $font-size-sm;
  1074. color: $text-color-assist;
  1075. margin-bottom: 10rpx;
  1076. }
  1077. .price_and_action {
  1078. width: 100%;
  1079. display: flex;
  1080. justify-content: space-between;
  1081. align-items: center;
  1082. .price {
  1083. font-size: $font-size-base;
  1084. font-weight: 600;
  1085. }
  1086. .btn-group {
  1087. display: flex;
  1088. justify-content: space-between;
  1089. align-items: center;
  1090. position: relative;
  1091. .btn {
  1092. padding: 0 20rpx;
  1093. box-sizing: border-box;
  1094. font-size: $font-size-sm;
  1095. height: 44rpx;
  1096. line-height: 44rpx;
  1097. &.property_btn {
  1098. border-radius: 24rpx;
  1099. }
  1100. &.add_btn,
  1101. &.reduce_btn {
  1102. padding: 0;
  1103. width: 44rpx;
  1104. border-radius: 44rpx;
  1105. }
  1106. }
  1107. .dot {
  1108. position: absolute;
  1109. background-color: #ffffff;
  1110. border: 1px solid $color-primary;
  1111. color: $color-primary;
  1112. font-size: $font-size-sm;
  1113. width: 36rpx;
  1114. height: 36rpx;
  1115. line-height: 36rpx;
  1116. text-align: center;
  1117. border-radius: 100%;
  1118. right: -12rpx;
  1119. top: -10rpx;
  1120. }
  1121. .number {
  1122. width: 44rpx;
  1123. height: 44rpx;
  1124. line-height: 44rpx;
  1125. text-align: center;
  1126. }
  1127. }
  1128. }
  1129. }
  1130. }
  1131. }
  1132. }
  1133. }
  1134. }
  1135. }
  1136. .modal-box {
  1137. max-height: 90vh;
  1138. }
  1139. .good-detail-modal {
  1140. width: 100%;
  1141. height: 100%;
  1142. display: flex;
  1143. flex-direction: column;
  1144. .cover {
  1145. height: 20rpx;
  1146. display: flex;
  1147. justify-content: center;
  1148. align-items: center;
  1149. .btn-group {
  1150. position: absolute;
  1151. right: 10rpx;
  1152. top: 0rpx;
  1153. display: flex;
  1154. align-items: center;
  1155. justify-content: space-around;
  1156. z-index: 210;
  1157. image {
  1158. width: 80rpx;
  1159. height: 80rpx;
  1160. }
  1161. }
  1162. }
  1163. .detail {
  1164. width: 100%;
  1165. min-height: 1vh;
  1166. max-height: calc(90vh - 320rpx - 80rpx - 120rpx);
  1167. position: relative;
  1168. .image {
  1169. display: flex;
  1170. justify-content: center;
  1171. align-items: center;
  1172. image {
  1173. width: 260rpx;
  1174. height: 260rpx;
  1175. }
  1176. }
  1177. .wrapper {
  1178. width: 100%;
  1179. height: 100%;
  1180. overflow: hidden;
  1181. .basic {
  1182. padding: 0 20rpx 30rpx;
  1183. display: flex;
  1184. flex-direction: column;
  1185. .name {
  1186. font-size: $font-size-base;
  1187. color: $text-color-base;
  1188. margin-bottom: 10rpx;
  1189. }
  1190. .tips {
  1191. font-size: $font-size-sm;
  1192. color: $text-color-grey;
  1193. }
  1194. }
  1195. .properties {
  1196. width: 100%;
  1197. border-top: 2rpx solid $bg-color-grey;
  1198. padding: 10rpx 30rpx 0;
  1199. display: flex;
  1200. flex-direction: column;
  1201. .property {
  1202. width: 100%;
  1203. display: flex;
  1204. flex-direction: column;
  1205. margin-bottom: 30rpx;
  1206. padding-bottom: -16rpx;
  1207. .title {
  1208. width: 100%;
  1209. display: flex;
  1210. justify-content: flex-start;
  1211. align-items: center;
  1212. margin-bottom: 20rpx;
  1213. .name {
  1214. font-size: 26rpx;
  1215. color: $text-color-base;
  1216. margin-right: 20rpx;
  1217. }
  1218. .desc {
  1219. flex: 1;
  1220. font-size: $font-size-sm;
  1221. color: $color-primary;
  1222. overflow: hidden;
  1223. text-overflow: ellipsis;
  1224. white-space: nowrap;
  1225. }
  1226. }
  1227. .values {
  1228. width: 100%;
  1229. display: flex;
  1230. flex-wrap: wrap;
  1231. .value {
  1232. border-radius: 8rpx;
  1233. //background-color: $bg-color-grey;
  1234. border: solid 1rpx;
  1235. padding: 10rpx 35rpx;
  1236. font-size: 26rpx;
  1237. color: $text-color-assist;
  1238. margin-right: 16rpx;
  1239. margin-bottom: 16rpx;
  1240. &.default {
  1241. border: solid 2rpx;
  1242. border-color: $color-primary;
  1243. //background-color: $color-primary;
  1244. color: $text-color-base;
  1245. }
  1246. }
  1247. }
  1248. }
  1249. }
  1250. }
  1251. }
  1252. .action {
  1253. display: flex;
  1254. align-items: center;
  1255. justify-content: space-between;
  1256. background-color: $bg-color-grey;
  1257. height: 120rpx;
  1258. padding: 0 26rpx;
  1259. .left {
  1260. flex: 1;
  1261. display: flex;
  1262. flex-direction: column;
  1263. justify-content: center;
  1264. margin-right: 20rpx;
  1265. overflow: hidden;
  1266. .price {
  1267. font-size: $font-size-lg;
  1268. color: $text-color-base;
  1269. }
  1270. .props {
  1271. color: $text-color-assist;
  1272. font-size: 24rpx;
  1273. width: 100%;
  1274. overflow: hidden;
  1275. text-overflow: ellipsis;
  1276. white-space: nowrap;
  1277. }
  1278. }
  1279. .btn-group {
  1280. display: flex;
  1281. align-items: center;
  1282. justify-content: space-around;
  1283. .number {
  1284. font-size: $font-size-base;
  1285. width: 44rpx;
  1286. height: 44rpx;
  1287. line-height: 44rpx;
  1288. text-align: center;
  1289. }
  1290. .btn {
  1291. padding: 0;
  1292. font-size: $font-size-base;
  1293. width: 44rpx;
  1294. height: 44rpx;
  1295. line-height: 44rpx;
  1296. border-radius: 100%;
  1297. }
  1298. }
  1299. }
  1300. .add-to-cart-btn {
  1301. display: flex;
  1302. justify-content: center;
  1303. align-items: center;
  1304. background-color: $color-primary;
  1305. color: $text-color-white;
  1306. font-size: $font-size-base;
  1307. height: 80rpx;
  1308. border-radius: 0 0 12rpx 12rpx;
  1309. }
  1310. }
  1311. .cart-box {
  1312. position: fixed;
  1313. bottom: 5rpx;
  1314. /* #ifdef H5 */
  1315. bottom:var(--window-bottom);
  1316. //bottom: 100rpx;
  1317. /* #endif */
  1318. left: 30rpx;
  1319. right: 30rpx;
  1320. height: 80rpx;
  1321. border-radius: 48rpx;
  1322. box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.2);
  1323. background-color: #000;
  1324. display: flex;
  1325. align-items: center;
  1326. justify-content: space-between;
  1327. z-index: 99;
  1328. .cart-img {
  1329. width: 83rpx;
  1330. height: 83rpx;
  1331. position: relative;
  1332. //margin-top: -8rpx;
  1333. }
  1334. .pay-btn {
  1335. height: 100%;
  1336. padding: 0 30rpx;
  1337. color: #ffffff;
  1338. border-radius: 0 50rpx 50rpx 0;
  1339. display: flex;
  1340. align-items: center;
  1341. font-size: $font-size-base;
  1342. }
  1343. .mark {
  1344. padding-left: 46rpx;
  1345. margin-right: 30rpx;
  1346. position: relative;
  1347. .tag {
  1348. //background-color: $color-warning;
  1349. background-color: #e45656;;
  1350. color: $text-color-white;
  1351. display: flex;
  1352. justify-content: center;
  1353. align-items: center;
  1354. font-size: $font-size-sm;
  1355. position: absolute;
  1356. right: -10rpx;
  1357. top: 10rpx;
  1358. border-radius: 100%;
  1359. padding: 4rpx;
  1360. width: 35rpx;
  1361. height: 35rpx;
  1362. opacity: 0.9;
  1363. }
  1364. }
  1365. .price {
  1366. flex: 1;
  1367. color: #fff;
  1368. }
  1369. }
  1370. .cart-popup {
  1371. .top {
  1372. background-color: $bg-color-primary;
  1373. //color: $color-primary;
  1374. color: #5A5B5C;
  1375. padding: 10rpx 30rpx;
  1376. font-size: 24rpx;
  1377. text-align: right;
  1378. }
  1379. .cart-list {
  1380. background-color: #ffffff;
  1381. width: 100%;
  1382. overflow: hidden;
  1383. min-height: 1vh;
  1384. max-height: 60vh;
  1385. .wrapper {
  1386. height: 100%;
  1387. display: flex;
  1388. flex-direction: column;
  1389. padding: 0 30rpx;
  1390. //margin-bottom: 10rpx;
  1391. .item {
  1392. display: flex;
  1393. justify-content: space-between;
  1394. align-items: center;
  1395. padding: 30rpx 0;
  1396. position: relative;
  1397. &::after {
  1398. content: ' ';
  1399. position: absolute;
  1400. bottom: 0;
  1401. left: 0;
  1402. width: 100%;
  1403. background-color: $border-color;
  1404. height: 2rpx;
  1405. transform: scaleY(0.6);
  1406. }
  1407. .left {
  1408. flex: 1;
  1409. display: flex;
  1410. flex-direction: column;
  1411. overflow: hidden;
  1412. margin-right: 30rpx;
  1413. .name {
  1414. font-weight: bolder;
  1415. font-size: $font-size-sm;
  1416. color: $text-color-base;
  1417. }
  1418. .props {
  1419. color: $text-color-assist;
  1420. font-size: 24rpx;
  1421. overflow: hidden;
  1422. text-overflow: ellipsis;
  1423. white-space: nowrap;
  1424. }
  1425. .price{
  1426. font-size: $font-size-sm;
  1427. color: #e45656;
  1428. }
  1429. }
  1430. .center {
  1431. margin-right: 120rpx;
  1432. font-size: $font-size-base;
  1433. }
  1434. .right {
  1435. display: flex;
  1436. align-items: center;
  1437. justify-content: space-between;
  1438. .btn {
  1439. width: 46rpx;
  1440. height: 46rpx;
  1441. border-radius: 100%;
  1442. padding: 0;
  1443. text-align: center;
  1444. line-height: 46rpx;
  1445. }
  1446. .number {
  1447. font-size: $font-size-base;
  1448. width: 46rpx;
  1449. height: 46rpx;
  1450. text-align: center;
  1451. line-height: 46rpx;
  1452. }
  1453. }
  1454. }
  1455. }
  1456. }
  1457. }
  1458. .backgroud-grey {
  1459. background-color: #e1e4e4;
  1460. padding: 15rpx !important;
  1461. }
  1462. </style>