新峰商城之购物车(二)

新峰商城购物车列表功能实现步骤

        购物车中列表功能,也是购物车的一个重要功能,购物车页面的商品列表是一个List对象和一些总览性字段。以下主要讲述购物车列表功能的主要实现步骤和代码。

一、数据格式的定义

        购物项列表数据中的商品标题字段、商品预览图字段、商品价格字段可以通过购物项表中的goods_id 来关联和查询,而其商品数量字段通过购物项表来查询,列表还有一个删除按钮,因此需要返回购物项的id字段。总览性数据包括加购总量字段和总价字段。返回数据的格式为购物项列表数据+加购总量字段+总价字段。购物项VO对象编码如下所示:

public class NewBeeMallShoppingCartItemVO implements Serializable {

    private Long cartItemId;

    private Long goodsId;

    private Integer goodsCount;

    private String goodsName;

    private String goodsCoverImg;

    private Integer sellingPrice;

}

二、购物车列表数据的获取

购物车列表中的字段可以分别通过查询shopping_cart_item购物项表和goods_info商品表获取。

实体层

(1)Mapper接口

首先在购物项实体Mapper接口的NewBeeMallShoppingCartItemMapper.java中增加如下方法:

//根据userId和number字段获取固定数量的购物项列表数据
  List<NewBeeMallShoppingCartItem> selectByUserId(
        @Param("newBeeMallUserId") Long newBeeMallUserId
      , @Param("number") int number);

(2)Mapper映射文件

映射文件NewBeeMallShoppingCartItemMapper.xml添加具体的SQL语句,代码如下:

<select id="selectByUserId" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from tb_newbee_mall_shopping_cart_item
        where user_id = #{newBeeMallUserId,jdbcType=BIGINT} and is_deleted = 0
        limit #{number}
</select>

业务层

在业务类中增加getMyShoppingCartItems方法,用以获取购物项列表数据,

在NewBeeMallShoppingCartService.java中增加方法,主要代码如下:

//获取我的购物车中的列表数据
List<NewBeeMallShoppingCartItemVO> getMyShoppingCartItems(Long newBeeMallUserId);

在NewBeeMallShoppingCartServiceImpl类中实现方法,主要代码如下:

 @Override
    public List<NewBeeMallShoppingCartItemVO> getMyShoppingCartItems(Long newBeeMallUserId) {
        List<NewBeeMallShoppingCartItemVO> newBeeMallShoppingCartItemVOS = new ArrayList<>();
        List<NewBeeMallShoppingCartItem> newBeeMallShoppingCartItems = newBeeMallShoppingCartItemMapper.selectByUserId(newBeeMallUserId, Constants.SHOPPING_CART_ITEM_TOTAL_NUMBER);
        if (!CollectionUtils.isEmpty(newBeeMallShoppingCartItems)) {
            //查询商品信息并做数据转换
            List<Long> newBeeMallGoodsIds = newBeeMallShoppingCartItems.stream().map(NewBeeMallShoppingCartItem::getGoodsId).collect(Collectors.toList());
            List<NewBeeMallGoods> newBeeMallGoods = newBeeMallGoodsMapper.selectByPrimaryKeys(newBeeMallGoodsIds);
            Map<Long, NewBeeMallGoods> newBeeMallGoodsMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(newBeeMallGoods)) {
                newBeeMallGoodsMap = newBeeMallGoods.stream().collect(Collectors.toMap(NewBeeMallGoods::getGoodsId, Function.identity(), (entity1, entity2) -> entity1));
            }
            for (NewBeeMallShoppingCartItem newBeeMallShoppingCartItem : newBeeMallShoppingCartItems) {
                NewBeeMallShoppingCartItemVO newBeeMallShoppingCartItemVO = new NewBeeMallShoppingCartItemVO();
                BeanUtil.copyProperties(newBeeMallShoppingCartItem, newBeeMallShoppingCartItemVO);
                if (newBeeMallGoodsMap.containsKey(newBeeMallShoppingCartItem.getGoodsId())) {
                    NewBeeMallGoods newBeeMallGoodsTemp = newBeeMallGoodsMap.get(newBeeMallShoppingCartItem.getGoodsId());
                    newBeeMallShoppingCartItemVO.setGoodsCoverImg(newBeeMallGoodsTemp.getGoodsCoverImg());
                    String goodsName = newBeeMallGoodsTemp.getGoodsName();
                    // 字符串过长导致文字超出的问题
                    if (goodsName.length() > 28) {
                        goodsName = goodsName.substring(0, 28) + "...";
                    }
                    newBeeMallShoppingCartItemVO.setGoodsName(goodsName);
                    newBeeMallShoppingCartItemVO.setSellingPrice(newBeeMallGoodsTemp.getSellingPrice());
                    newBeeMallShoppingCartItemVOS.add(newBeeMallShoppingCartItemVO);
                }
            }
        }
        return newBeeMallShoppingCartItemVOS;
    }

