购物车页面下订单
- 一、前端处理
- 1. 引入订单模态框
- 2.创建模态框对象、添加事件响应函数、定义下订单函数
- 二、后端处理
- 2.1加注解路径,加case子块
- 2.1 实现cartChkList函数
一、前端处理
1. 引入订单模态框
引入模态框组件,增加交互体验:
<div class="modal modal-lg fade" id="orderModal"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h1 class="modal-title fs-5 text-danger fw-bold">确认订单</h1><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div><div class="modal-body" id="orderContent"><table class="table align-middle"><thead><tr><th class="px-3" style="width: 120px;">餐品</th><th style="width: 300px;">描述</th><th>价格</th><th>数量</th></tr></thead><tbody id="orderList"><tr><td class="p-2"><img src="meal/pic?meal_pic=food01.jpeg" class="rounded"
style="width:100px;" /></td><td >XXX</td><td class=" fs-5 text-danger">¥50</td><td>2 </td></tr></tbody></table></div><div class="modal-footer"><div id="orderInfo" class="align-middle"></div><button id="payingBtn" class="btn btn-danger" style="display: none;"type="button" disabled><span class="spinner-border spinner-border-sm"></span><span>支付中...</span></button><button id="payBtn" type="button" class="btn btn-danger" style="display:block;">确认支付</button></div></div></div>
</div>
2.创建模态框对象、添加事件响应函数、定义下订单函数
创建模态框对象,转化为对象才可以使用模态框组件:
const orderModal = new bootstrap.Modal(document.querySelector("#orderModal"));
在购物车页面,为下订单按钮添加事件响应函数:
<button onclick="placeOrder()" type="button" class="btn btn-warning text-white" style="width:100px;">下订单
最后在购物车页面js部分,定义下订单函数,也就是实现下订单哪里调用的函数:
const placeOrder = async () => {let total = 0;let totalPrice = 0;const boxes = document.querySelectorAll(".my-box:checked");if (!boxes.length) {toast("错误!", "请选择要购买的商品!");return;}const idArgs = [...boxes].map(box => `meal_id=${box.value}`).join("&");const resp = await fetch(`cart/chklist?${idArgs}`);if (!resp.ok) {toast("错误!", "查询失败!");return;}const result = await resp.json();if (!result.success) {toast("失败!", result.message);return;}const chklist = result.data;let innerHTML = ``;for (let i = 0; i < chklist.length; i++) {const meal = chklist[i];total += meal.s_num;totalPrice += meal.s_num * meal.meal_price;innerHTML += ` <tr><td class="p-2"><img src="meal/pic?meal_pic=${meal.meal_pic}" class="rounded"style="width:100px;"/></td><td>${meal.meal_desc}</td><td class=" fs-5 text-danger">¥${meal.meal_price}</td><td>${meal.s_num}</td></tr>`;}document.querySelector("#orderList").innerHTML = innerHTML;document.querySelector("#orderInfo").innerHTML = `<span class="align-middle">已选</span><span class="text-danger align-middle">${total}</span><span class="align-middle">件,总价</span><span class="fw-bold fs-3 text-danger align-middle">¥${totalPrice}</span>`;orderModal.show();}
对一些关键代码进行解释:
-
let total = 0; 和 let totalPrice = 0;
:初始化两个变量,分别用于存储选中商品的数量总和和价格总和。 -
const boxes = document.querySelectorAll(".my-box:checked");
:使用 querySelectorAll 方法选择所有被选中的 .my-box 元素(通常是复选框),这些元素代表用户想要购买的商品。
3. if (!boxes.length) {
:检查是否有商品被选中。如果没有,显示一个错误提示,并返回,不继续执行函数。
-
const idArgs = [...boxes].map(box => meal_id=${box.value}).join("&");
:将选中的商品的 value 属性(也就是商品的ID)转换成查询字符串格式,用于后续的请求,向后端传达参数。 -
const resp = await fetch(cart/chklist?${idArgs});
:使用 fetch 方法向服务器发送请求,获取选中商品的详细信息。请求的URL包含了之前生成的查询字符串。
6. if (!resp.ok) {
:检查响应是否成功。如果不成功,显示错误提示,并返回。
-
const result = await resp.json();
:解析响应的JSON数据。 -
if (!result.success) {
:检查从服务器返回的结果是否表示成功。如果不成功,显示错误提示,并返回。 -
const chklist = result.data;
:获取服务器返回的商品列表。 -
let innerHTML = ``;
:初始化一个字符串,用于构建订单列表的HTML内容。 -
for (let i = 0; i < chklist.length; i++) {
:遍历商品列表,为每个商品构建HTML表格行。
在循环内部,构建每个商品的HTML表格行,包括商品图片、描述、单价和数量。
也就是在引入的模态框中orderList元素的静态内容如下,在循环中做成动态的,获取每一个商品:
<tr><td class="p-2"><img src="meal/pic?meal_pic=food01.jpeg" class="rounded"
style="width:100px;" /></td><td >XXX</td><td class=" fs-5 text-danger">¥50</td><td>2 </td></tr>
-
document.querySelector("#orderList").innerHTML = innerHTML;
:将构建好的HTML表格行插入为 #orderList 元素的内容,显示订单列表。 -
document.querySelector("#orderInfo").innerHTML = ...
:更新订单信息,包括已选商品的数量和总价,也是用反引号拼接模态框中orderInfo元素的内容,获取动态数据。 -
orderModal.show();
:显示订单模态框,通常是一个弹出窗口,用于让用户确认订单详情。
整个函数的流程是:检查用户是否选择了商品,获取商品信息,构建订单列表和订单信息,最后显示订单模态框供用户确认。
二、后端处理
关于购物车功能的实现,所以在CartServlet类中进行。依旧三步法,修改代码逻辑就好了。
2.1加注解路径,加case子块
增加路径 “/cart/chklist”,来调用新的方法:
@WebServlet({"/cart/list","/cart/num","/cart/del","/cart/chklist"})
相应的增加新的case子块:
case "/cart/chklist":cartChkList(req,resp);break;
最后实现调用的函数。
2.1 实现cartChkList函数
private void cartChkList(HttpServletRequest req, HttpServletResponse resp) throws IOException {{User user = (User) req.getSession().getAttribute("CurrUser");if (user == null) {MyWeb.printJson(resp, R.err("请先登录"));return;}String[] mealIds = req.getParameterValues("meal_id");if (mealIds == null || mealIds.length == 0) {MyWeb.printJson(resp, R.err("请选择商品!"));return;}String condition = Arrays.stream(mealIds).map(id -> "s.meal_id=" + id).collect(Collectors.joining(" or "));List<ShoppingCart> list = DaoCreater.currentDao().queryBeanList(ShoppingCart.class, "select s.*, m.meal_desc,m.meal_pic,m.meal_price from t_shoppingcart s join t_meal m on s.meal_id = m.meal_id where u_id = ? and (" + condition + ")", user.getU_id());MyWeb.printJson(resp, R.OK(list));}}
在函数中,代码也是异常的熟悉,主要流程是判断登录状态,判断商品选中状态,获取数据(参数),执行数据库操作,返回响应(包含数据信息)。
-
User user = (User) req.getSession().getAttribute("CurrUser");
:从HTTP请求的会话中获取当前登录的用户对象。 -
if (user == null) {
:检查用户是否已经登录。如果用户未登录,返回一个错误信息,并终止方法的执行。 -
String[] mealIds = req.getParameterValues("meal_id");
:从HTTP请求中获取名为 meal_id 的参数值,这个参数通常是由前端发送的,包含了用户想要查询的商品ID。
4. if (mealIds == null || mealIds.length == 0) {
:检查是否有商品ID被发送。如果没有,返回一个错误信息,并终止方法的执行。
-
String condition = Arrays.stream(mealIds).map(id -> "s.meal_id=" + id).collect(Collectors.joining(" or "));
:将商品ID数组转换为SQL查询条件字符串,用于后续的数据库查询。每个ID都被转换成 s.meal_id=某个ID 的形式,并且使用 or 连接,以便查询任何一个匹配的商品。关于这行代码,在上一篇文章中有更详细的解释,这里就不在重复解释了。 -
List<ShoppingCart> list = DaoCreater.currentDao().queryBeanList(ShoppingCart.class, ...);
:使用DAO(Data Access Object)模式查询数据库,获取购物车中的商品信息。查询包括购物车表 t_shoppingcart 和商品表 t_meal 的连接查询,条件是用户ID和商品ID。 -
MyWeb.printJson(resp, R.OK(list));
:将查询结果包装在一个响应对象中,并以JSON格式发送回客户端。
打这里购物车下订单操作就完成了。
用户选择商品点击下订单,会跳出模态框让用户确认,在模态框中进行支付然后加到订单页面中去,数据库中数据也会对应变化。
模态框中的操作在下一篇文章中进行…