day12 书城项目第五阶段

day12 书城项目第五阶段

1. 显示购物车页面

1.1目标

把购物车信息在专门的页面显示出来

1.2思路

在这里插入图片描述

1.3代码实现

1.3.1 购物车超链接

登录状态和未登录状态

<div class="topbar-right" th:if="${username} == null">
    <a href="user?method=toLoginPage" class="login">登录</a>
    <a href="user?method=toRegistPage" class="register">注册</a>
    <a
       href="cart?method=toCartPage"
       class="cart iconfont icon-gouwuche
              "
       >
        购物车
        <div class="cart-num">{{totalCount}}</div>
    </a>
    <a th:href="admin" class="admin">后台管理</a>
</div>
<div class="topbar-right" th:unless="${username} == null">
    <span>欢迎你 <b th:text="${username}">张总</b> </span>
    <a th:href="@{/user(method=logout)}">注销</a>
    <a
       href="cart?method=toCartPage"
       class="cart iconfont icon-gouwuche
              "
       >
        购物车
        <div class="cart-num">{{totalCount}}</div>
    </a>
    <a th:href="admin" class="admin">后台管理</a>
</div>
1.3.2 CartServlet添加跳转到cart.html页面的代码
    // 前往cart页面
    protected void toCartPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processTemplate("cart/cart", req, resp);
    }
1.3.3 cart.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <base th:href="@{/}">
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="static/css/minireset.css" />
    <link rel="stylesheet" href="static/css/common.css" />
    <link rel="stylesheet" href="static/css/cart.css" />
    <script src="static/script/axios.min.js"></script>
    <script src="static/script/vue.js"></script>
  </head>
  <body>
    <div id="box">
      <div class="header">
        <div class="w">
          <div class="header-left">
            <a href="index.html">
              <img src="static/img/logo.gif" alt=""
              /></a>
            <h1>我的购物车</h1>
          </div>
          <div class="header-right">
            <h3>欢迎<span>张总</span>光临尚硅谷书城</h3>
            <div class="order"><a href="order/order.html">我的订单</a></div>
            <div class="destory"><a href="index.html">注销</a></div>
            <div class="gohome">
              <a href="index.html">返回</a>
            </div>
          </div>
        </div>
      </div>
      <div class="list">
        <div class="w">
          <table>
            <thead>
            <tr>
              <th>图片</th>
              <th>商品名称</th>

              <th>数量</th>
              <th>单价</th>
              <th>金额</th>
              <th>操作</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="(e,index) in cart.cartList">
              <td>
                <img :src="e.imgPath" alt="" />
              </td>
              <td>{{e.title}}</td>
              <td>
                <span class="count">-</span>
                <input class="count-num" type="text" v-model="e.count" />
                <span class="count">+</span>
              </td>
              <td>{{e.price}}</td>
              <td>{{e.amount}}</td>
              <td><a href="" >删除</a></td>
            </tr>


            </tbody>
          </table>
          <div class="footer">
            <div class="footer-left">
              <a href="" class="clear-cart">清空购物车</a>
              <a href="#">继续购物</a>
            </div>
            <div class="footer-right">
              <div><span>{{cart.totalCount}}</span>件商品</div>
              <div class="total-price">总金额<span>{{cart.totalAmount}}</span></div>
              <a class="pay" href="checkout.html">去结账</a>
            </div>
          </div>
        </div>
      </div>
      <div class="bottom">
        <div class="w">
          <div class="top">
            <ul>
              <li>
                <a href="">
                  <img src="static/img/bottom1.png" alt="" />
                  <span>大咖级讲师亲自授课</span>
                </a>
              </li>
              <li>
                <a href="">
                  <img src="static/img/bottom.png" alt="" />
                  <span>课程为学员成长持续赋能</span>
                </a>
              </li>
              <li>
                <a href="">
                  <img src="static/img/bottom2.png" alt="" />
                  <span>学员真是情况大公开</span>
                </a>
              </li>
            </ul>
          </div>
          <div class="content">
            <dl>
              <dt>关于尚硅谷</dt>
              <dd>教育理念</dd>
              <!-- <dd>名师团队</dd>
              <dd>学员心声</dd> -->
            </dl>
            <dl>
              <dt>资源下载</dt>
              <dd>视频下载</dd>
              <!-- <dd>资料下载</dd>
              <dd>工具下载</dd> -->
            </dl>
            <dl>
              <dt>加入我们</dt>
              <dd>招聘岗位</dd>
              <!-- <dd>岗位介绍</dd>
              <dd>招贤纳师</dd> -->
            </dl>
            <dl>
              <dt>联系我们</dt>
              <dd>http://www.atguigu.com</dd>
              <dd></dd>
            </dl>
          </div>
        </div>
        <div class="down">
          尚硅谷书城.Copyright ©2015
        </div>
      </div>

    </div>
    <script>
      var vue = new Vue({
        "el":"#box",
        "data":{
            "cart":{
              "cartList":[
                {
                  "imgPath": "static/uploads/huozhe.jpg",
                  "title": "活着",
                  "count": 2,
                  "price": "36.8",
                  "amount": "73.6"
                },
                {
                  "imgPath": "static/uploads/huozhe.jpg",
                  "title": "活着真好",
                  "count": 2,
                  "price": "36.8",
                  "amount": "73.6"
                }
              ],
              "totalCount": "4",
              "totalAmount": "147.2"
            }
        },
        "created":function () {
          // 发起异步请求 获取购物车详情数据
          axios({
            "url":"cart",
            "method":"post",
            "params":{
              "method":"getCart"
            }
          }).
          then(function (value) {
            // 获取后台发送的数据
            console.log(value.data);
            if (value.data.flag){
                vue.cart = value.data.resultData;

              }
          })
        }
      });
    </script>
  </body>
