uni-app购物车页面详细代码

效果图:在这里插入图片描述

这里的购物车加减用的是uni-app中的sku插件

代码附下(全):

<script setup lang="ts">
import {
  reqMemberCartList,
  reqMemberdelentCart,
  reqMemberPutCart,
  putMemberCartSelectedAPI,
} from '@/services/cart/cart'
import type { CartItem } from '@/services/cart/type'
import { onShow } from '@dcloudio/uni-app'
import { ref } from 'vue'
import { useMemberStore } from '@/stores/modules/member'
import type { InputNumberBoxEvent } from '@/components/vk-data-input-number-box/vk-data-input-number-box'
import { computed } from 'vue'
let useMemberStores = useMemberStore()
//列表数组
let cartList = ref<CartItem[]>([])

//获取购物车列表
let GetCart = async () => {
  let res = await reqMemberCartList()
  cartList.value = res.result
}
// 删除购物车
const onDelentCart = (skuId: string) => {
  // 弹窗二次确认
  uni.showModal({
    content: '是否删除',
    success: async (res) => {
      if (res.confirm) {
        // 后端删除单品
        await reqMemberdelentCart({ ids: [skuId] })
        // 重新获取列表
        GetCart()
      }
    },
  })
}
// 修改商品数量
const onChangeCount = (ev: InputNumberBoxEvent) => {
  reqMemberPutCart(ev.index, { count: ev.value })
}
// 选中状态
const onChangeSelected = (item: CartItem) => {
  item.selected = !item.selected
  // 向后端发送请求
  reqMemberPutCart(item.skuId, { selected: item.selected })
}
// 全选
let onChangeSelectedAll = () => {
  // 全选状态取反
  const _isSelectedAll = !selectdAll.value
  // 前端数据更新
  cartList.value.forEach((item) => {
    item.selected = _isSelectedAll
  })
  // 后端数据更新
  putMemberCartSelectedAPI({ selected: _isSelectedAll })
}

// 计算全选状态
let selectdAll = computed(() => {
  return cartList.value.length && cartList.value.every((c) => c.selected)
})

// 计算选中单品列表
let selectedCartList = computed(() => {
  return cartList.value.filter((v) => v.selected)
})
// 计算选中总件数
let selectedCartListCount = computed(() => {
  return selectedCartList.value.reduce((sum, item) => sum + item.count, 0)
})
// 计算选中总金额
const selectedCartListMoney = computed(() => {
  return selectedCartList.value
    .reduce((sum, item) => sum + item.count * item.nowPrice, 0)
    .toFixed(2)
})
// 结算按钮
const gotoPayment = () => {
  if (selectedCartListCount.value === 0) {
    return uni.showToast({
      icon: 'none',
      title: '请选择商品',
    })
  }
  // 跳转到结算页
  uni.navigateTo({ url: '/pagesOrder/create/create' })
}
// 初始化调用
onShow(() => {
  // 用户已登录才允许调用
  if (useMemberStores.profile) {
    GetCart()
  }
})
</script>

