普通视图

发现新文章,点击刷新页面。
昨天 — 2025年12月4日首页

uni-app D8 实战(小兔鲜)

2025年12月3日 23:53

1.填写订单

1.1 渲染基本信息

image.png

1.1.1 设置独立的分包(静态结构)

<script setup lang="ts">
import { computed, ref } from 'vue';

// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync();
// 订单备注
const buyerMessage = ref('');
// 配送时间
const deliveryList = ref([
    { type: 1, text: '时间不限 (周一至周日)' },
    { type: 2, text: '工作日送 (周一至周五)' },
    { type: 3, text: '周末配送 (周六至周日)' }
]);
// 当前配送时间下标
const activeIndex = ref(0);
// 当前配送时间
const activeDelivery = computed(() => deliveryList.value[activeIndex.value]);
// 修改配送时间
const onChangeDelivery: UniHelper.SelectorPickerOnChange = (ev) => {
    activeIndex.value = ev.detail.value;
};
</script>

<template>
    <scroll-view scroll-y class="viewport">
        <!-- 收货地址 -->
        <navigator v-if="false" class="shipment" hover-class="none" url="/pagesMember/address/address?from=order">
            <view class="user">张三 13333333333</view>
            <view class="address">广东省 广州市 天河区 黑马程序员3</view>
            <text class="icon icon-right"></text>
        </navigator>
        <navigator v-else class="shipment" hover-class="none" url="/pagesMember/address/address?from=order">
            <view class="address">请选择收货地址</view>
            <text class="icon icon-right"></text>
        </navigator>

        <!-- 商品信息 -->
        <view class="goods">
            <navigator v-for="item in 2" :key="item" :url="`/pages/goods/goods?id=1`" class="item" hover-class="none">
                <image class="picture" src="https://yanxuan-item.nosdn.127.net/c07edde1047fa1bd0b795bed136c2bb2.jpg" />
                <view class="meta">
                    <view class="name ellipsis">ins风小碎花泡泡袖衬110-160cm</view>
                    <view class="attrs">藏青小花 130</view>
                    <view class="prices">
                        <view class="pay-price symbol">99.00</view>
                        <view class="price symbol">99.00</view>
                    </view>
                    <view class="count">x5</view>
                </view>
            </navigator>
        </view>

        <!-- 配送及支付方式 -->
        <view class="related">
            <view class="item">
                <text class="text">配送时间</text>
                <picker :range="deliveryList" range-key="text" @change="onChangeDelivery">
                    <view class="icon-fonts picker">{{ activeDelivery.text }}</view>
                </picker>
            </view>
            <view class="item">
                <text class="text">订单备注</text>
                <input class="input" :cursor-spacing="30" placeholder="选题,建议留言前先与商家沟通确认" v-model="buyerMessage" />
            </view>
        </view>

        <!-- 支付金额 -->
        <view class="settlement">
            <view class="item">
                <text class="text">商品总价:</text>
                <text class="number symbol">495.00</text>
            </view>
            <view class="item">
                <text class="text">运费:</text>
                <text class="number symbol">5.00</text>
            </view>
        </view>
    </scroll-view>

    <!-- 吸底工具栏 -->
    <view class="toolbar" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
        <view class="total-pay symbol">
            <text class="number">99.00</text>
        </view>
        <view class="button" :class="{ disabled: true }">提交订单</view>
    </view>
</template>

<style lang="scss">
page {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
    background-color: #f4f4f4;
}

.symbol::before {
    content: '¥';
    font-size: 80%;
    margin-right: 5rpx;
}

.shipment {
    margin: 20rpx;
    padding: 30rpx 30rpx 30rpx 84rpx;
    font-size: 26rpx;
    border-radius: 10rpx;
    background: url(https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/images/locate.png) 20rpx center / 50rpx no-repeat #fff;
    position: relative;

    .icon {
        font-size: 36rpx;
        color: #333;
        transform: translateY(-50%);
        position: absolute;
        top: 50%;
        right: 20rpx;
    }

    .user {
        color: #333;
        margin-bottom: 5rpx;
    }

    .address {
        color: #666;
    }
}