代码通过传入userid字段作为参数,然后通过SQL查询出当前userid下的购物项列表数据。因为购物车页面需要展示商品信息,所以通过购物项表中的goods_id 获取每个购物项对应的商品信息。接着填充数据,即将相关字段封装到NewBeeMallShoppingCartItemVO对象中。

三、购物车列表数据的渲染

控制层

数据最终通过Thymeleaf语法渲染到前端页面上,首先需要将获取的数据转发到对应模板页面中,就必须在Controller层方法中将查询到的数据放入request请求中。

ShoppingCartController中新增cartListPage()方法,代码如下:


    @GetMapping("/shop-cart")
    public String cartListPage(HttpServletRequest request,
                               HttpSession httpSession) {
        NewBeeMallUserVO user = (NewBeeMallUserVO) httpSession.getAttribute(Constants.MALL_USER_SESSION_KEY);
        int itemsTotal = 0;
        int priceTotal = 0;
        List<NewBeeMallShoppingCartItemVO> myShoppingCartItems = newBeeMallShoppingCartService.getMyShoppingCartItems(user.getUserId());
        if (!CollectionUtils.isEmpty(myShoppingCartItems)) {
            //购物项总数
            itemsTotal = myShoppingCartItems.stream().mapToInt(NewBeeMallShoppingCartItemVO::getGoodsCount).sum();
            if (itemsTotal < 1) {
                NewBeeMallException.fail("购物项不能为空");
            }
            //总价
            for (NewBeeMallShoppingCartItemVO newBeeMallShoppingCartItemVO : myShoppingCartItems) {
                priceTotal += newBeeMallShoppingCartItemVO.getGoodsCount() * newBeeMallShoppingCartItemVO.getSellingPrice();
            }
            if (priceTotal < 1) {
                NewBeeMallException.fail("购物项价格异常");
            }
        }
        request.setAttribute("itemsTotal", itemsTotal);
        request.setAttribute("priceTotal", priceTotal);
        request.setAttribute("myShoppingCartItems", myShoppingCartItems);
        return "mall/cart";
    }

 在代码中首先调用业务层的方法,把当前用户添加到购物车中的购物项数据全部读取出来,然后计算商品总数和总价,并将三个对象都放到request对象中,最后跳转到mall目录下的cart.html模板页面进行数据渲染。

前端

在resource/templates/mall目录中增加cart.html,模板代码如下所示:

<!-- Copyright (c) 2019-2020 十三 all rights reserved. -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>NewBee商城-购物车</title>
    <link rel="stylesheet" th:href="@{mall/css/iconfont.css}">
    <link rel="stylesheet" th:href="@{mall/css/common.css}">
    <link rel="stylesheet" th:href="@{mall/styles/header.css}">
    <link rel="stylesheet" th:href="@{mall/styles/cart.css}">
    <link rel="stylesheet" th:href="@{/admin/plugins/sweetalert2/sweetalert2.min.css}"/>
</head>
<body>

