点餐项目实现(二)

简介: 点餐项目实现(二)

刷新页面维持用户登录状态功能

//判断是否登录的方法
isLogin() {
    jQuery.getJSON("/user/islogin", {}, function (result) {
        if (result != null && result.data != null && result.data.id > 0) {
            //此时确定为登录状态,点击刷新后应该仍在主页面,而不是需要重新登录
            app.login.isLogin = true;
            //设置欢迎信息
            app.login.inputUsername = result.data.username;
            //请求后端得到菜品列表
            jQuery.getJSON("/dish/list", {}, function (result) {
                if (result != null && result.data != null) {
                    app.dishes = result.data;
                }
            });
        }
    });
},

注意要在最后调用这个isLogin方法

controller层

/**
 * 判断登录状态
 *
 * @param request
 * @return
 */
@RequestMapping("/islogin")
public ResponseBody<UserInfo> isLogin(HttpServletRequest request) {
    UserInfo user = null;
    HttpSession session = request.getSession(false);
    if (session != null && session.getAttribute(AppFinal.USERINFO_SESSION_KEY) != null) {
        user = (UserInfo) session.getAttribute(AppFinal.USERINFO_SESSION_KEY);
    }
    return new ResponseBody<UserInfo>(0, "", user);
}

isLogin方法是判断当前登录后,刷新页面不退出登录状态,最后在app外面调用了这个isLogin方法

原理是每次vue刷新页面会把就是会把变量如果改变了再全部变为初始值,所以如果我们不去设置isLogin方法的话,最终当我门点击刷新后,isLogin这个属性重新置为false,那么就会显示我们的导航栏了:因为!login.isLogin为true,

image.png

退出登录功能

前端

<v-list-item link v-on:click="logout">
    <v-list-item-action>
        <v-icon>mdi-logout</v-icon>
    </v-list-item-action>
    <v-list-item-content>
        <v-list-item-title>退出登录</v-list-item-title>
    </v-list-item-content>
</v-list-item>
//退出登录功能
logout() {
    if (confirm("是否确认退出?")) {
        jQuery.getJSON("/user/logout", {}, function (result) {
            if (result != null && result.data != null && result.data > 0) {
                //退出成功
                alert("退出成功");
                //刷新当前页面
                location.href = location.href;
            } else {
                alert("抱歉,操作失败,请重试");
            }
        });
    }
},

controller

/**
 * 退出登录
 * @param request
 * @return
 */
@RequestMapping("/logout")
public ResponseBody<Integer> logOut(HttpServletRequest request) {
    int data = 0;
    HttpSession session = request.getSession(false);
    if (session != null && session.getAttribute(AppFinal.USERINFO_SESSION_KEY) != null) {
        session.removeAttribute(AppFinal.USERINFO_SESSION_KEY);
        data = 1;
    }
    session.removeAttribute(AppFinal.USERINFO_SESSION_KEY);
    return new ResponseBody<>(0, "", data);
}

用户下单菜品功能

<v-col :cols="2">
    <v-btn color="primary" block v-on:click="dishSubmit">下单</v-btn>
</v-col>
dishSubmit() {
    if (confirm("确实提交?")) {
        let dids = "";//菜品id集合
        app.dishes.forEach(dish => {
            //选中了菜品就加1
            if (dish.isSelected) {
                dids += (dish.id + ",");
            }
        });
        if (dids != null) {
            //dids不等于null说明菜品已经下单提交,请求后端实现点餐
            //传递的参数为菜品id的集合
            jQuery.getJSON("/order/add", {"dids": dids}, function (result) {
                if (result != null && result.data != null && result.data > 0) {
                    alert("恭喜:点餐成功");
                }
            });
        } else {
            alert("请先选中菜品信息");
        }
    }
},

controller层

(1)菜品信息插入到OrderInfo表中

首先拿到下单的用户uid,从而拿到对应的订单oid

(2)中间表OrderDetail也要完成订单与菜品的关联

将之前拿到的订单oid与前端传来的菜品dids进行关联

