页面jsp :
<%@ page language="java" contentType="text/html charset=utf-8"pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html charset=utf-8" />
<title>易买网 - 首页</title>
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/css/style.css" />
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-2.1.1.js"></script>
<script type="text/javascript">
var contextPath = '${pageContext.request.contextPath }'
</script>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/shopping.js"></script>
</head>
<body>
<jsp:include page="top.jsp" />
<div id="position" class="wrap">
您现在的位置:<a href="Home">易买网</a> &gt 购物车
</div>
<div class="wrap">
<div id="shopping">
<form action="" method="post">
<table>
<tr>
<th>商品名称</th>
<th>商品价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>
<c:forEach items="${sessionScope.shopCar}" var="item" varStatus="status">
<tr id="product_id_${item.proId}">
<td class="thumb"><img src="${item.proImg }" height="50" width="30" /><a href="Product?action=view&entityId=${item.proId}">${item.proName}</a></td>
<td class="price" id="price_id_1">
<span><fmt:formatNumber value="${item.proPrice}" type="NUMBER" minFractionDigits="2" /></span>
<input type="hidden" value="${item.proPrice}" />
</td>
<td class="number">
<dl>
<dt><span onclick="sub('number_id_${item.proId}','${item.proId}')">-</span><input id="number_id_${item.proId}" type="text" readonly="readonly" name="number" value="${item.proNum}" /><span onclick="addNum('number_id_${item.proId}','${item.proId}')">+</span></dt>
</dl>
</td>
<td class="delete"><a href="javascript:deleteItem('product_id_${item.proId}','${item.proId}')">删除</a></td>
</tr>
</c:forEach>
</table>
<div class="button"><input type="submit" value="" /></div>
</form>
</div>
</div>
<div id="footer">
Copyright &copy kaka qq 292817678 itjob 远标培训.
</div>
</body>
</html>
页面关联的js 自己去网上下载一个jquery
/*数量减少*/function sub(id,proId){
//购买数量的值
var num = $('#'+id).val()
if(num > 1){
$('#'+id).val(num - 1)
}
edit(id,proId)
}
function edit(id,proId){
var url = contextPath + '/HomeCarManager'
//修改后的数量,购物明细的商品的id
num = $('#'+id).val()
$.post(url,{"num":num,"proId":proId},function (msg){
/*
if(msg == 'true'){
alert('修改成功')
} else {
alert('修改失败')
}*/
})
}
/**
* 数量增加
* @param {} id
*/
function addNum(id,proId){
//购买数量的值
var num = $('#'+id).val()
$('#'+id).val(parseInt(num) + 1)
edit(id,proId)
}
/**
* 删除购物明细
*/
function deleteItem(trId,proId){
//
//console.log($("#"+trId))
//js删除页面节点
//$("#"+trId).remove()
var url = contextPath + '/HomeCarManager'
$.post(url,{"proId":proId},function (msg){
if(msg == 'true'){
//js删除页面节点
$("#"+trId).remove()
}
})
}
后台servlet1
package com.kaka.webimport java.io.IOException
import java.io.PrintWriter
import java.util.ArrayList
import java.util.List
import javax.servlet.ServletException
import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
/**
* 购物车处理类
* @author @author ITJob 远标培训
*
*/
import com.kaka.entity.Items
import com.kaka.entity.Product
import com.kaka.service.ProductService
import com.kaka.service.impl.ProductServiceImpl
public class HomeCar extends HttpServlet {
private static final long serialVersionUID = 1L
ProductService ps = new ProductServiceImpl()
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取商品的id
String proId = req.getParameter("proId")
resp.setContentType("text/htmlcharset=UTF-8")
PrintWriter writer = resp.getWriter()
if(null != proId && !"".equals(proId)){
//返回添加购物车成功
//System.out.println("=============" + proId)
//根据商品的id查询商品
try {
Integer pId = Integer.parseInt(proId)
Product product = ps.findProductById(pId)
if(null != product){
//查询到了商品,将商品的相关参数构建一个购物明细放入到购物车
Items it = new Items()
it.setProId(product.getProId())
it.setProName(product.getProName())
it.setProPrice(product.getProPrice())
it.setProImg(product.getProImg())
//先判断session范围是否有购物车
List<Items> shopCar = (List<Items>)req.getSession().getAttribute("shopCar")
if(null == shopCar){
//购物车
shopCar = new ArrayList<Items>()
}
//将商品加入到购物车之前,判断购物车中是否已经包含了该购物明细,如果包含了,只需要修改购买的数量
if(shopCar.contains(it)){
int index = shopCar.indexOf(it)//寻找购物车中包含购物明细在购物车中位置
Items items = shopCar.get(index)//获取购物车中存在的购物明细
items.setProNum(items.getProNum()+1)
} else {
shopCar.add(it)
}
//将购物车放入到session访问
req.getSession().setAttribute("shopCar", shopCar)
//返回
writer.print(true)
} else {
writer.print(false)
}
} catch (Exception e) {
e.printStackTrace()
writer.print(false)
}
} else {
writer.print(false)
}
writer.flush()
writer.close()
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp)
}
}
后台管理servlet
package com.kaka.webimport java.io.IOException
import java.io.PrintWriter
import java.util.ArrayList
import java.util.List
import javax.mail.FetchProfile.Item
import javax.servlet.ServletException
import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
/**
* 购物车修改
* @author ITJob 远标培训
*
*/
import com.kaka.entity.Items
import com.kaka.entity.Product
import com.kaka.service.ProductService
import com.kaka.service.impl.ProductServiceImpl
public class HomeCarManager extends HttpServlet {
private static final long serialVersionUID = 1L
ProductService ps = new ProductServiceImpl()
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/htmlcharset=UTF-8")
PrintWriter writer = resp.getWriter()
//获取参数
String proId = req.getParameter("proId")
String num = req.getParameter("num")
if(null != proId && null != num
&& !"".equals(proId) && !"".equals(num)){
try {
Integer pId = Integer.parseInt(proId)
Float pNum = Float.parseFloat(num)
//根据商品的id获取对应的明细项
// 先判断session范围是否有购物车
List<Items> shopCar = (List<Items>) req.getSession().getAttribute("shopCar")
for(Items it : shopCar){
if(it.getProId()== pId){
it.setProNum(pNum)
}
}
writer.print(true)
} catch (Exception e) {
e.printStackTrace()
}
} else {
//删除的操作
try {
Integer pId = Integer.parseInt(proId)
//根据商品的id获取对应的明细项
// 先判断session范围是否有购物车
List<Items> shopCar = (List<Items>) req.getSession().getAttribute("shopCar")
Items items = null
for(Items it : shopCar){
if(it.getProId()== pId){
items = it
break
}
}
if(null != items){
shopCar.remove(items)
req.getSession().setAttribute("shopCar",shopCar)
}
writer.print(true)
} catch (Exception e) {
e.printStackTrace()
}
}
writer.flush()
writer.close()
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp)
}
}
一般有两种做法。
一种是
在页面加载完毕后,先初始化一次总金额。
在调用添加、减少方法时,获取总金额的值然后加上或减去物品*数量的值
另一种就是
同样先初始化总金额
在调用添加、减少方法后,直接重新计算所有price的值然后给总金额赋值。
```js
function updateTotalPrice() {
let count= 0
const priceNodes = document.querySelectorAll("li input[name='price']")
priceNodes.forEach(node => {
count+= parseFloat(node.value) * 100
})
document.querySelector("#totalPrice").innerHTML = count/ 100
}
```
写这篇文章的理由是 上周和一个优秀的同行的简短交流
他问我“如果待付款订单的商品没有库存了 怎么办?”
我当时的回答是“待付款订单的话 会有个继续付款按键吧,点击的时候做验证 确保订单所有商品sku大于1就对了,如果没有库存就提示用户 没有库存 可以触发到货提醒 操作”
然后 周日的时候隐约觉得我的答案没对。于是请教了 以前的leader 后台PM林先生。林先生带了我1年半时间,其智慧和卓见算是我见过的数一数二的人物。
是的 正如我觉得没对一样,我的答案错了。其实 待付款 是会锁库存的。甚至京东早期还做过 加入购物车就锁sku库存,一定时间后如果无后续操作 自动清楚锁库存 并且状态切换。
反思了自己没有仔细思考就说出了欠妥的答案,也在深夜带着问题继续思考。
然后调研了 京东 易迅 2家具被代表性的网站,发现了很多知识。
首先从购物车说起。
我的流程如下:
【京东】打开京东-登录-查看购物车-勾选了几个库存为0 无法销售的商品-点击 “去结算”-成功进入确认订单流程,并且 “提交订单”按键是亮的-点击 提交订单- 报错 返回购物车
【易迅】打开易迅-登录-查看购物车-勾选了库存为0 无法销售的商品- 点击“去结算”,咦 怎么按键是灰色的 ,旁边还写了 对不起,暂时无法结算。
是的,聪明的你 已经看出来区别了。其实这里应该做前台验证的(js)。另外购物车 还应该考虑到 所有商品当前价格 如果和加入购物车的时候发生变化,应该有提示(参考淘宝)。
接下来 思考下 锁库存问题。
翻了翻知乎,请教林先生:发现了下面3点
1 京东 曾经做过加入购物车 就锁库存,然后一定时间没操作后 清空购物车。
(是的 只是曾经做过,这样的设计师完全参考线下购物车做的。那么问题就在:“超市里面 买东西和付款 往往是 一条线时间节奏的,但是 线上是可能周一加点 周二几点 周五有钱了以前买的情况的”)
2 目前主流电商做法是这样的: 待付款 状态是需要锁库存。 然后 比如一周没有付款 就自动 取消订单。所以这也解释了 我之前回答错误的东西。其实 待付款 压根就没有 库存没有的情况好么~
也就是说 在 确认订单流程,只要提交成功 就肯定是 有库存的。京东就没提交成功 给我返回了购物车,易迅的话 直接在购物车就给我验证了。
3 其实更好的做法是为商品设置库存状态,有些商品即使sku库存小于0了 也可以进入备货期 晚几天发货。那么这样的商品 即使没货了 也是允许售卖的。叫做预售。
这样的商品 库存即使为0 ,也可以进入待付款状态,付款成功后 优先发有货的其他商品。对了在里面还设计了 母订单 付款成功后 拆分 子订单的 条件之一。这里不做过多叙述。
那么 没有备货器的商品怎么办,我就是 看中了 一个 限量版本的烤箱。 在我购物车里面。 等我准备买的时候,没货了 而且没法补货。 那么 我还能下单或者购物车结算么?
也许对这类做验证,报错 无法提交是个 简单的办法。
或许 更极点的做法 当用户提交的时候。。这部分订单会进入一个 待挽回订单。客服自动跟进 询问是否愿意 替换 替换的烤箱 然后尽可能地让用户买其他的烤箱。
今天就写到这里了,好困