<template>
  <scroll-view scroll-y class="scroll-view">
    <!-- 已登录: 显示购物车 -->
    <template v-if="cartList.length">
      <!-- 购物车列表 -->
      <view class="cart-list" v-if="true">
        <!-- 优惠提示 -->
        <view class="tips">
          <text class="label">满减</text>
          <text class="desc">1, 即可享受9折优惠</text>
        </view>
        <!-- 滑动操作分区 -->
        <uni-swipe-action>
          <!-- 滑动操作项 -->
          <uni-swipe-action-item v-for="item in cartList" :key="item.skuId" class="cart-swipe">
            <!-- 商品信息 -->
            <view class="goods">
              <!-- 选中状态 -->
              <text
                @tap="onChangeSelected(item)"
                class="checkbox"
                :class="{ checked: item.selected }"
              ></text>
              <navigator
                :url="`/pages/article/index?id=${item.id}`"
                hover-class="none"
                class="navigator"
              >
                <image mode="aspectFill" class="picture" :src="item.picture"></image>
                <view class="meta">
                  <view class="name ellipsis">{{ item.name }}</view>
                  <view class="attrsText ellipsis">{{ item.attrsText }}</view>
                  <view class="price">{{ item.nowPrice }}</view>
                </view>
              </navigator>
              <!-- 商品数量 -->
              <view class="count">
                <vk-data-input-number-box
                  v-model="item.count"
                  :min="1"
                  :max="item.stock"
                  :index="item.skuId"
                  @change="onChangeCount"
                />
              </view>
            </view>
            <!-- 右侧删除按钮 -->
            <template #right>
              <view class="cart-swipe-right">
                <button class="button delete-button" @tap="onDelentCart(item.skuId)">删除</button>
              </view>
            </template>
          </uni-swipe-action-item>
        </uni-swipe-action>
      </view>
      <!-- 购物车空状态 -->
      <view class="cart-blank" v-else>
        <image src="/static/images/blank_cart.png" class="image" />
        <text class="text">购物车还是空的,快来挑选好货吧</text>
        <navigator open-type="switchTab" url="/pages/index/index" hover-class="none">
          <button class="button">去首页看看</button>
        </navigator>
      </view>
      <!-- 吸底工具栏 -->
      <view class="toolbar">
        <text class="all" :class="{ checked: true }" @tap="onChangeSelectedAll">全选</text>
        <text class="text">合计:</text>
        <text class="amount">{{ selectedCartListMoney }}</text>
        <view class="button-grounp">
          <view class="button payment-button" :class="{ disabled: true }" @tap="gotoPayment">
            去结算({{ selectedCartListCount }})
          </view>
        </view>
      </view>
    </template>
    <!-- 未登录: 提示登录 -->
    <view class="login-blank" v-else>
      <text class="text">登录后可查看购物车中的商品</text>
      <navigator url="/pages/login/login" hover-class="none">
        <button class="button">去登录</button>
      </navigator>
    </view>
    <!-- 猜你喜欢 -->
    <XtxGuess ref="guessRef"></XtxGuess>
    <!-- 底部占位空盒子 -->
    <view class="toolbar-height"></view>
  </scroll-view>
</template>

<style lang="scss">
// 根元素
:host {
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background-color: #f7f7f8;
}

// 滚动容器
.scroll-view {
  flex: 1;
}

// 购物车列表
.cart-list {
  padding: 0 20rpx;

  // 优惠提示
  .tips {
    display: flex;
    align-items: center;
    line-height: 1;
    margin: 30rpx 10rpx;
    font-size: 26rpx;
    color: #666;

    .label {
      color: #fff;
      padding: 7rpx 15rpx 5rpx;
      border-radius: 4rpx;
      font-size: 24rpx;
      background-color: #27ba9b;
      margin-right: 10rpx;
    }
  }

  // 购物车商品
  .goods {
    display: flex;
    padding: 20rpx 20rpx 20rpx 80rpx;
    border-radius: 10rpx;
    background-color: #fff;
    position: relative;

    .navigator {
      display: flex;
    }

    .checkbox {
      position: absolute;
      top: 0;
      left: 0;

      display: flex;
      align-items: center;
      justify-content: center;
      width: 80rpx;
      height: 100%;

      &::before {
        content: '\e6cd';
        font-family: 'erabbit' !important;
        font-size: 40rpx;
        color: #444;
      }

      &.checked::before {
        content: '\e6cc';
        color: #27ba9b;
      }
    }

    .picture {
      width: 170rpx;
      height: 170rpx;
    }

    .meta {
      flex: 1;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      margin-left: 20rpx;
    }

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

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

    .price {
      line-height: 1;
      font-size: 26rpx;
      color: #444;
      margin-bottom: 2rpx;
      color: #cf4444;

      &::before {
        content: '¥';
        font-size: 80%;
      }
    }

    // 商品数量
    .count {
      position: absolute;
      bottom: 20rpx;
      right: 5rpx;

      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 220rpx;
      height: 48rpx;

      .text {
        height: 100%;
        padding: 0 20rpx;
        font-size: 32rpx;
        color: #444;
      }

      .input {
        height: 100%;
        text-align: center;
        border-radius: 4rpx;
        font-size: 24rpx;
        color: #444;
        background-color: #f6f6f6;
      }
    }
  }

  .cart-swipe {
    display: block;
    margin: 20rpx 0;
  }

  .cart-swipe-right {
    display: flex;
    height: 100%;

    .button {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 50px;
      padding: 6px;
      line-height: 1.5;
      color: #fff;
      font-size: 26rpx;
      border-radius: 0;
    }

    .delete-button {
      background-color: #cf4444;
    }
  }
}