</html>

1.3.4 修改Cart类添加getCartItem方法
    // 获取所有的购物项
    public List<CartItem> getCartItem(){
        Collection<CartItem> values = cartMap.values();
        // 将Collection转为集合
        ArrayList<CartItem> cartItems = new ArrayList<>(values);
        return cartItems;
    }

1.3.5 CartServlet中添加getCart()方法
    // 获取购物车内容
    protected void getCart(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        CommonResult result;
        // 获取购物车
        try {
            HttpSession session = req.getSession();
            Cart cart = (Cart) session.getAttribute(Constants.SESSION_CART_KEY);

            Map map = new HashMap<>();
            // 2.判断购物车是否存在
            if (cart != null) {
                // 获取对应的数据
                List<CartItem> cartItem = cart.getCartItem();
                int totalCount = cart.getTotalCount();
                Double totalAmount = cart.getTotalAmount();

                map.put("cartList", cartItem);
                map.put("totalCount", totalCount);
                map.put("totalAmount", totalAmount);

            }
            // 4.将数据封装到CommonResult
            result = CommonResult.ok(map);
        } catch (Exception e) {
            e.printStackTrace();
            result = CommonResult.error(e.getMessage());
        }
        JSONUtils.writeJson(resp, result);
    }

2. 清空购物车

2.1 目标

当用户确定点击清空购物车,将Session域中的Cart对象移除。

2.2 思路

cart.html→清空购物车超链接→点击事件→confirm()确认→确定→CartServlet.clearCart()→从Session域移除Cart对象→跳转回到cart.html页面

2.3 代码实现

