实训项目 “外卖点餐”系统(IDEA)

一、软硬件条件

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.再来一单功能:在查看个人订单中,对于已经完成的订单,用户可以点击再来一单,将已经购买过的菜品再次添加到购物车之中。

b2fce984ad5b4712b677acbeeade6599.png

 

 三、数据库设计

见文档

 四、具体实现

部分功能如下:

1.菜品和套餐-批量起售/删除功能

需要批量删除套餐记录,先通过 setmealService 对象的 removeByIds 方法批量删除对应 ID 的套餐记录,使用 for 循环遍历每个要删除的套餐 ID,将其对应的 SetmealDish 关联记录删除,通过 setmealDishService 对象的 remove 方法删除 SetmealDish 表中与该套餐 ID 相关的所有记录。

329bcaca62cb47919ea871fa50b01057.png

2.购物车删减功能

创建LambdaQueryWrapper对象,使用它来设置查询符合条件的购物车记录,调用shoppingCartService对象的getOne方法,获取符合条件的购物车记录,从购物车记录中获取购物车商品当前数量,如果购物车商品数量大于1,则将购物车记录中的购物车商品数量减少1,并将其更新到数据库中,如果购物车商品数量等于1,则直接从购物车记录中将购物车商品删除.

@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("删除成功");  // 返回操作结果
}

d8434acaa9024a0b918995b6c3d6651f.png

3.购物车清空功能

创建一个LambdaQueryWrapper对象,不设置查询条件即查询所有购物车商品,使用shoppingCartService对象的remove方法,将符合条件的购物车商品全部删除,返回一个包含“清空购物车成功”信息的R对象作为响应结果。

@DeleteMapping("/clean")
public R<String> clean() {
    shoppingCartService.remove(new LambdaQueryWrapper<ShoppingCart>());
    return R.success("清空购物车成功");
}

dc7d1fe15e4b405eaffafdba00b43d4c.png

4.查看订单功能

创建Page对象和LambdaQueryWrapper对象,使用Page对象来定义分页参数,使用LambdaQueryWrapper对象来设置查询条件,对LambdaQueryWrapper对象设置查询条件,限定订单查询的用户ID,并根据订单的时间倒序排列, 使用orderService对象的page方法查询符合条件的订单信息,结果保存在pageInfo对象中,遍历Page对象中记录列表,通过订单ID查询对应的订单详情,并根据查询结果将记录转换为OrderDto对象,将OrderDto添加到一个List集合中,并将它们添加到已经将查询结果分页的pageDto对象中,将分页查询结果和“success”信息组合在R对象中,返回给移动端。

//移动端展示自己的订单分页查询

@GetMapping("/userPage")
public R<Page> page(int page, int pageSize,HttpSession httpSession){
    //分页构造器对象
    Page<Orders> pageInfo = new Page<>(page,pageSize);
    Page<OrderDto> pageDto = new Page<>(page,pageSize);
    //构造条件查询对象
    LambdaQueryWrapper<Orders> 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<OrderDetail> queryWrapper2 = new LambdaQueryWrapper<>();
    //对OrderDto进行需要的属性赋值
    List<Orders> records = pageInfo.getRecords();
    List<OrderDto> orderDtoList = records.stream().map((item) ->{
        OrderDto orderDto = new OrderDto();
        
        Long orderId = item.getId();//获取订单id
        List<OrderDetail> 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);
}

6d40f0f89682455583bfeae0dcc7e0c0.png

5.地址修改功能

使用LocalDateTime对象获取当前的时间,并将其设置为AddressBook对象的修改时间,使用session对象获取当前用户ID,并将其设置为AddressBook对象的修改人ID,调用addressBookService对象的updateById方法,将AddressBook对象更新到数据库中。

//修改收货地址
@PutMapping("/edit")
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("修改地址成功!");
}

 

6.移动端查询菜品详情

改造分类中查询菜品的代码,使它在移动端中也能使用,并显示出更多的比如口味等信息,并添加至购物车。

 public R<List<DishDto>> list(Dish dish){
    //构造查询条件
    LambdaQueryWrapper<Dish> 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<Dish> list = dishService.list(queryWrapper);

    List<DishDto> 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<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
        List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
        dishDto.setFlavors(dishFlavorList);

        return dishDto;
    }).collect(Collectors.toList());

    return R.success(dishDtoList);


}

f531b7d878264d7180c8d363115c06eb.png

五、测试

1.员工管理功能测试

外卖系统的员工管理功能测试结果表如表所示。

表 员工管理测试表

测试用例

期望结果

实际结果

员工登录

管理员可以直接登录并查看所有员工的信息

测试通过

员工添加

系统可以正常的添加员工信息,并对插入异常的数据提示

测试通过

员工修改

管理员可以对员工的信息进行修改,例如修改名字、手机号等信息

测试通过

员工禁用/启用

管理员可以管理员工账号的启用和禁用状态

测试通过

外卖系统员工管理测试通过,符合要求,并能够满足正常员工管理的要求。

2.移动端功能测试

见文档

 

六、部署

见文档

七、总结

见文档

猜你喜欢

转载自blog.csdn.net/qq_70311894/article/details/131075271