微信小程序-黑马 6-7

填写订单

渲染基本信息

静态结构(分包)-封装请求API-初始化调用-类型声明-界面渲染

收货地址

计算默认收货地址-地址列表页-修改收货地址-收货地址store-选中收货地址

收取默认地址并展示在页面中---computed

定义独立的store模块,存放选中的地址

address.vue新增修改地址的函数

点击地址的时候调用change修改地址,记得传递item

有无选中的地址(selectedAddress) 没有才渲染默认

因为修改按钮原本绑定了跳转到表单界面 但是现在又有返回上一页(changeAddress) 所以禁止冒泡 绑定个空函数

立即购买

提交订单

javascript 复制代码
//提交订单
const onOrderSubmit = async () => {
  if (!selectAddress.value?.id) {
    return uni.showToast({ icon: 'none', title: '请选择收获地址' })
  }
  const res = await postMemberOrderAPI({
    addressId: selectAddress.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
  })
  //关闭当前页面,跳转到订单详情,传递订单id
  uni.redirectTo({ url: `/pagesOrder/detail/detail?id=${res.result.id}` })
}

订单详情

自定义导航栏交互

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

//页面渲染完毕,绑定动画效果
onReady(() => {
  //动画效果,导航栏背景色
  pageInstance.animate(
    '.navbar',
    [{ backgroundColor: 'transparent' }, { backgroundColor: '#f8f8f8' }],
    1000,
    {
      scrollSource: '#scroller',
      timeRange: 1000,
      startScrollOffset: 0,
      endScrollOffset: 50
    }
  ),
    //动画效果,导航栏标题
    pageInstance.animate('.navbar .title', [{ color: '#fff' }, { 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
    })
})

订单状态渲染

待支付倒计时

待付款-订单支付

javascript 复制代码
//接口封装
import { http } from '@/utils/http'

/**
 * 获取微信支付参数
 * @param data orderId 订单id
 */
export const getPayWxPayMiniPayAPI = (data: { orderId: string }) => {
  return http<WechatMiniprogram.RequestPaymentOption>({
    method: 'GET',
    url: '/pay/wxPay/miniPay',
    data
  })
}

/**
 * 模拟支付-内测版
 * @param data orderId 订单id
 */
export const getPayMockAPI = (data: { orderId: string }) => {
  return http({
    method: 'GET',
    url: '/pay/mock',
    data
  })
}

待发货-模拟发货

待收货

注意:1.DEV环境,订单状态为待发货时可模拟发货。isDEV判断环境

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

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

确认收货

javascript 复制代码
<script>
    //确认收货
const onOrderConfirm = async () => {
  //二次确认弹窗
  uni.showModal({
    content: '为保障您的权益,请收到货并确认无误后,再确认收货',
    success: async (success) => {
      if (success.confirm) {
        const res = await putMemberOrderReceiptByIdAPI(query.id)
        //更新订单状态
        order.value = res.result
        console.log('已经确认收货啦')
      }
    }
  })
}
<script>

<templete>
    <view v-if="order.orderState == OrderState.DaiShouHuo"
              @tap="onOrderConfirm"
              class="button"
            >
              确认收货
    </view>
</templete>
javascript 复制代码
/**
 * 确认收货
 * @description 仅在订单状态为待收货时,可确认收货。
 * @param id 订单id
 */
export const putMemberOrderReceiptByIdAPI = (id: string) => {
  return http<OrderResult>({
    method: 'PUT',
    url: `/member/order/${id}/receipt`
  })
}

订单物流

触发条件:获取订单详情的时候展现(onLoad),要求:orderState是发货完后

javascript 复制代码
/**
 * 获取订单物流
 * @description 仅在订单状态为待收货,待评价,已完成时,可获取物流信息。
 * @param id 订单id
 */
export const getMemberOrderLogisticsByIdAPI = (id: string) => {
  return http<OrderLogisticResult>({
    method: 'GET',
    url: `/member/order/${id}/logistics`
  })
}
javascript 复制代码
<script>
    //获取订单详情
const order = ref<OrderResult>()
const getMemberOrderByIdData = async () => {
  const res = await getMemberOrderByIdAPI(query.id)
  order.value = res.result
  if (
    [OrderState.YiWanCheng, OrderState.DaiPingJia, OrderState.DaiShouHuo].includes(
      order.value?.orderState
    )
  ) {
    getMemberOrderLogisticsByIdData()
  }
}

//获取物流信息
const logisticList = ref<LogisticItem[]>([])
const getMemberOrderLogisticsByIdData = async () => {
  const res = await getMemberOrderLogisticsByIdAPI(query.id)
  logisticList.value = res.result.list
}
</script>

删除订单

javascript 复制代码
/**
 * 删除订单
 * @description 仅在订单状态为待评价,已完成,已取消时,可删除订单。
 * @param data ids 订单集合
 */
export const deleteMemberOrderAPI = (data: { ids: string[] }) => {
  return http({
    method: 'DELETE',
    url: `/member/order`,
    data
  })
}
javascript 复制代码
<script>
//删除订单
const onOrderDelete = () => {
  uni.showModal({
    content: '是否删除订单',
    success: async (success) => {
      if (success.confirm) {
        await deleteMemberOrderAPI({ ids: [query.id] })
        uni.redirectTo({ url: '/pagesOrder/list/list' })
        console.log('已经删除成功了')
      }
    }
  })
}
<script>
<templete>
       <!-- 待评价/已完成/已取消 状态: 展示删除订单 -->
          <view
            class="button delete"
            @tap="onOrderDelete"
            v-if="order.orderState >= OrderState.DaiPingJia"
          >
            删除订单
          </view>
<templete>

订单列表

Tabs滑动切换

abs页面跳转高亮

javascript 复制代码
//获取页面参数(知道是'待付款'/'待发货。。')
const query = defineProps<{
  type: string
}>()
//高亮下标(query.type是string,通过Number(XX)转换成number格式)
const activeIndex = ref(orderTabs.value.findIndex((v) => v.orderState === Number(query.type)))

列表渲染

封装列表组件-订单状态父传子-封装请求API-准备请求参数-初始化调用-页面渲染

javascript 复制代码
//定义props
const props = defineProps<{ orderState: number }>()

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

//获取订单列表
const orderList = ref<OrderItem[]>([])

const isLoading = ref(false)

// 3. 把接口请求拆成两步:初始化 + 加载更多
const loadOrderList = async () => {
  if (isLoading.value) return
  isLoading.value = true
  try {
    // 关键:每次请求前,用 props.orderState 覆盖 queryParams
    queryParams.orderState = props.orderState
    const res = await getMemberOrderAPI(queryParams)
    orderList.value = res.result.items
  } catch (err) {
    uni.showToast({ icon: 'none', title: '加载失败' })
  } finally {
    isLoading.value = false
  }
}

onMounted(() => {
  // 初始化时,重置页码,再调用接口
  queryParams.page = 1
  loadOrderList()
})
javascript 复制代码
/**
 * 获取订单列表
 * @param data orderState 订单状态
 */
export const getMemberOrderAPI = (data: OrderListParams) => {
  return http<OrderListResult>({
    method: 'GET',
    url: `/member/order`,
    data
  })
}

订单支付

将detail页面的订单支付进行复用 但是! 原本的query.id由于query是局部变量,只能把query.id改成id,而这个id由函数进行调用的时候页面传参

javascript 复制代码
<script>
//订单支付
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: '支付成功', icon: 'success' })
  const order = orderList.value.find((v) => v.id === id)
  order!.orderState = OrderState.DaiFaHuo
}
</script>

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

