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>
<uv-navbar
:fixed="false"
:title="title"
left-arrow
@leftClick="$onClickLeft"
/>
<view class="pay-page container position-relative">
<uv-navbar :fixed="false" :title="title" left-arrow @leftClick="$onClickLeft" />
<view class="pay-page">
<view class="pay-page__content">
<view class="pay-page__section">
<template v-if="store.distance > 0">
<list-cell class="pay-page__cell pay-page__cell--location">
<view class="flex-fill d-flex justify-content-between align-items-center">
<view class="store-name flex-fill">{{ orderType == 'takeout' ? '外卖配送' : '点餐自取' }}</view>
<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 class="pay-page__store" @tap="goToShop">
<text class="iconfont-yshop" :class="orderType == 'takeout' ? 'icon-takeout' : 'icon-takein'"></text>
<text class="pay-page__store-type">{{ orderType == 'takeout' ? '外卖' : '堂食' }}</text>
<image v-if="store.image" :src="store.image" mode="aspectFill"></image>
<text class="pay-page__store-name">{{ store.name }}</text><text class="iconfont iconarrow-right"></text>
</view>
<view class="pay-page__section">
<template>
<list-cell class="pay-page__cell pay-page__cell--location" @click="goToShop">
<view class="flex-fill d-flex justify-content-between align-items-center">
<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 v-if="orderType == 'takeout'" class="pay-page__card pay-page__address" @tap="chooseAddress">
<text class="iconfont-yshop icon-location"></text>
<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>
<text v-else class="pay-page__empty-address">选择收货地址</text><text class="iconfont iconarrow-right"></text>
</view>
<!-- 购物车列表 begin -->
<view class="pay-page__section pay-page__section--cart">
<view class="pay-page__cart d-flex flex-column">
<list-cell last v-for="(item, index) in cart" :key="index">
<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 class="pay-page__card pay-page__goods"><view class="pay-page__section-title">商品清单 <text>共 {{ cart.length }} 件</text></view>
<view v-for="(item, index) in cart" :key="index" class="pay-page__goods-item">
<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>
<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>
<!-- 购物车列表 end -->
<view class="pay-page__notice d-flex align-items-center justify-content-start font-size-sm text-color-warning">
</view>
<!-- 支付方式 begin -->
<view class="pay-page__payment">
<list-cell last :hover="false"><text>支付方式</text></list-cell>
<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 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 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__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>
</view>
<!-- 付款栏 begin -->
<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 -->
<view class="pay-page__footer"><view>合计:<strong>¥{{ amount }}</strong></view><button @tap="debounce(submit, 500)">提交订单</button></view>
<modal :show="ensureAddressModalVisible" custom :mask-closable="false" :radius="'0rpx'" width="90%">
<view class="pay-page__modal">
<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 deliveryFee = ref(0)
const outOfRange = ref(false)
const title = ref('支付')
const title = ref('确认订单')
const jsStr = ref('')
const cart = ref([])
const form = ref({
@@ -380,7 +219,7 @@ onHide(() => {
coupons.value = 0;
})
onLoad((option) => {
cart.value = uni.getStorageSync('cart')
cart.value = uni.getStorageSync('cart') || []
if(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;
}
}
/* 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>