购物车下单实现思路【vue】

1、购物车

  • 在购物车页面会有一个点 提示当前购物车内商品的数量
  • 购物车内商品的展示
  • 购物车内商品的选中

1.1 使用pinia来存储购物车的状态

  state: () => ({
    // 首页订货单元信息 这个主要是用来展示购物车的数量的
    cartMetaInfo: <AnyObject>{},
    // 订货单列表 存储完整的购物车数据
    orderList: <AnyObject[]>[],
    // 点击结算的时候冻结选择的订单和数量进行结算
    freezeOrders: <AnyObject[]>[],
    // 设置一个值来保存用户的选中状态
    selectedOrders:[]
  }),

1.2 用户将商品加入购物车的时候

  • 1、调用添加商品的API 将商品添加到购物车
  • 2、添加成功后更新购物车内商品数量(这个数量也是存储在后端的)在pinia有一个state来记录这个数值 所以更新数量的方法写在action中
   // 获取首页订货单元信息
    async getCartMeta() {
      try {
        this.cartMetaInfo = await OrderAPI.getCartMeta();
      } catch (e) {
        const err = e as AnyObject;
        showMessage("获取订货单信息失败");
      }
    },
  • 3、刷新购物车列表

注意点: 需要保存用户的选中状态,这个选中状态只是保存在vuex,并没有保存到后端,因为选中状态保存在前端所以购物车的数据都是从vuex中拿到的

这个方法用来修改购物车中的某个数据 如选中状态

 // action
 // 设置单个订货单数据
    setOrder(index: number, data: AnyObject) {
      Object.assign(this.orderList[index], data);
      this.selectedOrders = state.orderList.filter((o) => o.checked)
    },
   // getter
    // 在订货单页面选中的订货单
    selectedOrders(state) {
      return state.orderList.filter((o) => o.checked);
    },

    // 在订货单页面选中的订货单的id数组
    selectedOrderIds() {
      const selectedOrders = this.selectedOrders as AnyObject[];
      return selectedOrders.map((o) => o.sku_id);
    },

// 单选状态改变
const handleChangeChecked = (index: number) => {
  const flag = list.value[index].checked;
  orderStore.setOrder(index, { checked: !flag });
};
  • pinia中有一个action来修改购物车列表
    // 设置订货单
    setOrderList(orderList: AnyObject[], isRefresh = true) {
      if (isRefresh) {
        this.orderList = orderList;
      } else {
        this.orderList.push(...orderList);
      }
    },

当点击加入购物车的时候会向后端发送网络请求,将商品加入到购物车,之后保存上一次已经选中的商品,重新获取购物车显示的商品个数,(这个步骤也可以等到切换到购物车在做:清空购物车list,重新获取购物车列表,确保购物车中的数据与数据库中的一致,获取到的商品判断是否和之前选中的一样如何一样则将其绑定选中状态)

2、点击结算按钮

  • 1、当点击结算按钮的时候跳转到订单页面,将已经选择的商品的id去向后端发送网络请求拿到具体的信息
    在这里插入图片描述

  • 2、请求用户余额和返点余额,如果用户已经填写收货地址,就创建订单。

  • 3、如果用户的余额和返点余额抵扣后没有剩余需要支付的则直接生成订单

  • 4、如果还有剩下需要支付的则弹出付款界面使用微信支付。

3、封装支付

  • 1、将所有的关于关于支付的方法都封装到组件里面,通过判断什么时候调用哪个接口