项目打包

微信小程序端发布上线

条件编译和网页端打包

<!-- #ifdef MP-WEIXIN --><!-- #ifdef MP-WEIXIN -->

<!-- #ifdef APP-PLUS|| H5 --><!-- #ifdef MP-WEIXIN -->

Android端

预览和调试

云打包

iOS端-预览、调试、打包

跨端兼容

样式兼容

视口差异

pnpm build:h5--打开网页版命令

样式隔离

组件兼容

eg 有open-type属性的button组件只在小程序平台可应用

JSAPI兼容

uniCloud云开发

准备工作

城市选择和云数据库

javascript 复制代码
<!-- #ifdef MP-WEIXIN -->
        <picker
          class="picker"
          mode="region"
          :value="form.fullLocation?.split(' ') || []"
          @change="onRegionChange"
        >
          <view v-if="form.fullLocation">{{ form.fullLocation }}</view>
          <view v-else class="placeholder">请选择省/市/区(县)</view>
        </picker>
        <!-- #endif -->
        <!-- #ifdef APP-PLUS||H5 -->
        <uni-data-picker
          popup-title="请选择城市"
          placeholder="请选择地址"
          collection="opendb-city-china"
          field="code as value, name as text"
          orderby="value asc"
          :step-searh="true"
          self-field="code"
          parent-field="parent_code"
        >
        </uni-data-picker>
        <!-- #endif -->

城市选择完成