UniappDay06

1.填写订单-渲染基本信息

  1. 静态结构(分包)

  2. 封装请求API

    import { http } from '@/utils/http'
    import { OrderPreResult } from '@/types/order'

    export const getmemberOrderPreAPI = () => {
    return http<OrderPreResult>({
    method: 'GET',
    url: '/member/order/pre',
    })
    }

  3. 初始化调用

    // 获取订单信息
    const orderPre = ref<OrderPreResult>()
    const getmemberOrderPreData = async () => {
    const res = await getmemberOrderPreAPI()
    orderPre.value = res.result
    }
    // 初始化调用
    onLoad(() => {
    getmemberOrderPreData()
    })

  4. 类型声明

  5. 界面渲染

    复制代码
     <view class="goods">
       <navigator
         v-for="item in orderPre?.goods"
         :key="item.skuId"
         :url="`/pages/goods/goods?id=${item.id}`"
         class="item"
         hover-class="none"
       >
         <image class="picture" :src="item.picture" />
         <view class="meta">
           <view class="name ellipsis"> {{ item.name }} </view>
           <view class="attrs">{{ item.attrsText }} </view>
           <view class="prices">
             <view class="pay-price symbol">{{ item.payPrice }}</view>
             <view class="price symbol">{{ item.price }}</view>
           </view>
           <view class="count">x{{ item.count }}</view>
         </view>
       </navigator>
     </view>
     <!-- 吸底工具栏 -->
    <view class="toolbar" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }"> <view class="total-pay symbol"> <text class="number">{{ orderPre?.summary.totalPayPrice.toFixed(2) }}</text> </view> <view class="button" :class="{ disabled: true }"> 提交订单 </view> </view>

2. 收货地址

  1. 计算默认收货地址

    const selectedAddress = computed(() => {
    // 查找默认收货地址
    return orderPre.value?.userAddresses.find((v) => v.isDefault)
    })

  2. 地址列表页

  3. 修改收货地址

    <view class="item-content" @tap="onChangeAddress(item)">

  4. 收货地址Store

    import { AddressItem } from '@/types/address'
    import { defineStore } from 'pinia'
    import { ref } from 'vue'

    export const useAddressStore = defineStore('address', () => {
    const selectedAddress = ref<AddressItem>()

    const changeSelectedAddress = (val: AddressItem) => {
    selectedAddress.value = val
    }

    return {
    selectedAddress,
    changeSelectedAddress,
    }
    })

  5. 选中收货地址

    // 单纯的阻止冒泡,否则修改页面没法跳转
    @tap.stop="() => {}"

    // 修改收货地址
    const onChangeAddress = (item: AddressItem) => {
    //修改地址
    const addressStore = useAddressStore()
    addressStore.changeSelectedAddress(item)
    // 返回上一页
    uni.navigateBack()
    }

3.立即购买

  1. 封装

    export const getmemberOrderPreNowAPI = (data: {
    skuId: string
    count: string
    addressId?: string
    }) => {
    return http<OrderPreResult>({
    method: 'GET',
    url: '/member/order/pre/now',
    data,
    })
    }

  2. 立即购买事件,跳转页面传参

    @buy-now="onBuyNow"

    // 立即购买
    const onBuyNow = (ev: SkuPopupEvent) => {
    // 跳转并传参
    uni.navigateTo({ url: /pagesOrder/create/create?skuId=${ev._id}&count=${ev.buy_num} })
    }

  3. 立即购买

    // 页面参数
    const query = defineProps<{
    // 可有可无
    skuId?: string
    count?: string
    }>()

    // 获取订单信息
    const orderPre = ref<OrderPreResult>()
    const getmemberOrderPreData = async () => {
    if (query.count && query.skuId) {
    const res = await getmemberOrderPreNowAPI({
    skuId: query.skuId,
    count: query.count,
    })
    orderPre.value = res.result
    } else {
    const res = await getmemberOrderPreAPI()
    orderPre.value = res.result
    }
    }

4.提交订单

  1. 封装请求API

    // /member/order
    export const postMemberOrderAPI = (data: OrderCreateParams) => {
    return http<{ id: string }>({
    method: 'POST',
    url: '/member/order',
    data,
    })
    }

  2. 类型声明文件

  3. 提交按钮事件

  4. 调用接口成功

  5. 跳转订单详情

    // 提交订单
    const onOrderSubmit = async () => {
    if (!selectedAddress.value?.id) {
    uni.showToast({ title: '请选择收货地址' })
    }
    const res = await postMemberOrderAPI({
    addressId: selectedAddress.value!.id,
    buyerMessage: buyerMessage.value,
    deliveryTimeType: activeDelivery.value.type,
    goods: orderPre.value!.goods.map((v) => ({ count: v.count, skuId: v.skuId })),
    payChannel: 2,
    payType: 1,
    })
    // 关闭当前页面,再跳转
    uni.redirectTo({ url: /pagesOrder/detail/detail?id=${res.result.id} })
    }

  6. 无收货地址交互