// 空状态
.cart-blank,
.login-blank {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  height: 60vh;
  .image {
    width: 400rpx;
    height: 281rpx;
  }
  .text {
    color: #444;
    font-size: 26rpx;
    margin: 20rpx 0;
  }
  .button {
    width: 240rpx !important;
    height: 60rpx;
    line-height: 60rpx;
    margin-top: 20rpx;
    font-size: 26rpx;
    border-radius: 60rpx;
    color: #fff;
    background-color: #27ba9b;
  }
}

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

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

  .all {
    margin-left: 25rpx;
    font-size: 14px;
    color: #444;
    display: flex;
    align-items: center;
  }

  .all::before {
    font-family: 'erabbit' !important;
    content: '\e6cd';
    font-size: 40rpx;
    margin-right: 8rpx;
  }

  .checked::before {
    content: '\e6cc';
    color: #27ba9b;
  }

  .text {
    margin-right: 8rpx;
    margin-left: 32rpx;
    color: #444;
    font-size: 14px;
  }

  .amount {
    font-size: 20px;
    color: #cf4444;

    .decimal {
      font-size: 12px;
    }

    &::before {
      content: '¥';
      font-size: 12px;
    }
  }

  .button-grounp {
    margin-left: auto;
    display: flex;
    justify-content: space-between;
    text-align: center;
    line-height: 72rpx;
    font-size: 13px;
    color: #fff;

    .button {
      width: 240rpx;
      margin: 0 10rpx;
      border-radius: 72rpx;
    }

    .payment-button {
      background-color: #27ba9b;

      &.disabled {
        opacity: 0.6;
      }
    }
  }
}
// 底部占位空盒子
.toolbar-height {
  height: 100rpx;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/327434.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

go语言初探(一)

package mainimport ("fmt""time" )func main() {fmt.Print("hello go!")time.Sleep(1 * time.Second)}运行后&#xff0c;结果如下&#xff1a; 1、golang表达式中&#xff0c;加&#xff1b;和不加&#xff1b;都可以 2、函数的{和函数名一…

解决com.alibaba.fastjson.JSONException: default constructor not found的问题

1.问题描述 在进行JSON和对象互转时&#xff0c;发现有个报错&#xff1a; com.alibaba.fastjson.JSONException: default constructor not found. class com.hellobike.ph.match.service.taxi.model.message.DelayAddSkuMsg 2.原因和解决方案 通过其提示可以看出在利用fastJ…

【RTOS】快速体验FreeRTOS所有常用API(7)任务通知

目录 七、任务通知7.1 基本概念7.2 发出通知7.3 等待通知7.4 实例 七、任务通知 该部分在上份代码基础上修改得来&#xff0c;代码下载链接&#xff1a; https://wwzr.lanzout.com/i4Efu1la39wh 密码:cbvx 该代码尽量做到最简&#xff0c;不添加多余的、不规范的代码。 内容主要…

白码ERP快速实现库存不足时自动生成采购单功能

创建生产订单时&#xff0c;系统自动根据产品所需物料库存是否充足&#xff0c;如有物料库存不足&#xff0c;自动生成对应的采购订单&#xff1b; 前期准备&#xff1a; 需创建产品、物料、BOM、生产订单、生产订单明细、需求物料、采购订单、采购订单明细数据表&#xff0c…

如何查看centos7中dataease的安装位置

在 CentOS 7 中查找 DataEase 的安装位置&#xff0c;可以通过以下步骤进行&#xff1a; 检查服务状态&#xff1a; 如果 DataEase 作为服务运行&#xff0c;您可以使用 systemctl 命令来查看服务的状态&#xff0c;这通常会显示相关的路径信息。例如&#xff1a; systemctl st…

开发企业微信中的内嵌h5时如何开发与调试

前言&#xff1a; 在我们的项目中&#xff0c;开发企业微信内部的项目的话&#xff0c;分为两种&#xff0c;1种是直接开发企业微信的小程序&#xff0c;另一种则是企业微信内嵌我们的H5界面&#xff0c;我们这里讲一讲企业微信内嵌h5的方法与注意点。 1、开发h5项目 这点没有…

文件操作一(非常重要)

文件操作一&#xff08;非常重要&#xff09; 一、为什么使用文件&#xff1f;二、什么是文件&#xff1f;三、文件名(简单理解)四、二进制文件和文本文件&#xff08;重要&#xff09;五、流的概念&#xff08;非常重要&#xff09;六、文件的打开和关闭七、文件的顺序读写函数…

C++I/O流——(2)预定义格式的输入/输出(第二节)

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 含泪播种的人一定能含笑收获&#xff…

安达发|APS工序排程甘特图功能介绍

工序排程甘特图的主要功能 1. 显示工序时间安排&#xff1a;工序排程甘特图可以清晰地展示生产过程中各个工序的开始时间、结束时间和持续时间&#xff0c;从而帮助企业了解生产过程中各个环节的时间安排。 2. 显示工序进度情况&#xff1a;通过工序排程甘特图&#xff0c;企业…

用Python“自动连发消息”

自动连发消息&#xff0c;基本上C和Python的思路都是不停的模拟“击键”操作&#xff0c;还有一种VB的脚本写法&#xff0c;反成每种语言都能写&#xff0c;更厉害的可以用java做出个GUI界面&#xff0c;先上代码。 一 代码 import pyautogui # 鼠标 import p…

Springboot+vue的智能无人仓库管理(有报告),Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的智能无人仓库管理&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的智能无人仓库管理&#xff0c;采用M&#xff08…

华为设备VRRP配置

核心代码&#xff1a; 需要对所有虚拟路由器设置&#xff08;要进入到对应的端口&#xff09; vrrp vrid 38 virtual-ip 192.168.10.254 vrrp vrid 38 priority 120 vrrp vrid 38 track int g0/0/1 reduced 30①mac由vrid生成 ②指定虚拟ip ③虚拟ip作为内部主机的网关&#x…

2024美赛数学建模思路 - 案例:FPTree-频繁模式树算法

文章目录 算法介绍FP树表示法构建FP树实现代码 建模资料 ## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c…

STM32之OLED显示

一、模块介绍 1、常见的显示设备 LED、数码管、点阵、LCD屏(1602/12864)、OLED屏(消费电子) 2、OLED屏的概述 OLED&#xff0c;即有机发光二极管&#xff08;Organic Light-Emitting Diode&#xff09;&#xff0c;又称为有机电激光显示&#xff08;Organic Electroluminesenc…

IDEA集成Gitee(码云)

文章目录 创建新仓库&#xff0c;存放项目拉取Gitee上的项目 1、安装插件 Idea默认不带码云插件&#xff0c;我们第一步要安装Gitee插件。 如图所示&#xff0c;在Idea插件商店搜索Gitee&#xff0c;然后点击右侧的Install按钮。 2、Settings>Version Conttol>Gitee 这里…

Ubuntu12.0安装g++过程及其报错

Ubuntu12.0安装g过程及其报错 https://blog.csdn.net/weixin_51286763/article/details/120703953 https://blog.csdn.net/dingd1234/article/details/124029945 2.报错二&#xff1a; [41/80] Building CXX object absl/synchronization/CMakeFiles/graphcycles_internal.di…

JVM实战(14)——Young GC调优

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 学习必须往深处挖&…

如何将github copilot当gpt4用

现在写代码已经离不开ai辅助了我用的是github copilot&#xff0c;一方面是因为它和vscode结合得比较好&#xff0c;另一方面就是copilot chat了。可以在不切换工具的情况下&#xff0c;问它问题&#xff0c;在copilot chat还在内测阶段的时候我就申请使用了&#xff08;现在已…

vscode(visual studio code) 免密登陆服务器

1.生成密钥 首先&#xff0c;在本地&#xff0c;打开命令输入框&#xff1a; WinR–>弹出输入框&#xff0c;输入cmd,打开命令框。 然后&#xff0c;在命令框&#xff0c;输入 ssh-keygen -t rsa -C "love"按两次回车键&#xff0c;问你是否重写&#xff0c;选择…

初识XSS漏洞

目录 一、XSS的原理和分类 二、Xss漏洞分类 1. 反射性xss 简单的演示&#xff1a; 2.基于DOM的XSS 简单的演示&#xff1a; 3.存储型XSS ​编辑简单的演示 4、self xss 三、XSS漏洞的危害 四、XSS漏洞的验证 五、XSS漏洞的黑盒测试 六、XSS漏洞的白盒测试 七、XS…