wip: frontend refactor

This commit is contained in:
Kroytz committed 2026-07-10 18:06:02 +08:00
1 parent aef417409a
commit c61283f466
2 files changed
+131 -262

No files matched your search

@@ -1,194 +1,33 @@
<template> <template>
<uv-navbar <uv-navbar :fixed="false" :title="title" left-arrow @leftClick="$onClickLeft" />
:fixed="false" <view class="pay-page">
:title="title"
left-arrow
@leftClick="$onClickLeft"
/>
<view class="pay-page container position-relative">
<view class="pay-page__content"> <view class="pay-page__content">
<view class="pay-page__section"> <view class="pay-page__store" @tap="goToShop">
<template v-if="store.distance > 0"> <text class="iconfont-yshop" :class="orderType == 'takeout' ? 'icon-takeout' : 'icon-takein'"></text>
<list-cell class="pay-page__cell pay-page__cell--location"> <text class="pay-page__store-type">{{ orderType == 'takeout' ? '外卖' : '堂食' }}</text>
<view class="flex-fill d-flex justify-content-between align-items-center"> <image v-if="store.image" :src="store.image" mode="aspectFill"></image>
<view class="store-name flex-fill">{{ orderType == 'takeout' ? '外卖配送' : '点餐自取' }}</view> <text class="pay-page__store-name">{{ store.name }}</text><text class="iconfont iconarrow-right"></text>
<uv-switch activeColor="#09b4f1" v-model="active" @change="takout">
</uv-switch>
</view>
</list-cell>
</template>
<template v-if="orderType == 'takeout'">
<list-cell @click="chooseAddress">
<view v-if="address.realName" class="w-100 d-flex flex-column">
<view class="d-flex align-items-center justify-content-between mb-10">
<view class="font-size-lg text-color-base">
{{ address.address + ' ' + address.detail }}
</view>
<image src="/static/images/navigator-1.png" class="pay-page__arrow"></image>
</view>
<view class="d-flex text-color-assist font-size-sm align-items-center">
<view class="mr-10">{{ address.realName }}</view>
<view>{{ address.phone }}</view>
</view>
</view>
<view v-else class="flex-fill d-flex justify-content-between align-items-center">
<view class="store-name flex-fill">选择收货地址</view>
<image src="/static/images/navigator-1.png" class="pay-page__arrow"></image>
</view>
</list-cell>
</template>
</view> </view>
<view class="pay-page__section"> <view v-if="orderType == 'takeout'" class="pay-page__card pay-page__address" @tap="chooseAddress">
<template> <text class="iconfont-yshop icon-location"></text>
<list-cell class="pay-page__cell pay-page__cell--location" @click="goToShop"> <view v-if="address.realName" class="pay-page__address-info"><view><text>{{ address.realName }}</text><text>{{ address.phone }}</text></view><text>{{ address.address + ' ' + address.detail }}</text></view>
<view class="flex-fill d-flex justify-content-between align-items-center"> <text v-else class="pay-page__empty-address">选择收货地址</text><text class="iconfont iconarrow-right"></text>
<view class="store-name flex-fill">{{ store.name }}</view>
<image src="/static/images/navigator-1.png" class="pay-page__arrow"></image>
</view>
</list-cell>
</template>
<template>
<list-cell arrow class="pay-page__cell pay-page__cell--meal-time" v-if="orderType == 'takein'">
<view class="flex-fill d-flex justify-content-between align-items-center"
@click="takeinTIme = !takeinTIme">
<view class="title">取餐时间</view>
<view class="time">
{{ takeinRange[defaultSelector[0]].name }}
<u-picker v-model="takeinTIme" :range="takeinRange" range-key="name" mode="selector"
@cancel="takeinCancelTime" @confirm="takeinConfirmTime"
:default-selector="defaultSelector"></u-picker>
</view>
</view>
</list-cell>
<list-cell class="pay-page__cell pay-page__cell--contact" last :hover="false" v-if="orderType == 'takein'">
<view class="flex-fill d-flex justify-content-between align-items-center">
<view class="title flex-fill">联系电话</view>
<view class="time"><input class="text-right" placeholder="请输入手机号码" :value="member.mobile" />
</view>
<button class="pay-page__contact-tip font-size-sm">自动填写</button>
</view>
</list-cell>
</template>
<template v-if="orderType == 'takeout'">
<list-cell>
<view class="w-100 d-flex flex-column">
<view class="d-flex align-items-center font-size-base text-color-base">
<view class="flex-fill">预计送达时间</view>
<view class="mr-10">
{{ defaultTime }}
<u-picker :default-time="defaultTime" v-model="takeoutTIme" :params="paramsTime"
mode="time" @cancel="cancelTime" @confirm="choiceTime"></u-picker>
</view>
</view>
</view>
</list-cell>
</template>
</view> </view>
<!-- 购物车列表 begin -->
<view class="pay-page__section pay-page__section--cart"> <view class="pay-page__card pay-page__goods"><view class="pay-page__section-title">商品清单 <text>共 {{ cart.length }} 件</text></view>
<view class="pay-page__cart d-flex flex-column"> <view v-for="(item, index) in cart" :key="index" class="pay-page__goods-item">
<list-cell last v-for="(item, index) in cart" :key="index"> <image v-if="item.image" :src="item.image" mode="aspectFill"></image><view class="pay-page__goods-main"><text>{{ item.name }}</text><text v-if="item.valueStr">规格:{{ item.valueStr }}</text><text>单价:¥{{ item.price }}</text></view><view class="pay-page__goods-price"><text>x{{ item.number }}</text><strong>¥{{ (item.number * item.price).toFixed(2) }}</strong></view>
<view class="w-100 d-flex flex-column">
<view class="d-flex align-items-center mb-10">
<view
class="d-flex flex-fill justify-content-between align-items-center text-color-base font-size-lg">
<image class="pay-page__cart-thumb" mode="aspectFill" :src="item.image">
</image>
</view>
<view class="pay-page__cart-name overflow-hidden">
<view class="text-color-base font-size-lg">{{ item.name }}</view>
</view>
<view
class="d-flex flex-fill justify-content-between align-items-center text-color-base font-size-lg">
<view>x{{ item.number }}</view>
<view>¥{{ item.price }}</view>
</view>
</view>
<view class="text-truncate font-size-base text-color-assist">{{ item.valueStr }}</view>
</view>
</list-cell>
</view> </view>
<list-cell arrow @click="goToPackages">
<view class="flex-fill d-flex justify-content-between align-items-center">
<view class="text-color-base">优惠券</view>
<view v-if="coupons == 0" class="text-color-base">暂无可用</view>
<view v-else-if="coupon.title" class="text-color-danger">
{{ coupon.title }}(满{{ coupon.least }}减{{ coupon.value }})
</view>
<view v-else class="text-color-primary">可用优惠券{{ coupons }}张</view>
</view>
</list-cell>
<list-cell last>
<view class="flex-fill d-flex justify-content-end align-items-center">
<view>
总计¥{{ total }}
<text v-if="orderType == 'takeout'">,配送费¥{{ deliveryFee }}</text>
<text v-if="coupon.value">,¥-{{ coupon.value }}</text>
,实付
</view>
<view class="font-size-extra-lg font-weight-bold">¥{{ amount }}</view>
</view>
</list-cell>
</view> </view>
<!-- 购物车列表 end -->
<view class="pay-page__notice d-flex align-items-center justify-content-start font-size-sm text-color-warning"> <view class="pay-page__card pay-page__options"><view @tap="goToRemark"><text>备注</text><text>{{ form.remark || '口味、偏好等要求可填写' }}</text><text class="iconfont iconarrow-right"></text></view><view @tap="goToPackages"><text>优惠券</text><text v-if="coupon.title" class="pay-page__orange">{{ coupon.title }} -¥{{ coupon.value }}</text><text v-else-if="coupons" class="pay-page__orange">可用优惠券 {{ coupons }} 张</text><text v-else>暂无可用</text><text class="iconfont iconarrow-right"></text></view></view>
</view>
<!-- 支付方式 begin --> <view class="pay-page__card pay-page__summary"><view><text>商品金额</text><text>¥{{ total.toFixed(2) }}</text></view><view v-if="orderType == 'takeout'"><text>配送费</text><text>¥{{ deliveryFee.toFixed(2) }}</text></view><view v-if="coupon.value"><text>优惠</text><text class="pay-page__orange">-¥{{ coupon.value }}</text></view><view class="pay-page__total"><text>合计</text><strong>¥{{ amount }}</strong></view></view>
<view class="pay-page__payment">
<list-cell last :hover="false"><text>支付方式</text></list-cell> <view class="pay-page__card pay-page__payments"><view class="pay-page__section-title">支付方式</view><view class="pay-page__payment-row" :class="{ active: payType == 'weixin' }" @tap="setPayType('weixin')"><text class="iconfont iconwxpay"></text><text>微信支付</text><text class="iconfont" :class="payType == 'weixin' ? 'iconradio-button-on' : 'iconradio-button-off'"></text></view><view v-if="member.nowMoney !== undefined" class="pay-page__payment-row" :class="{ active: payType == 'yue' }" @tap="setPayType('yue')"><text class="iconfont iconbalance"></text><text>余额支付</text><text class="iconfont" :class="payType == 'yue' ? 'iconradio-button-on' : 'iconradio-button-off'"></text></view></view>
<list-cell>
<view class="pay-page__payment-row pay-page__payment-row--disabled d-flex align-items-center justify-content-between w-100"
@click="setPayType('yue')">
<view class="iconfont iconbalance line-height-100 pay-page__payment-icon"></view>
<view class="flex-fill">余额支付(余额¥{{ member.nowMoney }})</view>
<view class="font-size-sm" v-if="member.nowMoney == 0">余额不足</view>
<view class="iconfont line-height-100 pay-page__checkbox pay-page__checkbox--checked iconradio-button-on" v-if="payType == 'yue'">
</view>
<view class="iconfont line-height-100 pay-page__checkbox iconradio-button-off" v-else></view>
</view>
</list-cell>
<list-cell last>
<view class="pay-page__payment-row d-flex align-items-center justify-content-between w-100" @click="setPayType('weixin')">
<view class="iconfont iconwxpay line-height-100 pay-page__payment-icon pay-page__payment-icon--wechat"></view>
<view class="flex-fill">微信支付</view>
<view class="iconfont line-height-100 pay-page__checkbox pay-page__checkbox--checked iconradio-button-on" v-if="payType == 'weixin'">
</view>
<view class="iconfont line-height-100 pay-page__checkbox iconradio-button-off" v-else></view>
</view>
</list-cell>
<!-- #ifdef H5 -->
<list-cell>
<view class="pay-page__payment-row d-flex align-items-center justify-content-between w-100" @click="setPayType('alipay')">
<view class="iconfont-yshop icon-alipay line-height-100 pay-page__payment-icon pay-page__payment-icon--alipay"></view>
<view class="flex-fill">支付宝</view>
<view class="iconfont line-height-100 pay-page__checkbox pay-page__checkbox--checked iconradio-button-on" v-if="payType == 'alipay'" ></view>
<view class="iconfont line-height-100 pay-page__checkbox iconradio-button-off" v-else ></view>
</view>
</list-cell>
<!-- #endif -->
</view>
<!-- 支付方式 end -->
<!-- 备注 begin -->
<list-cell last @click="goToRemark">
<view class="pay-page__remark d-flex flex-fill align-items-center justify-content-between overflow-hidden">
<view class="flex-shrink-0 mr-20">备注</view>
<view class="text-color-primary flex-fill text-truncate text-right">{{ form.remark || '点击填写备注' }}
</view>
</view>
</list-cell>
<!-- 备注 end -->
</view> </view>
<!-- 付款栏 begin --> <view class="pay-page__footer"><view>合计:<strong>¥{{ amount }}</strong></view><button @tap="debounce(submit, 500)">提交订单</button></view>
<view class="pay-page__footer w-100 position-fixed fixed-bottom d-flex align-items-center justify-content-between bg-white">
<view class="pay-page__footer-label font-size-sm">合计:</view>
<view class="pay-page__footer-amount font-size-lg flex-fill">¥{{ amount }}</view>
<view class="pay-page__footer-btn bg-primary h-100 d-flex align-items-center just-content-center text-color-white font-size-base"
@tap="debounce(submit, 500)">付款</view>
</view>
<!-- 付款栏 end -->
<modal :show="ensureAddressModalVisible" custom :mask-closable="false" :radius="'0rpx'" width="90%"> <modal :show="ensureAddressModalVisible" custom :mask-closable="false" :radius="'0rpx'" width="90%">
<view class="pay-page__modal"> <view class="pay-page__modal">
<view class="d-flex justify-content-end"> <view class="d-flex justify-content-end">
@@ -245,7 +84,7 @@ const { orderType,address, store,location,isLogin,member,mycoupon } = storeToRef
const active = ref(false) const active = ref(false)
const deliveryFee = ref(0) const deliveryFee = ref(0)
const outOfRange = ref(false) const outOfRange = ref(false)
const title = ref('支付') const title = ref('确认订单')
const jsStr = ref('') const jsStr = ref('')
const cart = ref([]) const cart = ref([])
const form = ref({ const form = ref({
@@ -380,7 +219,7 @@ onHide(() => {
coupons.value = 0; coupons.value = 0;
}) })
onLoad((option) => { onLoad((option) => {
cart.value = uni.getStorageSync('cart') cart.value = uni.getStorageSync('cart') || []
if(option.remark) { if(option.remark) {
form.value.remark = option.remark form.value.remark = option.remark
} }
@@ -902,4 +741,55 @@ $pay-modal-change-btn-line-height: 2;
border-radius: $pay-modal-btn-radius !important; border-radius: $pay-modal-btn-radius !important;
} }
} }
/* Confirm-order layout: all content comes from the existing store, cart, address and coupon APIs. */
.pay-page {
min-height: 100vh;
padding-bottom: 150rpx;
background: #faf9f7;
color: #251a14;
&__content { padding: 24rpx; }
&__store, &__card { background: #fff; border-radius: 26rpx; box-shadow: 0 3rpx 15rpx rgba(70, 44, 18, .05); }
&__store { display: flex; align-items: center; min-height: 94rpx; margin-bottom: 22rpx; padding: 0 24rpx; background: linear-gradient(120deg, #fff5e8, #fffaf5); }
&__store > .iconfont-yshop { font-size: 46rpx; color: #ff7619; }
&__store-type { margin: 0 26rpx 0 14rpx; color: #ff7619; font-size: 32rpx; font-weight: 700; }
&__store image { width: 62rpx; height: 62rpx; margin-right: 16rpx; border-radius: 10rpx; }
&__store-name { flex: 1; overflow: hidden; font-size: 29rpx; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
&__address { display: flex; align-items: center; min-height: 122rpx; margin-bottom: 22rpx; padding: 24rpx; }
&__address > .iconfont-yshop { margin-right: 24rpx; font-size: 54rpx; color: #ff7619; }
&__address-info { flex: 1; display: flex; flex-direction: column; gap: 10rpx; min-width: 0; color: #756d67; font-size: 26rpx; }
&__address-info view { color: #251a14; font-size: 31rpx; font-weight: 700; }
&__address-info view text + text { margin-left: 36rpx; font-weight: 400; }
&__empty-address { flex: 1; font-size: 29rpx; }
&__card { margin-bottom: 22rpx; padding: 24rpx; box-sizing: border-box; }
&__section-title { display: flex; justify-content: space-between; margin-bottom: 18rpx; font-size: 34rpx; font-weight: 700; }
&__section-title text { color: #8d8580; font-size: 25rpx; font-weight: 400; }
&__goods-item { display: flex; min-height: 124rpx; padding: 18rpx 0; border-top: 1rpx solid #f2ece7; }
&__goods-item image { flex: 0 0 118rpx; width: 118rpx; height: 118rpx; margin-right: 18rpx; border-radius: 14rpx; }
&__goods-main { flex: 1; display: flex; flex-direction: column; gap: 8rpx; min-width: 0; }
&__goods-main text:first-child { overflow: hidden; font-size: 30rpx; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
&__goods-main text:not(:first-child) { color: #918984; font-size: 24rpx; }
&__goods-price { display: flex; flex-direction: column; align-items: flex-end; justify-content: space-between; padding: 5rpx 0; color: #817975; font-size: 26rpx; }
&__goods-price strong { color: #ff6817; font-size: 31rpx; }
&__options > view { display: flex; align-items: center; min-height: 84rpx; border-bottom: 1rpx solid #f2ece7; }
&__options > view:last-child { border-bottom: 0; }
&__options > view > text:first-child { font-size: 30rpx; font-weight: 700; }
&__options > view > text:nth-child(2) { flex: 1; overflow: hidden; margin-left: 32rpx; color: #938b86; font-size: 25rpx; text-align: right; text-overflow: ellipsis; white-space: nowrap; }
&__orange { color: #ff6817 !important; }
&__summary > view { display: flex; justify-content: space-between; padding: 10rpx 0; color: #756d67; font-size: 27rpx; }
&__total { margin-top: 10rpx; padding-top: 22rpx !important; border-top: 1rpx dashed #e9e2db; color: #251a14 !important; font-size: 34rpx !important; font-weight: 700; }
&__total strong { color: #ff6817; font-size: 44rpx; }
&__payment-row { display: flex; align-items: center; min-height: 82rpx; padding: 0 18rpx; border: 2rpx solid #eee8e3; border-radius: 16rpx; }
&__payment-row + &__payment-row { margin-top: 16rpx; }
&__payment-row > text:first-child { margin-right: 18rpx; color: #15b94f; font-size: 38rpx; }
&__payment-row > text:nth-child(2) { flex: 1; font-size: 28rpx; }
&__payment-row > text:last-child { color: #c8c0bb; font-size: 32rpx; }
&__payment-row.active { border-color: #ff7a1b; }
&__payment-row.active > text:last-child { color: #ff7a1b; }
&__footer { position: fixed; right: 0; bottom: 0; left: 0; z-index: 10; display: flex; align-items: center; height: 124rpx; padding: 0 28rpx; box-sizing: border-box; background: rgba(255,255,255,.98); box-shadow: 0 -4rpx 20rpx rgba(74, 50, 31, .08); }
&__footer > view { flex: 1; font-size: 28rpx; }
&__footer strong { color: #ff6817; font-size: 42rpx; }
&__footer button { width: 270rpx; height: 84rpx; margin: 0; line-height: 84rpx; color: #fff; font-size: 34rpx; font-weight: 700; border-radius: 44rpx; background: linear-gradient(90deg, #ff9b20, #ff6817); }
}
</style> </style>
+56 -77
View File
@@ -14,16 +14,16 @@
<view class="notice-bar" v-if="store.notice"> <view class="notice-bar" v-if="store.notice">
<uv-notice-bar :text="store.notice"></uv-notice-bar> <uv-notice-bar :text="store.notice"></uv-notice-bar>
</view> </view>
<view class="main"> <view class="main menu-page">
<view class="nav"> <view class="nav">
<view class="header"> <view class="header">
<view class="mr-1"><image :src="store.image" class="store-header-img"></image></view> <image v-if="store.image" :src="store.image" mode="aspectFill" class="store-header-img"></image>
<view class="left" v-if="orderType == 'takein'"> <view class="left" v-if="orderType == 'takein'">
<view class="store-name" @click="selectShop()"> <view class="store-name" @click="selectShop()">
<text>{{ store.name }}</text> <text>{{ store.name }}</text>
<view class="iconfont iconarrow-right"></view> <view class="iconfont iconarrow-right"></view>
</view> </view>
<view class="store-location"> <view class="store-location" v-if="store.dis">
<text>距离您 {{kmUnit(store.dis)}}</text> <text>距离您 {{kmUnit(store.dis)}}</text>
</view> </view>
</view> </view>
@@ -39,14 +39,18 @@
</view> </view>
<view class="right"> <view class="right">
<view class="dinein" :class="{active: orderType == 'takein'}" @tap="takein"> <view class="dinein" :class="{active: orderType == 'takein'}" @tap="takein">
<text>自取</text> <text class="iconfont-yshop icon-takein"></text><text>堂食</text>
</view> </view>
<view class="takeout" :class="{active: orderType == 'takeout'}" @tap="takout"> <view class="takeout" :class="{active: orderType == 'takeout'}" @tap="takout">
<text>外卖</text> <text class="iconfont-yshop icon-takeout"></text><text>外卖</text>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<view class="menu-search">
<text class="iconsearch">⌕</text>
<input v-model="keyword" placeholder="搜索菜品、饮品" confirm-type="search" />
</view>
<!-- #ifdef H5 --> <!-- #ifdef H5 -->
<view class="content" <view class="content"
@@ -78,20 +82,20 @@
</view> </view>
<view class="items"> <view class="items">
<!-- 商品 begin --> <!-- 商品 begin -->
<view class="good" v-for="(good, key) in item.goodsList" :key="key" <view class="good" v-for="(good, key) in item.goodsList" :key="key" v-show="isGoodVisible(good)"
:class="{'background-grey': good.stock <= 0}"> :class="{'background-grey': good.stock <= 0}">
<image mode="aspectFill" :src="good.image" class="image" <image mode="aspectFill" :src="good.image" class="image"
@tap="showGoodDetailModal(item, good)"></image> @tap="showGoodDetailModal(item, good)"></image>
<view class="right"> <view class="right">
<text class="name">{{ good.storeName }}</text> <text class="name">{{ good.storeName }}</text>
<text class="tips">{{ good.storeInfo }}</text> <text v-if="good.storeInfo" class="tips">{{ good.storeInfo }}</text>
<view class="price_and_action"> <view class="price_and_action">
<text class="price">¥{{ good.price }}</text> <text class="price">¥{{ good.price }}</text>
<view class="btn-group" v-if="good.stock > 0"> <view class="btn-group" v-if="good.stock > 0">
<button type="primary" class="btn property_btn" <button type="primary" class="btn property_btn"
hover-class="none" size="mini" hover-class="none" size="mini"
@tap="showGoodDetailModal(item, good)"> @tap="showGoodDetailModal(item, good)">
选规格 <text class="iconfont iconadd-select"></text><text> 选规格</text>
</button> </button>
<view class="dot" v-show="goodCartNum(good.id)"> <view class="dot" v-show="goodCartNum(good.id)">
{{ goodCartNum(good.id) }}</view> {{ goodCartNum(good.id) }}</view>
@@ -143,7 +147,7 @@
<view class="wrapper"> <view class="wrapper">
<view class="basic"> <view class="basic">
<view class="name">{{ good.storeName }}</view> <view class="name">{{ good.storeName }}</view>
<view class="tips flex justify-between">{{ good.storeInfo }} <text style="color: red;">可获积分:10</text></view> <view v-if="good.storeInfo" class="tips">{{ good.storeInfo }}</view>
</view> </view>
<view class="properties"> <view class="properties">
<view class="property" v-for="(item, index) in good.productAttr" :key="index"> <view class="property" v-for="(item, index) in good.productAttr" :key="index">
@@ -252,8 +256,9 @@ import {
} from '@/api/market' } from '@/api/market'
const main = useMainStore() const main = useMainStore()
const { orderType,address, store,location,isLogin } = storeToRefs(main) const { orderType,address, store,location,isLogin } = storeToRefs(main)
const title = ref('点餐') const title = ref('食刻点单')
const text = ref('滚动通知') const text = ref('滚动通知')
const keyword = ref('')
const goods = ref([]) const goods = ref([])
const ads = ref([]) const ads = ref([])
@@ -272,76 +277,9 @@ const shopAd = ref('')
const isCartShow = ref(true) const isCartShow = ref(true)
const popup = ref() const popup = ref()
// #region agent log
// const debugLog = (hypothesisId, location, message, data = {}) => {
// fetch('http://127.0.0.1:7584/ingest/889fdfba-29d4-4509-84ce-3dfa9254da00', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': 'e0348b' },
// body: JSON.stringify({
// sessionId: 'e0348b',
// runId: 'pre-fix',
// hypothesisId,
// location,
// message,
// data,
// timestamp: Date.now()
// })
// }).catch(() => {})
// }
const measureMenuLayout = () => { const measureMenuLayout = () => {
const sys = uni.getSystemInfoSync()
const notice = !!store.value?.notice
const inlineHeight = `calc(100vh - 500rpx + ${notice ? '0rpx' : '60rpx'})`
let platform = 'OTHER'
// #ifdef H5
platform = 'H5'
// #endif
// #ifdef MP-WEIXIN
platform = 'MP-WEIXIN'
// #endif
debugLog('H1', 'menu.vue:measureMenuLayout', 'layout context', {
platform,
windowHeight: sys.windowHeight,
screenHeight: sys.screenHeight,
statusBarHeight: sys.statusBarHeight,
hasNotice: notice,
inlineHeight,
cssExpectedH5: 'calc(100vh - 212rpx - 188rpx)',
cssExpectedDefault: 'calc(100vh - 212rpx)'
})
const q = uni.createSelectorQuery()
q.select('.container').boundingClientRect()
q.select('.main').boundingClientRect()
q.select('.content').boundingClientRect()
q.select('.menus').boundingClientRect()
q.select('.goods').boundingClientRect()
q.select('.nav').boundingClientRect()
q.exec((res) => {
const [container, main, content, menus, goods, nav] = res || []
debugLog('H3', 'menu.vue:measureMenuLayout', 'parent rects', {
containerH: container?.height,
mainH: main?.height,
navH: nav?.height
})
debugLog('H1', 'menu.vue:measureMenuLayout', 'content rect', {
contentH: content?.height,
contentTop: content?.top,
windowHeight: sys.windowHeight,
heightRatio: content?.height && sys.windowHeight ? (content.height / sys.windowHeight).toFixed(3) : null
})
debugLog('H5', 'menu.vue:measureMenuLayout', 'scroll columns', {
menusH: menus?.height,
goodsH: goods?.height,
menusGoodsDelta: menus?.height != null && goods?.height != null ? Math.abs(menus.height - goods.height) : null
})
})
} }
// #endregion
const newkmUnit = computed(() => (param) =>{
console.log('param:',param)
return '10km'
})
const goodCartNum = computed(() => { //计算单个饮品添加到购物车的数量 const goodCartNum = computed(() => { //计算单个饮品添加到购物车的数量
return (id) => cart.value.reduce((acc, cur) => { return (id) => cart.value.reduce((acc, cur) => {
if (cur.id === id) { if (cur.id === id) {
@@ -373,6 +311,8 @@ const spread = computed(() => { //差多少元起送
if (orderType.value != 'takeout') return if (orderType.value != 'takeout') return
return parseFloat((store.value.minPrice - getCartGoodsPrice).toFixed(2)) return parseFloat((store.value.minPrice - getCartGoodsPrice).toFixed(2))
}) })
const isGoodVisible = (good) => !keyword.value || [good.storeName, good.storeInfo]
.filter(Boolean).join(' ').toLowerCase().includes(keyword.value.trim().toLowerCase())
// 监听自定义事件 // 监听自定义事件
uni.$on('refreshMenu', () => { uni.$on('refreshMenu', () => {
@@ -1508,4 +1448,43 @@ page {
padding: 15rpx !important; padding: 15rpx !important;
background-color: $menu-sold-out-bg; background-color: $menu-sold-out-bg;
} }
.menu-page {
padding: 0 24rpx;
box-sizing: border-box;
background: #fff;
.nav { height: auto; padding-top: 12rpx; }
.nav .header { height: 170rpx; padding: 24rpx; box-sizing: border-box; border-radius: 28rpx; background: linear-gradient(120deg, #fff3e5, #fffaf4); }
.nav .header .left { margin-left: 18rpx; }
.nav .header .left .store-name { font-size: 34rpx; font-weight: 700; }
.nav .header .right { padding: 4rpx; background: #fff; border: 2rpx solid #f5eee8; }
.nav .header .right .dinein, .nav .header .right .takeout { gap: 8rpx; margin: 0; padding: 16rpx 22rpx; }
.nav .header .right .active { margin: 0; background: linear-gradient(90deg, #ff9b20, #ff6f13); }
.menu-search { display: flex; align-items: center; height: 78rpx; margin: 22rpx 0; padding: 0 24rpx; border: 2rpx solid #eee9e5; border-radius: 42rpx; color: #9d9d9d; background: #fff; }
.menu-search input { flex: 1; margin-left: 14rpx; font-size: 28rpx; }
.menu-search .iconsearch { font-size: 40rpx; line-height: 1; }
.content { height: calc(100vh - 440rpx) !important; }
.menus { width: 156rpx; border-radius: 24rpx 0 0 24rpx; background: #fffaf5; }
.menus .wrapper .menu { justify-content: center; padding: 30rpx 10rpx; color: #7c756e; }
.menus .wrapper .menu.current { color: #ff7119; font-weight: 700; background: #fff; }
.menus .wrapper .menu.current::before { content: ''; position: absolute; left: 0; width: 8rpx; height: 42rpx; border-radius: 0 8rpx 8rpx 0; background: #ff781b; }
.goods { border-radius: 0 24rpx 24rpx 0; }
.goods .wrapper { padding: 0 20rpx; }
.goods .wrapper .list .category .title { padding: 24rpx 0 14rpx; font-size: 34rpx; font-weight: 700; }
.goods .wrapper .list .category .title::before { content: ''; width: 8rpx; height: 30rpx; margin-right: 12rpx; border-radius: 8rpx; background: #ff9b20; }
.goods .wrapper .list .category .items .good { padding: 20rpx 0; border-bottom: 1rpx solid #f4f0ec; }
.goods .wrapper .list .category .items .good .image { width: 178rpx; height: 178rpx; border-radius: 18rpx; }
.goods .wrapper .list .category .items .good .right { height: 178rpx; }
.goods .wrapper .list .category .items .good .right .name { font-size: 31rpx; font-weight: 700; }
.goods .wrapper .list .category .items .good .right .price_and_action .price { font-size: 36rpx; color: #ff6817; }
.goods .wrapper .list .category .items .good .right .price_and_action .btn-group .btn.property_btn { height: 56rpx; padding: 0 18rpx; line-height: 56rpx; border-radius: 28rpx; background: #ff7417; }
.cart-box { bottom: 28rpx; height: 116rpx; border-radius: 58rpx; box-shadow: 0 8rpx 28rpx rgba(91, 61, 32, .16); }
.cart-box .cart-img { width: 116rpx; height: 116rpx; }
.cart-box .pay-btn { padding: 0 46rpx; border-radius: 58rpx; background: linear-gradient(90deg, #ff9b20, #ff6817); }
}
.store-header-img { flex: 0 0 118rpx; width: 118rpx; height: 118rpx; border-radius: 16rpx; }
</style> </style>