在上一篇文章中,我们完成了在购物车页面的下订单操作,选取商品进行下订单后会弹出订单页面的模态框,在模态框中我们还要对商品进行确认,进行确认支付,完成支付,当然在这里的支付只是页面效果达成的,在当前下项目中我们并没有设计支付板块。
一、前端处理
首先是在订单的模态框中对确认支付
元素进行添加点击事件响应:
<button id="payBtn" type="button" class="btn btn-danger" style="display: block;"
onclick="confirmOrder()" >确认支付</button>
下一步自然而然也就是实现点击事件中调用的函数:
const confirmOrder = async () => {
const boxes = document.querySelectorAll(".my-box:checked");
if (boxes.length == 0) {
toast("错误", "请选择商品!");
return;
}
const idArgs = [...boxes].map(box => `meal_id=${box.value}`).join("&");
document.querySelector('#payingBtn').style.display = 'block';
document.querySelector('#payBtn').style.display = 'none';
const resp = await fetch(`cart/order?${idArgs}`);
await new Promise((resolve => setTimeout(resolve, 2000)));
if (!resp.ok) {
toast("失败!", "下订单失败!");
document.querySelector('#payingBtn').style.display = 'none';
document.querySelector('#payBtn').style.display = 'block';
return;
}
const result = await resp.json();
if(!result.success)
{
toast("失败!", result.message);
document.querySelector('#payingBtn').style.display = 'none';
document.querySelector('#payBtn').style.display = 'block';
return;
}
getList();
toast("成功!", "下订单成功!");
document.querySelector('#payingBtn').style.display = 'none';
document.querySelector('#payBtn').style.display = 'block';
orderModal.hide();
await new Promise(resolve => setTimeout(resolve, 2000));
location.href = 'order.html';
}
在这里我们对函数部分代码进行解释:
-
const confirmOrder = async () => { ... }
:定义了一个异步函数 confirmOrder。 -
const boxes = document.querySelectorAll(".my-box:checked");
:使用 querySelectorAll 获取所有选中的 .my-box 类的复选框。
if (boxes.length == 0) { ... }
:检查是否有复选框被选中。如果没有,显示错误提示并返回。 -
const idArgs = [...boxes].map(box => meal_id=${box.value}).join("&");
:将选中的复选框的值映射为查询参数字符串,用于构建请求 URL。之前解释的比较详细,若还是不懂,就会看吧,懒得再打一遍了。 -
document.querySelector('#payingBtn').style.display = 'block';
:显示支付按钮。 -
document.querySelector('#payBtn').style.display = 'none';
:隐藏下单按钮。 -
const resp = await fetch(cart/order?${idArgs});
:fetch函数向服务器发送一个带有选中商品 ID 的 GET 请求。 -
await new Promise((resolve => setTimeout(resolve, 2000)));
:等待 2 秒,可能是为了模拟加载过程。 -
if (!resp.ok) { ... }
:检查响应是否成功。如果不成功,显示失败提示并返回。 -
const result = await resp.json();
:解析响应为 JSON 格式。 -
if(!result.success) { ... }
:检查响应的 JSON 数据中的 success 字段。如果不是成功状态,显示失败提示并返回。 -
getList();
:调用 getList 函数,重新刷新商品列表。 -
toast("成功!", "下订单成功!");
:显示成功提示。 -
document.querySelector('#payingBtn').style.display = 'none';
:隐藏支付按钮。 -
document.querySelector('#payBtn').style.display = 'block';
:显示下单按钮。 -
orderModal.hide();
:隐藏订单模态框。 -
await new Promise(resolve => setTimeout(resolve, 2000));
:再次等待 2 秒。 -
location.href = 'order.html';
:跳转到订单页面。
主要功能是处理用户在网页上选择商品并提交订单的过程。它包括了错误处理、用户反馈、页面跳转等操作。
将数据通过请求发送给后端进行数据库操作。
二、后端处理
还是在CartServlet类中进行确认订单的操作
- 添加新的注解路径:“/cart/order”
@WebServlet({
"/cart/list",
"/cart/num",
"/cart/del",
"/cart/chklist",
"/cart/order"
})
- 根据路径新增case子块调用函数:
case "/cart/order":
cartOrder(req, resp);
break;
- 最后实现函数:
private void cartOrder(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 -> "meal_id=" + id).collect(Collectors.joining("or"));
Date now = new Date();
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (int i = 0; i < mealIds.length; i++) {
DaoCreater.currentDao().update("insert into t_order(u_id,meal_id,o_num,o_date,o_status) " +
"select '" + user.getU_id() + "', meal_id, s_num, '" + fmt.format(now) + "', 0 from t_shoppingcart where meal_id = ? ", mealIds[i]);
DaoCreater.currentDao().update("delete from t_shoppingcart where u_id =? and (" + condition + ")",user.getU_id());
MyWeb.printJson(resp,R.OK());
}
}
在函数中,重复的是判断用户信息是否登录,以及判断用户是否选择有商品。
所以就不在重复解释这部分的代码了,直接对核心的部分进行解释:
4. String condition = Arrays.stream(mealIds).map(id -> "meal_id=" + id).collect(Collectors.joining("or"));
:将用户选择的商品 ID 转换为 SQL 查询条件字符串,用于后续的数据库操作。
-
Date now = new Date();
:创建一个表示当前日期和时间的 Date 对象。 -
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
:创建一个 SimpleDateFormat 对象,用于将日期格式化为字符串。其中:
yyyy
:表示四位年份,如 2024。
MM
:表示两位月份,01 表示一月,12 表示十二月。
dd
:表示两位的天数,01 到 31。
HH
:表示两位的小时数,24 小时制,00 到 23。
mm
:表示两位的分钟数,00 到 59。
ss
:表示两位的秒数,00 到 59。
例如,如果你有一个 Date 对象表示的是 2024 年 5 月 28 日下午 3 点 30 分 45 秒,使用"yyyy-MM-dd HH:mm:ss"
格式,格式化后的结果将是 “2024-05-28 15:30:45”。 -
for (int i = 0; i < mealIds.length; i++) { ... }
:遍历用户选择的所有商品 ID。 -
DaoCreater.currentDao().update(...)
:调用 DAO 层的方法,将用户选择的商品从购物车插入到订单表中。这里使用了预处理语句来防止 SQL 注入。 -
DaoCreater.currentDao().update(...)
:在同一个循环中,删除用户购物车中已下单的商品。 -
MyWeb.printJson(resp,R.OK());
:在所有操作完成后,返回一个成功的 JSON 响应。
最后这段代码的主要逻辑是:
- 验证用户是否登录。
- 验证用户是否选择了商品。
- 将用户选择的商品从购物车转移到订单表。
- 删除购物车中已转移的商品。
- 返回操作结果。