2.3.1 前端页面代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <base th:href="@{/}">
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="static/css/minireset.css" />
    <link rel="stylesheet" href="static/css/common.css" />
    <link rel="stylesheet" href="static/css/cart.css" />
    <script src="static/script/axios.min.js"></script>
    <script src="static/script/vue.js"></script>
  </head>
  <body>
    <div id="box">
      <div class="header">
        <div class="w">
          <div class="header-left">
            <a href="index.html">
              <img src="static/img/logo.gif" alt=""
              /></a>
            <h1>我的购物车</h1>
          </div>
          <div class="header-right">
            <h3>欢迎<span>张总</span>光临尚硅谷书城</h3>
            <div class="order"><a href="order/order.html">我的订单</a></div>
            <div class="destory"><a href="index.html">注销</a></div>
            <div class="gohome">
              <a href="index.html">返回</a>
            </div>
          </div>
        </div>
      </div>
      <div class="list">
        <div class="w">
          <table>
            <thead>
            <tr>
              <th>图片</th>
              <th>商品名称</th>

              <th>数量</th>
              <th>单价</th>
              <th>金额</th>
              <th>操作</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="(e,index) in cart.cartList">
              <td>
                <img :src="e.imgPath" alt="" />
              </td>
              <td>{{e.title}}</td>
              <td>
                <span class="count" @click="subItem(e.id,e.title,e.count,index)">-</span>
                <input class="count-num" type="text" v-model="e.count"/>
                <span class="count">+</span>
              </td>
              <td>{{e.price}}</td>
              <td>{{e.amount}}</td>
              <td><a href="">删除</a></td>
            </tr>


            </tbody>
          </table>
          <div class="footer">
            <div class="footer-left">
              <a href="cart?method=clearCart" @click="clearCart()" class="clear-cart">清空购物车</a>
              <a href="#">继续购物</a>
            </div>
            <div class="footer-right">
              <div><span>{{cart.totalCount}}</span>件商品</div>
              <div class="total-price">总金额<span>{{cart.totalAmount}}</span></div>
              <a class="pay" href="checkout.html">去结账</a>
            </div>
          </div>
        </div>
      </div>
      <div class="bottom">
        <div class="w">
          <div class="top">
            <ul>
              <li>
                <a href="">
                  <img src="static/img/bottom1.png" alt="" />
                  <span>大咖级讲师亲自授课</span>
                </a>
              </li>
              <li>
                <a href="">
                  <img src="static/img/bottom.png" alt="" />
                  <span>课程为学员成长持续赋能</span>
                </a>
              </li>
              <li>
                <a href="">
                  <img src="static/img/bottom2.png" alt="" />
                  <span>学员真是情况大公开</span>
                </a>
              </li>
            </ul>
          </div>
          <div class="content">
            <dl>
              <dt>关于尚硅谷</dt>
              <dd>教育理念</dd>
              <!-- <dd>名师团队</dd>
              <dd>学员心声</dd> -->
            </dl>
            <dl>
              <dt>资源下载</dt>
              <dd>视频下载</dd>
              <!-- <dd>资料下载</dd>
              <dd>工具下载</dd> -->
            </dl>
            <dl>
              <dt>加入我们</dt>
              <dd>招聘岗位</dd>
              <!-- <dd>岗位介绍</dd>
              <dd>招贤纳师</dd> -->
            </dl>
            <dl>
              <dt>联系我们</dt>
              <dd>http://www.atguigu.com</dd>
              <dd></dd>
            </dl>
          </div>
        </div>
        <div class="down">
          尚硅谷书城.Copyright ©2015
        </div>
      </div>

    </div>
    <script>
      var vue = new Vue({
        "el":"#box",
        "data":{
            "cart":{
              "cartList":[
                {
                  "imgPath": "static/uploads/huozhe.jpg",
                  "title": "活着",
                  "count": 2,
                  "price": "36.8",
                  "amount": "73.6"
                },
                {
                  "imgPath": "static/uploads/huozhe.jpg",
                  "title": "活着真好",
                  "count": 2,
                  "price": "36.8",
                  "amount": "73.6"
                }
              ],
              "totalCount": "4",
              "totalAmount": "147.2"
            }
        },
        "methods":{
          "clearCart":function () {
              var falg = confirm("请问您真的要清空购物车吗?");
              // 点击取消清空 则阻止默认行为
              if(!falg){
                event.preventDefault();
              }
          },
        "created":function () {
          // 发起异步请求 获取购物车详情数据
          axios({
            "url":"cart",
            "method":"post",
            "params":{
              "method":"getCart"
            }
          }).
          then(function (value) {
            // 获取后台发送的数据
            console.log(value.data);
            if (value.data.flag){
                vue.cart = value.data.resultData;

              }
          })
        }
      });
    </script>
  </body>
</html>

2.3.2 CartServlet.cleanCart()
/**
     * 清空购物车
     * @param request
     * @param response
     */
public void cleanCart(HttpServletRequest request, HttpServletResponse response) throws IOException {
    //1. 将cart从session中移除
    request.getSession().removeAttribute(BookStoreConstants.CARTSESSIONKEY);
    //2. 跳转回到cart.html页面
    processTemplate("cart/cart",request,response);
}

3. 减号

3.1 目标

  • 在大于1的数值基础上-1:执行-1的逻辑
  • 在1的基础上-1:执行删除item的逻辑

3.2 思路

在这里插入图片描述

3.3 前端代码

3.3.1 给减号绑定点击事件
<span class="count" @click="subItem(e.id,e.title,e.count,index)">-</span>
3.3.2 Vue代码
"subItem":function (id,title,count,index){
    console.log(id + "," + title + "," + count + "," + index);
    // 1.判断数量是否为1
    if (count==1){
        // 2. 提示是否删除
        let flag = confirm("请问您要删除【" + title + "】吗?");
        if (!flag){
            // 不删除的话则什么都不做
            return ;
        }
    }
    // 3.不是1 发起异步请求 减少购物车数量
    axios({
        "url":"cart",
        "method":"post",
        "params":{
            "method":"subItem",
            "id":id
        }
    }).then(function (value) {
        console.log(value.data);
        if (value.data.flag){
            if (count == 1){
                vue.cart.cartList.splice(index, 1);
            }else{
                // 更新指定下标的金额数量
                vue.cart.cartList[index].count = value.data.resultData.count;
                vue.cart.cartList[index].amount = value.data.resultData.amount;
            }
            // 更新总金额总数量
            vue.cart.totalCount = value.data.resultData.totalCount;
            vue.cart.totalAmount = value.data.resultData.totalAmount;
        }
    })
}

3.4 后端代码

CartServlet.subItem()方法

    protected void subItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        CommonResult result;
        try {
            // 1.获取请求参数id
            String id = req.getParameter("id");
            int intId = Integer.parseInt(id);
            // 2.获取购物车
            HttpSession session = req.getSession();
            Cart cart = (Cart) session.getAttribute(Constants.SESSION_CART_KEY);
            // 3.对指定的id的条目进行数量-1
            cart.cartItemCountDecrease(intId);
            // 4.封装反馈的数据
            Map map = getMap(intId, cart);
            result = CommonResult.ok(map);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            result = CommonResult.error(e.getMessage());
        }
        JSONUtils.writeJson(resp, result);

    }