@RequestMapping("/add")
public ResponseBody<Integer> addOrder(String dids, HttpServletRequest request) {
    int data = 0;
    //1:添加订单信息,返回一个订单ID
    //(1):要想添加订单信息,第一步是获取用户的id,因为在订单列表中,用户id是订单表的逻辑外键
    //我们是要通过用户的id来拿到对应的订单id
    // 如果当前Session没有就为null
    HttpSession session = request.getSession(false);
    if (session != null && session.getAttribute(AppFinal.USERINFO_SESSION_KEY) != null) {
        int uid = ((UserInfo) session.getAttribute(AppFinal.USERINFO_SESSION_KEY)).getId();
        //(2):将用户的id存入到OrderInfo
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUid(uid);
        //订单添加方法
        //result代表添加影响的行数
        //addOrder方法会获取到订单表的自增id
        int result = orderInfoMapper.addOrder(orderInfo);
        //result大于0说明插入成功,因为在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数
        if (result > 0) {
            //2:添加订单详情,需要用到订单ID
            data = orderDetailMapper.add(orderInfo.getId(), dids.split(","));
        }
    }
    return new ResponseBody<>(0, "", data);
}

mapper层

//添加订单
public int addOrder(OrderInfo orderInfo);
//传参的时候订单的id可能只有一个,但是菜品的id可能有多个,所以用String数组来表示
public int add(int oid,String[] dids);

xml