const getRealOperation = (): {
  sendData: AnyObject;
  apiFn: (...args: any[]) => Promise<unknown>;
} => {
  let sendData = {
    ...omit(params.value, "amount", "showAmount", "type", "success", "fail"),
    pay_type: selectedPayType.value,
  };
  console.log(sendData, "????????");
  let apiFn: (...args: any[]) => Promise<unknown>;
  switch (params.value.type) {
    case "continue":
      // 订单继续支付
      apiFn = OrderAPI.payOrder;
      return { sendData, apiFn };

    case "recharge":
      // 余额充值
      apiFn = BalanceAPI.recharge;
      return { sendData, apiFn };

    case "continueRecharge":
      // 余额充值
      apiFn = BalanceAPI.continueRecharge;
      return { sendData, apiFn };

    default:
      // 创建订单
      apiFn = OrderAPI.submitOrder;
      return { sendData, apiFn };
  }
};
// 提交订单、创建订单
const handleSubmitOrder = async () => {
  showLoading();

  const { run, data, error, isSuccess, isError } = useAsync();
  const { sendData, apiFn } = getRealOperation();
  if (
    params.value.type == "recharge" ||
    params.value.type == "continueRecharge"
  ) {
    await run(apiFn({ ...omit(sendData) }));
  } else {
    await run(apiFn({ ...omit(sendData, "pay_type") }));
  }
  uni.hideLoading();

  if (isSuccess.value) {
    const res = data.value as AnyObject;
    console.log("submit order result: ", res);
    console.log(sendData, "sendData");

    if (selectedPayType.value === PayType.BALANCE) {
      await userStore.getDealerBalance();
      toPage("my-order", {}, { prefix: "/order-core", target: 2 });
    } else if (selectedPayType.value === PayType.WX_PAY) {
    // 返回预支付id
      await handlePay(res as OrderResParams);
    }
  }

在这里插入图片描述

const handlePay = async (info: OrderResParams) => {
  showLoading();

  const { run, data, error, isSuccess, isError } = useAsync();
  await run(PayAPI.getPrepayInfo(info.pay_serial_id));

  if (isSuccess.value) {
    console.log("预支付信息:", data.value);
    const payInfo = data.value as AnyObject;

    showLoading("购买中");
    uni.requestPayment({
      // 时间戳
      timeStamp: "",
      // 随机字符串
      nonceStr: "",
      // 统一下单接口返回的 prepay_id 参数值
      package: "",
      // 签名类型
      signType: "",
      // 签名
      paySign: "",
      // 调用成功回调
      success() {},
      // 失败回调
      fail() {},
      // 接口调用结束回调
      complete() {},
    });
  }

  if (isError.value) {
    uni.hideLoading();
    console.log("预支付失败:", error.value);
    const err = error.value as AnyObject;
    showMessage(err?.msg || "支付失败");
  }
};

在这里插入图片描述

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-03-10 08:40:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-10 08:40:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-10 08:40:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-10 08:40:01       18 阅读

热门阅读

  1. 大型语言模型的智能助手:检索增强生成(RAG)

    2024-03-10 08:40:01       20 阅读
  2. 编程笔记 html5&css&js 005 小学数学四则运算练习

    2024-03-10 08:40:01       19 阅读
  3. [力扣 Hot100]Day46 二叉树展开为链表

    2024-03-10 08:40:01       22 阅读
  4. 面试中如何介绍zookeeper的ZAB协议

    2024-03-10 08:40:01       21 阅读
  5. .Net Core/.net 6/.Net 8 实现Mqtt服务器

    2024-03-10 08:40:01       18 阅读
  6. 【杂言】迟到的 2024 展望

    2024-03-10 08:40:01       22 阅读
  7. 程序员如何选择职业赛道?

    2024-03-10 08:40:01       21 阅读
  8. rabbitmq4

    rabbitmq4

    2024-03-10 08:40:01      18 阅读
  9. 题目 1908: 蓝桥杯-矩阵相乘

    2024-03-10 08:40:01       20 阅读
  10. 3.Rust数据类型

    2024-03-10 08:40:01       20 阅读
  11. 【C++ 学习】C++ 传值 传指针 传引用

    2024-03-10 08:40:01       19 阅读
  12. 防抖与节流

    2024-03-10 08:40:01       20 阅读
  13. Lua 脚本语言基础语法及应用

    2024-03-10 08:40:01       17 阅读