• 点餐项目实现


    项目简介

    现如今,随着餐饮行业的不断扩大,消费者的年轻化,餐饮行业的点餐逐渐由线下转为线上点单,因此我们这个点餐系统就应运而生。点餐系统为餐厅增添了用户与餐厅的互动性,还可以实现更加多样化的点餐。

    本项目运用spingboot + springmvc + mybatis + vue实现了一个具有商家和普通用户的双角色点餐系统。

    功能设计

    在这里插入图片描述

    数据库表设计

    用户表

    • 主键id(自增)

    • 用户名

    • 密码

    • 身份标识

      +----------+--------------+------+-----+---------+----------------+
      | Field    | Type         | Null | Key | Default | Extra          |
      +----------+--------------+------+-----+---------+----------------+
      | id       | int(11)      | NO   | PRI | NULL    | auto_increment |
      | username | varchar(250) | YES  |     | NULL    |                |
      | password | varchar(50)  | YES  |     | NULL    |                |
      | isadmin  | int(11)      | YES  |     | NULL    |                |
      +----------+--------------+------+-----+---------+----------------+
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

    订单表

    • 订单主键ID(自增)

    • 用户ID

    • 订单创建时间

    • 状态(0:未完成; 1:已完成)

      +------------+----------+------+-----+-------------------+----------------+
      | Field      | Type     | Null | Key | Default           | Extra          |
      +------------+----------+------+-----+-------------------+----------------+
      | id         | int(11)  | NO   | PRI | NULL              | auto_increment |
      | uid        | int(11)  | YES  |     | NULL              |                |
      | createtime | datetime | YES  |     | CURRENT_TIMESTAMP |                |
      | status     | int(11)  | YES  |     | NULL              |                |
      +------------+----------+------+-----+-------------------+----------------+
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

    菜品表

    • 主键ID(自增)

    • 菜品名

    • 价格

      +-------+---------------+------+-----+---------+----------------+
      | Field | Type          | Null | Key | Default | Extra          |
      +-------+---------------+------+-----+---------+----------------+
      | id    | int(11)       | NO   | PRI | NULL    | auto_increment |
      | name  | varchar(250)  | NO   |     | NULL    |                |
      | price | decimal(10,0) | NO   |     | NULL    |                |
      +-------+---------------+------+-----+---------+----------------+
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    订单详情表(关联菜品表和订单表)

    • 订单id

    • 菜品id

      +-------+---------+------+-----+---------+-------+
      | Field | Type    | Null | Key | Default | Extra |
      +-------+---------+------+-----+---------+-------+
      | did   | int(11) | NO   |     | NULL    |       |
      | oid   | int(11) | NO   |     | NULL    |       |
      +-------+---------+------+-----+---------+-------+
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    这个表是为了处理订单表和菜品表的多对多关系,也就是中间表

    配置类

    package com.example.ordersys.config;
    
    /**
     * @author SongBiao
     * @Date 2021/1/18
     */
    //此类专门存储session中的key值
    public class AppFinal {
        //将session中的key值提取出来,单独放到一个类里面去
        //用户的session key
        public static final String USERINFO_SESSION_KEY = "USERINFO_SESSION_KEY";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    此类用于统一session存储过程中的key值

    实体类

    Dish

    package com.example.ordersys.model;
    
    import lombok.Data;
    
    import java.math.BigDecimal;
    
    /**
     * @author SongBiao
     * @Date 2021/1/18
     */
    @Data
    public class Dish {
        private int id;
        private String name;
        private BigDecimal price;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    OrderDetail

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    OrderInfo

    package com.example.ordersys.model;
    
    import lombok.Data;
    
    import java.util.Date;
    
    /**
     * @author SongBiao
     * @Date 2021/1/18
     */
    @Data
    public class OrderInfo {
        private int id;
        private int uid;
        private Date createtime;
        private int status;
        private String uname;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    UserInfo

    package com.example.ordersys.model;
    
    import lombok.Data;
    
    /**
     * @author SongBiao
     * @Date 2021/1/18
     */
    @Data
    public class UserInfo {
        private int id;
        private String username;
        private String password;
        private int isadmin;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    统一后端返回内容

    package com.example.ordersys.tools;
    
    import lombok.Data;
    
    /**
     * @author SongBiao
     * 此类用于规范controller类返回的数据类型的统一,我们定义如下类
     * @Date 2021/1/18
     */
    @Data
    public class ResponseBody<T> {
        //后端返回给前端的状态
        private int status;
        //定义参数的描述信息
        private String msg;
        //后端返回给前端的数据
        private T data;
        public ResponseBody(int status,
                            String msg,
                            T data){
            this.status = status;
            this.msg = msg;
            this.data = data;
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    用户模块

    用户注册功能

    mapper接口

     //注册方法
        public int register(UserInfo userInfo);
    
    • 1
    • 2

    xml文件

     <insert id="register">
          insert into userinfo(username,password,isadmin)
          values(#{username},#{password},0)
        insert>
    
    • 1
    • 2
    • 3
    • 4

    controller层

     /**
         * 用户注册功能,这里指的是顾客
         */
        @RequestMapping("/reg")
        public ResponseBody<Integer> register(UserInfo userInfo) {
            int data = userMapper.register(userInfo);
            return new ResponseBody<>(0, "", data);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    前端

    
                
                    
                        
                            
                                注册
                            
                            
                                
                                    
                                        
                                            
                                        
                                    
                                    
                                        
                                            
                                        
                                    
                                    
                                        
                                            
                                        
                                    
                                    
                                        
                                            注册
                                        
                                        
                                            取消
                                            
                                        
                                    
                                
                            
                        
                    
                
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    // 注册方法
                doRegister() {
                    //获取用户输入的值,通过v-model来确定如何获取值
                    let username = app.reg.name;
                    let password = app.reg.password;
                    let password2 = app.reg.password2;
                    //非空校验
                    if (username == "") {
                        alert("请先输入用户名");
                        return false;
                    }
                    if (password == "") {
                        alert("请先输入密码");
                        return false;
                    }
                    if (password2 == "") {
                        alert("请先输入确认密码");
                        return false;
                    }
                    if (password != password2) {
                        alert("两次输入的密码不一致,请核对");
                        return false;
                    }
                    //请求后端接口实现注册功能
                    jQuery.getJSON("/user/reg", {
                        "username": username,
                        "password": password
                    }, function (result) {
                        if (result != null && result.data != null && result.data > 0) {
                            alert("恭喜添加成功");
                            //每次一个用户注册信息后将信息置空
                            app.reg.name = "";
                            app.reg.password = "";
                            app.reg.password2 = "";
                            //隐藏注册窗体
                            app.reg.showRegister = false;
                        } else {
                            alert("抱歉,添加失败,请重试");
                        }
                    });
                },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    用户登录功能

    (1)验证用户的账号和密码

    (2)存储session信息

    (3)显示欢迎信息

    在这里插入图片描述

    (4)显示所有用户可以点的菜品列表
    在这里插入图片描述

    (5)刷新页面维持页面登录状态

    (6)退出登录

    验证用户账号和密码(session存储)

    session key值
    package com.example.ordersys.config;
    
    /**
     * @author SongBiao
     * @Date 2021/1/18
     */
    //此类专门存储session中的key值
    public class AppFinal {
        //将session中的key值提取出来,单独放到一个类里面去
        //用户的session key
        public static final String USERINFO_SESSION_KEY = "USERINFO_SESSION_KEY";
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    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);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    mapper层
    //登录方法
        public UserInfo login(UserInfo userInfo);
    
    • 1
    • 2
    xml
    <select id="login" resultType="com.example.ordersys.model.UserInfo">
        select * from userinfo where
        username=#{username} and password=#{password}
    select>
    
    • 1
    • 2
    • 3
    • 4
    前端
    // 登录方法
    doLogin() {
        //获取用户输入的用户名和密码,还是看v-model
        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) {
                //登录成功
                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("用户名或密码错误,请重新输入");
            }
        });
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    显示所有用户可以点的菜品列表

    显示菜品
    controller层
    @RequestMapping("/list")
    public ResponseBody<List<Dish>> getList() {
        List<Dish> data = dishMapper.getDishList();
        return new ResponseBody<>(0, "", data);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    mapper层
    //查询菜单列表
    public List<Dish> getDishList();
    
    • 1
    • 2
    xml
    <select id="getDishList" resultType="com.example.ordersys.model.Dish">
       select * from dish
    select>
    
    • 1
    • 2
    • 3
    前端
    
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    jQuery.getJSON("/dish/list", {}, function (result) {
                    if (result != null && result.data != null) {
                        app.dishes = result.data;
                    }
                });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    统计点的菜品个数以及下单总价
    
        
            
    已点 {{selectedDishCount}} 道菜, 总计 {{selectedDishPrice}} 元
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    computed: {
        // 点餐的个数
        selectedDishCount() {
            let count = 0;
            this.dishes.forEach(dish => {
                if (dish.isSelected) {
                    count++;
                }
            });
            return count;
        },
        // 计算下单的菜品总价
        selectedDishPrice() {
            let price = 0;
            this.dishes.forEach(dish => {
                if (dish.isSelected) {
                    price += dish.price;
                }
            })
            return price;
        }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    刷新页面维持用户登录状态功能
    //判断是否登录的方法
    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;
                    }
                });
            }
        });
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    注意要在最后调用这个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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    isLogin方法是判断当前登录后,刷新页面不退出登录状态,最后在app外面调用了这个isLogin方法
    原理是每次vue刷新页面会把就是会把变量如果改变了再全部变为初始值,所以如果我们不去设置isLogin方法的话,最终当我门点击刷新后,isLogin这个属性重新置为false,那么就会显示我们的导航栏了:因为!login.isLogin为true,
    在这里插入图片描述

    退出登录功能

    前端
    
        
            mdi-logout
        
        
            退出登录
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    //退出登录功能
    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("抱歉,操作失败,请重试");
                }
            });
        }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    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);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    用户下单菜品功能

    
        下单
    
    
    • 1
    • 2
    • 3
    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("请先选中菜品信息");
            }
        }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    mapper层

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

    xml

    
    <insert id="addOrder" useGeneratedKeys="true" keyProperty="id">
     insert into orderinfo(uid,status) values(#{uid},0)
    insert>
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TfIWhawh-1669814415971)(点餐项目.assets/image-20221129170348928.png)]

    
    
    <insert id="add">
        insert into orderdetail(oid,did) values
        <foreach collection="dids" item="item" separator=",">
            (#{oid},#{item})
        foreach>
    insert>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    用户查看订单详情功能

    前端

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

    
        
            mdi-cart-outline
        
        
            我的订单
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    orderList() {
        jQuery.getJSON("/order/list", {}, function (result) {
            if (result != null && result.data != null) {
                //获取订单列表成功
                app.orders = result.data;
                app.status = 'ordersPage';
            } else {
                //获取订单失败
                alert("获取订单列表失败,请重试");
            }
    
        });
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    
    
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    查看详情的代码

    
    
        
            
                
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    //计算某个订单详情的总钱数
    curOrderMoney() {
        let money = 0;
        app.curOrder.forEach(order => {
            money += order.dish.price;
        });
        return money;
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    //查看订单详情
    detail(oid) {
        jQuery.getJSON("/detail/list", {"oid": oid}, function (result) {
            if (result != null && result.data != null) {
                app.curOrder = result.data;
                //显示订单详情页面
                app.showCurOrder = true;
            }
        });
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    查看详情代码

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

    mapper接口

    显示订单代码

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

    查看详情代码

    public List<OrderDetail> getList(int oid);
    
    • 1

    xml

    显示订单代码

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

    查看详情代码

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

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    可以看到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>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    同时再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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    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 |
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

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

    商家模块

    商家登录功能

    前端

    
    
        
            
                
                    mdi-login
                
                
                    登录
                
            
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    
        
            
                
                    登录
                
                
                    
                        
                            
                                
                                
                            
                        
                        
                            
                                
                                
                            
                        
                        
                            
                                登录
                            
                            
                                取消
                                
                            
                        
                    
                
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    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("用户名或密码错误,请重新输入");
            }
        });
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    @RequestMapping("/list")
    public ResponseBody<List<Dish>> getList() {
        List<Dish> data = dishMapper.getDishList();
        return new ResponseBody<>(0, "", data);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    mapper

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

    xml

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

    保持登录状态

    前端

    //保持登录状态的方法
    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;
                        }
                    });
                }
            }
        });
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在new Vue外部调用isLogin方法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kgL3SaIs-1669814415972)(点餐项目.assets/image-20221130114507392.png)]

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    菜品添加功能

    前端

    
        
        
        
            新增菜品
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    
    
        
            
                
                    新增菜品
                
                
                    
                        
                            
                                
                            
                        
                        
                            
                                
                                
                            
                        
                        
                            
                                新增
                            
                            
                                取消
                            
                        
                    
                
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    //新增菜品
    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("抱歉:操作失败请重试!");
                    }
                });
        }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    controller

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

    mapper

    public int addDish(Dish dish);
    
    • 1

    xml

    <insert id="addDish">
        insert into dish(name,price)
         values(#{name},#{price})
    insert>
    
    • 1
    • 2
    • 3
    • 4

    菜品添加的逻辑就是每次添加完菜品到Dish表后,刷新页面,调用isLogin方法判断是否延续登录状态,然后isLogin方法重新获取后台的菜单列表,然后进行展示

    菜品删除功能

    前端

    
        删除
    
    
    • 1
    • 2
    • 3
    //删除菜品
    del(did) {
        if (confirm("确认删除?")) {
            jQuery.getJSON("/dish/del", {"id": did}, function (result) {
                if (result != null && result.data != null && result.data > 0) {
                    //删除成功
                    alert("删除成功");
                    //刷新当前界面
                    location.href = location.href;
                } else {
                    alert("抱歉,操作失败,请重试");
                }
            });
        }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    controller

    //管理员删除订单的后台方法
    @RequestMapping("/del")
    public ResponseBody<Integer> deleteDish(int id) {
        int data = dishMapper.del(id);
        return new ResponseBody<>(0, "", data);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    mapper

    public int del(int id);
    
    • 1

    xml

    <delete id="del">
        delete from dish where id=#{id}
    delete>
    
    • 1
    • 2
    • 3

    菜品删除的逻辑就是每次删除菜品后,刷新页面,调用isLogin方法判断是否延续登录状态,然后isLogin方法重新获取后台的菜单列表,然后进行展示

    获取订单列表功能

    前端

    查看所有订单
     
                    
                        mdi-cart-outline
                    
                    
                        查看订单
                    
                
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    //查看所有人的订单
                showOrder() {
                    jQuery.getJSON("/order/alllist", {},
                        function (result) {
                            if (result != null && result.data != null) {
                                app.orders = result.data;
                                // 显示订单列表窗体
                                app.status = 'ordersPage';
                            }
                        });
                },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    
    
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    修改订单状态
    //管理员修改状态
    update(oid, status) {
        //因为选中的这个状态在前端我们显示选中为true,不选中为false,所以此处需要用三元符进行一个选择
        status = status ? 1 : 0;
        jQuery.getJSON("/order/update", {"oid": oid, "status": status}, function (result) {
            if (result != null && result.data != null && result.data > 0) {
                alert("恭喜,状态修改成功");
            } else {
                alert("修改失败,请重试");
            }
        });
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    查看某个订单详情
    //查看某个订单详情
    detail(oid) {
        jQuery.getJSON("/detail/list", {"oid": oid}, function (result) {
            if (result != null && result.data != null) {
                app.curOrder = result.data;
                //显示订单详情页面
                app.showCurOrder = true;
            }
        });
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    
    
        
            
                
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    //计算某个订单详情的总价
    totalPrice() {
        let money = 0;
        app.curOrder.forEach(item => {
            money += item.dish.price;
        });
        return money;
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    controller

    查看所有订单
    //管理员查看所有人列表信息
        @RequestMapping("/alllist")
        public ResponseBody<List<OrderInfo>> getAllList(HttpServletRequest request) {
            List<OrderInfo> orderinfo = null;
            orderinfo = orderInfoMapper.getAllList();
            return new ResponseBody<>(0, "", orderinfo);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    修改订单状态
    //管理员修改用户订单的状态
    @RequestMapping("/update")
    public ResponseBody<Integer> updateStautus(int oid,int status) {
        int data = orderInfoMapper.update(oid,status);
        return new ResponseBody<>(0, "", data);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    查看某个订单详情
    @RequestMapping("/list")
    public ResponseBody<List<OrderDetail>> getList(int oid){
        List<OrderDetail> list = orderDetailMapper.getList(oid);
        return new ResponseBody<>(0,"",list);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    mapper

    查看所有订单
    //获取所有人的订单列表
    public List<OrderInfo> getAllList();
    
    • 1
    • 2
    修改订单状态
    //修改订单的状态
     public int update(int oid,int status);
    
    • 1
    • 2
    查看某个订单详情
    public List getList(int oid);
    
    • 1

    xml

    查看所有订单
    <select id="getAllList" resultType="com.example.ordersys.model.OrderInfo">
        select o.*,u.username uname from orderinfo o left join userinfo u on o.uid=u.id order by o.id desc
    select>
    
    • 1
    • 2
    • 3

    注意这里我们依旧使用到了联表查询,左连接

    修改订单状态
    <update id="update">
        update orderinfo set status=#{status} where id=#{oid}
    update>
    
    • 1
    • 2
    • 3
    查看某个订单详情
    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这块的代码逻辑跟之前用户查看订单详情功能一样

    退出登录功能

    前端

    
        
            mdi-logout
        
        
            退出登录
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    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("抱歉,操作失败,请重试");
                }
            });
        }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    SuperMap 云原生常见问题解决办法-keycloak启动异常
    Elastic基本操作
    在 Python 中使用 Selenium 按文本查找元素
    iOS Xcode15 适配:Other Linker Flags:-ld_classic
    logback1.3.x配置详解与实践
    Jenkins--部署--3.1--代码提交自动触发jenkins--方式1
    聊聊HttpClient的KeepAlive
    【小沐学QT】QT学习之OpenGL开发笔记
    TypeScript 初学总结
    实践案例丨CenterNet-Hourglass论文复现
  • 原文地址:https://blog.csdn.net/qq_41972686/article/details/128121578