5.自定义导航栏交互

  1. 导航栏左上角按钮,返回首页

    // 获取页面栈
    // pages是一个数组
    const pages = getCurrentPages()
    // 获取当前页面实例,数组最后一项
    const pageInstance = pages.at(-1) as any

    <navigator v-if="pages.length > 1" open-type="navigateBack" class="back icon-left" ></navigator>

  2. 滚动驱动的动画

    // 页面渲染完毕,绑定动画效果d
    onReady(() => {
    // 动画效果,导航栏背景色
    pageInstance.animate(
    '.navbar', // 选择器
    [{ backgroundColor: 'transparent' }, { backgroundColor: '#f8f8f8' }], // 关键帧信息
    1000, // 动画持续时长
    {
    scrollSource: '#scroller', // scroll-view 的选择器
    startScrollOffset: 0, // 开始滚动偏移量
    endScrollOffset: 50, // 停止滚动偏移量
    timeRange: 1000, // 时间长度
    },
    )
    // 动画效果,导航栏标题
    pageInstance.animate('.navbar .title', [{ color: 'transparent' }, { color: '#000' }], 1000, {
    scrollSource: '#scroller',
    timeRange: 1000,
    startScrollOffset: 0,
    endScrollOffset: 50,
    })
    // 动画效果,导航栏返回按钮
    pageInstance.animate('.navbar .back', [{ color: '#fff' }, { color: '#000' }], 1000, {
    scrollSource: '#scroller',
    timeRange: 1000,
    startScrollOffset: 0,
    endScrollOffset: 50,
    })
    })

6.订单状态渲染

  1. 渲染订单状态

    <template v-if="order"> <view class="overview" :style="{ paddingTop: safeAreaInsets!.top + 20 + 'px' }"> <template v-if="order.orderState === OrderState.DaiFuKuan"> <view class="status icon-clock">等待付款</view> <view class="tips"> <text class="money">应付金额: ¥ 99.00</text> <text class="time">支付剩余</text> 00 时 29 分 59 秒 </view> <view class="button">去支付</view> </template> <template v-else> <view class="status"> {{ orderStateList[order.orderState].text }} </view> <view class="button-group"> <navigator class="button" :url="`/pagesOrder/create/create?orderId=${query.id}`" hover-class="none" > 再次购买 </navigator> <view v-if="false" class="button"> 模拟发货 </view> </view> </template> </view>
  2. 订单状态常量

    /** 订单状态枚举 /
    export enum OrderState {
    /
    * 待付款 /
    DaiFuKuan = 1,
    /
    * 待发货 /
    DaiFaHuo = 2,
    /
    * 待收货 /
    DaiShouHuo = 3,
    /
    * 待评价 /
    DaiPingJia = 4,
    /
    * 已完成 /
    YiWanCheng = 5,
    /
    * 已取消 */
    YiQuXiao = 6,
    }

    /** 订单状态列表 */
    export const orderStateList = [
    { id: 0, text: '' },
    { id: 1, text: '待付款' },
    { id: 2, text: '待发货' },
    { id: 3, text: '待收货' },
    { id: 4, text: '待评价' },
    { id: 5, text: '已完成' },
    { id: 6, text: '已取消' },
    ]

7.待支付倒计时

复制代码
//倒计时
const onTimeUp = () => {
  // 修改订单状态为已取消
  order.value!.orderState = OrderState.YiQuXiao
}

  <uni-countdown
              color="#fff"
              :show-colon="false"
              :show-day="false"
              splitor-color="#fff"
              :second="order.countdown"
              @timeup="onTimeUp"
            />

8. 代付款-订单支付

复制代码
// 去支付
const onOrderPay = async () => {
  if (import.meta.env.DEV) {
    // 开发环境模拟支付
    await getPayMockAPI({ orderId: query.id })
  } else {
    // 正式微信支付
    const res = await getPayWxPayMiniPayAPI({ orderId: query.id })
    wx.requestPayment(res.result)
  }
  // 关闭当前页,再跳转
  uni.redirectTo({ url: `/pagesOrder/Payment/Payment?id=${query.id}` })
}
复制代码
主要测试,开发环境模拟支付,即可

