1933 lines
53 KiB
Vue
1933 lines
53 KiB
Vue
<template>
|
||
<view>
|
||
<NavBar :title="navTitle" bgColor="#F2F3F7" isRightButton @right-click="onConfirm"></NavBar>
|
||
<view class="page-container">
|
||
<view class="tab-box" v-if="!isEditMode">
|
||
<view class="tab" :class="{ active: item.key == activeTab }" v-for="item in waimaiType" :key="item.key"
|
||
@click="switchTab(item)">
|
||
<text>{{ item.label }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="!isEditMode" class="random-dice">
|
||
<image style="width: 2rem;height: 2rem;" src="/static/image/common/random-dice.png"
|
||
@click="clickRandomDate"></image>
|
||
</view>
|
||
|
||
<!-- 未支付 -->
|
||
<template v-if="activeTab == 'weizhifu'">
|
||
<view class="weizhifu card">
|
||
<view class="title">
|
||
<picker mode="multiSelector" :range="countdownRange" :value="countdownValue"
|
||
@change="handleCountdownChange">
|
||
<text>请在{{ order.statusDesc || '29:59' }} <image class="edit-icon"
|
||
src="/static/image/common/edit.png"></image>内支付</text>
|
||
</picker>
|
||
</view>
|
||
<view class="time">现在支付,预计 <text class="time-text" @click="onDeliveryTimeClick('deliveryTime')">{{
|
||
order.deliveryTime || '11:17-11:32' }}<image class="edit-icon"
|
||
src="/static/image/common/edit.png"></image>
|
||
</text> 送达</view>
|
||
<!-- <view class="flex flex-justify-between flex-align-center" style="margin-top: 32rpx;">
|
||
<text>更多</text>
|
||
<view class="flex flex-align-center">
|
||
<view class="btn cancel-btn">取消订单</view>
|
||
<view class="btn pay-btn">立即支付 ¥14.5</view>
|
||
</view>
|
||
</view> -->
|
||
</view>
|
||
<view class="card location-box flex flex-justify-between flex-align-center">
|
||
<view class="w100">
|
||
<view class="card-title">
|
||
<image class="location-icon" src="/static/image/shopping/jingdong/waimai/location.png">
|
||
</image>
|
||
<auto-width-input class="name" placeholder="请输入姓名" v-model="order.consignee"
|
||
fontSize="30rpx" type="text" color="#1A1A1A" fontWeight="500" show-edit />
|
||
<auto-width-input class="phone" placeholder="请输入号码" v-model="order.phone" fontSize="26rpx"
|
||
type="number" color="#87868E" show-edit />
|
||
<!-- <text class="desc">号码保护中</text> -->
|
||
</view>
|
||
<view class="loction-text">
|
||
<auto-width-input class="value" placeholder="请输入收货地址" v-model="order.address"
|
||
fontSize="26rpx" type="textarea" color="#87868E" show-edit />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 备餐中/取餐中 -->
|
||
<view v-if="activeTab == 'beicanzhong' || activeTab == 'qvcanzhong'" class="time-box"
|
||
@click="onClickTrackingTime">
|
||
<text style="color: #87868E;">{{ activeTab == 'beicanzhong' ? '备餐时间' : '取餐时间' }}
|
||
<text style="color: #1A1A1A;font-weight: 500; margin-left: 10rpx;">{{
|
||
order.trackingTime }}</text>
|
||
<image class="edit-icon" src="/static/image/common/edit.png"></image>
|
||
</text>
|
||
</view>
|
||
<view v-if="activeTab == 'beicanzhong' || activeTab == 'qvcanzhong'" class="card-box">
|
||
|
||
<view class="card beicanzhong-card">
|
||
<view class="title flex">
|
||
<text class="time" @click="onDeliveryTimeClick('trackingTitle')">{{ order.trackingTitle ||
|
||
'10:43-10:58'
|
||
}}</text>
|
||
<text>预计送达</text>
|
||
</view>
|
||
<view class="desc">
|
||
<auto-width-input v-model="order.trackingDesc" fontSize="30rpx" fontWeight="500"
|
||
placeholder="请输入描述信息" color="#1A1A1A" show-edit />
|
||
</view>
|
||
<view class="progress">
|
||
<view class="progress-bar">
|
||
<view class="progress-bar-fill"
|
||
:style="{ width: activeTab == 'qvcanzhong' ? '70%' : '50%' }">
|
||
</view>
|
||
<image class="progress-icon fukuan" src="/static/image/shopping/jingdong/waimai/fukuan.png">
|
||
</image>
|
||
<image class="progress-icon beican" src="/static/image/shopping/jingdong/waimai/beican.png">
|
||
</image>
|
||
<image class="progress-icon songcan"
|
||
:src="`/static/image/shopping/jingdong/waimai/${activeTab == 'qvcanzhong' ? 'qvcan' : 'songcan'}.png`">
|
||
</image>
|
||
<image class="progress-icon qianshou"
|
||
src="/static/image/shopping/jingdong/waimai/qianshou.png">
|
||
</image>
|
||
</view>
|
||
</view>
|
||
<view class="image-box flex-center" @click="chooseDeliveryImage">
|
||
<image v-if="!order.deliveryImages" class="add-img" src="/static/image/common/add.png"
|
||
mode="aspectFill">
|
||
</image>
|
||
<image v-else class="w100 h100" :src="order.deliveryImages" mode="aspectFill"></image>
|
||
</view>
|
||
<view class="btn-box flex-align-center">
|
||
<view class="btn">查看发票</view>
|
||
<view class="btn">订单跟踪</view>
|
||
<view class="btn">申请退款</view>
|
||
<view class="btn">联系商家</view>
|
||
</view>
|
||
</view>
|
||
<view class="notice-box flex-align-center">
|
||
<image class="icon" src="/static/image/shopping/jingdong/waimai/notice.png" mode="aspectFill">
|
||
</image>
|
||
<text class="flex-1 notice-text">开启系统通知,第一时间获取订单聊天信息</text>
|
||
<view class="open-btn">去开启</view>
|
||
</view>
|
||
</view>
|
||
<!-- 已完成/已取消 -->
|
||
<view v-if="order.type == 'yiwancheng' || order.type == 'yiquxiao'" class="weizhifu card yiwancheng">
|
||
<view class="title flex-align-center">{{ order.type == 'yiwancheng' ? '订单已完成' : '订单已取消' }} <uni-icons
|
||
style="margin-left: 6rpx;" type="right" size="12" color="#1A1A1A"></uni-icons>
|
||
</view>
|
||
<view v-if="order.type == 'yiwancheng'" class="desc">订单已送达,请厉行节约,拒绝浪费,期待能再次光临</view>
|
||
<view v-if="order.type == 'yiquxiao'" class="desc quxiao">抱歉本次未能让您满意,我们会努力改进</view>
|
||
<view class="flex flex-justify-between flex-align-center" style="margin-top: 32rpx;">
|
||
<text style="font-size: 24rpx;color: #87868E;line-height: 24rpx;">{{ order.type == 'yiwancheng' ?
|
||
'更多' :
|
||
'' }}</text>
|
||
<view class="flex flex-align-center">
|
||
<view v-if="order.type == 'yiquxiao'" class="btn cancel-btn">删除订单</view>
|
||
<view class="btn cancel-btn">联系商家</view>
|
||
<view v-if="order.type == 'yiwancheng'" class="btn cancel-btn">联系骑手</view>
|
||
<view v-if="order.type == 'yiwancheng'" class="btn cancel-btn primary">评价晒单</view>
|
||
<view class="btn cancel-btn primary">再次购买</view>
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
<!-- 已取消 -->
|
||
<view v-if="order.type == 'yiquxiao'" class="cancel-progress-box">
|
||
<view class="cancel-content">
|
||
<view class="title-row">
|
||
<view class="left">
|
||
<image class="icon" src="/static/image/shopping/jingdong/detail/tuikuan.png"
|
||
mode="aspectFit">
|
||
</image>
|
||
<text class="title">取消/退款进度</text>
|
||
</view>
|
||
|
||
<uni-icons type="right" size="10" color="#1A1A1A"></uni-icons>
|
||
</view>
|
||
<text class="desc">您的订单已取消,请查看取消进度详情。</text>
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
<text class="tips" style="margin-top: 24rpx;">*轻点可替换商品图片,长按可从相册中选择图片*</text>
|
||
<!-- 推荐商品 -->
|
||
<view class="shop-recommend flex-center" @click="toggleRecommendImg" @longpress="chooseRecommendImg">
|
||
<image v-if="!order.recommendImg" class="w100 h100"
|
||
src="/static/image/shopping/jingdong/waimai/shop-recoomend/style-1.png" mode="aspectFit"></image>
|
||
<image v-else class="w100 h100" :src="order.recommendImg" mode="aspectFit"></image>
|
||
</view>
|
||
|
||
|
||
|
||
<!-- 商品卡片 -->
|
||
<view class="product-card">
|
||
<view class="title-box">
|
||
<view class="left-box">
|
||
<image class="img" src="/static/image/shopping/jingdong/waimai/waimai.png">
|
||
</image>
|
||
<view class="title flex animate-scale">
|
||
<auto-width-input v-model="order.shopName" fontSize="26rpx" fontWeight="500"
|
||
placeholder="请输入店铺名称" color="#1A1A1A" show-edit />
|
||
</view>
|
||
</view>
|
||
<uni-icons class="right-icon" size="14" color="#1A1A1A" type="right"></uni-icons>
|
||
</view>
|
||
<!-- 商品列表 -->
|
||
<view class="product-info-wrapper" v-for="(product, pIndex) in order.products" :key="pIndex">
|
||
<view class="product-info">
|
||
<view class="image-box" @click="chooseImage(pIndex)">
|
||
<view v-if="!product.image" class="w100 h100 flex flex-center"
|
||
style="background-color: #eeeeee;">
|
||
<image style="width: 60rpx;height: 60rpx;" src="/static/image/common/add.png"></image>
|
||
</view>
|
||
<image v-else class="w100 h100" :src="product.image"></image>
|
||
</view>
|
||
<view class="info-box">
|
||
<view class="name-row flex flex-justify-between">
|
||
<auto-width-input class="name flex-1" v-model="product.title" fontSize="26rpx"
|
||
fontWeight="500" placeholder="商品标题名称" color="#1A1A1A" show-edit type="textarea" />
|
||
<uni-icons v-if="order.products.length > 1" type="trash" size="18" color="#FE1528"
|
||
@click="deleteProduct(pIndex)" style="margin-left: 20rpx;"></uni-icons>
|
||
</view>
|
||
<view class="flex flex-align-center animate-scale">
|
||
<auto-width-input class="desc" v-model="product.desc" type="textarea" fontSize="22rpx"
|
||
placeholder="商品描述" color="#87868E" show-edit />
|
||
</view>
|
||
|
||
<view class="flex flex-align-center animate-scale desc">
|
||
<auto-width-input style="width: calc(100% - 18px);" v-model="product.count" type="number"
|
||
fontSize="22rpx" placeholder="请输入数量" color="#8D8D8D" show-edit minWidth="100%" />
|
||
</view>
|
||
<view class="flex flex-align-center animate-scale wx-font-medium"
|
||
style="align-items: baseline;margin-top: 10rpx;">
|
||
<text style="font-size: 28rpx;font-weight: 500;">¥</text>
|
||
<auto-width-input class="flex-1 wx-font-medium" v-model="product.price" type="digit"
|
||
fontSize="36rpx" placeholder="0.00" color="#1A1A1A" fontWeight="500" show-edit />
|
||
</view>
|
||
<!-- 新增:商品单项优惠额度 -->
|
||
<view class="flex flex-align-center animate-scale wx-font-medium"
|
||
style="align-items: baseline;margin-top: 4rpx; color: #F10F1A;">
|
||
<text style="font-size: 22rpx;font-weight: 500;">优惠 ¥</text>
|
||
<auto-width-input class="flex-1 wx-font-medium" v-model="product.discount" type="digit"
|
||
fontSize="28rpx" placeholder="0.00" color="#F10F1A" fontWeight="500" show-edit />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view v-if="pIndex < order.products.length - 1" class="product-divider"></view>
|
||
</view>
|
||
|
||
<!-- 添加商品按钮 -->
|
||
<view class="add-product-btn flex flex-center" @click="addProduct">
|
||
<image class="icon" src="/static/image/common/add.png" style="width: 24rpx; height: 24rpx;"></image>
|
||
<text>添加商品</text>
|
||
</view>
|
||
<view v-if="activeTab == 'weizhifu' || activeTab == 'yiquxiao'" class="order-info"
|
||
style="margin-top: 24rpx;">
|
||
<view class="item flex-justify-between">
|
||
<text class="label shrink-0">餐具数量</text>
|
||
<view class="flex-1 flex-align-center"
|
||
style="justify-content: flex-end;width: 300rpx;overflow-x: auto;margin-left: 20rpx;">
|
||
<auto-width-input class="value" v-model="order.productsInfo.cutleryCount" fontSize="26rpx"
|
||
type="textarea" color="#1A1A1A" show-edit />
|
||
</view>
|
||
</view>
|
||
<view class="item flex-justify-between">
|
||
<text class="label shrink-0">配送偏好</text>
|
||
<view class="flex-1 flex-align-center"
|
||
style="justify-content: flex-end;width: 300rpx;overflow-x: auto;margin-left: 20rpx;">
|
||
<auto-width-input class="value" v-model="order.productsInfo.deliveryPreference" type="textarea"
|
||
fontSize="26rpx" color="#1A1A1A" show-edit />
|
||
</view>
|
||
|
||
</view>
|
||
<view class="item flex-justify-between">
|
||
<text class="label shrink-0">如遇缺货</text>
|
||
<view class="flex-1 flex-align-center"
|
||
style="justify-content: flex-end;width: 300rpx;overflow-x: auto;margin-left: 20rpx;">
|
||
<auto-width-input class="value" v-model="order.productsInfo.outOfStock" type="textarea"
|
||
fontSize="26rpx" color="#1A1A1A" show-edit />
|
||
</view>
|
||
|
||
</view>
|
||
</view>
|
||
<view v-else class="order-info " style="margin-top: 50rpx;">
|
||
<view class="item flex-justify-between">
|
||
<text class="label shrink-0" style="color: #545454;">商品总价</text>
|
||
<view class="flex-1 flex-align-center wx-font-medium"
|
||
style="justify-content: flex-end; margin-left: 20rpx;font-weight: 500;">
|
||
¥<auto-width-input class="wx-font-medium" v-model="order.totalPrice" fontSize="32rpx"
|
||
placeholder="商品总价" color="#1A1A1A" fontWeight="500" type="digit" show-edit />
|
||
</view>
|
||
</view>
|
||
<view class="item flex-justify-between">
|
||
<view class="flex flex-align-center">
|
||
<text class="label" style="color: #545454;">运费</text>
|
||
<image style="width: 22rpx;height: 22rpx;margin-right: 4rpx;margin-left: 4rpx;"
|
||
src="/static/image/shopping/jingdong/detail/help.png">
|
||
</image>
|
||
</view>
|
||
|
||
|
||
<view class="wx-font-medium flex flex-align-center">
|
||
<text style="color: #F10F1A;">已减¥</text>
|
||
<auto-width-input class="wx-font-medium" v-model="order.discountCarriage" fontSize="26rpx"
|
||
placeholder="优惠运费" color="#F10F1A" fontWeight="500" type="digit" show-edit />
|
||
<auto-width-input style="margin-left: 10rpx;" class="wx-font-medium" v-model="order.carriage"
|
||
fontSize="26rpx" placeholder="运费" color="#1A1A1A" fontWeight="500" type="text" show-edit />
|
||
</view>
|
||
</view>
|
||
<view class="item flex-justify-between">
|
||
<text class="label shrink-0" style="color: #545454;">打包费</text>
|
||
<view class="flex-1 flex-align-center wx-font-medium"
|
||
style="justify-content: flex-end; margin-left: 20rpx;font-weight: 500;">
|
||
¥<auto-width-input style="margin-left: 10rpx;" class="wx-font-medium"
|
||
v-model="order.packagingFee" fontSize="26rpx" placeholder="打包费" color="#1A1A1A"
|
||
fontWeight="500" type="text" show-edit />
|
||
</view>
|
||
</view>
|
||
<view class="item flex-justify-between total-box">
|
||
<text class="label shrink-0" style="color: #545454;">合计</text>
|
||
<view class="flex-1 flex-align-center"
|
||
style="justify-content: flex-end; margin-left: 20rpx;font-weight: 500;">
|
||
<text class="red" style="color: #F10F1A;">共减¥<auto-width-input style="margin-left: 10rpx;"
|
||
class="wx-font-medium" v-model="order.discount" fontSize="26rpx" placeholder="优惠"
|
||
color="#F10F1A" fontWeight="500" type="text" show-edit /></text>
|
||
<text class="wx-font-medium money" style="margin-left: 16rpx;font-size: 28rpx;">¥<text
|
||
style="font-size: 36rpx;"><auto-width-input style="margin-left: 10rpx;"
|
||
class="wx-font-medium" v-model="order.amountTo" fontSize="36rpx" placeholder="合计金额"
|
||
color="#1A1A1A" fontWeight="500" type="text" show-edit /></text></text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
<!-- 商品总价 -->
|
||
<view v-if="activeTab == 'weizhifu' || activeTab == 'yiquxiao'" class="product-price">
|
||
<view class="title flex-justify-between">
|
||
<text>商品总价</text>
|
||
<view class="wx-font-medium flex flex-align-center"><text
|
||
style="font-size: 32rpx;font-weight: 500;">¥</text>
|
||
<auto-width-input class="wx-font-medium" v-model="order.totalPrice" fontSize="32rpx"
|
||
placeholder="商品总价" color="#1A1A1A" fontWeight="500" type="digit" show-edit />
|
||
</view>
|
||
</view>
|
||
<view class="item flex-justify-between">
|
||
<view class="flex flex-align-center">
|
||
<text class="label">运费</text>
|
||
<image style="width: 22rpx;height: 22rpx;margin-right: 4rpx;margin-left: 4rpx;"
|
||
src="/static/image/shopping/jingdong/detail/help.png">
|
||
</image>
|
||
</view>
|
||
|
||
<view class="wx-font-medium flex flex-align-center">
|
||
<text style="color: #F10F1A;">已减¥</text>
|
||
<auto-width-input class="wx-font-medium" v-model="order.discountCarriage" fontSize="26rpx"
|
||
placeholder="优惠运费" color="#F10F1A" fontWeight="500" type="digit" show-edit />
|
||
<auto-width-input style="margin-left: 10rpx;" class="wx-font-medium" v-model="order.carriage"
|
||
fontSize="26rpx" placeholder="运费" color="#1A1A1A" fontWeight="500" type="text" show-edit />
|
||
</view>
|
||
</view>
|
||
<view class="price">
|
||
<view class="label">合计</view>
|
||
<view>
|
||
共减<text class="number wx-font-medium" style="font-size: 32rpx;">¥<auto-width-input
|
||
style="margin-left: 10rpx;" class="wx-font-medium" v-model="order.discount" fontSize="26rpx"
|
||
placeholder="优惠运费" color="#F10F1A" fontWeight="500" type="text" show-edit /></text>
|
||
需付款 <text class="number wx-font-medium">
|
||
¥{{ order.amountTo || '0.00' }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
<!-- 订单信息 -->
|
||
<view class="order-info-box">
|
||
<view class="title flex-justify-between">
|
||
<text>订单信息</text>
|
||
</view>
|
||
<!-- 用户信息 -->
|
||
<template v-if="activeTab != 'weizhifu' && activeTab != 'yiquxiao'">
|
||
<view class="item flex-justify-between"
|
||
@click="onClickItemInfo({ label: '期望时间', type: 'timeRange', key: 'deliveryTime' })">
|
||
<text class="label shrink-0">期望时间</text>
|
||
<view class="flex-1 flex-align-center"
|
||
style="justify-content: flex-end;width: 300rpx;overflow-x: auto;margin-left: 20rpx;">
|
||
<auto-width-input class="value" v-model="order.productsInfo.deliveryTime" fontSize="26rpx"
|
||
type="text" color="#1A1A1A" show-edit :disabled="true" />
|
||
</view>
|
||
</view>
|
||
<view class="item flex-justify-between">
|
||
<text class="label shrink-0">配送地址</text>
|
||
<view class="flex-1 flex-align-center"
|
||
style="justify-content: flex-end;width: 300rpx;overflow-x: auto;margin-left: 20rpx;">
|
||
<auto-width-input class="value" v-model="order.address" fontSize="26rpx" type="textarea"
|
||
color="#1A1A1A" show-edit />
|
||
</view>
|
||
</view>
|
||
<view class="item flex-justify-between">
|
||
<text class="label shrink-0">餐具数量</text>
|
||
<view class="flex-1 flex-align-center"
|
||
style="justify-content: flex-end;width: 300rpx;overflow-x: auto;margin-left: 20rpx;">
|
||
<auto-width-input class="value" v-model="order.productsInfo.cutleryCount" fontSize="26rpx"
|
||
type="text" color="#1A1A1A" show-edit />
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<view class="order-info">
|
||
<view class="item flex-justify-between" v-for="(item, index) in order.orderInfo" :key="index"
|
||
@click="onClickItemInfo(item)">
|
||
<text class="label shrink-0">{{ item.label }}</text>
|
||
<view class="flex-1 flex-align-center"
|
||
style="justify-content: flex-end;width: 300rpx;overflow-x: auto;margin-left: 20rpx;">
|
||
<auto-width-input class="value" v-model="item.value" fontSize="26rpx" color="#1A1A1A"
|
||
:type="item.type ? item.type : 'text'" show-edit
|
||
:disabled="item.type == 'time' || item.type == 'timeRange'" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<template v-if="screenshotImage">
|
||
<view class="w100 flex-center" style="margin-top: 40rpx;margin-bottom: 32rpx;">
|
||
<image style="width: 32rpx;height: 20rpx;" src="/static/image/shopping/jingdong/detail/like-left.png">
|
||
</image>
|
||
<text
|
||
style="font-size: 26rpx;color: #1A1A1A;line-height: 26rpx;font-weight: 500;margin: 0 10rpx;">你可能还喜欢</text>
|
||
<image style="width: 32rpx;height: 20rpx;" src="/static/image/shopping/jingdong/detail/like-right.png">
|
||
</image>
|
||
</view>
|
||
|
||
<!-- 上传图片 -->
|
||
<view class="upload-screenshot-box">
|
||
<view class="upload-screenshot-content w100">
|
||
<!-- <image class="upload-screenshot" src="/static/image/common/upload-screenshot.png" mode="aspectFit">
|
||
</image>
|
||
<view class="upload-screenshot-text">长按替换截图</view> -->
|
||
<image class="w100" :src="screenshotImage" mode="widthFix"></image>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
</view>
|
||
|
||
<uni-popup ref="deliveryTimePopup" type="bottom">
|
||
<view class="timeBox">
|
||
<view class="titleBox">
|
||
<view class="title" @click="closeDeliveryPopup">取消</view>
|
||
<view class="btn" @click="confirmDeliveryTime">确定</view>
|
||
</view>
|
||
<view class="picker-container">
|
||
<picker-view class="range-picker-view" :value="deliveryPickerValue" @change="onDeliveryPickerChange">
|
||
<picker-view-column>
|
||
<view class="picker-item" v-for="item in deliveryHours" :key="item">{{ item }}</view>
|
||
</picker-view-column>
|
||
<picker-view-column>
|
||
<view class="picker-item" v-for="item in deliveryMinutes" :key="item">{{ item }}</view>
|
||
</picker-view-column>
|
||
<picker-view-column>
|
||
<view class="picker-item flex-center">-</view>
|
||
</picker-view-column>
|
||
<picker-view-column>
|
||
<view class="picker-item" v-for="item in deliveryHours" :key="item">{{ item }}</view>
|
||
</picker-view-column>
|
||
<picker-view-column>
|
||
<view class="picker-item" v-for="item in deliveryMinutes" :key="item">{{ item }}</view>
|
||
</picker-view-column>
|
||
</picker-view>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
|
||
<uni-popup ref="timepopup" type="bottom">
|
||
<!-- 单点时间选择 -->
|
||
<view v-if="selectItemInfo.type == 'time'" class="timeBox">
|
||
<view class="titleBox">
|
||
<view class="title" @click="closeTimePicker">取消</view>
|
||
<view class="btn" @click="settmes">确定</view>
|
||
</view>
|
||
<DateTimePicker :defaultDate="datePickerData.selectDate" :minDate="datePickerData.startDate"
|
||
:maxDate="datePickerData.endDate" :mode="4" @onChange="onChangeStartDate" />
|
||
</view>
|
||
|
||
<!-- 时间段选择 -->
|
||
<view v-if="selectItemInfo.type == 'timeRange'" class="timeBox">
|
||
<view class="titleBox">
|
||
<view class="title" @click="closeTimePicker">取消</view>
|
||
<view class="btn" @click="settmes">确定</view>
|
||
</view>
|
||
<view class="picker-container">
|
||
<picker-view class="range-picker-view" :value="timeRangePickerData.rangeSelect"
|
||
@change="onTimeRangeChange">
|
||
<picker-view-column v-for="(col, colIdx) in timeRangePickerData.rangeCols" :key="colIdx">
|
||
<view class="picker-item" v-for="(item, idx) in col" :key="idx">{{ item }}</view>
|
||
</picker-view-column>
|
||
</picker-view>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { onLoad } from "@dcloudio/uni-app";
|
||
import { ref, computed, watch, onMounted, nextTick, reactive, toRefs } from "vue";
|
||
import NavBar from "@/components/nav-bar/nav-bar.vue";
|
||
import { waimaiType, waimaiClassfiy, waimaiProductList } from "../json/order.json";
|
||
import AutoWidthInput from "@/components/common/auto-width-input.vue";
|
||
import DateTimePicker from '@/components/dengrq-datetime-picker/dateTimePicker/index.vue';
|
||
import { stringUtil } from "@/utils/common.js";
|
||
|
||
const data = reactive({
|
||
activeTab: 'weizhifu',
|
||
order: {},
|
||
isEditMode: false,
|
||
currentId: ''
|
||
})
|
||
let { activeTab, order, isEditMode, currentId } = toRefs(data);
|
||
|
||
const navTitle = computed(() => isEditMode.value ? "修改外卖订单" : "新增外卖订单");
|
||
|
||
/**
|
||
* 切换tab
|
||
* @param index
|
||
*/
|
||
/**
|
||
* @param item
|
||
*/
|
||
const switchTab = (item) => {
|
||
// 备份当前数据用于跨页签恢复
|
||
const oldData = JSON.parse(JSON.stringify(order.value));
|
||
|
||
data.activeTab = item.key;
|
||
order.value = JSON.parse(JSON.stringify(waimaiClassfiy[data.activeTab]));
|
||
|
||
// 恢复基础通用字段
|
||
if (oldData) {
|
||
order.value.id = oldData.id || order.value.id;
|
||
order.value.consignee = oldData.consignee || order.value.consignee;
|
||
order.value.phone = oldData.phone || order.value.phone;
|
||
order.value.fullAddress = oldData.fullAddress || order.value.fullAddress;
|
||
order.value.shopName = oldData.shopName || order.value.shopName;
|
||
order.value.shopType = oldData.shopType || order.value.shopType;
|
||
|
||
// 恢复商品列表 (如果旧数据有商品,尝试继承,防止切 Tab 丢失已添加内容)
|
||
if (oldData.products && oldData.products.length > 0) {
|
||
order.value.products = JSON.parse(JSON.stringify(oldData.products));
|
||
}
|
||
|
||
// 恢复 orderInfo 中的手动输入值
|
||
if (order.value.orderInfo && oldData.orderInfo) {
|
||
order.value.orderInfo.forEach(newInfo => {
|
||
const target = oldData.orderInfo.find(o => o.label === newInfo.label);
|
||
if (target && target.value) {
|
||
newInfo.value = target.value;
|
||
}
|
||
});
|
||
}
|
||
|
||
// 统一调用初始化逻辑补全缺失时间(下单、支付、交易、期望时间)
|
||
initDefaultTimes();
|
||
|
||
// 如果是新增模式,切换 tab 时也随机一下商品 (符合用户要求)
|
||
if (!isEditMode.value) {
|
||
clickRandomDate();
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 选择图片
|
||
* @param index 商品索引
|
||
*/
|
||
const chooseImage = (index = 0) => {
|
||
uni.chooseImage({
|
||
count: 1,
|
||
sizeType: ['original'],
|
||
sourceType: ['album'],
|
||
success: (res) => {
|
||
const tempFile = res.tempFilePaths[0];
|
||
|
||
// #ifdef APP-PLUS || MP-WEIXIN
|
||
// App端/小程序端:将临时路径持久化
|
||
uni.saveFile({
|
||
tempFilePath: tempFile,
|
||
success: (saveRes) => {
|
||
order.value.products[index].image = saveRes.savedFilePath;
|
||
},
|
||
fail: () => {
|
||
// 如果持久化失败,回退到临时路径
|
||
order.value.products[index].image = tempFile;
|
||
}
|
||
});
|
||
// #endif
|
||
|
||
// #ifdef H5
|
||
// H5端:直接使用临时路径 (Blob URL)
|
||
order.value.products[index].image = tempFile;
|
||
// #endif
|
||
}
|
||
});
|
||
};
|
||
|
||
const chooseDeliveryImage = () => {
|
||
// 记录旧图路径用于清理
|
||
const oldImagePath = order.value.deliveryImages;
|
||
|
||
uni.chooseImage({
|
||
count: 1,
|
||
sizeType: ['original'],
|
||
sourceType: ['album'],
|
||
success: (res) => {
|
||
const tempFilePath = res.tempFilePaths[0];
|
||
|
||
// #ifdef H5
|
||
// H5端直接使用,不进行持久化保存
|
||
order.value.deliveryImages = tempFilePath;
|
||
uni.showToast({ title: '上传预览成功', icon: 'success' });
|
||
// #endif
|
||
|
||
// #ifdef APP-PLUS || MP-WEIXIN
|
||
uni.showLoading({ title: '处理图片中...' });
|
||
// 将新图保存为持久化文件
|
||
uni.saveFile({
|
||
tempFilePath: tempFilePath,
|
||
success: (saveRes) => {
|
||
// 1. 设置新图片路径
|
||
order.value.deliveryImages = saveRes.savedFilePath;
|
||
|
||
// 2. 如果旧图是本地持久化文件,则物理删除它
|
||
if (oldImagePath && (oldImagePath.includes('_doc') || oldImagePath.includes('store_') || oldImagePath.includes('at_'))) {
|
||
uni.removeSavedFile({
|
||
filePath: oldImagePath,
|
||
success: () => console.log('旧配送图已清理:', oldImagePath),
|
||
fail: (err) => console.error('旧图清理失败:', err)
|
||
});
|
||
}
|
||
uni.showToast({ title: '上传成功', icon: 'success' });
|
||
},
|
||
fail: (err) => {
|
||
console.error('保存图片失败:', err);
|
||
order.value.deliveryImages = tempFilePath;
|
||
},
|
||
complete: () => {
|
||
uni.hideLoading();
|
||
}
|
||
});
|
||
// #endif
|
||
}
|
||
});
|
||
};
|
||
|
||
/**
|
||
* 添加商品
|
||
*/
|
||
const addProduct = () => {
|
||
if (!order.value.products) {
|
||
order.value.products = [];
|
||
}
|
||
order.value.products.push({
|
||
image: "",
|
||
title: "",
|
||
desc: "",
|
||
service: "不支持7天无理由退货",
|
||
price: "0.00",
|
||
discount: "0.00",
|
||
count: 1
|
||
});
|
||
};
|
||
|
||
/**
|
||
* 删除商品
|
||
* @param index
|
||
*/
|
||
const deleteProduct = (index) => {
|
||
if (!order.value.products || order.value.products.length <= 1) return;
|
||
order.value.products.splice(index, 1);
|
||
};
|
||
|
||
/**
|
||
* 通用:检测并清理本地持久化文件
|
||
*/
|
||
const detectAndRemoveLocalFile = (path) => {
|
||
if (!path) return;
|
||
// 仅对沙盒路径执行物理删除
|
||
if (path.includes('_doc') || path.includes('store_') || path.includes('at_')) {
|
||
uni.removeSavedFile({
|
||
filePath: path,
|
||
success: () => console.log('本地冗余文件已物理清理:', path),
|
||
fail: (err) => console.log('物理清理跳过或失败:', err)
|
||
});
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 切换推荐商品图片 (点击切换内置样式)
|
||
*/
|
||
const toggleRecommendImg = () => {
|
||
const style1 = '/static/image/shopping/jingdong/waimai/shop-recoomend/style-1.png';
|
||
const style2 = '/static/image/shopping/jingdong/waimai/shop-recoomend/style-2.png';
|
||
|
||
// 如果当前是自定义路径,在切回内置样式前,先清理物理文件
|
||
detectAndRemoveLocalFile(order.value.recommendImg);
|
||
|
||
if (order.value.recommendImg === style1) {
|
||
order.value.recommendImg = style2;
|
||
} else {
|
||
order.value.recommendImg = style1;
|
||
}
|
||
};
|
||
|
||
// 推荐商品图选择逻辑 (直接持久化)
|
||
const chooseRecommendImg = () => {
|
||
const oldImagePath = order.value.recommendImg;
|
||
|
||
uni.chooseImage({
|
||
count: 1,
|
||
sizeType: ['original'],
|
||
sourceType: ['album'],
|
||
success: (res) => {
|
||
const tempFilePath = res.tempFilePaths[0];
|
||
|
||
// #ifdef H5
|
||
order.value.recommendImg = tempFilePath;
|
||
uni.showToast({ title: '更换预览成功', icon: 'success' });
|
||
// #endif
|
||
|
||
// #ifdef APP-PLUS || MP-WEIXIN
|
||
uni.showLoading({ title: '处理图片中...' });
|
||
uni.saveFile({
|
||
tempFilePath: tempFilePath,
|
||
success: (saveRes) => {
|
||
// 1. 先清理旧的本地文件
|
||
detectAndRemoveLocalFile(oldImagePath);
|
||
|
||
// 2. 设置新路径
|
||
order.value.recommendImg = saveRes.savedFilePath;
|
||
|
||
uni.showToast({ title: '自定义图片成功', icon: 'success' });
|
||
},
|
||
fail: () => {
|
||
order.value.recommendImg = tempFilePath;
|
||
},
|
||
complete: () => {
|
||
uni.hideLoading();
|
||
}
|
||
});
|
||
// #endif
|
||
}
|
||
});
|
||
};
|
||
|
||
|
||
// 初始化默认时间值与订单号
|
||
const initDefaultTimes = () => {
|
||
if (!order.value) return;
|
||
const now = new Date();
|
||
const timeStr = formatTime(now);
|
||
|
||
// 1. 初始化订单基本信息 (时间、订单编号)
|
||
if (order.value.orderInfo) {
|
||
order.value.orderInfo.forEach(item => {
|
||
const label = item.label;
|
||
// 填充时间
|
||
if ((label === '下单时间' || label === '支付时间' || label === '交易时间') && (!item.value || item.value.trim() === '' || item.value === '请输入')) {
|
||
item.value = timeStr;
|
||
}
|
||
// 填充随机订单号
|
||
if (label === '订单编号' && (!item.value || item.value.trim() === '' || item.value === '请输入')) {
|
||
item.value = generateRandomOrder().toString();
|
||
}
|
||
});
|
||
}
|
||
|
||
// 3. 为未支付状态初始化默认倒计时
|
||
if (activeTab.value === 'weizhifu' && (!order.value.statusDesc || order.value.statusDesc.trim() === '')) {
|
||
const m = (Math.floor(Math.random() * 30) + 1).toString().padStart(2, '0');
|
||
const s = Math.floor(Math.random() * 60).toString().padStart(2, '0');
|
||
order.value.statusDesc = `${m}:${s}`;
|
||
}
|
||
|
||
// 2. 初始化期望时间 (当前+40min 至 当前+65min)
|
||
if (order.value.productsInfo) {
|
||
if (!order.value.productsInfo.deliveryTime || order.value.productsInfo.deliveryTime.trim() === '' || order.value.productsInfo.deliveryTime === '请输入') {
|
||
const start = new Date(now.getTime() + 40 * 60000);
|
||
const end = new Date(now.getTime() + 65 * 60000);
|
||
const startText = `${start.getHours().toString().padStart(2, '0')}:${start.getMinutes().toString().padStart(2, '0')}`;
|
||
const endText = `${end.getHours().toString().padStart(2, '0')}:${end.getMinutes().toString().padStart(2, '0')}`;
|
||
order.value.productsInfo.deliveryTime = `今天${startText}-${endText}`;
|
||
}
|
||
}
|
||
|
||
// 强制通知 Vue 更新
|
||
order.value = { ...order.value };
|
||
};
|
||
|
||
onLoad((options) => {
|
||
console.log('外卖页面接收参数:', options);
|
||
const editFlag = String(options.isEdit) === 'true' || options.isEdit === true;
|
||
|
||
if (editFlag && options.id) {
|
||
// 1. 设置编辑标志
|
||
isEditMode.value = true;
|
||
currentId.value = String(options.id);
|
||
|
||
// 2. 从缓存加载数据回填
|
||
const list = uni.getStorageSync('jingdongShopping') || [];
|
||
const editData = list.find(item => String(item.id) === String(options.id));
|
||
|
||
if (editData) {
|
||
order.value = JSON.parse(JSON.stringify(editData));
|
||
if (editData.activeTab) {
|
||
activeTab.value = editData.activeTab;
|
||
}
|
||
console.log('编辑模式激活,数据回显:', activeTab.value);
|
||
}
|
||
} else {
|
||
// 新增模式
|
||
initDefaultTimes();
|
||
switchTab({ key: activeTab.value });
|
||
// 初始化随机
|
||
clickRandomDate();
|
||
}
|
||
});
|
||
|
||
/**
|
||
* 随机选择外卖商品 (避开当前商品)
|
||
*/
|
||
const clickRandomDate = () => {
|
||
if (!waimaiProductList || waimaiProductList.length === 0) return;
|
||
|
||
// 获取当前店铺名称 (用于去重)
|
||
const currentShop = order.value?.shopName || '';
|
||
|
||
// 过滤掉当前已经选中的店铺
|
||
let available = waimaiProductList.filter(p => p.shopName !== currentShop);
|
||
|
||
// 如果过滤后没剩,则全量随机
|
||
if (available.length === 0) {
|
||
available = waimaiProductList;
|
||
}
|
||
|
||
// 随机抽选
|
||
const randomIndex = Math.floor(Math.random() * available.length);
|
||
const selected = JSON.parse(JSON.stringify(available[randomIndex]));
|
||
|
||
// 更新到当前订单对象
|
||
if (order.value) {
|
||
order.value.shopName = selected.shopName || order.value.shopName;
|
||
if (selected.products && selected.products.length > 0) {
|
||
// 替换整个商品列表
|
||
order.value.products = selected.products;
|
||
}
|
||
// 触发 UI 更新
|
||
order.value = { ...order.value };
|
||
}
|
||
};
|
||
|
||
const deliveryTimePopup = ref(null);
|
||
const timepopup = ref(null); // 单点时间选择器引用
|
||
const deliveryHours = Array.from({ length: 24 }, (_, i) => i.toString().padStart(2, '0'));
|
||
const deliveryMinutes = Array.from({ length: 60 }, (_, i) => i.toString().padStart(2, '0'));
|
||
const deliveryPickerValue = ref([11, 17, 0, 11, 32]);
|
||
|
||
// 倒计时选择器范围 (0-59分, 0-59秒)
|
||
const countdownRange = ref([
|
||
Array.from({ length: 60 }, (_, i) => i.toString().padStart(2, '0')),
|
||
Array.from({ length: 60 }, (_, i) => i.toString().padStart(2, '0'))
|
||
]);
|
||
|
||
// 倒计时数值解析索引
|
||
const countdownValue = computed(() => {
|
||
if (!order.value || !order.value.statusDesc) return [29, 59];
|
||
const parts = order.value.statusDesc.split(':');
|
||
if (parts.length !== 2) return [29, 59];
|
||
return [
|
||
parseInt(parts[0]) || 0,
|
||
parseInt(parts[1]) || 0
|
||
];
|
||
});
|
||
|
||
/**
|
||
* 处理倒计时修改
|
||
*/
|
||
const handleCountdownChange = (e) => {
|
||
const val = e.detail.value;
|
||
const m = countdownRange.value[0][val[0]];
|
||
const s = countdownRange.value[1][val[1]];
|
||
order.value.statusDesc = `${m}:${s}`;
|
||
};
|
||
|
||
const editingField = ref('deliveryTime');
|
||
|
||
// 单点时间选择状态
|
||
const selectItemInfo = ref({
|
||
type: '',
|
||
value: '',
|
||
label: '',
|
||
id: ''
|
||
});
|
||
|
||
const datePickerData = ref({
|
||
selectDate: "",
|
||
startDate: "",
|
||
endDate: "",
|
||
});
|
||
|
||
// 时间段选择器数据 (参考 add-order)
|
||
const timeRangePickerData = ref({
|
||
rangeCols: [[], [], [], [], []], // 年, 月, 日, 开始时间, 结束时间
|
||
rangeSelect: [0, 5, 14, 9, 22]
|
||
});
|
||
|
||
/**
|
||
* 初始化时间段选择器列
|
||
*/
|
||
const initTimeRangeColumns = () => {
|
||
const years = [];
|
||
const now = new Date();
|
||
const currentYear = now.getFullYear();
|
||
for (let i = currentYear - 5; i <= currentYear + 5; i++) {
|
||
years.push(i + '年');
|
||
}
|
||
const months = Array.from({ length: 12 }, (_, i) => (i + 1).toString().padStart(2, '0') + '月');
|
||
const days = Array.from({ length: 31 }, (_, i) => (i + 1).toString().padStart(2, '0') + '日');
|
||
const hours = Array.from({ length: 24 }, (_, i) => i.toString().padStart(2, '0') + ':00');
|
||
timeRangePickerData.value.rangeCols = [years, months, days, hours, hours];
|
||
};
|
||
|
||
onMounted(() => {
|
||
initTimeRangeColumns();
|
||
});
|
||
|
||
/**
|
||
* 点击信息项
|
||
*/
|
||
const onClickItemInfo = (item) => {
|
||
if (item.label === '收货信息') return;
|
||
if (item.type == 'time') {
|
||
datePickerData.value.selectDate = item.value || formatTime(new Date());
|
||
datePickerData.value.endDate = "2099-12-31 23:59:59";
|
||
selectItemInfo.value = item;
|
||
if (timepopup.value) timepopup.value.open();
|
||
} else if (item.type == 'timeRange') {
|
||
selectItemInfo.value = item;
|
||
// 预设选择器索引 (默认设为今天)
|
||
const now = new Date();
|
||
const yIdx = timeRangePickerData.value.rangeCols[0].indexOf(now.getFullYear() + '年');
|
||
const mIdx = now.getMonth();
|
||
const dIdx = now.getDate() - 1;
|
||
timeRangePickerData.value.rangeSelect = [yIdx > -1 ? yIdx : 5, mIdx, dIdx, 9, 22];
|
||
|
||
if (timepopup.value) timepopup.value.open();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 点击“备餐时间”或“取餐时间”
|
||
*/
|
||
const onClickTrackingTime = () => {
|
||
const label = activeTab.value === 'beicanzhong' ? '备餐时间' : '取餐时间';
|
||
// 设置选择器上下文
|
||
selectItemInfo.value = {
|
||
label: label,
|
||
value: order.value.trackingTime || formatTime(new Date()),
|
||
type: 'time',
|
||
key: 'trackingTime'
|
||
};
|
||
datePickerData.value.selectDate = selectItemInfo.value.value;
|
||
datePickerData.value.endDate = "2099-12-31 23:59:59";
|
||
|
||
if (timepopup.value) timepopup.value.open();
|
||
}
|
||
|
||
/**
|
||
* 时间段选择器变化回调
|
||
*/
|
||
const onTimeRangeChange = (e) => {
|
||
timeRangePickerData.value.rangeSelect = e.detail.value;
|
||
}
|
||
|
||
/**
|
||
* 设置时间
|
||
*/
|
||
const settmes = () => {
|
||
if (selectItemInfo.value.type == 'time') {
|
||
selectItemInfo.value.value = datePickerData.value.selectDate;
|
||
// 额外同步到 order.trackingTime
|
||
if (selectItemInfo.value.key === 'trackingTime') {
|
||
order.value.trackingTime = datePickerData.value.selectDate;
|
||
}
|
||
} else if (selectItemInfo.value.type == 'timeRange') {
|
||
const cols = timeRangePickerData.value.rangeCols;
|
||
const sel = timeRangePickerData.value.rangeSelect;
|
||
const yStr = cols[0][sel[0]].replace('年', '');
|
||
const mStr = cols[1][sel[1]].replace('月', '');
|
||
const dStr = cols[2][sel[2]].replace('日', '');
|
||
const startStr = cols[3][sel[3]];
|
||
const endStr = cols[4][sel[4]];
|
||
|
||
// 判断是否为今天
|
||
const now = new Date();
|
||
const isToday = parseInt(yStr) === now.getFullYear() &&
|
||
parseInt(mStr) === (now.getMonth() + 1) &&
|
||
parseInt(dStr) === now.getDate();
|
||
|
||
const dateLabel = isToday ? '今天' : `${yStr}-${mStr}-${dStr} `;
|
||
const resultValue = `${dateLabel}${startStr}-${endStr}`;
|
||
|
||
if (selectItemInfo.value.key === 'deliveryTime') {
|
||
order.value.productsInfo.deliveryTime = resultValue;
|
||
} else {
|
||
selectItemInfo.value.value = resultValue;
|
||
}
|
||
}
|
||
// 强制触发响应式
|
||
order.value = { ...order.value };
|
||
closeTimePicker();
|
||
}
|
||
|
||
/**
|
||
* 单点时间选择器变化回调
|
||
*/
|
||
const onChangeStartDate = (e) => {
|
||
datePickerData.value.selectDate = e;
|
||
}
|
||
|
||
/**
|
||
* 关闭单点时间选择器弹窗
|
||
*/
|
||
const closeTimePicker = () => {
|
||
if (timepopup.value) timepopup.value.close();
|
||
}
|
||
|
||
/**
|
||
* 配送时间点击事件
|
||
*/
|
||
const onDeliveryTimeClick = (field = 'deliveryTime') => {
|
||
editingField.value = field;
|
||
// 解析当前时间字符串设置索引
|
||
const currentOrder = data.order;
|
||
const timeStr = currentOrder[field];
|
||
|
||
if (timeStr) {
|
||
const parts = timeStr.split('-');
|
||
if (parts.length === 2) {
|
||
const start = parts[0].split(':');
|
||
const end = parts[1].split(':');
|
||
deliveryPickerValue.value = [
|
||
parseInt(start[0]) || 0,
|
||
parseInt(start[1]) || 0,
|
||
0,
|
||
parseInt(end[0]) || 0,
|
||
parseInt(end[1]) || 0
|
||
];
|
||
}
|
||
}
|
||
nextTick(() => {
|
||
if (deliveryTimePopup.value) deliveryTimePopup.value.open();
|
||
})
|
||
};
|
||
|
||
/**
|
||
* 关闭配送时间选择器弹窗
|
||
*/
|
||
const closeDeliveryPopup = () => {
|
||
if (deliveryTimePopup.value) deliveryTimePopup.value.close();
|
||
}
|
||
|
||
/**
|
||
* 配送时间选择器变化回调
|
||
*/
|
||
const onDeliveryPickerChange = (e) => {
|
||
deliveryPickerValue.value = e.detail.value;
|
||
};
|
||
|
||
/**
|
||
* 确认配送时间
|
||
*/
|
||
const confirmDeliveryTime = () => {
|
||
const val = deliveryPickerValue.value;
|
||
const startH = deliveryHours[val[0]];
|
||
const startM = deliveryMinutes[val[1]];
|
||
const endH = deliveryHours[val[3]];
|
||
const endM = deliveryMinutes[val[4]];
|
||
const finalTime = `${startH}:${startM}-${endH}:${endM}`;
|
||
|
||
// 直接操作 order.value (由于 toRefs 解构,它直接指向 data.order)
|
||
if (order.value) {
|
||
console.log(editingField.value, finalTime);
|
||
order.value[editingField.value] = finalTime;
|
||
// 显式触发全量替换以确保 UI 刷新
|
||
order.value = { ...order.value };
|
||
}
|
||
|
||
closeDeliveryPopup();
|
||
};
|
||
|
||
/**
|
||
* 格式化时间
|
||
*/
|
||
const formatTime = (date) => {
|
||
const y = date.getFullYear();
|
||
const m = (date.getMonth() + 1).toString().padStart(2, '0');
|
||
const d = date.getDate().toString().padStart(2, '0');
|
||
const h = date.getHours().toString().padStart(2, '0');
|
||
const min = date.getMinutes().toString().padStart(2, '0');
|
||
const s = date.getSeconds().toString().padStart(2, '0');
|
||
return `${y}-${m}-${d} ${h}:${min}:${s}`;
|
||
};
|
||
|
||
/**
|
||
* 生成随机订单号
|
||
*/
|
||
const generateRandomOrder = () => {
|
||
return Math.floor(Math.random() * 9000000000) + 1000000000;
|
||
};
|
||
|
||
|
||
/**
|
||
* 计算商品总价
|
||
*/
|
||
const totalProductPrice = computed(() => {
|
||
if (!order.value || !order.value.products) return '0.00';
|
||
const total = order.value.products.reduce((sum, item) => {
|
||
const price = parseFloat(item.price) || 0;
|
||
const countStr = String(item.count || '1');
|
||
// 处理可能包含 "数量x" 字符的情况
|
||
const count = parseInt(countStr.replace(/[^\d]/g, '')) || 0;
|
||
return sum + (price * count);
|
||
}, 0);
|
||
return total.toFixed(2);
|
||
});
|
||
|
||
// 监听商品列表变化,实现自动计算总价逻辑
|
||
watch(() => order.value.products, (newProducts) => {
|
||
if (newProducts && newProducts.length > 0) {
|
||
order.value.totalPrice = totalProductPrice.value;
|
||
}
|
||
}, { deep: true, immediate: true });
|
||
|
||
/**
|
||
* 自动计算总优惠 (order.discount)
|
||
* 逻辑:所有商品优惠记录之和 + 运费优惠 (discountCarriage)
|
||
*/
|
||
watch([
|
||
() => order.value.products,
|
||
() => order.value.discountCarriage
|
||
], () => {
|
||
if (!order.value) return;
|
||
const productsDiscount = order.value.products ? order.value.products.reduce((sum, p) => {
|
||
const disc = parseMoney(p.discount || '0');
|
||
const countStr = String(p.count || '1');
|
||
const count = parseInt(countStr.replace(/[^\d]/g, '')) || 0;
|
||
return sum + (disc * count);
|
||
}, 0) : 0;
|
||
const shippingDiscount = parseMoney(order.value.discountCarriage || '0');
|
||
const totalDiscount = productsDiscount + shippingDiscount;
|
||
order.value.discount = totalDiscount > 0 ? totalDiscount.toFixed(2) : '0.00';
|
||
}, { deep: true, immediate: true });
|
||
|
||
/**
|
||
* 安全转换数值
|
||
*/
|
||
const parseMoney = (val) => {
|
||
if (!val) return 0;
|
||
if (typeof val === 'number') return val;
|
||
// 移除非数字符号(保留小数点)
|
||
const num = parseFloat(String(val).replace(/[^\d.]/g, ''));
|
||
return isNaN(num) ? 0 : num;
|
||
}
|
||
|
||
// 监听相关分项变化,实现自动计算合计金额逻辑
|
||
// 逻辑:总金额 = 商品总价 + 运费 + 打包费 - 优惠
|
||
watch([
|
||
() => order.value.totalPrice,
|
||
() => order.value.carriage,
|
||
() => order.value.packagingFee,
|
||
() => order.value.discount
|
||
], ([tp, c, pf, d]) => {
|
||
const total = parseMoney(tp) + parseMoney(c) + parseMoney(pf) - parseMoney(d);
|
||
order.value.amountTo = total > 0 ? total.toFixed(2) : '0.00';
|
||
}, { immediate: true });
|
||
|
||
/**
|
||
* 确认订单
|
||
*/
|
||
const onConfirm = () => {
|
||
let list = uni.getStorageSync('jingdongShopping') || [];
|
||
if (!Array.isArray(list)) {
|
||
list = [];
|
||
}
|
||
order.value.activeTab = activeTab.value;
|
||
if (isEditMode.value) {
|
||
// 修改模式:查找原有 ID 并替换 (强制转字符串匹配)
|
||
const index = list.findIndex(item => String(item.id) === String(currentId.value));
|
||
if (index > -1) {
|
||
list[index] = JSON.parse(JSON.stringify(order.value));
|
||
} else {
|
||
// 如果缓存中没找到(可能是第一次修改系统默认数据),则追加
|
||
list.push(JSON.parse(JSON.stringify(order.value)));
|
||
}
|
||
} else {
|
||
// 新增模式:仅在真正新增时生成 UUID 并追加
|
||
order.value.id = stringUtil.uuid();
|
||
list.push(JSON.parse(JSON.stringify(order.value)));
|
||
}
|
||
uni.setStorageSync('jingdongShopping', list);
|
||
console.log("确认订单", order.value);
|
||
uni.showToast({
|
||
title: isEditMode.value ? '修改成功' : '保存成功',
|
||
icon: 'success'
|
||
});
|
||
setTimeout(() => {
|
||
uni.navigateBack();
|
||
}, 1500);
|
||
}
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.tab-box {
|
||
background-color: #F2F3F7;
|
||
padding: 22rpx 24rpx;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
overflow: hidden;
|
||
overflow-x: scroll;
|
||
|
||
&::-webkit-scrollbar {
|
||
display: none;
|
||
/* 隐藏滚动条 */
|
||
}
|
||
|
||
.tab {
|
||
white-space: nowrap;
|
||
padding: 10rpx 20rpx;
|
||
border-radius: 28rpx;
|
||
margin-right: 16rpx;
|
||
background-color: #fff;
|
||
font-size: 26rpx;
|
||
color: #1a1a1a;
|
||
flex-shrink: 0;
|
||
font-weight: 500;
|
||
|
||
&.active {
|
||
color: #1B71F8;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
.card {
|
||
background-color: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 20rpx 22rpx;
|
||
margin: 0 24rpx;
|
||
}
|
||
|
||
.weizhifu {
|
||
|
||
.title {
|
||
font-size: 52rpx;
|
||
color: #1A1A1A;
|
||
line-height: 52rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.time {
|
||
font-size: 30rpx;
|
||
color: #1A1A1A;
|
||
line-height: 30rpx;
|
||
margin-top: 26rpx;
|
||
font-weight: 500;
|
||
|
||
.time-text {
|
||
color: #F10F1A;
|
||
}
|
||
}
|
||
|
||
.btn {
|
||
|
||
padding: 0 20rpx;
|
||
border-radius: 8rpx;
|
||
margin-left: 16rpx;
|
||
background-color: #fff;
|
||
font-size: 26rpx;
|
||
line-height: 60rpx;
|
||
color: #1a1a1a;
|
||
flex-shrink: 0;
|
||
font-weight: 500;
|
||
border: 0.5px solid #C7C7C7;
|
||
|
||
&.pay-btn {
|
||
width: 380rpx;
|
||
border: none;
|
||
color: #fff;
|
||
text-align: center;
|
||
background: linear-gradient(87deg, #FF435B 0%, #FE1528 100%);
|
||
}
|
||
}
|
||
}
|
||
|
||
.location-box {
|
||
margin-top: 16rpx;
|
||
padding: 26rpx 22rpx;
|
||
|
||
.location-icon {
|
||
width: 26rpx;
|
||
height: 26rpx;
|
||
}
|
||
|
||
.name {
|
||
font-size: 30rpx;
|
||
color: #1A1A1A;
|
||
line-height: 30rpx;
|
||
font-weight: 500;
|
||
margin: 0 16rpx;
|
||
}
|
||
|
||
.phone {
|
||
font-size: 26rpx;
|
||
color: #87868E;
|
||
line-height: 26rpx;
|
||
}
|
||
|
||
.desc {
|
||
background-color: #F3F3F5;
|
||
border-radius: 4rpx 4rpx 4rpx 4rpx;
|
||
font-size: 22rpx;
|
||
line-height: 22rpx;
|
||
color: #1A1A1A;
|
||
padding: 6rpx 8rpx;
|
||
margin-left: 16rpx;
|
||
}
|
||
|
||
.loction-text {
|
||
margin: 10rpx 0 0 42rpx;
|
||
font-size: 26rpx;
|
||
color: #87868E;
|
||
line-height: 40rpx;
|
||
}
|
||
}
|
||
|
||
.card-box {
|
||
margin: 0 16rpx;
|
||
background-color: #F6F7FB;
|
||
border: 2rpx solid #FFFFFF;
|
||
border-radius: 24rpx;
|
||
}
|
||
|
||
.beicanzhong-card {
|
||
padding: 24rpx 20rpx;
|
||
margin: 0;
|
||
|
||
.title {
|
||
font-size: 26rpx;
|
||
color: #1A1A1A;
|
||
font-weight: 500;
|
||
align-items: flex-end;
|
||
|
||
.time {
|
||
font-size: 60rpx;
|
||
color: #1A1A1A;
|
||
line-height: 52rpx;
|
||
font-weight: 500;
|
||
margin-right: 12rpx;
|
||
}
|
||
|
||
}
|
||
|
||
.desc {
|
||
margin-top: 32rpx;
|
||
font-size: 30rpx;
|
||
color: #1A1A1A;
|
||
line-height: 30rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.progress {
|
||
margin-top: 34rpx;
|
||
margin: 34rpx 27rpx 0;
|
||
|
||
.progress-bar {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 24rpx;
|
||
background-color: #F2F2F4;
|
||
border-radius: 0rpx;
|
||
|
||
.progress-bar-fill {
|
||
width: 50%;
|
||
height: 100%;
|
||
background-color: #FE0F22;
|
||
}
|
||
|
||
.progress-icon {
|
||
position: absolute;
|
||
width: 54rpx;
|
||
height: 54rpx;
|
||
}
|
||
|
||
.fukuan {
|
||
left: 0;
|
||
top: 50%;
|
||
transform: translate(-50%, -50%);
|
||
}
|
||
|
||
.beican {
|
||
left: calc(30.3% - 27rpx/2);
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
}
|
||
|
||
.songcan {
|
||
left: calc(60.6% + 27rpx/2);
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
}
|
||
|
||
.qianshou {
|
||
right: 0;
|
||
top: 50%;
|
||
transform: translate(50%, -50%);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
.image-box {
|
||
width: 100%;
|
||
height: 432rpx;
|
||
background-color: #F2F2F2;
|
||
margin-top: 40rpx;
|
||
border-radius: 28rpx;
|
||
overflow: hidden;
|
||
|
||
.add-img {
|
||
width: 112rpx;
|
||
height: 112rpx;
|
||
}
|
||
}
|
||
|
||
.btn-box {
|
||
justify-content: flex-end;
|
||
margin-top: 28rpx;
|
||
|
||
.btn {
|
||
font-size: 22rpx;
|
||
color: #1A1A1A;
|
||
line-height: 62rpx;
|
||
border: 0.5px solid #C7C7C7;
|
||
padding: 0 16rpx;
|
||
margin-left: 16rpx;
|
||
border-radius: 8rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.notice-box {
|
||
padding: 20rpx 26rpx;
|
||
|
||
.icon {
|
||
width: 26rpx;
|
||
height: 26rpx;
|
||
}
|
||
|
||
.notice-text {
|
||
font-size: 22rpx;
|
||
color: #4D4D4D;
|
||
line-height: 22rpx;
|
||
margin: 0 10rpx;
|
||
}
|
||
|
||
.open-btn {
|
||
font-size: 22rpx;
|
||
color: #4D4D4D;
|
||
line-height: 22rpx;
|
||
border-radius: 8rpx 8rpx 8rpx 8rpx;
|
||
border: 1rpx solid #ACACAC;
|
||
padding: 10rpx 6rpx 8rpx;
|
||
}
|
||
}
|
||
|
||
.yiwancheng {
|
||
.title {
|
||
font-weight: 700;
|
||
}
|
||
|
||
.desc {
|
||
margin-top: 26rpx;
|
||
font-size: 26rpx;
|
||
color: #1A1A1A;
|
||
line-height: 30rpx;
|
||
|
||
&.quxiao {
|
||
font-size: 26rpx;
|
||
color: #87868E;
|
||
}
|
||
}
|
||
|
||
.btn {
|
||
font-size: 22rpx;
|
||
line-height: 62rpx;
|
||
}
|
||
|
||
.primary {
|
||
color: #ED1C04;
|
||
border-color: #ED1C04;
|
||
}
|
||
}
|
||
|
||
.cancel-progress-box {
|
||
display: flex;
|
||
align-items: center;
|
||
background-color: #ffffff;
|
||
border-radius: 24rpx;
|
||
margin: 10rpx 16rpx;
|
||
padding: 26rpx 22rpx 30rpx;
|
||
|
||
.cancel-icon {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
margin-right: 16rpx;
|
||
}
|
||
|
||
.cancel-content {
|
||
flex: 1;
|
||
|
||
.title-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.left {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.icon {
|
||
width: 46rpx;
|
||
height: 46rpx;
|
||
margin-right: 16rpx;
|
||
}
|
||
|
||
.title {
|
||
font-size: 30rpx;
|
||
line-height: 30rpx;
|
||
font-weight: 500;
|
||
color: #1A1A1A;
|
||
}
|
||
}
|
||
|
||
.desc {
|
||
margin-top: 4rpx;
|
||
font-size: 26rpx;
|
||
color: #8C8C8C;
|
||
line-height: 36rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.shop-recommend {
|
||
height: 208rpx;
|
||
background-color: #FFFFFF;
|
||
margin: 16rpx;
|
||
border-radius: 24rpx;
|
||
overflow: hidden;
|
||
margin-top: 4rpx;
|
||
}
|
||
|
||
.product-card {
|
||
padding: 28rpx 22rpx;
|
||
margin: 16rpx;
|
||
background-color: #FFFFFF;
|
||
border-radius: 24rpx;
|
||
|
||
.title-box {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
.left-box {
|
||
display: flex;
|
||
align-items: center;
|
||
flex: 1;
|
||
width: 200px;
|
||
|
||
.img {
|
||
width: 50rpx;
|
||
height: 26rpx;
|
||
margin-right: 8rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.title {
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
font-size: 26rpx;
|
||
color: #1A1A1A;
|
||
line-height: 28rpx;
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
.right-icon {
|
||
margin-left: 12rpx;
|
||
}
|
||
}
|
||
|
||
.product-info-wrapper {
|
||
margin-top: 14rpx;
|
||
|
||
.product-divider {
|
||
height: 1rpx;
|
||
background-color: #f2f2f2;
|
||
margin: 20rpx 0;
|
||
}
|
||
}
|
||
|
||
.product-info {
|
||
display: flex;
|
||
position: relative;
|
||
|
||
.image-box {
|
||
width: 152rpx;
|
||
height: 152rpx;
|
||
border-radius: 24rpx;
|
||
overflow: hidden;
|
||
margin-right: 24rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.info-box {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
|
||
.name-row {
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.name {
|
||
width: 100%;
|
||
font-size: 26rpx;
|
||
color: #1A1A1A;
|
||
line-height: 28rpx;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.desc {
|
||
margin-top: 16rpx;
|
||
font-size: 22rpx;
|
||
color: #87868E;
|
||
display: -webkit-box;
|
||
-webkit-box-orient: vertical;
|
||
-webkit-line-clamp: 2;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.tag {
|
||
font-size: 22rpx;
|
||
color: #A96F24;
|
||
margin-top: 18rpx;
|
||
}
|
||
}
|
||
|
||
.price-box {
|
||
font-weight: 500;
|
||
font-size: 28rpx;
|
||
color: #1A1A1A;
|
||
line-height: 28rpx;
|
||
|
||
.price {
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
|
||
.add-product-btn {
|
||
margin-top: 30rpx;
|
||
height: 70rpx;
|
||
border: 1rpx dashed #C7C7C7;
|
||
padding: 0 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 12rpx;
|
||
font-size: 24rpx;
|
||
color: #87868E;
|
||
|
||
.icon {
|
||
margin-right: 10rpx;
|
||
}
|
||
|
||
&:active {
|
||
background-color: #f9f9f9;
|
||
}
|
||
}
|
||
|
||
.btn-box {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
margin-top: 26rpx;
|
||
|
||
.btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 144rpx;
|
||
white-space: nowrap;
|
||
font-size: 22rpx;
|
||
line-height: 22rpx;
|
||
height: 60rpx;
|
||
line-height: 58rpx;
|
||
border-radius: 8rpx;
|
||
border: 0.5px solid #C7C7C7;
|
||
color: #1A1A1A;
|
||
margin-left: 22rpx;
|
||
|
||
.icon {
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
margin-right: 6rpx;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
.red {
|
||
color: #F10F1A;
|
||
border: 0.5px solid #F10F1A;
|
||
}
|
||
|
||
|
||
.img {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
flex-shrink: 0;
|
||
margin-right: 14rpx;
|
||
}
|
||
}
|
||
|
||
.name {
|
||
font-size: 26rpx;
|
||
color: #1A1A1A;
|
||
}
|
||
|
||
.text {
|
||
font-size: 22rpx;
|
||
color: #87868E;
|
||
line-height: 24rpx;
|
||
margin-top: 8rpx;
|
||
}
|
||
|
||
|
||
.item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-top: 26rpx;
|
||
|
||
.label {
|
||
font-size: 26rpx;
|
||
color: #87868E;
|
||
line-height: 26rpx;
|
||
}
|
||
|
||
.value {
|
||
font-size: 26rpx;
|
||
color: #1A1A1A;
|
||
line-height: 26rpx;
|
||
text-align: right;
|
||
}
|
||
}
|
||
}
|
||
|
||
.product-price {
|
||
background-color: #FFFFFF;
|
||
padding: 38rpx 22rpx;
|
||
border-radius: 24rpx;
|
||
margin: 16rpx;
|
||
|
||
.title {
|
||
font-size: 30rpx;
|
||
color: #1A1A1A;
|
||
line-height: 30rpx;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.item {
|
||
margin-top: 36rpx;
|
||
|
||
.label {
|
||
color: #87868E;
|
||
font-size: 26rpx;
|
||
line-height: 26rpx;
|
||
}
|
||
|
||
.value {
|
||
font-size: 32rpx;
|
||
line-height: 32rpx;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
|
||
.price {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-top: 32rpx;
|
||
font-size: 26rpx;
|
||
color: #ED1C04;
|
||
line-height: 26rpx;
|
||
font-weight: 500;
|
||
align-items: baseline;
|
||
|
||
.label {
|
||
font-size: 30rpx;
|
||
color: #1A1A1A;
|
||
line-height: 30rpx;
|
||
}
|
||
|
||
.number {
|
||
font-size: 36rpx;
|
||
font-weight: 500;
|
||
margin-left: 6rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
.order-info-box {
|
||
margin: 16rpx;
|
||
background-color: #FFFFFF;
|
||
border-radius: 24rpx;
|
||
padding: 28rpx 22rpx;
|
||
align-items: flex-start;
|
||
|
||
&.product-info-box {
|
||
padding: 0;
|
||
margin: 0;
|
||
}
|
||
|
||
.title {
|
||
font-size: 30rpx;
|
||
color: #1A1A1A;
|
||
line-height: 30rpx;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.order-info {
|
||
padding-bottom: 34rpx;
|
||
}
|
||
|
||
|
||
.item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-top: 24rpx;
|
||
min-height: 38rpx;
|
||
|
||
.label {
|
||
font-size: 26rpx;
|
||
color: #4D4D4D;
|
||
line-height: 26rpx;
|
||
}
|
||
|
||
.value {
|
||
font-size: 26rpx;
|
||
color: #1A1A1A;
|
||
line-height: 26rpx;
|
||
text-align: right;
|
||
}
|
||
}
|
||
}
|
||
|
||
.timeBox {
|
||
background-color: #fff;
|
||
border-radius: 20rpx 20rpx 0 0;
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
|
||
.titleBox {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
padding: 30rpx 40rpx;
|
||
font-size: 32rpx;
|
||
border-bottom: 2rpx solid #f5f5f5;
|
||
|
||
.title {
|
||
color: #999;
|
||
}
|
||
|
||
.btn {
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
|
||
.picker-container {
|
||
height: 500rpx;
|
||
width: 100%;
|
||
|
||
.range-picker-view {
|
||
height: 100%;
|
||
width: 100%;
|
||
|
||
.picker-item {
|
||
line-height: 50px;
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.flex-center {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
</style>
|
||
<style>
|
||
/* 直接在页面导入公共样式 */
|
||
@import '/common/main.css';
|
||
@import "@/common/specify-style.less";
|
||
|
||
.edit-icon {
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
margin-left: 0;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.tips {
|
||
display: inline-block;
|
||
margin: 0 24rpx;
|
||
font-size: 18rpx;
|
||
color: #87868E;
|
||
line-height: 24rpx;
|
||
margin-top: 16rpx;
|
||
}
|
||
|
||
.time-box {
|
||
text-align: left;
|
||
margin: 8rpx 20rpx;
|
||
padding: 16rpx;
|
||
background-color: #ffffff;
|
||
border-radius: 24rpx;
|
||
}
|
||
|
||
.random-dice {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
margin: 0 16rpx;
|
||
}
|
||
</style> |