CartServlet.getMap()方法

    // 增加 减少 改变值 通用的反馈结果方法
    private Map getMap(int intId, Cart cart) {
        // 封装反馈的结果
        Map map = new HashMap();
        // 获取指定的购物项
        CartItem cartItem = cart.getCartMap().get(intId);

        if (cartItem != null) {
            map.put("count", cartItem.getCount());
            map.put("amount", cartItem.getAmount());
        }
        map.put("totalCount", cart.getTotalCount());
        map.put("totalAmount", cart.getTotalAmount());
        return map;
    }

4. 加号

4.1 目标

告诉Servlet将Session域中Cart对象里面对应的CartItem执行count+1操作

4.2 思路在这里插入图片描述

4.3 代码实现

4.3.1 前端代码

给加号绑定点击事件

<span class="count" @click="addItem(e.id, index)">+</span>

vue代码

"addItem":function (id, index) {
    axios({
        "url":"cart",
        "method":"post",
        "params":{
            "method":"addItem",
            "id":id
        }
    }).then(function (value) {
        console.log(value.data)
        if (value.data.flag){
            vue.cart.cartList[index].count = value.data.resultData.count;
            vue.cart.cartList[index].amount = value.data.resultData.amount;
            vue.cart.totalCount = value.data.resultData.totalCount;
            vue.cart.totalAmount = value.data.resultData.totalAmount;
        }
    })
}
4.3.2 后端代码

CartServlet.addItem()

    protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        CommonResult result;
        try {
            // 1.获取id
            String id = req.getParameter("id");
            int intId = Integer.parseInt(id);
            // 2.获取购物车
            HttpSession session = req.getSession();
            Cart cart = (Cart) session.getAttribute(Constants.SESSION_CART_KEY);
            // 3.对指定的id的条目进行数量+1
            cart.cartItemCountIncrease(intId);
            // 4.封装反馈的数据
            Map map = getMap(intId, cart);
            result = CommonResult.ok(map);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            result = CommonResult.error(e.getMessage());
        }
        JSONUtils.writeJson(resp, result);


    }

5. 删除

5.1 目标

点击删除超链接后,把对应的CartItem从Cart中删除

5.2 思路

在这里插入图片描述

5.3 代码实现

5.3.1 前端代码

给删除按钮绑定点击事件

<td><a href="" @click="removeItem(e.title,index,e.id)">删除</a></td>

vue和axios代码

"removeItem":function (title,index,id){
    event.preventDefault();  // 取消默认行为
    // console.log(title + "--->" + index + "--->" + id);
    var flag = confirm("请问你真的要删除【" + title + "】吗?");
    if(!flag){
        // 不删除则return
        return ;
    }
    // 确认删除 则像后端发送请求
    axios({
        "url":"cart",
        "method":"post",
        "params":{
            "method":"delCartItem",
            "id":id
        }
    }).then(function (value) {
        console.log(value.data);
        // 请求成功
        if (value.data.flag){
            // splice(下标,数量);
            // 删除指定下标开始的元素 1个
            vue.cart.cartList.splice(index, 1);
            vue.cart.totalCount = value.data.resultData.totalCount;
            vue.cart.totalAmount = value.data.resultData.totalAmount;
        }
    })
}
}
5.3.2 后端代码