9.待发货-模拟发货

  1. dev环境

    // 是否为开发环境
    const isDev = import.meta.env.DEV

    <view
    @tap="onOrderSend"
    v-if="isDev && order.orderState === OrderState.DaiFaHuo"
    class="button"
    >
    模拟发货
    </view>

  2. 模拟发货,并更新订单状态

    // 模拟发货
    const onOrderSend = async () => {
    if (isDev) {
    await getMemberOrderConsignmentByIdAPI(query.id)
    // 轻提示
    uni.showToast({ icon: 'success', title: '模拟成功' })
    // 主动更新订单状态
    order.value!.orderState = OrderState.DaiFaHuo
    }
    }

打包时这里的代码会被自动剔除,优化掉

10.待收货-确认收货

仅在订单状态为待收货时,可确认收货

复制代码
// 待收货=>确认收货
const onOrderConfirm = () => {
  // 二次确认弹窗
  uni.showModal({
    content: '为保障你的权益,请收到货并确认无误后,再确认收货',
    success: async (success) => {
      if (success.confirm) {
        const res = await putMemberOrderReceiptByIdAPI(query.id)
        // 主动更新
        order.value = res.result
      }
    },
  })
}

  <!-- 待收货状态: 展示确认收货按钮 -->
            <view
              v-if="order.orderState === OrderState.DaiShouHuo"
              @tap="onOrderConfirm"
              class="button"
            >
              确认收货
            </view>

11.订单详情-待收货-订单物流

  1. 封装请求API

  2. 获取订单详情后

  3. 判断订单状态

    // 获取订单详情
    const order = ref<OrderResult>()
    const getMemberOrderByIdData = async () => {
    const res = await getMemberOrderByIdAPI(query.id)
    order.value = res.result
    // include的数是否包含在[]前面的这个数组里面,包含就是true,反之
    if (
    [OrderState.DaiShouHuo, OrderState.DaiPingJia, OrderState.YiWanCheng].includes(
    order.value.orderState,
    )
    ) {
    getMemberOrderLogisticsByIdData()
    }
    }

  4. 获取物流信息

注意:仅在订单状态为待收货、待评价、已完成时,可获取物流信息

复制代码
// 获取物流信息
const logisticList = ref<LogisticItem[]>([])
const getMemberOrderLogisticsByIdData = async () => {
  const res = await getMemberOrderLogisticsByIdAPI(query.id)
  logisticList.value = res.result.list
}
  1. 渲染物流信息

    复制代码
       <view class="shipment">
         <!-- 订单物流信息 -->
         <view v-for="item in logisticList" :key="item.id" class="item">
           <view class="message">
             {{ item.text }}
           </view>
           <view class="date"> {{ item.time }} </view>
         </view>
         <!-- 用户收货地址 -->
         <view class="locate">
           <view class="user"> {{ order.receiverContact }} {{ order.receiverMobile }}</view>
           <view class="address"> {{ order.receiverAddress }} </view>
         </view>
       </view>

12.删除订单

注意:仅在订单状态为待评价,已完成,已取消,可删除订单

  1. 封装请求API

  2. 条件渲染&事件绑定

    <view
    class="button delete"
    @tap="onOrderDelete"
    v-if="order.orderState >= OrderState.DaiPingJia"
    >
    删除订单
    </view>

  3. 二次确认弹窗

  4. 调用API成功

  5. 跳转到订单列表

    // 删除订单
    const onOrderDelete = () => {
    // 二次确认
    uni.showModal({
    content: '是否删除订单',
    success: async (success) => {
    if (success.confirm) {
    await deleteMemberOrderAPI({ ids: [] })
    uni.redirectTo({ url: '/pagesOrder/list/list' })
    }
    },
    })
    }

13.订单列表-Tabs滑动切换

  1. 静态结构

  2. Tabs文字渲染

  3. 点击文字高亮切换

    // 高亮下标
    const activeIndex = ref(0)

    复制代码
     <view class="tabs">
       <text
         class="item"
         @tap="activeIndex = index"
         v-for="(item, index) in orderTabs"
         :key="item.title"
       >
         {{ item.orderState }}
       </text>
       <!-- 游标 -->
       <view class="cursor" :style="{ left: activeIndex * 20 + '%' }"></view>
     </view>
  4. swiper滑动切换
    可以实现上下两个模块的关联,交互

    复制代码
     <swiper class="swiper" :current="activeIndex" @change="activeIndex = $event.detail.current">
       <!-- 滑动项 -->
       <swiper-item v-for="item in orderTabs" :key="item.title">