<div id="cart">
    <div class="banner_x center">
        <a th:href="@{/index}" target="_blank">
            <div class="logo fl">
                <img src="mall/image/new-bee-logo-3.png"/>
            </div>
        </a>

        <div class="wdgwc fl ml20">购物车</div>
        <div class="wxts fl ml20">温馨提示:产品是否购买成功,以最终下单为准哦,请尽快结算</div>
        <div class="clear"></div>
    </div>
    <div class="cart_line"></div>
    <div class="cart_bg">
        <th:block th:if="${#lists.isEmpty(myShoppingCartItems)}">
            <div class="list center">
                <img style="position: absolute;margin-top: 16px;left: 45%;" th:src="@{/mall/image/null-content.png}">
            </div>
        </th:block>
        <th:block th:unless="${#lists.isEmpty(myShoppingCartItems)}">
            <div class="list center">
                <div class="top2 center">
                    <div class="sub_top fl">
                    </div>
                    <div class="sub_top fl">商品名称</div>
                    <div class="sub_top fl">单价</div>
                    <div class="sub_top fl">数量</div>
                    <div class="sub_top fl">小计</div>
                    <div class="sub_top fr">操作</div>
                    <div class="clear"></div>
                </div>
                <th:block th:each="item : ${myShoppingCartItems}">
                    <div class="content2 center">
                        <div class="sub_content fl ">
                        </div>
                        <div class="sub_content cover fl"><img th:src="@{${item.goodsCoverImg}}"></div>
                        <div class="sub_content fl ft20" th:text="${item.goodsName}">商品名称</div>
                        <div class="sub_content fl" th:text="${item.sellingPrice+'元'}">1299元</div>
                        <div class="sub_content fl">
                            <input class="goods_count" th:id="${'goodsCount'+item.cartItemId}" type="number"
                                   th:onblur="'updateItem('+${item.cartItemId}+')'"
                                   th:value="${item.goodsCount}" step="1" min="1"
                                   max="5">
                        </div>
                        <div class="sub_content fl" th:text="${item.goodsCount*item.sellingPrice+'元'}">1299元</div>
                        <div class="sub_content fl"><a href="##" th:onclick="'deleteItem('+${item.cartItemId}+')'">×</a>
                        </div>
                        <div class="clear"></div>
                    </div>
                </th:block>
            </div>
        </th:block>
        <div class="pre_order mt20 center">
            <div class="tips fl ml20">
                <ul>
                    <li><a th:href="@{/index}">继续购物</a></li>
                    <li>|</li>
                    <li>共<span th:text="${itemsTotal}">13</span>件商品</li>
                    <div class="clear"></div>
                </ul>
            </div>
            <div class="order_div fr">
                <div class="order_total fl">合计(不含运费):<span th:text="${priceTotal}+'.00元'">1299.00元</span></div>
                <div class="order_button fr">
                    <th:block th:if="${itemsTotal == 0}">
                        <input class="order_button_c" type="button" name="tip"
                               onclick="tip()"
                               value="去结算"/>
                    </th:block>
                    <th:block th:unless="${itemsTotal == 0}">
                        <input class="order_button_d" type="button" name="settle"
                               onclick="settle()"
                               value="去结算"/>
                    </th:block>
                </div>
                <div class="clear"></div>
            </div>
            <div class="clear"></div>
        </div>
    </div>
</div>
<div th:replace="mall/footer::footer-fragment"></div>

</body>
<!-- jQuery -->
<script th:src="@{/admin/plugins/jquery/jquery.min.js}"></script>
<script th:src="@{/admin/plugins/sweetalert2/sweetalert2.all.min.js}"></script>
<script type="text/javascript">

    /**
     * 购物车中数量为0时提示
     */
    function tip() {
        Swal.fire({
            text: "购物车中无数据,无法结算",
            icon: "error",iconColor:"#f05b72",
        });
    }

    /**
     * 跳转至结算页面
     */
    function settle() {
        window.location.href = '/shop-cart/settle'
    }

    /**
     *更新购物项
     */
    function updateItem(id) {
        var domId = 'goodsCount' + id;
        var goodsCount = $("#" + domId).val();
        if (goodsCount > 5) {
            Swal.fire({
                text: "单个商品最多可购买5个",
                icon: "error",iconColor:"#f05b72",
            });
            return;
        }
        if (goodsCount < 1) {
            Swal.fire({
                text: "数量异常",
                icon: "error",iconColor:"#f05b72",
            });
            return;
        }
        var data = {
            "cartItemId": id,
            "goodsCount": goodsCount
        };
        $.ajax({
            type: 'PUT',
            url: '/shop-cart',
            contentType: 'application/json',
            data: JSON.stringify(data),
            success: function (result) {
                if (result.resultCode == 200) {
                    window.location.reload();
                } else {
                    Swal.fire({
                        text: "操作失败",
                        icon: "error",iconColor:"#f05b72",
                    });
                }
            },
            error: function () {
                Swal.fire({
                    text: "操作失败",
                    icon: "error",iconColor:"#f05b72",
                });
            }
        });
    }

    /**
     * * 删除购物项
     * @param id
     */
    function deleteItem(id) {
        Swal.fire({
            title: "确认弹框",
            text: "确认要删除数据吗?",
            icon: "warning",iconColor:"#dea32c",
            showCancelButton: true,
            confirmButtonText: '确认',
            cancelButtonText: '取消'
        }).then((flag) => {
                if (flag.value) {
                    $.ajax({
                        type: 'DELETE',
                        url: '/shop-cart/' + id,
                        success: function (result) {
                            if (result.resultCode == 200) {
                                window.location.reload();
                            } else {
                                Swal.fire({
                                    text: "操作失败",
                                    icon: "error",iconColor:"#f05b72",
                                });
                            }
                        },
                        error: function () {
                            Swal.fire({
                                text: "操作失败",
                                icon: "error",iconColor:"#f05b72",
                            });
                        }
                    });
                }
            }
        )
        ;
    }
