alipay-emulator/pages/shopping/jingdong/add-waimai/add-waimai.vue

1933 lines
53 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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();
}, 500);
}
</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>