Windows、JDK1.8、IDEA
Web服务器:可选,开发和测试阶段通常使用内置的Tomcat服务器
MySQL数据库服务器
前端技术:通常使用HTML、CSS、JavaScript等网页原生技术和一些前端框架,如Vue.js、React等
后端技术:通常使用Spring、Spring Boot框架搭建RESTful服务,并使用MyBatis等框架进行数据库操作
通信协议:通常使用HTTP协议通信,采用JSON等数据格式进行数据传输
Maven: 项目构建工具。
1.登录/退出:员工必须登录后,才可以访问系统管理后台。
2.员工管理:管理员可以对员工信息进行管理,包含查询、新增、编辑、禁用等功能。
3.分类管理:主要管理当前餐厅经营的菜品分类或套餐分类, 包含查询、新增、修改、删除等功能。
4.菜品管理:管理各个分类下的菜品信息,包含查询、新增、修改、删除、启售、停售等功能。
5.套餐管理:管理当前餐厅中的套餐信息,包含查询、新增、修改、删除、启售、停售等功能。
6.订单明细:主要维护用户在移动端下的订单信息,包含查询、取消、派送、完成,更改菜品信息包括价格、口味、材料等功能。
1. 登录注册功能:移动端用户通过手机号获取验证码进行登录,如果是第一次登录就代表注册功能。
2. 菜品显示功能:用户登录过后可以根据不同的分类浏览菜品。
3. 购物车功能:用户可以添加菜品或套餐到购物车里,可在购物车里对菜品进行增加、删除或清空操作。
4. 地址管理功能:用户可以新增、删除、修改收货地址,可以设置一个默认地址。
5. 结算功能:用户可以结算购物车中的菜品,地址默认选择默认地址,但可以更换收货地址。
6.查看订单功能:用户可以在付款成功后或者在个人信息里面查看订单信息。订单信息包括各个菜品信息。
7.再来一单功能:在查看个人订单中,对于已经完成的订单,用户可以点击再来一单,将已经购买过的菜品再次添加到购物车之中。
见文档
需要批量删除套餐记录,先通过 setmealService 对象的 removeByIds 方法批量删除对应 ID 的套餐记录,使用 for 循环遍历每个要删除的套餐 ID,将其对应的 SetmealDish 关联记录删除,通过 setmealDishService 对象的 remove 方法删除 SetmealDish 表中与该套餐 ID 相关的所有记录。
创建LambdaQueryWrapper对象,使用它来设置查询符合条件的购物车记录,调用shoppingCartService对象的getOne方法,获取符合条件的购物车记录,从购物车记录中获取购物车商品当前数量,如果购物车商品数量大于1,则将购物车记录中的购物车商品数量减少1,并将其更新到数据库中,如果购物车商品数量等于1,则直接从购物车记录中将购物车商品删除.
@PostMapping("/sub")
public R sub(@RequestBody ShoppingCart shoppingCart, HttpSession session) {
// 1.获取当前用户
User user = (User) session.getAttribute("employee");
// 2.查询当前用户、当前商品在购物车表里是否已存在
LambdaQueryWrapper 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("删除成功"); // 返回操作结果
}
创建一个LambdaQueryWrapper对象,不设置查询条件即查询所有购物车商品,使用shoppingCartService对象的remove方法,将符合条件的购物车商品全部删除,返回一个包含“清空购物车成功”信息的R对象作为响应结果。
@DeleteMapping("/clean")
public R clean() {
shoppingCartService.remove(new LambdaQueryWrapper());
return R.success("清空购物车成功");
}
创建Page对象和LambdaQueryWrapper对象,使用Page对象来定义分页参数,使用LambdaQueryWrapper对象来设置查询条件,对LambdaQueryWrapper对象设置查询条件,限定订单查询的用户ID,并根据订单的时间倒序排列, 使用orderService对象的page方法查询符合条件的订单信息,结果保存在pageInfo对象中,遍历Page对象中记录列表,通过订单ID查询对应的订单详情,并根据查询结果将记录转换为OrderDto对象,将OrderDto添加到一个List集合中,并将它们添加到已经将查询结果分页的pageDto对象中,将分页查询结果和“success”信息组合在R对象中,返回给移动端。
//移动端展示自己的订单分页查询
@GetMapping("/userPage")
public R page(int page, int pageSize,HttpSession httpSession){
//分页构造器对象
Page pageInfo = new Page<>(page,pageSize);
Page pageDto = new Page<>(page,pageSize);
//构造条件查询对象
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
Long userID = ((User) httpSession.getAttribute("employee")).getId();
queryWrapper.eq(Orders::getUserId,userID );
//这里是直接把当前用户分页的全部结果查询出来,要添加用户id作为查询条件,否则会出现用户可以查询到其他用户的订单情况
//添加排序条件,根据更新时间降序排列
queryWrapper.orderByDesc(Orders::getOrderTime);
orderService.page(pageInfo,queryWrapper);
//通过OrderId查询对应的OrderDetail
LambdaQueryWrapper queryWrapper2 = new LambdaQueryWrapper<>();
//对OrderDto进行需要的属性赋值
List records = pageInfo.getRecords();
List orderDtoList = records.stream().map((item) ->{
OrderDto orderDto = new OrderDto();
Long orderId = item.getId();//获取订单id
List orderDetailList= orderDetailService.list(queryWrapper2.eq(OrderDetail::getOrderId, orderId));
BeanUtils.copyProperties(item,orderDto);
//对orderDto进行OrderDetails属性的赋值
orderDto.setOrderDetails(orderDetailList);
return orderDto;
}).collect(Collectors.toList());
BeanUtils.copyProperties(pageInfo,pageDto,"records");
pageDto.setRecords(orderDtoList);
return R.success(pageDto);
}
使用LocalDateTime对象获取当前的时间,并将其设置为AddressBook对象的修改时间,使用session对象获取当前用户ID,并将其设置为AddressBook对象的修改人ID,调用addressBookService对象的updateById方法,将AddressBook对象更新到数据库中。
//修改收货地址
@PutMapping("/edit")
public R addressBookupdate(@RequestBody AddressBook addressBook, HttpSession session){
//设置修改时间
addressBook.setUpdateTime(LocalDateTime.now());
//设置修改人
addressBook.setUpdateUser((Long)session.getAttribute("user"));
addressBookService.updateById(addressBook);
return R.success("修改地址成功!");
}
改造分类中查询菜品的代码,使它在移动端中也能使用,并显示出更多的比如口味等信息,并添加至购物车。
public R> list(Dish dish){
//构造查询条件
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(dish.getCategoryId() != null ,Dish::getCategoryId,dish.getCategoryId());
//添加条件,查询状态为1(起售状态)的菜品
queryWrapper.eq(Dish::getStatus,1);
//添加排序条件
queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
List list = dishService.list(queryWrapper);
List dishDtoList = list.stream().map((item) -> {
DishDto dishDto = new DishDto();
BeanUtils.copyProperties(item,dishDto);
Long categoryId = item.getCategoryId();//分类id
//根据id查询分类对象
Category category = categoryService.getById(categoryId);
if(category != null){
String categoryName = category.getName();
dishDto.setCategoryName(categoryName);
}
//当前菜品的id
Long dishId = item.getId();
LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
List dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
dishDto.setFlavors(dishFlavorList);
return dishDto;
}).collect(Collectors.toList());
return R.success(dishDtoList);
}
外卖系统的员工管理功能测试结果表如表所示。
表 员工管理测试表
测试用例 |
期望结果 |
实际结果 |
员工登录 |
管理员可以直接登录并查看所有员工的信息 |
测试通过 |
员工添加 |
系统可以正常的添加员工信息,并对插入异常的数据提示 |
测试通过 |
员工修改 |
管理员可以对员工的信息进行修改,例如修改名字、手机号等信息 |
测试通过 |
员工禁用/启用 |
管理员可以管理员工账号的启用和禁用状态 |
测试通过 |
外卖系统员工管理测试通过,符合要求,并能够满足正常员工管理的要求。
见文档
见文档
见文档