点餐项目实现(一)

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

目录

项目简介

功能设计

数据库表设计

用户表

订单表

菜品表

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

配置类

实体类

Dish

OrderDetail

OrderInfo

UserInfo

统一后端返回内容

用户模块

用户注册功能

mapper接口

xml文件

controller层

前端

用户登录功能

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

session key值

controller层

mapper层

xml

前端

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

显示菜品

controller层

mapper层

xml

前端

统计点的菜品个数以及下单总价

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

退出登录功能

前端

controller

用户下单菜品功能

controller层

mapper层

xml

用户查看订单详情功能

前端

controller

mapper接口

xml

商家模块

商家登录功能

前端

controller

mapper

xml

保持登录状态

前端

controller

菜品添加功能

前端

controller

mapper

xml

菜品删除功能

前端

controller

mapper

xml

获取订单列表功能

前端

查看所有订单

修改订单状态

查看某个订单详情

controller

查看所有订单

修改订单状态

查看某个订单详情

mapper

查看所有订单

修改订单状态

查看某个订单详情

xml

查看所有订单

修改订单状态

查看某个订单详情

退出登录功能

前端

controller

项目简介

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


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

功能设计

image.png

数据库表设计

用户表

  • 主键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    |                |
+----------+--------------+------+-----+---------+----------------+

订单表

  • 订单主键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              |                |
+------------+----------+------+-----+-------------------+----------------+

菜品表

  • 主键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    |                |
+-------+---------------+------+-----+---------+----------------+

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

  • 订单id
  • 菜品id
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| did   | int(11) | NO   |     | NULL    |       |
| oid   | int(11) | NO   |     | NULL    |       |
+-------+---------+------+-----+---------+-------+

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

配置类

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";
}

此类用于统一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;
}

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;
}

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;
}

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;
}

统一后端返回内容

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;
    }
}

用户模块

用户注册功能

mapper接口

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

xml文件

 <insert id="register">
      insert into userinfo(username,password,isadmin)
      values(#{username},#{password},0)
    </insert>

controller层

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

前端

<!-- 注册窗口 -->
            <v-row justify="center">
                <v-dialog v-model="reg.showRegister" 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="reg.name" required></v-text-field>
                                    </v-col>
                                </v-row>
                                <v-row>
                                    <v-col cols="12" sm="12">
                                        <v-text-field label="密码*" v-model="reg.password" required></v-text-field>
                                    </v-col>
                                </v-row>
                                <v-row>
                                    <v-col cols="12" sm="12">
                                        <v-text-field label="确认密码*" v-model="reg.password2" required></v-text-field>
                                    </v-col>
                                </v-row>
                                <v-row>
                                    <v-col cols="12" sm="6">
                                        <v-btn color="primary" block v-on:click="doRegister">注册</v-btn>
                                    </v-col>
                                    <v-col cols="12" sm="6">
                                        <v-btn color="primary" block v-on:click="reg.showRegister = false">取消
                                        </v-btn>
                                    </v-col>
                                </v-row>
                            </v-container>
                        </v-card-text>
                    </v-card>
                </v-dialog>
            </v-row>
// 注册方法
            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)存储session信息

(3)显示欢迎信息

image.png

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

image.png

(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";
}

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);
    }

mapper层

//登录方法
    public UserInfo login(UserInfo userInfo);

xml

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

前端

// 登录方法
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("用户名或密码错误,请重新输入");
        }
    });
},

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

显示菜品

controller层
@RequestMapping("/list")
public ResponseBody<List<Dish>> getList() {
    List<Dish> data = dishMapper.getDishList();
    return new ResponseBody<>(0, "", data);
}
mapper层
//查询菜单列表
public List<Dish> getDishList();
xml
<select id="getDishList" resultType="com.example.ordersys.model.Dish">
   select * from dish
</select>
前端
<v-simple-table v-show="status == 'dishesPage' && login.isLogin">
    <template v-slot:default>
        <thead>
        <tr>
            <th class="text-left">菜名</th>
            <th class="text-left">价格</th>
            <th class="text-left">选择</th>
        </tr>
        </thead>
        <tbody>
        <tr v-for="dish in dishes">
            <td>
                <v-icon>mdi-food</v-icon>
                {{dish.name}}
            </td>
            <td>
                <v-icon>mdi-cash</v-icon>
                {{dish.price}}
            </td>
            <!--   选择窗体-->
            <td>
                <v-switch v-model="dish.isSelected"></v-switch>
            </td>
        </tr>
        </tbody>
    </template>
</v-simple-table>
jQuery.getJSON("/dish/list", {}, function (result) {
                if (result != null && result.data != null) {
                    app.dishes = result.data;
                }
            });

统计点的菜品个数以及下单总价

<v-row v-show="status == 'dishesPage' && login.isLogin">
    <v-col :col="11">
        <div class="pa-2">已点 {{selectedDishCount}} 道菜, 总计 {{selectedDishPrice}} 元</div>
    </v-col>
</v-row>
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;
    }
},


相关文章
|
安全 网络安全 数据安全/隐私保护
DMZ是什么?它是如何工作的?
DMZ,中文通常译为“隔离区”或“非军事化区”,是在网络安全领域中用来描述一个逻辑或物理的网络子段,这个子段通常位于组织的内部网络和外部网络(如互联网)之间。DMZ的主要目的是提供一个受限制且受控的环境,允许对外提供服务的服务器放置在此区域,从而在一定程度上保护内部网络的安全。
2630 1
|
消息中间件 监控 Java
使用Java进行实时数据处理的工具和技术
使用Java进行实时数据处理的工具和技术
|
存储 Java API
GraphQL(二)Spring boot + Netflix DGS
Spring boot + Netflix Domain Graph Service(DGS) + Apollo Federation Netflix DGS根据GraphQl schema及对应实体类,加载模式并结合DataFetcher将对象的字段进行绑定,执行相应的逻辑
|
存储
地理探测器Geodetector软件下载、操作方法与结果解释
本文介绍Geodetector软件的下载方法,以及地理探测器分析的完整操作,并对其结果加以解读~
2130 1
地理探测器Geodetector软件下载、操作方法与结果解释
|
JavaScript Oracle 前端开发
小满Vue3第三十六章(Vue如何开发移动端)
如果你用的vite 是 ts 他这个插件并没有提供声明文件我已经帮大家写好了声明文件(良心)
752 0
小满Vue3第三十六章(Vue如何开发移动端)
|
SQL 关系型数据库 MySQL
MySQL外键约束(FOREIGN KEY)
MySQL外键约束(FOREIGN KEY)
631 0
|
算法
基于matlab实现生成模糊fis文件,包括模糊隶属函数和模糊规则等,不使用fuzzy工具箱
基于matlab实现生成模糊fis文件,包括模糊隶属函数和模糊规则等,不使用fuzzy工具箱
685 0
|
JavaScript 安全 前端开发
在Vue中实现回车键切换焦点
在Vue中实现回车键切换焦点
768 0
|
存储 消息中间件 缓存
基于 MaxCompute 的实时数据处理实践
MaxCompute 通过流式数据高性能写入和秒级别查询能力(查询加速),提供EB级云原生数仓近实时分析能力;高效的实现对变化中的数据进行快速分析及决策辅助。当前Demo基于近实时交互式BI分析/决策辅助场景,实现指标卡近实时BI分析、近实时市场监测、近实时趋势分析、近实时销量拆分功能。
2155 1
基于 MaxCompute 的实时数据处理实践

热门文章

最新文章