</script>
</html>

        在购物项列表区域对应的位置读取myShoppingCartItems数据,首先使用th:each循环语法将商品标题字段、商品预览图字段、商品价格字段、商品数量字段、单个商品的总价字段进行渲染,然后读取读取底部两个小计字段并渲染至页面中。

### 新蜂商城的使用指南与开发文档 #### 1. 构建工具配置 构建系统的配置文件 `build.gradle` 或者 `pom.xml` 是项目的核心部分之一,用于定义项目的依赖项以及编译、打包和发布的具体指令。这些文件的存在使得开发者可以轻松管理复杂的依赖关系并自动化许多重复性的任务[^1]。 对于采用 Gradle 的项目而言,在 `build.gradle` 文件中会指定插件版本号、库依赖列表以及其他必要的设置参数;而 Maven 用户则通过编辑其对应的 XML 配置来实现相同目的——即确保所有必需组件都被正确引入到工程当中以便顺利完成整个软件生命周期内的各项操作流程。 #### 2. 应用程序属性配置 在 Spring Boot 框架下运行的新蜂商城还需要关注另一个重要方面:应用程序级别的个性化调整选项通常存储于名为 `application.properties` 或 YAML 格式的同名替代品之中。这类资源允许管理员自定义端口号、数据库连接字符串等敏感数据而不必修改源码本身即可生效[^1]。 #### 3. 客户端前端架构概述 针对基于现代 JavaScript 技术栈所打造出来的全新一代 web 应用场景解决方案—newbee-mall-vue3-app 提供了一个完整的实例演示如何利用 Vue.js 生态圈中的最新成果快速搭建起功能齐全且用户体验优秀的在线购物平台界面布局设计思路及其背后的技术细节描述如下: 该项目采用了当前流行的 Vue3 全家桶作为主要框架支持,并辅以 vue-router 路由管理和 pinia 状态管理模式共同协作完成跨组件间通信需求处理工作流的同时还集成了 vant UI 组件库从而极大简化了日常编码过程中频繁遇到的一些常见交互逻辑实现难度降低维护成本提升效率等方面均表现出色[^2]。 ```javascript // 示例代码片段展示Pinia状态管理器基本用法 import { defineStore } from 'pinia'; export const useCartStore = defineStore('cart', { state: () => ({ items: [] }), actions: { addItem(item){ this.items.push(item); } } }); ``` #### 4. Java 运行时环境准备 如果计划部署该服务至类 Unix 平台之上,则可能需要提前做好 JDK 安装及相关路径映射等工作步骤指导信息可参见下面给出的具体命令行脚本样例内容说明材料里提到过相关内容可供参考学习之用[^3]: ```bash vim /etc/profile # 添加以下几行 export JAVA_HOME=/usr/local/src/jdk1.8 export PATH=${JAVA_HOME}/bin:${PATH} export CLASSPATH=.:${JAVA_HOME}/lib/tools.jar source /etc/profile java -version ``` 以上就是关于新蜂商城后端服务器端一直到客户端表现层各个层面涉及到的主要知识点总结归纳希望能够帮助您更好地理解和掌握这个开源电商系统整体运作原理!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值