CartServlet.delCartItem()

    protected void delCartItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        CommonResult result;
        try {
            // 获取id
            String id = req.getParameter("id");
            int intId = Integer.parseInt(id);
            // 获取session
            HttpSession session = req.getSession();
            // 获取购物车
            Cart cart = (Cart) session.getAttribute(Constants.SESSION_CART_KEY);
            // 删除购物项
            cart.removeItem(intId);

            // 4.封装数据进行返回
            Map map = new HashMap();
            // 将数据封装到map内
            map.put("totalCount", cart.getTotalCount());
            map.put("totalAmount", cart.getTotalAmount());

            result = CommonResult.ok(map);
        } catch (Exception e) {
            e.printStackTrace();
            result = CommonResult.error(e.getMessage());
        }
        JSONUtils.writeJson(resp, result);
    }

6. 文本框修改

6.1 目标

用户在文本框输入新数据后,根据用户输入在Session中的Cart中修改CartItem中的count

6.2 思路

在这里插入图片描述

6.3 代码实现

6.3.1 前端代码

绑定失去change事件

<input class="count-num" type="text" v-model="e.count" @change="updateItem(e.id,e.count,index)"/>

vue和axios代码

"updateItem":function (id, count, index) {
    // 判断count是否符合规范
    var reg = /[1-9][0-9]*/
    if (reg.test(count)){
        // 符合规范 发送axios请求
        axios({
            "url":"cart",
            "method":"post",
            "params":{
                "method":"updateItem",
                "id":id,
                "count":count
            }
        }).then(function (value){
            console.log(value.data)
            if (value.data.flag){
                vue.cart.cartList[index].count = value.data.resultData.count;
                vue.cart.cartList[index].amount = value.data.resultData.amount;
                vue.cart.totalCount = value.data.resultData.totalCount;
                vue.cart.totalAmount = value.data.resultData.totalAmount;

            }
        })
    }
}
6.3.2后端代码

CartServlet.updateCartItemCount()

protected void updateItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    CommonResult result;
    try {
        // 1.获取id
        String id = req.getParameter("id");
        String count = req.getParameter("count");
        int intId = Integer.parseInt(id);
        int intCount = Integer.parseInt(count);
        // 2.获取购物车
        HttpSession session = req.getSession();
        Cart cart = (Cart) session.getAttribute(Constants.SESSION_CART_KEY);
        // 3.对指定的条目进行数量修改
        cart.cartItemSetCount(intId, intCount);
        // 4.封装反馈的数据
        Map map = getMap(intId, cart);
        result = CommonResult.ok(map);
    } catch (NumberFormatException e) {
        e.printStackTrace();
        result = CommonResult.error(e.getMessage());
    }
    JSONUtils.writeJson(resp, result);


}

7. Double数据运算过程中精度调整

7.1 问题现象

在这里插入图片描述

7.2 解决方案

  • 使用BigDecimal类型来进行Double类型数据运算
  • 创建BigDecimal类型对象时将Double类型的数据转换为字符串

Cart类:

    // 获取总金额
    public Double getTotalAmount(){
//        this.totalAmount = 0.0;
        BigDecimal bigDecimalTotalAmount = new BigDecimal(0.0);
        // 获取购物车中所有的购物项
        Collection<CartItem> values = cartMap.values();
        for (CartItem item : values) {
            // 计算所有购物项的总金额
//            totalAmount += item.getAmount();
            bigDecimalTotalAmount = bigDecimalTotalAmount.add(new BigDecimal(item.getAmount() + ""));
        }
        // 将totalAmount转成double类型
        totalAmount = bigDecimalTotalAmount.doubleValue();
        return totalAmount;
    }

CartItem类:

    public Double getAmount() {
//        return amount * count;

        BigDecimal bigDecimalPrice = new BigDecimal(price + "");
        BigDecimal bigDecimalCount = new BigDecimal(count + "");

        amount = bigDecimalCount.multiply(bigDecimalPrice).doubleValue();
        return amount;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值