<!--注意此处插入时需要获取自增id,则需要使用useGeneratedKeys和keyProperty
keyProperty会将得到的主键id值赋给对应表中的主键,useGeneratedKeys为是否使用自动主键,肯定值为true-->
<insert id="addOrder" useGeneratedKeys="true" keyProperty="id">
 insert into orderinfo(uid,status) values(#{uid},0)
</insert>

注意:在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数

image.png

<!--使用foreach来遍历我们前台传过来的菜单id这个集合,将集合中的每一条数据存入到did中
oid代表订单id,订单id只有一个,但是菜单id可以有很多个,因为每个菜品都对应一个id -->
<!--因为我们要往did中插入的菜单id是一个集合,所以我们可以使用foreach循环,collection是
集合,我们放入的是add方法的参数:数组dids,item代表列,separator代表分隔符,意思就是
values后面是(),(),()这样的形式-->
<insert id="add">
    insert into orderdetail(oid,did) values
    <foreach collection="dids" item="item" separator=",">
        (#{oid},#{item})
    </foreach>
</insert>

用户查看订单详情功能

前端

显示用户自身订单状态代码

<v-list-item link v-on:click="orderList">
    <v-list-item-action>
        <v-icon>mdi-cart-outline</v-icon>
    </v-list-item-action>
    <v-list-item-content>
        <v-list-item-title>我的订单</v-list-item-title>
    </v-list-item-content>
</v-list-item>
orderList() {
    jQuery.getJSON("/order/list", {}, function (result) {
        if (result != null && result.data != null) {
            //获取订单列表成功
            app.orders = result.data;
            app.status = 'ordersPage';
        } else {
            //获取订单失败
            alert("获取订单列表失败,请重试");
        }
    });
},
<!-- 个人订单列表 -->
<v-simple-table v-show="status == 'ordersPage' && login.isLogin">
    <template v-slot:default>
        <thead>
        <tr>
            <th class="text-left">序号</th>
            <th class="text-left">状态</th>
            <th class="text-left">时间</th>
            <th class="text-left">详情</th>
        </tr>
        </thead>
        <tbody>
        <tr v-for="order in orders">
            <td>{{order.id}}</td>
            <!--三元运算符在vue中可以使用-->
            <td>{{order.status==0?'未完成':'已完成'}}</td>
            <td>{{order.createtime}}</td>
            <td>
                <v-btn color='primary' v-on:click="detail(order.id)">查看详情</v-btn>
            </td>
        </tr>
        </tbody>
    </template>
</v-simple-table>

查看详情的代码:

<!-- 某个订单的详情 -->
<v-row justify="center">
    <v-dialog v-model="showCurOrder" persistent max-width="600px">
        <v-simple-table>
            <template v-slot:default>
                <thead>
                <tr>
                    <th class="text-left">菜品</th>
                    <th class="text-left">价格</th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="dish in curOrder">
                    <td>{{dish.dish.name}}</td>
                    <td>{{dish.dish.price}}</td>
                </tr>
                <tr>
                    <td>总金额:{{curOrderMoney()}}</td>
                    <td>
                        <v-btn color="primary" v-on:click="showCurOrder = false">关闭</v-btn>
                    </td>
                </tr>
                </tbody>
            </template>
        </v-simple-table>
    </v-dialog>
</v-row>
//计算某个订单详情的总钱数
curOrderMoney() {
    let money = 0;
    app.curOrder.forEach(order => {
        money += order.dish.price;
    });
    return money;
},
//查看订单详情
detail(oid) {
    jQuery.getJSON("/detail/list", {"oid": oid}, function (result) {
        if (result != null && result.data != null) {
            app.curOrder = result.data;
            //显示订单详情页面
            app.showCurOrder = true;
        }
    });
},

controller

显示订单代码

/**
 * 用户获取订单列表
 *
 * @return
 */
@RequestMapping("/list")
public ResponseBody<List<OrderInfo>> getList(HttpServletRequest request) {
    List<OrderInfo> orderinfo = null;
    HttpSession session = request.getSession(false);
    int uid = 0;
    if (session != null && session.getAttribute(AppFinal.USERINFO_SESSION_KEY) != null) {
        //获取用户id
        uid = ((UserInfo) session.getAttribute(AppFinal.USERINFO_SESSION_KEY)).getId();
        orderinfo = orderInfoMapper.list(uid);
    }
    return new ResponseBody<>(0, "", orderinfo);
}

查看详情代码

@RequestMapping("/list")
public ResponseBody<List<OrderDetail>> getList(int oid){
    List<OrderDetail> list = orderDetailMapper.getList(oid);
    return new ResponseBody<>(0,"",list);
}

mapper接口

显示订单代码

//获取订单列表
public List<OrderInfo> list(int uid);

查看详情代码

public List<OrderDetail> getList(int oid);

xml

显示订单代码

<select id="list" resultType="com.example.ordersys.model.OrderInfo">
   select * from orderinfo where uid=#{uid}
</select>

查看详情代码


这里要注意,先来看订单详情表的实体类设计:


package com.example.ordersys.model;
import lombok.Data;
/**
 * @author SongBiao
 * @Date 2021/1/18
 */
@Data
public class OrderDetail {
    private int oid;
    private int did;
    private Dish dish;
}

可以看到OrderDetail实体类中还有一个Dish对象,但是注意这个对象在我们表中是没有的,原因是当我们用户查看订单详情的时候,需要查看菜品的详细信息以及总价格,我们直接再这里定义一个对象后,后期通过连表查询,然后将查询的结果包装成一个Dish类对象即可。那么我们再xml中就需要使用resultMap来指定对应的映射关系,

首先再DishMapper.xml中指定dish表对应的实体类的映射关系;


<resultMap id="BaseResultMap" type="com.example.ordersys.model.Dish">
    <id column="id" property="id"></id>
    <result column="name" property="name"></result>
    <result column="price" property="price"></result>
</resultMap>

同时再OrderDetailMapper.xml中指定OrderDetail实体类的映射关系,注意需要使用到association属性来表示一对一的关系,因为后期我们使用连表查询中,orderdetail与dish进行左连接后,查询出来的记录是一行一行的,也就是说一个订单编号对应一个菜品名称,而不是多个


<resultMap id="BaseResultMap" type="com.example.ordersys.model.OrderDetail">
        <result property="did" column="did"></result>
        <result property="oid" column="oid"></result>
        <association property="dish" columnPrefix="d_" resultMap="com.example.ordersys.mapper.DishMapper.BaseResultMap">
        </association>
    </resultMap>
<select id="getList" resultMap="BaseResultMap">
    select o.*,d.name d_name,d.price d_price from orderdetail o left join dish d on o.did=d.id
   where o.oid=#{oid}
</select>
mysql> select o.*,d.name d_name,d.price d_price from orderdetail o left join dish d on o.did=d.id
    ->    where o.oid=16;
+-----+-----+--------+---------+
| did | oid | d_name | d_price |
+-----+-----+--------+---------+
|   3 |  16 | 红烧肉 |      30 |
|   4 |  16 | 茄子   |      25 |

这里就可以显示出订单编号为16的用户点了两个菜,其菜品编号为3,4,菜品名称为红烧肉,茄子,价格分别为30,25

注意这里我们使用了连表查询(左连接)

商家模块

商家登录功能

前端

<!-- 左侧导航 -->
<v-navigation-drawer v-model="drawer" app>
    <v-list dense v-show="!login.isLogin">
        <v-list-item link v-on:click="login.showLoginDialog=true">
            <v-list-item-action>
                <v-icon>mdi-login</v-icon>
            </v-list-item-action>
            <v-list-item-content>
                <v-list-item-title>登录</v-list-item-title>
            </v-list-item-content>
        </v-list-item>
    </v-list>
<v-row justify="center">
    <v-dialog v-model="login.showLoginDialog" persistent max-width="400px">
        <v-card>
            <v-card-title>
                <span class="headline">登录</span>
            </v-card-title>
            <v-card-text>
                <v-container>
                    <v-row>
                        <v-col cols="12" sm="12">
                            <v-text-field label="用户名*" v-model="login.inputUsername" required>
                            </v-text-field>
                        </v-col>
                    </v-row>
                    <v-row>
                        <v-col cols="12" sm="12">
                            <v-text-field label="密码*" v-model="login.inputPassword" required>
                            </v-text-field>
                        </v-col>
                    </v-row>
                    <v-row>
                        <v-col cols="12" sm="6">
                            <v-btn color="primary" block v-on:click="userLogin">登录</v-btn>
                        </v-col>
                        <v-col cols="12" sm="6">
                            <v-btn color="primary" block v-on:click="login.showLoginDialog=false">取消
                            </v-btn>
                        </v-col>
                    </v-row>
                </v-container>
            </v-card-text>
        </v-card>
    </v-dialog>
</v-row>
userLogin() {
    let username = app.login.inputUsername;
    let password = app.login.inputPassword;
    //非空校验
    if (username == "") {
        alert("请输入用户名");
        return false;
    }
    if (password == "") {
        alert("请输入密码");
        return false;
    }
    //访问后端接口,验证用户信息
    jQuery.getJSON("/user/login", {
        "username": username,
        "password": password
    }, function (result) {
        if (result != null && result.data != null && result.data.id > 0) {
            //等于1,说明是管理员登录
            if (result.data.isadmin == 1) {
                //登录成功
                alert("登录成功!");
                //登录成功后,隐藏左侧未登录之前的导航,并显示欢迎信息
                //因为两者的v-show是一样的
                app.login.isLogin = true;
                //去掉登录时的窗口,还是查看v-model
                app.login.showLoginDialog = false;
                //请求后端得到菜品列表
                jQuery.getJSON("/dish/list", {}, function (result) {
                    if (result != null && result.data != null) {
                        app.dishes = result.data;
                    }
                });
            } else {
                alert("非法操作,权限不足");
            }
        } else {
            //用户名或密码错误,请重新输入
            alert("用户名或密码错误,请重新输入");
        }
    });
},

controller

//登录功能
@RequestMapping("/login")
public ResponseBody<UserInfo> login(UserInfo userInfo, HttpServletRequest request) {
    UserInfo user = userMapper.login(userInfo);
    //登录后将信息存入session当中
    if (user != null && user.getId() > 0) {
        HttpSession session = request.getSession();
        session.setAttribute(AppFinal.USERINFO_SESSION_KEY,
                user);
    }
    return new ResponseBody<>(0, "", user);
}
@RequestMapping("/list")
public ResponseBody<List<Dish>> getList() {
    List<Dish> data = dishMapper.getDishList();
    return new ResponseBody<>(0, "", data);
}

mapper

//登录方法
public UserInfo login(UserInfo userInfo);
//查询菜单列表
public List<Dish> getDishList();

xml

<select id="getDishList" resultType="com.example.ordersys.model.Dish">
   select * from dish
</select>
<select id="login" resultType="com.example.ordersys.model.UserInfo">
    select * from userinfo where
    username=#{username} and password=#{password}
</select>

保持登录状态

前端

//保持登录状态的方法
isLogin() {
    jQuery.getJSON("/user/islogin", {}, function (result) {
        if (result != null && result.data != null && result.data.id > 0) {
            if (result.data.isadmin == 1) {
                //等于1是超级管理员
                //此时确定为登录状态,点击刷新后应该仍在主页面,而不是需要重新登录
                app.login.isLogin = true;
                //设置欢迎信息
                app.login.inputUsername = result.data.username;
                //请求后端得到菜品列表
                jQuery.getJSON("/dish/list", {}, function (result) {
                    if (result != null && result.data != null) {
                        app.dishes = result.data;
                    }
                });
            }
        }
    });
},

在new Vue外部调用isLogin方法

controller

@RequestMapping("/islogin")
public ResponseBody<UserInfo> isLogin(HttpServletRequest request) {
    UserInfo user = null;
    HttpSession session = request.getSession(false);
    if (session != null && session.getAttribute(AppFinal.USERINFO_SESSION_KEY) != null) {
        user = (UserInfo) session.getAttribute(AppFinal.USERINFO_SESSION_KEY);
    }
    return new ResponseBody<UserInfo>(0, "", user);
}

菜品添加功能

前端

<v-row v-show="status == 'dishesPage' && login.isLogin">
    <v-col :col="11">
    </v-col>
    <v-col :cols="2">
        <v-btn color="primary" block v-on:click="showAddDish = true">新增菜品</v-btn>
    </v-col>
</v-row>
<!-- 新增菜品 -->
<v-row justify="center">
    <v-dialog v-model="showAddDish" persistent max-width="600px">
        <v-card>
            <v-card-title>
                <span class="headline">新增菜品</span>
            </v-card-title>
            <v-card-text>
                <v-container>
                    <v-row>
                        <v-col cols="12" sm="12">
                            <v-text-field label="菜品名*" v-model="newDish.name" required></v-text-field>
                        </v-col>
                    </v-row>
                    <v-row>
                        <v-col cols="12" sm="12">
                            <v-text-field label="价格(元)*" v-model="newDish.price" required>
                            </v-text-field>
                        </v-col>
                    </v-row>
                    <v-row>
                        <v-col cols="12" sm="6">
                            <v-btn color="primary" block v-on:click="addDish()">新增</v-btn>
                        </v-col>
                        <v-col cols="12" sm="6">
                            <v-btn color="primary" block v-on:click="showAddDish = false">取消</v-btn>
                        </v-col>
                    </v-row>
                </v-container>
            </v-card-text>
        </v-card>
    </v-dialog>
</v-row>
//新增菜品
addDish() {
    if (confirm("确认是否提交?")) {
        let name = app.newDish.name;
        let price = app.newDish.price;
        //
        if (name == "") {
            alert("请先输入菜品名称!");
            return false;
        }
        if (price == "" || price == 0) {
            alert("请先输入价格!");
            return false;
        }
        jQuery.getJSON("/dish/add", {"name": name, "price": price},
            function (result) {
                if (result != null && result.data != null && result.data > 0) {
                    //data>0表示添加成功
                    alert("恭喜:菜品添加成功!");
                    //每次添加完菜品后自动刷新
                    location.href = location.href;
                } else {
                    alert("抱歉:操作失败请重试!");
                }
            });
    }
},

controller

//管理员添加菜品的后台方法
@RequestMapping("/add")
public ResponseBody<Integer> addDish(Dish dish) {
    int data = dishMapper.addDish(dish);
    return new ResponseBody<>(0, "", data);
}

mapper

public int addDish(Dish dish);


相关文章
|
7月前
|
小程序 API
点餐小程序实战教程09-订单功能开发
点餐小程序实战教程09-订单功能开发
|
SQL 安全 JavaScript
基于JavaWeb的电影院在线选座订票管理系统
基于JavaWeb的电影院在线选座订票管理系统
702 0
基于JavaWeb的电影院在线选座订票管理系统
|
7月前
|
小程序 JavaScript Java
奶茶点餐|奶茶店自助点餐系统|基于微信小程序的饮品点单系统的设计与实现(源码+数据库+文档)
奶茶点餐|奶茶店自助点餐系统|基于微信小程序的饮品点单系统的设计与实现(源码+数据库+文档)
394 1
|
6月前
|
JavaScript Java 测试技术
基于小程序的民宿预订系统(2024全新定制)
基于小程序的民宿预订系统(2024全新定制)
36 0
|
7月前
|
搜索推荐 JavaScript 前端开发
基于SSM个性化点餐配送系统的设计与实现
基于SSM个性化点餐配送系统的设计与实现
75 1
|
7月前
|
小程序 JavaScript Java
点餐|外卖订餐小程序|基于微信小程序的外卖订餐系统设计与实现(源码+数据库+文档)
点餐|外卖订餐小程序|基于微信小程序的外卖订餐系统设计与实现(源码+数据库+文档)
208 0
|
7月前
|
SQL Java Go
java项目超市购物管理系统
java项目超市购物管理系统
|
小程序
【带源码】基于微信小程序的旅游订票旅游预订小程序酒店预订项目
重要的事情说三遍,可白嫖,可白嫖,可白嫖!!! 源码下载链接:docs.qq.com/doc/DYm5DSlBWZEplalBP 随着移动互联网的迅速发展,人们对于旅游信息获取和旅行订票的需求也逐渐增加。传统的旅游指南和订票方式往往不够便捷和灵活,而微信作为一种广泛使用的社交媒体平台,拥有巨大的用户群体和强大的社交属性,成为了传递信息和服务的重要渠道。
|
7月前
|
小程序 算法 数据可视化
点餐小程序实战教程07-点餐功能开发
点餐小程序实战教程07-点餐功能开发
|
存储 小程序 前端开发
【易售小程序项目】私聊功能uniapp界面实现 (买家、卖家 沟通商品信息)【后端基于若依管理系统开发】
【易售小程序项目】私聊功能uniapp界面实现 (买家、卖家 沟通商品信息)【后端基于若依管理系统开发】
174 0