14.tabs页面跳转高亮

  1. 个人中心页

  2. 页面传参

  3. 订单详情页

  4. 接收页面参数

  5. 查找高亮下标

    // 获取页面参数
    const query = defineProps<{
    type: string
    }>()

    // 高亮下标
    const activeIndex = ref(orderTabs.value.findIndex((v) => v.orderState === Number(query.type)))

15.列表渲染

  1. 封装列表组件

    复制代码
         <OrderList />
  2. 订单状态父传子

    // 定义props
    const props = defineProps<{
    orderState: number
    }>()

  3. 封装请求API

  4. 准备请求参数

    // 请求参数
    const queryParams: OrderListParams = {
    page: 1,
    pageSize: 5,
    orderState: props.orderState,
    }

    // 获取订单列表
    const orderList = ref<OrderItem[]>([])
    const getMemberOrderData = async () => {
    const res = await getMemberOrderAPI(queryParams)
    orderList.value = res.result.items
    }

  5. 初始化调用

    // 初始化调用
    onMounted(() => {
    getMemberOrderData()
    })

  6. 页面渲染

16.订单支付

复制代码
// 订单支付
const onOrderPay = async (id: string) => {
  if (import.meta.env.DEV) {
    // 开发环境模拟支付
    await getPayMockAPI({ orderId: id })
  } else {
    // 正式微信支付
    const res = await getPayWxPayMiniPayAPI({ orderId: id })
    wx.requestPayment(res.result)
  }
  // 成功提示
  uni.showToast({ title: '支付成功!' })
  // 更新订单状态
  const order = orderList.value.find((v) => v.id === id)
  order!.orderState = OrderState.DaiFaHuo
}

          <view class="button primary" @tap="onOrderPay(order.id)">去支付</view>

17.项目打包-微信小程序端发布上线

复制代码
pnpm build:mp-weixin

18.项目打包-条件编译和网页端打包

常见问题:按照 uni-app 规范开发可保证多平台兼容,但每个平台有自己的一些特性,该如何处理?

注意事项:网页端不支持微信平台授权登录等功能,可通过条件编译,让代码按条件编译到不同平台。

条件编译语法:通过特殊注释,以 #ifdef 或 #ifndef 加平台名称开头,以 #endif 结尾。

复制代码
pnpm dev:h5

<script setup lang="ts">
// #ifdef MP-WEIXIN
wx.login()
wx.requestOrderPayment()
// #endif
</script>
 
 
<template>
<!-- #ifdef MP-WEIXIN -->
<button open-type="openSetting">授权管理</button>
<button open-type="feedback">问题反馈</button>
<button open-type="contact">联系我们</button>
<!-- #endif -->
</template>

支持: vue, js, ts, css, scss, pages.json 等文件

编译网页端

复制代码
pnpm build:h5

将绝对定位改为相对定位

复制代码
// 在manifest中配置
/* 网页端特有配置 */
  "h5": {
    "router": {
      "base": "./"
    }
  },
  // 最后重启,pnpm build:h5
相关推荐
Lsx_8 分钟前
MultiRepo 和 Monorepo:代码管理的演进与选择
前端·javascript·架构
Warren9839 分钟前
Java泛型
java·开发语言·windows·笔记·python·spring·maven
destinying40 分钟前
当部分请求失败时,前端如何保证用户体验不崩溃?
前端·javascript·程序员
仪器科学与传感技术博士41 分钟前
python:以支持向量机(SVM)为例,通过调整正则化参数C和核函数类型来控制欠拟合和过拟合
开发语言·python·算法·机器学习·支持向量机·过拟合·欠拟合
科大饭桶44 分钟前
C++入门自学Day5-- C/C++内存管理(续)
c语言·开发语言·c++
一只乔哇噻1 小时前
Java,八股,cv,算法——双非研0四修之路day24
java·开发语言·经验分享·学习·算法
子壹1 小时前
大文件分片上传
javascript·node.js
叁金Coder1 小时前
业务系统跳转Nacos免登录方案实践
前端·javascript·nginx·nacos
馨语轩1 小时前
Springboot原理和Maven高级
java·开发语言·spring
CodeTransfer1 小时前
今天给大家带来的是一个简单的小球抛物线动画效果
前端·javascript