.goods {
    margin: 20rpx;
    padding: 0 20rpx;
    border-radius: 10rpx;
    background-color: #fff;

    .item {
        display: flex;
        padding: 30rpx 0;
        border-top: 1rpx solid #eee;

        &:first-child {
            border-top: none;
        }

        .picture {
            width: 170rpx;
            height: 170rpx;
            border-radius: 10rpx;
            margin-right: 20rpx;
        }

        .meta {
            flex: 1;
            display: flex;
            flex-direction: column;
            justify-content: center;
            position: relative;
        }

        .name {
            height: 80rpx;
            font-size: 26rpx;
            color: #444;
        }

        .attrs {
            line-height: 1.8;
            padding: 0 15rpx;
            margin-top: 6rpx;
            font-size: 24rpx;
            align-self: flex-start;
            border-radius: 4rpx;
            color: #888;
            background-color: #f7f7f8;
        }

        .prices {
            display: flex;
            align-items: baseline;
            margin-top: 6rpx;
            font-size: 28rpx;

            .pay-price {
                margin-right: 10rpx;
                color: #cf4444;
            }

            .price {
                font-size: 24rpx;
                color: #999;
                text-decoration: line-through;
            }
        }

        .count {
            position: absolute;
            bottom: 0;
            right: 0;
            font-size: 26rpx;
            color: #444;
        }
    }
}

.related {
    margin: 20rpx;
    padding: 0 20rpx;
    border-radius: 10rpx;
    background-color: #fff;

    .item {
        display: flex;
        justify-content: space-between;
        align-items: center;
        min-height: 80rpx;
        font-size: 26rpx;
        color: #333;
    }

    .input {
        flex: 1;
        text-align: right;
        margin: 20rpx 0;
        padding-right: 20rpx;
        font-size: 26rpx;
        color: #999;
    }

    .item .text {
        width: 125rpx;
    }

    .picker {
        color: #666;
    }

    .picker::after {
        content: '\e6c2';
    }
}

/* 结算清单 */
.settlement {
    margin: 20rpx;
    padding: 0 20rpx;
    border-radius: 10rpx;
    background-color: #fff;

    .item {
        display: flex;
        align-items: center;
        justify-content: space-between;
        height: 80rpx;
        font-size: 26rpx;
        color: #333;
    }

    .danger {
        color: #cf4444;
    }
}

/* 吸底工具栏 */
.toolbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(var(--window-bottom));
    z-index: 1;

    background-color: #fff;
    height: 100rpx;
    padding: 0 20rpx;
    border-top: 1rpx solid #eaeaea;
    display: flex;
    justify-content: space-between;
    align-items: center;
    box-sizing: content-box;

    .total-pay {
        font-size: 40rpx;
        color: #cf4444;

        .decimal {
            font-size: 75%;
        }
    }

    .button {
        width: 220rpx;
        text-align: center;
        line-height: 72rpx;
        font-size: 26rpx;
        color: #fff;
        border-radius: 72rpx;
        background-color: #27ba9b;
    }

    .disabled {
        opacity: 0.6;
    }
}
</style>

结果:

image.png

1.1.2 封装订单API

image.png

1.1.3 获取订单的函数

image.png

1.1.4 封装类型声明文件

import type { AddressItem } from './address'

/** 获取预付订单 返回信息 */
export type OrderPreResult = {
  /** 商品集合 [ 商品信息 ] */
  goods: OrderPreGoods[]
  /** 结算信息 */
  summary: {
    /** 商品总价 */
    totalPrice: number
    /** 邮费 */
    postFee: number
    /** 应付金额 */
    totalPayPrice: number
  }
  /** 用户地址列表 [ 地址信息 ] */
  userAddresses: AddressItem[]
}

/** 商品信息 */
export type OrderPreGoods = {
  /** 属性文字,例如“颜色:瓷白色 尺寸:8寸” */
  attrsText: string
  /** 数量 */
  count: number
  /** id */
  id: string
  /** 商品名称 */
  name: string
  /** 实付单价 */
  payPrice: string
  /** 图片 */
  picture: string
  /** 原单价 */
  price: string
  /** SKUID */
  skuId: string
  /** 实付价格小计 */
  totalPayPrice: string
  /** 小计总价 */
  totalPrice: string
}

image.png

1.1.5 存储获取到的订单信息到ref

image.png

1.1.6 渲染获取到的数据到标签中

image.png

image.png

1.1.7 再在先前的购物车代码中添加一行结算代码

image.png 结果: image.png

1.2 收货地址

❌
❌