1 实训基本信息
1.1 实训项目名称
“外卖点餐”系统。
1.2 实训时间及地点
2 实训内容简介
本项目(“外卖点餐”系统)是专门为餐饮企业(餐厅、饭店)定制的-款软件产品,包括系统管理后台和移动端应用两部分。
其中系统管理后台主要提供给餐饮企业内部员工使用,可以对餐厅的菜品、套餐、订单等进行管理维护。移动端应用主要提供给消费者使用,可以在线浏览菜品、添加购物车、下单等。
3 需求分析
3.1 软硬件条件
IDEA 2021.2.3
MySQL 5.5
MyBatis
MyBatisPlus
Git: 版本控制工具。
Maven: 3.6.1
Junit:单元测试工具。
3.2 技术可行性
3.2.1 技术需求
外卖点单、支付、订单管理、配送等功能是瑞吉外卖必不可少的技术需求。此外,还需要提供用户注册、登录、反馈、推荐等功能。
3.2.2 市场需求
外卖市场的需求是巨大的,但竞争也是非常激烈的。应该进行市场细分,并确定与众不同的商业模式和目标用户,同时提供具有差异化的服务和体验。
3.2.3 开发成本
应该评估开发瑞吉外卖应用所需的成本,包括技术设计、软件工程、移动端应用开发、数据分析等方面。
3.2.4 数据连通性
外卖应用需要和多个配送和支付供应商的应用进行连接,确保订单的顺利传递和支付的正确处理。
3.2.5 用户体验
好的用户体验是被用户所赞赏和记住的重要要素。外卖应用中,用户体验包括易用、快速、准确、方便等多个方面。
4 功能设计
4.1 管理端
4.1.1 登录/退出
内部员工必须登录后,才可以访问系统管理后台。
4.1.2 员工管理
管理员可以在系统后台对员工信息进行管理,包含查询、新增、编辑、禁用等功能。
4.1.3 分类管理
主要对当前餐厅经营的菜品分类或套餐分类进行管理维护,包含查询、新增、修改、删除等功能。
4.1.4 菜品管理
主要维护各个分类下的菜品信息,包含查询、新增、修改、删除、启售、停售等功能。
4.1.5 套餐管理
主要维护当前餐厅中的套餐信息,包含查询、新增、修改、删除、启售、停售等功能。
4.1.6 订单明细
主要维护用户在移动端下的订单信息,包含查询、取消、派送、完成,以及订单报表下载等功能。
4.2 用户端
4.2.1 登录/退出
在移动端, 用户也需要登录后使用APP进行点餐。
4.2.2 点餐-菜单
在点餐界面需要展示出菜品分类/套餐分类, 并根据当前选择的分类加载其中的菜品信息, 供用户查询选择。
4.2.3 点餐-购物车
用户选中的菜品就会加入用户的购物车, 主要包含查询购物车、加入购物车、删除购物车、清空购物车等功能。
4.2.4 订单支付
用户选完菜品/套餐后, 可以对购物车菜品进行结算支付, 这时就需要进行订单的支付。
4.2.5 个人信息
在个人中心页面中会展示当前用户的基本信息, 用户可以管理收货地址, 也可以查询历史订单数据。
5 数据库设计
用户表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
Name |
varchar(50) |
否 |
否 |
否 |
姓名 |
Phone |
varchar(100) |
否 |
否 |
否 |
手机号 |
Sex |
varchar(2) |
否 |
否 |
否 |
性别 |
Id_number |
varchar(18) |
否 |
否 |
否 |
身份证号 |
Avatar Status |
varchar(500) int(11) |
否 否 |
否 否 |
否 否 |
头像 状态 |
购物车表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
Name |
varchar(50) |
否 |
否 |
否 |
名称 |
Image |
varchar(100) |
否 |
否 |
否 |
图片 |
User_id |
bigint(20) |
否 |
否 |
否 |
用户ID |
Dish_Id |
bigint(20) |
否 |
否 |
否 |
菜品ID |
Setmeal_Id DishFlavor |
bigint(20)varchar(50) |
否 否 |
否 否 |
否 否 |
套餐ID 口味 |
Number |
int(11) |
否 |
否 |
否 |
数量 |
Amount CreateTime |
decimal(10) datetime |
否 否 |
否 否 |
否 否 |
金额 创建时间 |
地址薄表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
User_Id |
bigint(20) |
否 |
否 |
否 |
用户ID |
Consignee |
varchar(50) |
否 |
否 |
否 |
收货人 |
Sex |
tinyint(4) |
否 |
否 |
否 |
性别 |
Phone Province |
varchar(11) varchar(12) |
否 否 |
否 否 |
否 否 |
手机号 省级编号 |
Province |
Varchar(32) |
否 |
否 |
否 |
省级名称 |
City_code City_name |
varchar(12) varchar(32) |
否 否 |
否 否 |
否 否 |
市级编号 市级名称 |
District |
varchar(12) |
否 |
否 |
否 |
区级编号 |
District |
varchar(32) |
否 |
否 |
否 |
区级名称 |
Detail |
varchar(200) |
否 |
否 |
否 |
详细地址 |
Label |
varchar(100) |
否 |
否 |
否 |
标签 |
Is_default |
tinyint(1) |
否 |
否 |
否 |
是否默认 |
Createtime |
datetime |
否 |
否 |
否 |
创建时间 |
Updatetime |
datetime |
否 |
否 |
否 |
更新时间 |
Createuser |
Bigint(20) |
否 |
否 |
否 |
创建者 |
Updateuser |
Bigint(20) |
否 |
否 |
否 |
修改者 |
Is_deleted |
int(11) |
否 |
否 |
否 |
是否删除 |
分类表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
Type |
int(11) |
否 |
否 |
否 |
类型 |
Name |
varchar(64) |
否 |
否 |
否 |
名称 |
Sort |
int(11) |
否 |
否 |
否 |
顺序 |
CreateTime UpdateTime |
datetime datetime |
否 否 |
否 否 |
否 否 |
创建时间 更新时间 |
Createuser |
bigint(20) |
否 |
否 |
否 |
创建者 |
Updateuser |
bigint(20) |
否 |
否 |
否 |
修改者 |
菜品表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
Name |
varchar(64) |
否 |
否 |
否 |
菜品名称 |
CategoryId |
bigint(20) |
否 |
否 |
否 |
菜品分类ID |
Price |
decimal(10) |
否 |
否 |
否 |
菜品价格 |
Code |
varchar(64) |
否 |
否 |
否 |
商品码 |
Image Descripte |
varchar(200) varchar(400) |
否 否 |
否 否 |
否 否 |
图片 描述信息 |
Status |
int(11) |
否 |
否 |
否 |
状态码 |
Sort |
int(11) |
否 |
否 |
否 |
顺序 |
CreateTime UpdateTime |
datetime datetime |
否 否 |
否 否 |
否 否 |
创建时间 更新时间 |
Createuser |
Bigint(20) |
否 |
否 |
否 |
创建者 |
Updateuser |
Bigint(20) |
否 |
否 |
否 |
修改者 |
Is_deleted |
int(11) |
否 |
否 |
否 |
是否删除 |
口味表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
Dish_Id |
bigint(20) |
否 |
否 |
否 |
菜品ID |
Name |
varchar(64) |
否 |
否 |
否 |
口味名称 |
Value |
varchar(500) |
否 |
否 |
否 |
口味数据 |
CreateTime UpdateTime |
datetime datetime |
否 否 |
否 否 |
否 否 |
创建时间 更新时间 |
Createuser |
Bigint(20) |
否 |
否 |
否 |
创建者 |
Updateuser |
Bigint(20) |
否 |
否 |
否 |
修改者 |
Is_deleted |
int(11) |
否 |
否 |
否 |
是否删除 |
员工表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
Name |
varchar(32) |
否 |
否 |
否 |
姓名 |
Username |
varchar(32) |
否 |
否 |
否 |
用户名 |
Password |
varchar(64) |
否 |
否 |
否 |
密码 |
Phone |
varchar(11) |
否 |
否 |
否 |
手机号 |
Sex |
varchar(2) |
否 |
否 |
否 |
性别 |
Id_Number |
varchar(18) |
否 |
否 |
否 |
身份证号 |
Status |
Int(11) |
否 |
否 |
否 |
状态 |
CreateTime UpdateTime |
datetime datetime |
否 否 |
否 否 |
否 否 |
创建时间 更新时间 |
Createuser |
Bigint(20) |
否 |
否 |
否 |
创建者 |
Updateuser |
Bigint(20) |
否 |
否 |
否 |
修改者 |
订单表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
Number |
varchar(50) |
否 |
否 |
否 |
订单号 |
Status |
Int(11) |
否 |
否 |
否 |
订单状态 |
User_Id |
bigint(20) |
否 |
否 |
否 |
下单用户 |
Address_id |
bigint(20) |
否 |
否 |
否 |
地址ID |
Order_Time CheckTime |
datetime datetime |
否 否 |
否 否 |
否 否 |
下单时间 结账时间 |
Pay_method |
int(11) |
否 |
否 |
否 |
支付方式 |
Amount |
decimal(10) |
否 |
否 |
否 |
实收金额 |
Remark |
varchar(100) |
否 |
否 |
否 |
备注 |
Phone |
varchar(255) |
否 |
否 |
否 |
手机号 |
Address |
varchar(255) |
否 |
否 |
否 |
用户地址 |
User_name |
varchar(255) |
否 |
否 |
否 |
用户名 |
Consignee |
varchar(255) |
否 |
否 |
否 |
收货人 |
订单详情表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
Name |
varchar(50) |
否 |
否 |
否 |
名称 |
Image |
varchar(100) |
否 |
否 |
否 |
图片 |
Order_Id |
bigint(20) |
否 |
否 |
否 |
订单ID |
Dish_Id |
bigint(20) |
否 |
否 |
否 |
菜品ID |
Setmeal_Id DishFlavor |
bigint(20) varchar(50) |
否 否 |
否 否 |
否 否 |
套餐ID 口味 |
Number |
int(11) |
否 |
否 |
否 |
数量 |
Amount |
decimal(10) |
否 |
否 |
否 |
金额 |
套餐表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
CategoryId |
bigint(20) |
否 |
否 |
否 |
分类ID |
Name |
varchar(64) |
否 |
否 |
否 |
套餐名称 |
Price |
decimal(10) |
否 |
否 |
否 |
套餐价格 |
Status |
Int(11) |
否 |
否 |
否 |
状态 |
Code |
varchar(32) |
否 |
否 |
否 |
编码 |
Descripte |
varchar(512) |
否 |
否 |
否 |
描述信息 |
Image |
varchar(255) |
否 |
否 |
否 |
图片 |
CreateTime UpdateTime |
datetime datetime |
否 否 |
否 否 |
否 否 |
创建时间 更新时间 |
Createuser |
Bigint(20) |
否 |
否 |
否 |
创建者 |
Updateuser |
Bigint(20) |
否 |
否 |
否 |
修改者 |
Is_Delete |
varchar(50) |
否 |
否 |
否 |
是否删除 |
分类表
菜品表
口味表
员工表
套餐关系表
字段 |
数据类型 |
主键 |
外键 |
是否为空 |
说明 |
Id |
bigint(20) |
是 |
否 |
否 |
|
CategoryId |
bigint(20) |
否 |
否 |
否 |
分类ID |
Name |
varchar(64) |
否 |
否 |
否 |
套餐名称 |
Price |
decimal(10) |
否 |
否 |
否 |
套餐价格 |
Status |
Int(11) |
否 |
否 |
否 |
状态 |
Code |
varchar(32) |
否 |
否 |
否 |
编码 |
Descripte |
varchar(512) |
否 |
否 |
否 |
描述信息 |
Image |
varchar(255) |
否 |
否 |
否 |
图片 |
CreateTime UpdateTime |
datetime datetime |
否 否 |
否 否 |
否 否 |
创建时间 更新时间 |
Createuser |
Bigint(20) |
否 |
否 |
否 |
创建者 |
Updateuser |
Bigint(20) |
否 |
否 |
否 |
修改者 |
Is_Delete |
varchar(50) |
否 |
否 |
否 |
是否删除 |
用户表
购物车表
地址薄表
分类表
菜品表
口味表
员工表
订单表
订单详情表
套餐表
套餐关系表
实体E-R图
6 具体实现
6.1 员工登录
6.1.1 登录功能
内部员工必须输入员工账号和密码,通过验证后才可以访问系统管理后台。过滤器会判断用户是否已经完成了登录,如果没有登录则跳转到登陆页面。
员工登录与退出核心代码:
@PostMapping("/employee/login")
public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){
//RequestBody可以接收JSON格式的数据并解析为实体类(Employee)
String username = employee.getUsername();
String password = DigestUtils.md5DigestAsHex(employee.getPassword().getBytes());
System.out.println("用户名:"+username+"--密码:"+password);
//LambdaQueryWrapper<List<Map>> lambdaQueryWrapper = new LambdaQueryWrapper<>();
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
//查询结果是单张表,用实体类接收;如果是if交叉查询(多张表查询)用List<Map>
queryWrapper.eq(Employee::getUsername,username);
//使用LambdaQueryWrapper免除写sql,相当于进行select操作
Employee employee1 = employeeService.getOne(queryWrapper);
System.out.println("2********username:"+employee1.getPhone());
if (employee1 == null){
return R.error("用户名错误,登录失败,请重试!");
}
if (!password.equals(employee1.getPassword())){
return R.error("密码错误,登录失败,请重试!");
}
if (employee1.getStatus()!=1){
return R.error("该账户被删除或禁用,登录失败!");
}
request.getSession().setAttribute("employee",employee1); //为了filter、后续调用方便
BaseContext.setCurrentUserID(employee1.getId()); //为了普通类能够调用
return R.success(employee1);
}
@PostMapping("/employee/logout")
public R<Employee> logout(HttpServletRequest request){
request.getSession().removeAttribute("employee");
request.getSession().invalidate();
return R.success(null);
}
6.2 员工管理
6.2.1 查询功能
输入对应的员工名称可查找该员工。
6.2.2 添加功能
通过输入新员工的信息实现对员工的新增操作。
6.2.3 修改功能
点击编辑可以对所选员工的个人信息进行修改。
6.2.4 禁用功能
可以点击禁用禁止该员工的登录权限。
6.3 分类管理
6.3.1 查看功能
可以查看当前显示所有菜品或套餐类型。
6.3.2 添加功能
对新的菜品和套餐类型进行添加操作。
6.3.3 修改功能
对于一些错误的菜品或套餐信息进行更改。
6.3.4 删除功能
对于某些过时或者冷门的菜品或套餐进行删除。
6.4 菜品管理
6.4.1 查询功能
可以根据个人需求查找当前现有菜品信息。
6.4.2 添加功能
对于当前热门菜品可以新增到菜品管理中。
6.4.3 修改功能
对一些冷门菜品可以对其价格进行修改。
6.4.4 删除功能
对于一些冷门菜品可以进行停售或删除操作。
菜品信息修改核心代码:
@PutMapping("/edit")
public R<String> update(@RequestBody DishDto dishDto) {
// 更新dish表
dishService.updateById(dishDto);
// 清理当前菜品口味信息,dish_flavor表的delete操作
// 不能使用removeById, 因为dishDto的id不是dish_flavor的主键
LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DishFlavor::getDishId, dishDto.getId());
dishFlavorService.remove(queryWrapper);
// 重新插入菜品口味信息,dish_flavor表的insert操作
List<DishFlavor> dishFlavor = new ArrayList<>();
for (DishFlavor item :dishDto.getFlavors()) {
item.setDishId(dishDto.getId());
dishFlavor.add(item);
}
dishFlavorService.saveBatch(dishFlavor);
return R.success("修改成功");
}
6.5 套餐管理
6.5.1 查询功能
对于所需要的套餐类型进行检索。
6.5.2 添加功能
对于新的套餐类型加入到套餐管理中。
6.5.3 修改功能
针对一些信息有误的套餐进行修改。
6.5.4 删除功能
某些套餐长期无人购买可以选择性进行删除。
6.6 订单明细
6.6.1 查询功能
在订单明细中可以查看用户的所有订单和派送状态。
6.6.2 订单查看
点击查看订单可以看到用户的个人信息以及地址详情等。
6.7 用户管理
6.7.1 登录管理
在移动端, 手机用户需要输入手机号验证码登录后进入APP进行点餐。
6.7.2 点餐-菜单
在点餐界面需要展示出菜品分类/套餐分类, 并根据当前选择的分类加载其中的菜品信息, 供用户查询选择。
6.7.3 点餐-购物车
用户选中的菜品就会加入用户的购物车, 主要包含查询购物车、加入购物车、删除购物车、清空购物车等功能。
减少购物车菜品核心代码:
@PostMapping("/sub")
public R<String> sub(@RequestBody ShoppingCart shoppingCart, HttpSession session) {
// 1.获取当前用户
User user = (User) session.getAttribute("employee");
// 2.查询当前用户、当前商品在购物车表里是否已存在
LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(ShoppingCart::getUserId, user.getId()) // 筛选用户ID
.eq(shoppingCart.getDishId() != null, ShoppingCart::getDishId, shoppingCart.getDishId()) // 如果传入的商品ID不为空,筛选商品ID
.eq(shoppingCart.getSetmealId() != null, ShoppingCart::getSetmealId, shoppingCart.getSetmealId()); // 如果传入的套餐ID不为空,筛选套餐ID
ShoppingCart shoppingCart1 = shoppingCartService.getOne(lambdaQueryWrapper); // 返回符合条件的购物车记录
int shoppingCartNumber = shoppingCart1.getNumber();
try {
if (shoppingCartNumber > 1) { // 如果记录的数量大于1,则减少数量
shoppingCartNumber = shoppingCart1.getNumber() - 1; // 记录的数量减1
shoppingCart1.setNumber(shoppingCartNumber); // 更新记录的数量
shoppingCartService.updateById(shoppingCart1); // 更新购物车记录
} else { // 如果记录的数量为1,则删除该记录
shoppingCartService.removeById(shoppingCart1.getId());
}
} catch (Exception e) {
return R.error("删除失败");
}
return R.success("删除成功");
}
6.7.4 订单支付
用户选完菜品/套餐后, 可以对购物车菜品进行结算支付, 这时就需要进行订单的支付。
6.7.5 个人信息
在个人中心页面中会展示当前用户的基本信息, 用户可以管理收货地址, 也可以查询历史订单数据。
地址修改与删除核心代码:
@PutMapping
public R<String> addressBookupdate(@RequestBody AddressBook addressBook, HttpSession session){
//设置修改时间
addressBook.setUpdateTime(LocalDateTime.now());
//设置修改人
addressBook.setUpdateUser((Long)session.getAttribute("user"));
addressBookService.updateById(addressBook);
return R.success("修改地址成功!");
}
@DeleteMapping
public R<String> detele(@RequestParam("ids") Long id){
addressBookService.removeById(id);
return R.success("删除地址成功!");
}
7 测试
7.1 员工管理功能测试
员工管理测试表
测试用例 |
期望结果 |
实际结果 |
查询员工 |
通过账号登录进入后可以根据员工姓名查找该员工信息 |
测试通过 |
添加员工 |
通过输入新员工的信息实现对新员工的添加操作。 |
测试通过 |
修改员工 |
点击编辑可以对所选员工的个人信息进行修改 |
测试通过 |
禁用员工 |
点击禁用能够有效的禁止该员工的登录权限 |
测试通过 |
根据上面的测试结果来看,该功能通过所有的测试用例并且符合需求。
7.2 分类管理功能测试
分类管理测试表
测试用例 |
期望结果 |
实际结果 |
查看菜品/套餐 |
员工可以查看当前显示所有菜品或套餐类型 |
测试通过 |
添加菜品/套餐 |
员工能够对新的菜品或套餐类型进行添加操作 |
测试通过 |
修改菜品/套餐 |
员工可以对于信息错误的菜品或套餐进行更改 |
测试通过 |
删除菜品/套餐 |
员工能够对于过时或冷门的菜品或套餐进行删除 |
测试通过 |
根据上面的测试结果来看,该功能通过所有的测试用例并且符合需求。
7.3 地址管理功能测试
地址管理测试表
测试用例 |
期望结果 |
实际结果 |
查看地址 |
用户可以查看当前显示的所有个人地址信息 |
测试通过 |
添加地址 |
用户能够对新的地址信息进行添加操作 |
测试通过 |
修改地址 |
用户可以对于错误的地址信息进行更改 |
测试通过 |
删除地址 |
用户能够对于一些不常用的地址进行删除 |
测试通过 |
根据上面的测试结果来看,该功能通过所有的测试用例并且符合需求。
8 部署
- 首先打开项目Maven工具栏,确定将要打包的模块,点开Lifecycle选项,然后选择Install开始打包。
- 先在IDEA控制台上单击切换到Terminal终端页面,然后在项目所在位置后的指令输入提示位置指令部署即可。
9 总结
通过实训我们学习到MyBatisPlus是MyBatis的增强工具,它为MyBatis提供了更加方便快捷的使用方式,同时也提供了更多的扩展功能。
它提供了大量的注解和接口,如@TableField注解可以定义表字段的属性等等。另外它还提供了一些高级特性,如分页查询、逻辑删除和多表关联查询等。
在这次实训中,我通过编写代码、模拟实际场景等方式,来提升自己的编程能力,同时需要注重代码规范和功能的完整性,不断优化和完善项目。
其次,我深刻的认识到Java编程需要掌握各种开发工具和框架,如IntelliJ IDEA、Spring boot等,这些工具和框架可以提高开发效率。因此,在实训中也应该注重培养学员的独立学习能力,让他们自主学习并运用各种工具和框架。
最后,Java编程需要具备良好的团队协作能力,因为实际项目中不可能仅仅由单人完成,需要多人协作完成。在实训中也应该注重培养个人的沟通技巧和团队合作精神,如果能够在团队中融洽合作,就能极大地提高项目的实战效果。文章来源:https://www.toymoban.com/news/detail-731914.html
注:由于源码量过多,需要的朋友可在资源中下载,也可私信我拿取! 文章来源地址https://www.toymoban.com/news/detail-731914.html
到了这里,关于Spring Boot实训项目 瑞吉外卖功能实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!