商城项目 —— 订单的生成功能(vue实现)
首先理一下思路,订单功能应该是商场项目中最复杂的功能之一。
关键:其实还是一步一步想清楚了,其实分开慢慢来,还是可以做出来的。
首先我们购物的的顺序,是先将商品添加至购物车,然后在购物车中选中某一件(某一些)商品,然后提交到下一步,下一步是确认订单的页面,主要包括你要购买的商品的信息以及你的地址等信息然后填写到数据库中,随之要也要删掉前面购物车中的数据,然后生成订单。
直接看实际列子:
购物车的样子
购物车图1
然后我们要选中商品提交,那么我们勾选的商品肯定要做上标记,用它的id即可
//mm是一个数组,然后选中某一件商品,我就把它的id赋给value
<input v-model="mm" type="checkbox" :value="s.ciid">
<div class="bottom">
<a href="cart.html" id="clear" class="clear">清空购物车</a>
//直接将数组的值传过去
//pay.html?ciid='+mm 进入pay页面然后带着前面选中的商品的id信息
<a :href="'pay.html?ciid='+mm" id="submit" class="submit">提交订单</a>
</div>
拿到这个id那么下一步就好办了,我们要先渲染出确认订单的界面:
那么我们看下servlet端怎么写:
/**
* 将购物车中的商品勾选 然后进入确认订单页面
* 渲染出前面勾选的商品信息
* @param req
* @param resp
* @throws IOException
* @throws BizException
* @throws SQLException
*/
@SuppressWarnings("null")
public void getcheckpro(HttpServletRequest req, HttpServletResponse resp) throws IOException, SQLException, BizException {
//首先获取到ciid的字符串值
String ciid=req.getParameter("ciid");
//判断该字符串中是否有,如果有证明选中的最少是两个或多个商品
//如果没有则表示 只有一样商品选中
if(ciid.contains(",")) {
//将字符串分割 并生成一个新的数组 用于存放前面的id值
String[] ss=ciid.split(",");
List<Map<String, Object>> list=null;
//通过id个数循环 确保每一个编号的商品能被查到
for(int i=0;i<ss.length;i++) {
//第一个id先直接调用方法 吧list装好
if(i>=1) {
list.addAll(od.querycheckpro(ss[i]));
}else {
list = od.querycheckpro(ss[i]);
}
}
write(resp, list);
}else { //只选中一件商品 直接返回该商品信息
try {
write(resp,od.querycheckpro(ciid));
} catch (IOException |SQLException|BizException e) {
e.printStackTrace();
write(resp, "更新失败 原因:"+e.getMessage());
}
}
}
然后我们看下dao层:
/**
* 将购物车中的商品勾选 然后进入确认订单页面
* 渲染出前面勾选的商品信息
* @param ciid
* @return
* @throws SQLException
* @throws BizException
*/
public List<Map<String, Object>> querycheckpro(String ciid) throws SQLException, BizException{
Utils.checkNull(ciid, "选中商品的id不能为空");
String sql="select * from cart a LEFT JOIN product b on a.pid=b.pid where a.ciid=?";
return DBHelper.selectListMap(sql, ciid);
}
至此如何将你想购买的商品,添加到确认订单就完成了,看下效果:
然后我们就是要把这个页面的商品生成到一个订单上去
包括了两个表,我们先看下表的结构:
订单表:(orders表)
订单明细表:(orderitem表)
那么要完成订单功能,对这两个表的操作就至关重要了
首先我们考虑:
如何生成orders表
我们看orders的表结构不难发现,其实orders表的的字段我们都是可以直接获取到的,但是这个oid我们如何传给orderitem表呢,
请看:(cao层)
/**
* 新增订单
* @param total
* @param addr
* @param phone
* @param uid
* @param name
* @throws SQLException
*/
public Object createorders(String total,String addr,String phone,int uid,String name) throws SQLException {
String sql="insert into orders values(null,?,now(),1,?,?,?,?)";
java.sql.Connection conn=DBHelper.getConnection();
// /*****/打上这个标志的这几行就是关键了 直接获取到自增键 然后返回
PreparedStatement ps=conn.prepareStatement(sql,
PreparedStatement.RETURN_GENERATED_KEYS);/*****/
ps.setObject(1, total);
ps.setObject(2, addr);
ps.setObject(3, phone);
ps.setObject(4, uid);
ps.setObject(5, name);
ps.executeUpdate();
ResultSet rs=ps.getGeneratedKeys();/*****/
rs.next();
// rs.getObject(1) 表示的就是生成够一个订单的oid值
return rs.getObject(1);/*****/
}
/**
* 新增订单明细
* @param oid
* @param uid
* @param ciid
* @throws SQLException
*/
public void createorderitem(Object oid,int uid,String ciid) throws SQLException {
//生成orderitem数据 其中values用一个查询语句代替
//insert的时候 它的values值可以用一个查询语句来充当 可以自己去试一下
String sql="INSERT INTO orderitem SELECT\n" +
" NULL,\n" +
" count,\n" +
" (a.count * b.shop_price),\n" +
" b.pid,\n" +
" ?\n" +
"FROM\n" +
" cart a\n" +
"LEFT JOIN product b ON a.pid = b.pid\n" +
"WHERE\n" +
" uid = ?\n" +
"AND ciid = ?";
DBHelper.update(sql, oid,uid,ciid);
}
/**
/**
* 删除购物车中前面选中的商品记录
* @param uid
* @param ciid
* @throws SQLException
*/
public void deletecart(int uid,String ciid) throws SQLException {
String sql="DELETE from cart where uid=? and ciid=?";
DBHelper.update(sql, uid,ciid);
}
然后我们看biz层:
为什么这里用一个static?
为什么生成订单和生成订单明细要分成两个方法写?
看下面的servelt层你就知道了:
package com.yc.Biz;
import java.sql.SQLException;
import com.yc.Dao.OrderDao;
import com.yc.common.biz.BizException;
import com.yc.common.util.Utils;
public class OrderBiz {
private OrderDao od = new OrderDao();
// 为什么这里用一个static?
// 为什么生成订单和生成订单明细要分成两个方法写?
static Object oid;
/**
* 新增订单
*
* @param total
* @param addr
* @param phone
* @param uid
* @param name
* @throws BizException
*/
public void addorders(String total, String addr, String phone, int uid, String name) throws BizException {
Utils.checkNull(total, "总金额不能为空");
Utils.checkNull(addr, "地址不能为空");
Utils.checkNull(phone, "电话不能为空");
try {
oid=od.createorders(total, addr, phone, uid, name);
} catch (SQLException e) {
throw new BizException("系统繁忙 请稍后再试");
}
}
/**
* 新增订单明细
* @param uid
* @param name
* @param ciid
* @throws BizException
*/
public void addorderitems( int uid, String name,String ciid) throws BizException {
try {
od.createorderitem(oid, uid, ciid);
od.deletecart(uid, ciid);
} catch (SQLException e) {
throw new BizException("系统繁忙 请稍后再试");
}
}
}
servlet端的方法:
问题:
为什么生成订单和生成订单明细要分成两个方法写
原因是:
因为我们是要取到数组的id值 只能循环
如果写在一个方法中,
那么生成订单也会循环
从而生成多个订单 所以我们就要分开写
这样的话 我们第一个问题为什么要用静态的 就得到了解释
因为我们的
oid
是从
addorders中来的****,而我们addorderitems方法要执行就必须得到这个oid的值
所以我们就通过一个static将其设置为全局
只要先调用了addorders方法我们就能取到oid的值啦
/**
* 出单
* 添加订单,订单明细及删除购物车中选中的商品
* @param req
* @param resp
* @throws IOException
* @throws SQLException
* @throws BizException
*/
public void orderoption(HttpServletRequest req, HttpServletResponse resp) throws IOException, SQLException, BizException {
String ciid=req.getParameter("ciid");
String total=req.getParameter("totalmoney");
String addr=req.getParameter("addr");
String phone=req.getParameter("phone");
int uid=(Integer) req.getSession().getAttribute("uid");
String name=(String) req.getSession().getAttribute("name");
if(ciid.contains(",")) {
String[] ss=ciid.split(",");
try {
//下面这三行仔细看:
//第一行添加订单 没问题
ob.addorders(total, addr, phone, uid, name);
//第二行 循环数组 目的是取到每一个商品然后添加到明细中
for(int i=0;i<ss.length;i++) {
//第三行 直接调用生成订单明细方法
ob.addorderitems(uid, name, ss[i]);
}
//所以为什么生成订单和生成订单明细要分成两个方法写
//原因是: 因为我们是要取到数组的id值 只能循环 如果写在一个方法中,那么生成订单也会循环
//从而生成多个订单 所以我们就要分开写
//这样的话 我们第一个问题为什么要用静态的 就得到了解释
//因为我们的oid是从addorders中来的,而我们addorderitems方法要执行就必须得到这个oid的值
//所以我们就通过一个static将其设置为全局 只要先调用了addorders方法我们就能取到oid的值啦
write(resp, "成功");
}catch(IOException |BizException e) {
write(resp, "失败 原因:"+e.getMessage());
}
}else { //只有一件商品 那就直接调用两个方法就行了 但是要注意先调用addorders方法
try {
ob.addorders(total, addr, phone, uid, name);
ob.addorderitems(uid, name, ciid);
write(resp,"成功");
} catch (IOException |BizException e) {
e.printStackTrace();
write(resp, "失败 原因:"+e.getMessage());
}
}
}
而我们的html那边呢只要用一个v-model将一些需要的参数通过append方法传给服务器就行了,一些相关代码贴出来看看吧
data:{
listproduct:[],
ciid:"",
total:0,
addr:"",
phone:"",
name:"",
},
methods:{
Tj(){
var p=new URLSearchParams();
p.append("totalmoney",this.total);
p.append("name",this.name);
p.append("phone",this.phone);
p.append("addr",this.addr);
axios.post("../cart.do?op=orderoption&ciid="+this.ciid,p).then(res=>{
if(res.data=="成功"){
alert(res.data);
location.href="cart.html";
}else{
alert(res.data);
}
});
}
至此整个的一个订单功能就算完成了,我们将我们想买的商品添加到确认订单,然后点击确定付款就可以生成订单和订单明细和删除购物车中选中商品的记录啦
代码没全,但是思路应该是讲清楚了,关键是这个思路,一步一步的比较重要,当然可能也许会有更好更简洁的方法,这只是我在开发中的实现方式,欢迎大家交流~~~